1+ { lib , ... } :
2+ let
3+ inherit ( builtins ) head tail isList isAttrs isInt attrNames ;
4+
5+ in
6+
7+ with lib . lists ;
8+ with lib . attrsets ;
9+ with lib . strings ;
10+
11+ rec {
12+
13+ # returns default if env var is not set
14+ maybeEnv = name : default :
15+ let value = builtins . getEnv name ; in
16+ if value == "" then default else value ;
17+
18+ defaultMergeArg = x : y : if builtins . isAttrs y then
19+ y
20+ else
21+ ( y x ) ;
22+ defaultMerge = x : y : x // ( defaultMergeArg x y ) ;
23+ foldArgs = merger : f : init : x :
24+ let arg = ( merger init ( defaultMergeArg init x ) ) ;
25+ # now add the function with composed args already applied to the final attrs
26+ base = ( setAttrMerge "passthru" { } ( f arg )
27+ ( z : z // { __id_static = "0.4553087592557379" ; __id_dynamic = builtins . hashFile "sha256" /Users/jeffhykin/repos/snowball/random.ignore ;
28+
29+ function = foldArgs merger f arg ;
30+ args = ( lib . attrByPath [ "passthru" "args" ] { } z ) // x ;
31+ } ) ) ;
32+ withStdOverrides = base // { __id_static = "0.8985474209071187" ; __id_dynamic = builtins . hashFile "sha256" /Users/jeffhykin/repos/snowball/random.ignore ;
33+
34+ override = base . passthru . function ;
35+ } ;
36+ in
37+ withStdOverrides ;
38+
39+
40+ # shortcut for attrByPath ["name"] default attrs
41+ maybeAttrNullable = maybeAttr ;
42+
43+ # shortcut for attrByPath ["name"] default attrs
44+ maybeAttr = name : default : attrs : attrs . ${ name } or default ;
45+
46+
47+ # Return the second argument if the first one is true or the empty version
48+ # of the second argument.
49+ ifEnable = cond : val :
50+ if cond then val
51+ else if builtins . isList val then [ ]
52+ else if builtins . isAttrs val then { }
53+ # else if builtins.isString val then ""
54+ else if val == true || val == false then false
55+ else null ;
56+
57+
58+ # Return true only if there is an attribute and it is true.
59+ checkFlag = attrSet : name :
60+ if name == "true" then true else
61+ if name == "false" then false else
62+ if ( elem name ( attrByPath [ "flags" ] [ ] attrSet ) ) then true else
63+ attrByPath [ name ] false attrSet ;
64+
65+
66+ # Input : attrSet, [ [name default] ... ], name
67+ # Output : its value or default.
68+ getValue = attrSet : argList : name :
69+ ( attrByPath [ name ] ( if checkFlag attrSet name then true else
70+ if argList == [ ] then null else
71+ let x = builtins . head argList ; in
72+ if ( head x ) == name then
73+ ( head ( tail x ) )
74+ else ( getValue attrSet
75+ ( tail argList ) name ) ) attrSet ) ;
76+
77+
78+ # Input : attrSet, [[name default] ...], [ [flagname reqs..] ... ]
79+ # Output : are reqs satisfied? It's asserted.
80+ checkReqs = attrSet : argList : condList :
81+ (
82+ foldr lib . and true
83+ ( map ( x : let name = ( head x ) ; in
84+
85+ ( ( checkFlag attrSet name ) ->
86+ ( foldr lib . and true
87+ ( map ( y : let val = ( getValue attrSet argList y ) ; in
88+ ( val != null ) && ( val != false ) )
89+ ( tail x ) ) ) ) ) condList ) ) ;
90+
91+
92+ # This function has O(n^2) performance.
93+ uniqList = { inputList , acc ? [ ] } :
94+ let go = xs : acc :
95+ if xs == [ ]
96+ then [ ]
97+ else let x = head xs ;
98+ y = if elem x acc then [ ] else [ x ] ;
99+ in y ++ go ( tail xs ) ( y ++ acc ) ;
100+ in go inputList acc ;
101+
102+ uniqListExt = { inputList ,
103+ outputList ? [ ] ,
104+ getter ? ( x : x ) ,
105+ compare ? ( x : y : x == y ) } :
106+ if inputList == [ ] then outputList else
107+ let x = head inputList ;
108+ isX = y : ( compare ( getter y ) ( getter x ) ) ;
109+ newOutputList = outputList ++
110+ ( if any isX outputList then [ ] else [ x ] ) ;
111+ in uniqListExt { __id_static = "0.5416861884942961" ; __id_dynamic = builtins . hashFile "sha256" /Users/jeffhykin/repos/snowball/random.ignore ;
112+ outputList = newOutputList ;
113+ inputList = ( tail inputList ) ;
114+ inherit getter compare ;
115+ } ;
116+
117+ condConcat = name : list : checker :
118+ if list == [ ] then name else
119+ if checker ( head list ) then
120+ condConcat
121+ ( name + ( head ( tail list ) ) )
122+ ( tail ( tail list ) )
123+ checker
124+ else condConcat
125+ name ( tail ( tail list ) ) checker ;
126+
127+ lazyGenericClosure = { startSet , operator } :
128+ let
129+ work = list : doneKeys : result :
130+ if list == [ ] then
131+ result
132+ else
133+ let x = head list ; key = x . key ; in
134+ if elem key doneKeys then
135+ work ( tail list ) doneKeys result
136+ else
137+ work ( tail list ++ operator x ) ( [ key ] ++ doneKeys ) ( [ x ] ++ result ) ;
138+ in
139+ work startSet [ ] [ ] ;
140+
141+ innerModifySumArgs = f : x : a : b : if b == null then ( f a b ) // x else
142+ innerModifySumArgs f x ( a // b ) ;
143+ modifySumArgs = f : x : innerModifySumArgs f x { } ;
144+
145+
146+ innerClosePropagation = acc : xs :
147+ if xs == [ ]
148+ then acc
149+ else let y = head xs ;
150+ ys = tail xs ;
151+ in if ! isAttrs y
152+ then innerClosePropagation acc ys
153+ else let acc' = [ y ] ++ acc ;
154+ in innerClosePropagation
155+ acc'
156+ ( uniqList { __id_static = "0.43591725975550166" ; __id_dynamic = builtins . hashFile "sha256" /Users/jeffhykin/repos/snowball/random.ignore ;
157+ inputList = ( maybeAttrNullable "propagatedBuildInputs" [ ] y )
158+ ++ ( maybeAttrNullable "propagatedNativeBuildInputs" [ ] y )
159+ ++ ys ;
160+ acc = acc' ;
161+ }
162+ ) ;
163+
164+ closePropagationSlow = list : ( uniqList { __id_static = "0.4333385880390894" ; __id_dynamic = builtins . hashFile "sha256" /Users/jeffhykin/repos/snowball/random.ignore ;
165+ inputList = ( innerClosePropagation [ ] list ) ; } ) ;
166+
167+ # This is an optimisation of lib.closePropagation which avoids the O(n^2) behavior
168+ # Using a list of derivations, it generates the full closure of the propagatedXXXBuildInputs
169+ # The ordering / sorting / comparison is done based on the `outPath`
170+ # attribute of each derivation.
171+ # On some benchmarks, it performs up to 15 times faster than lib.closePropagation.
172+ # See https://github.com/NixOS/nixpkgs/pull/194391 for details.
173+ closePropagationFast = list :
174+ builtins . map ( x : x . val ) ( builtins . genericClosure { __id_static = "0.4393836786265646" ; __id_dynamic = builtins . hashFile "sha256" /Users/jeffhykin/repos/snowball/random.ignore ;
175+
176+ startSet = builtins . map ( x : { __id_static = "0.42616742269720653" ; __id_dynamic = builtins . hashFile "sha256" /Users/jeffhykin/repos/snowball/random.ignore ;
177+
178+ key = x . outPath ;
179+ val = x ;
180+ } ) ( builtins . filter ( x : x != null ) list ) ;
181+ operator = item :
182+ if ! builtins . isAttrs item . val then
183+ [ ]
184+ else
185+ builtins . concatMap ( x :
186+ if x != null then [ { __id_static = "0.7684626401674357" ; __id_dynamic = builtins . hashFile "sha256" /Users/jeffhykin/repos/snowball/random.ignore ;
187+
188+ key = x . outPath ;
189+ val = x ;
190+ } ] else
191+ [ ] ) ( ( item . val . propagatedBuildInputs or [ ] )
192+ ++ ( item . val . propagatedNativeBuildInputs or [ ] ) ) ;
193+ } ) ;
194+
195+ closePropagation = if builtins ? genericClosure
196+ then closePropagationFast
197+ else closePropagationSlow ;
198+
199+ # calls a function (f attr value ) for each record item. returns a list
200+ mapAttrsFlatten = f : r : map ( attr : f attr r . ${ attr } ) ( attrNames r ) ;
201+
202+ # attribute set containing one attribute
203+ nvs = name : value : listToAttrs [ ( nameValuePair name value ) ] ;
204+ # adds / replaces an attribute of an attribute set
205+ setAttr = set : name : v : set // ( nvs name v ) ;
206+
207+ # setAttrMerge (similar to mergeAttrsWithFunc but only merges the values of a particular name)
208+ # setAttrMerge "a" [] { a = [2];} (x: x ++ [3]) -> { a = [2 3]; }
209+ # setAttrMerge "a" [] { } (x: x ++ [3]) -> { a = [ 3]; }
210+ setAttrMerge = name : default : attrs : f :
211+ setAttr attrs name ( f ( maybeAttr name default attrs ) ) ;
212+
213+ # Using f = a: b = b the result is similar to //
214+ # merge attributes with custom function handling the case that the attribute
215+ # exists in both sets
216+ mergeAttrsWithFunc = f : set1 : set2 :
217+ foldr ( n : set : if set ? ${ n }
218+ then setAttr set n ( f set . ${ n } set2 . ${ n } )
219+ else set )
220+ ( set2 // set1 ) ( attrNames set2 ) ;
221+
222+ # merging two attribute set concatenating the values of same attribute names
223+ # eg { a = 7; } { a = [ 2 3 ]; } becomes { a = [ 7 2 3 ]; }
224+ mergeAttrsConcatenateValues = mergeAttrsWithFunc ( a : b : ( toList a ) ++ ( toList b ) ) ;
225+
226+ # merges attributes using //, if a name exists in both attributes
227+ # an error will be triggered unless its listed in mergeLists
228+ # so you can mergeAttrsNoOverride { buildInputs = [a]; } { buildInputs = [a]; } {} to get
229+ # { buildInputs = [a b]; }
230+ # merging buildPhase doesn't really make sense. The cases will be rare where appending /prefixing will fit your needs?
231+ # in these cases the first buildPhase will override the second one
232+ # ! deprecated, use mergeAttrByFunc instead
233+ mergeAttrsNoOverride = { mergeLists ? [ "buildInputs" "propagatedBuildInputs" ] ,
234+ overrideSnd ? [ "buildPhase" ]
235+ } : attrs1 : attrs2 :
236+ foldr ( n : set :
237+ setAttr set n ( if set ? ${ n }
238+ then # merge
239+ if elem n mergeLists # attribute contains list, merge them by concatenating
240+ then attrs2 . ${ n } ++ attrs1 . ${ n }
241+ else if elem n overrideSnd
242+ then attrs1 . ${ n }
243+ else throw "error mergeAttrsNoOverride, attribute ${ n } given in both attributes - no merge func defined"
244+ else attrs2 . ${ n } # add attribute not existing in attr1
245+ ) ) attrs1 ( attrNames attrs2 ) ;
246+
247+
248+ # example usage:
249+ # mergeAttrByFunc {
250+ # inherit mergeAttrBy; # defined below
251+ # buildInputs = [ a b ];
252+ # } {
253+ # buildInputs = [ c d ];
254+ # };
255+ # will result in
256+ # { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; }
257+ # is used by defaultOverridableDelayableArgs and can be used when composing using
258+ # foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
259+ mergeAttrByFunc = x : y :
260+ let
261+ mergeAttrBy2 = { __id_static = "0.11202360130761346" ; __id_dynamic = builtins . hashFile "sha256" /Users/jeffhykin/repos/snowball/random.ignore ;
262+ mergeAttrBy = lib . mergeAttrs ; }
263+ // ( maybeAttr "mergeAttrBy" { } x )
264+ // ( maybeAttr "mergeAttrBy" { } y ) ; in
265+ foldr lib . mergeAttrs { } [
266+ x y
267+ ( mapAttrs ( a : v : # merge special names using given functions
268+ if x ? ${ a }
269+ then if y ? ${ a }
270+ then v x . ${ a } y . ${ a } # both have attr, use merge func
271+ else x . ${ a } # only x has attr
272+ else y . ${ a } # only y has attr)
273+ ) ( removeAttrs mergeAttrBy2
274+ # don't merge attrs which are neither in x nor y
275+ ( filter ( a : ! x ? ${ a } && ! y ? ${ a } )
276+ ( attrNames mergeAttrBy2 ) )
277+ )
278+ )
279+ ] ;
280+ mergeAttrsByFuncDefaults = foldl mergeAttrByFunc { __id_static = "0.6726806392463629" ; __id_dynamic = builtins . hashFile "sha256" /Users/jeffhykin/repos/snowball/random.ignore ;
281+ inherit mergeAttrBy ; } ;
282+ mergeAttrsByFuncDefaultsClean = list : removeAttrs ( mergeAttrsByFuncDefaults list ) [ "mergeAttrBy" ] ;
283+
284+ # sane defaults (same name as attr name so that inherit can be used)
285+ mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; }
286+ listToAttrs ( map ( n : nameValuePair n lib . concat )
287+ [ "nativeBuildInputs" "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" "patches" ] )
288+ // listToAttrs ( map ( n : nameValuePair n lib . mergeAttrs ) [ "passthru" "meta" "cfg" "flags" ] )
289+ // listToAttrs ( map ( n : nameValuePair n ( a : b : "${ a } \n ${ b } " ) ) [ "preConfigure" "postInstall" ] )
290+ ;
291+
292+ nixType = x :
293+ if isAttrs x then
294+ if x ? outPath then "derivation"
295+ else "attrs"
296+ else if lib . isFunction x then "function"
297+ else if isList x then "list"
298+ else if x == true then "bool"
299+ else if x == false then "bool"
300+ else if x == null then "null"
301+ else if isInt x then "int"
302+ else "string" ;
303+
304+ /* deprecated:
305+
306+ For historical reasons, imap has an index starting at 1.
307+
308+ But for consistency with the rest of the library we want an index
309+ starting at zero.
310+ */
311+ imap = imap1 ;
312+
313+ # Fake hashes. Can be used as hash placeholders, when computing hash ahead isn't trivial
314+ fakeHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" ;
315+ fakeSha256 = "0000000000000000000000000000000000000000000000000000000000000000" ;
316+ fakeSha512 = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ;
317+ }
0 commit comments