writeStringReferencesToFile
pkgs.writeStringReferencesToFile
Docs pulled from | This Revision | 43 minutes ago
Extract a string's references to derivations and paths (its context) and write them to a text file, removing the input string itself from the dependency graph. This is useful when you want to make a derivation depend on the string's references, but not its contents (to avoid unnecessary rebuilds, for example).
Note that this only works as intended on Nix >= 2.3.
Inputs
string
-
1. Function argument
Noogle detected
Implementation
The following is the current implementation of this function.
writeStringReferencesToFile = string:
/**
The basic operation this performs is to copy the string context
from `string` to a second string and wrap that string in a
derivation. However, that alone is not enough, since nothing in the
string refers to the output paths of the derivations/paths in its
context, meaning they'll be considered build-time dependencies and
removed from the wrapper derivation's closure. Putting the
necessary output paths in the new string is however not very
straightforward - the attrset returned by `getContext` contains
only references to derivations' .drv-paths, not their output
paths. In order to "convert" them, we try to extract the
corresponding paths from the original string using regex.
*/
let
# Taken from https://github.com/NixOS/nix/blob/130284b8508dad3c70e8160b15f3d62042fc730a/src/libutil/hash.cc#L84
nixHashChars = "0123456789abcdfghijklmnpqrsvwxyz";
context = builtins.getContext string;
derivations = lib.filterAttrs (n: v: v ? outputs) context;
# Objects copied from outside of the store, such as paths and
# `builtins.fetch*`ed ones
sources = lib.attrNames (lib.filterAttrs (n: v: v ? path) context);
packages =
lib.mapAttrs'
(name: value:
{
inherit value;
name = lib.head (builtins.match "${builtins.storeDir}/[${nixHashChars}]+-(.*)\\.drv" name);
})
derivations;
# The syntax of output paths differs between outputs named `out`
# and other, explicitly named ones. For explicitly named ones,
# the output name is suffixed as `-name`, but `out` outputs
# aren't suffixed at all, and thus aren't easily distinguished
# from named output paths. Therefore, we find all the named ones
# first so we can use them to remove false matches when looking
# for `out` outputs (see the definition of `outputPaths`).
namedOutputPaths =
lib.flatten
(lib.mapAttrsToList
(name: value:
(map
(output:
lib.filter
lib.isList
(builtins.split "(${builtins.storeDir}/[${nixHashChars}]+-${name}-${output})" string))
(lib.remove "out" value.outputs)))
packages);
# Only `out` outputs
outputPaths =
lib.flatten
(lib.mapAttrsToList
(name: value:
if lib.elem "out" value.outputs then
lib.filter
(x: lib.isList x &&
# If the matched path is in `namedOutputPaths`,
# it's a partial match of an output path where
# the output name isn't `out`
lib.all (o: !lib.hasPrefix (lib.head x) o) namedOutputPaths)
(builtins.split "(${builtins.storeDir}/[${nixHashChars}]+-${name})" string)
else
[ ])
packages);
allPaths = lib.concatStringsSep "\n" (lib.unique (sources ++ namedOutputPaths ++ outputPaths));
allPathsWithContext = builtins.appendContext allPaths context;
in
if builtins ? getContext then
writeText "string-references" allPathsWithContext
else
writeDirectReferencesToFile (writeText "string-file" string);