query
On this page

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);