@ -465,6 +465,88 @@ rec {
'' ;
/*
* 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 .
* /
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 " c o n v e r t " 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 = " 0 1 2 3 4 5 6 7 8 9 a b c d f g h i j k l m n p q r s v w x y z " ;
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 } ] + - ( . * ) \. d r v " 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 " o u t " value . outputs ) ) )
packages ) ;
# Only `out` outputs
outputPaths =
lib . flatten
( lib . mapAttrsToList
( name : value :
if lib . elem " o u t " 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 " s t r i n g - r e f e r e n c e s " allPathsWithContext
else
writeDirectReferencesToFile ( writeText " s t r i n g - f i l e " string ) ;
/* P r i n t a n e r r o r m e s s a g e i f t h e f i l e w i t h t h e s p e c i f i e d n a m e a n d
* hash doesn't exist in the Nix store . This function should only
* be used by non-redistributable software with an unfree license