| 
									
										
										
										
											2009-05-24 10:57:46 +00:00
										 |  |  | let lib = import ./default.nix; | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |     inherit (builtins) isFunction head tail isList isAttrs isInt attrNames; | 
					
						
							| 
									
										
										
										
											2009-05-24 10:57:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | in | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | with import ./lists.nix; | 
					
						
							|  |  |  | with import ./attrsets.nix; | 
					
						
							|  |  |  | with import ./strings.nix; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | rec { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-27 18:44:23 +00:00
										 |  |  |   # returns default if env var is not set | 
					
						
							|  |  |  |   maybeEnv = name: default: | 
					
						
							|  |  |  |     let value = builtins.getEnv name; in | 
					
						
							|  |  |  |     if value == "" then default else value; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |   defaultMergeArg = x : y: if builtins.isAttrs y then | 
					
						
							|  |  |  |     y | 
					
						
							|  |  |  |   else  | 
					
						
							|  |  |  |     (y x); | 
					
						
							|  |  |  |   defaultMerge = x: y: x // (defaultMergeArg x y); | 
					
						
							|  |  |  |   foldArgs = merger: f: init: x:  | 
					
						
							| 
									
										
										
										
											2010-07-08 13:25:52 +00:00
										 |  |  |     let arg=(merger init (defaultMergeArg init x)); | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |       # now add the function with composed args already applied to the final attrs | 
					
						
							| 
									
										
										
										
											2010-07-08 13:25:52 +00:00
										 |  |  |         base = (setAttrMerge "passthru" {} (f arg)  | 
					
						
							|  |  |  |                         ( z : z // rec {  | 
					
						
							|  |  |  |                           function = foldArgs merger f arg;  | 
					
						
							|  |  |  | 			  args = (lib.attrByPath ["passthru" "args"] {} z) // x; | 
					
						
							|  |  |  |                           } )); | 
					
						
							|  |  |  | 	withStdOverrides = base // { | 
					
						
							|  |  |  | 	   override = base.passthru.function; | 
					
						
							|  |  |  | 	   deepOverride = a : (base.passthru.function ((lib.mapAttrs (lib.deepOverrider a) base.passthru.args) // a)); | 
					
						
							|  |  |  | 	   } ; | 
					
						
							|  |  |  |         in | 
					
						
							|  |  |  | 	withStdOverrides; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:12 +00:00
										 |  |  |   # predecessors: proposed replacement for applyAndFun (which has a bug cause it merges twice) | 
					
						
							|  |  |  |   # the naming "overridableDelayableArgs" tries to express that you can | 
					
						
							|  |  |  |   # - override attr values which have been supplied earlier | 
					
						
							|  |  |  |   # - use attr values before they have been supplied by accessing the fix point | 
					
						
							|  |  |  |   #   name "fixed" | 
					
						
							|  |  |  |   # f: the (delayed overridden) arguments are applied to this | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   # initial: initial attrs arguments and settings. see defaultOverridableDelayableArgs | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   # returns: f applied to the arguments // special attributes attrs | 
					
						
							|  |  |  |   #     a) merge: merge applied args with new args. Wether an argument is overridden depends on the merge settings | 
					
						
							|  |  |  |   #     b) replace: this let's you replace and remove names no matter which merge function has been set | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   # examples: see test cases "res" below; | 
					
						
							|  |  |  |   overridableDelayableArgs = | 
					
						
							|  |  |  |           f :        # the function applied to the arguments | 
					
						
							|  |  |  |           initial :  # you pass attrs, the functions below are passing a function taking the fix argument | 
					
						
							|  |  |  |     let | 
					
						
							| 
									
										
										
										
											2012-12-28 19:54:15 +01:00
										 |  |  |         takeFixed = if isFunction initial then initial else (fixed : initial); # transform initial to an expression always taking the fixed argument | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:12 +00:00
										 |  |  |         tidy = args :  | 
					
						
							|  |  |  |             let # apply all functions given in "applyPreTidy" in sequence | 
					
						
							|  |  |  |                 applyPreTidyFun = fold ( n : a : x : n ( a x ) ) lib.id (maybeAttr "applyPreTidy" [] args); | 
					
						
							|  |  |  |             in removeAttrs (applyPreTidyFun args) ( ["applyPreTidy"] ++ (maybeAttr  "removeAttrs" [] args) ); # tidy up args before applying them | 
					
						
							|  |  |  |         fun = n : x : | 
					
						
							|  |  |  |              let newArgs = fixed : | 
					
						
							|  |  |  |                      let args = takeFixed fixed;  | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |                          mergeFun = args.${n}; | 
					
						
							| 
									
										
										
										
											2009-05-24 10:57:46 +00:00
										 |  |  |                      in if isAttrs x then (mergeFun args x) | 
					
						
							|  |  |  |                         else assert isFunction x; | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:12 +00:00
										 |  |  |                              mergeFun args (x ( args // { inherit fixed; })); | 
					
						
							|  |  |  |              in overridableDelayableArgs f newArgs; | 
					
						
							|  |  |  |     in | 
					
						
							|  |  |  |     (f (tidy (lib.fix takeFixed))) // { | 
					
						
							|  |  |  |       merge   = fun "mergeFun"; | 
					
						
							|  |  |  |       replace = fun "keepFun"; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   defaultOverridableDelayableArgs = f :  | 
					
						
							|  |  |  |       let defaults = { | 
					
						
							|  |  |  |             mergeFun = mergeAttrByFunc; # default merge function. merge strategie (concatenate lists, strings) is given by mergeAttrBy | 
					
						
							|  |  |  |             keepFun = a : b : { inherit (a) removeAttrs mergeFun keepFun mergeAttrBy; } // b; # even when using replace preserve these values | 
					
						
							|  |  |  |             applyPreTidy = []; # list of functions applied to args before args are tidied up (usage case : prepareDerivationArgs) | 
					
						
							|  |  |  |             mergeAttrBy = mergeAttrBy // { | 
					
						
							|  |  |  |               applyPreTidy = a : b : a ++ b; | 
					
						
							|  |  |  |               removeAttrs = a : b: a ++ b; | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  |             removeAttrs = ["mergeFun" "keepFun" "mergeAttrBy" "removeAttrs" "fixed" ]; # before applying the arguments to the function make sure these names are gone | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  |       in (overridableDelayableArgs f defaults).merge; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   # rec { # an example of how composedArgsAndFun can be used | 
					
						
							|  |  |  |   #  a  = composedArgsAndFun (x : x) { a = ["2"]; meta = { d = "bar";}; }; | 
					
						
							|  |  |  |   #  # meta.d will be lost ! It's your task to preserve it (eg using a merge function) | 
					
						
							|  |  |  |   #  b  = a.passthru.function { a = [ "3" ]; meta = { d2 = "bar2";}; }; | 
					
						
							|  |  |  |   #  # instead of passing/ overriding values you can use a merge function: | 
					
						
							|  |  |  |   #  c  = b.passthru.function ( x: { a = x.a  ++ ["4"]; }); # consider using (maybeAttr "a" [] x) | 
					
						
							|  |  |  |   # } | 
					
						
							|  |  |  |   # result: | 
					
						
							|  |  |  |   # { | 
					
						
							|  |  |  |   #   a = { a = ["2"];     meta = { d = "bar"; }; passthru = { function = .. }; }; | 
					
						
							|  |  |  |   #   b = { a = ["3"];     meta = { d2 = "bar2"; }; passthru = { function = .. }; }; | 
					
						
							|  |  |  |   #   c = { a = ["3" "4"]; meta = { d2 = "bar2"; }; passthru = { function = .. }; }; | 
					
						
							|  |  |  |   #   # c2 is equal to c | 
					
						
							|  |  |  |   # } | 
					
						
							|  |  |  |   composedArgsAndFun = f: foldArgs defaultMerge f {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-29 22:18:49 +00:00
										 |  |  |   # shortcut for attrByPath ["name"] default attrs | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |   maybeAttrNullable = maybeAttr; | 
					
						
							| 
									
										
										
										
											2010-06-29 22:18:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-24 10:57:41 +00:00
										 |  |  |   # shortcut for attrByPath ["name"] default attrs | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |   maybeAttr = name: default: attrs: attrs.${name} or default; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Return the second argument if the first one is true or the empty version | 
					
						
							|  |  |  |   # of the second argument. | 
					
						
							|  |  |  |   ifEnable = cond: val: | 
					
						
							|  |  |  |     if cond then val | 
					
						
							|  |  |  |     else if builtins.isList val then [] | 
					
						
							|  |  |  |     else if builtins.isAttrs val then {} | 
					
						
							|  |  |  |     # else if builtins.isString val then "" | 
					
						
							| 
									
										
										
										
											2012-12-28 19:54:15 +01:00
										 |  |  |     else if val == true || val == false then false | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |     else null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |   # Return true only if there is an attribute and it is true. | 
					
						
							|  |  |  |   checkFlag = attrSet: name: | 
					
						
							| 
									
										
										
										
											2012-12-28 19:54:15 +01:00
										 |  |  |         if name == "true" then true else | 
					
						
							|  |  |  |         if name == "false" then false else | 
					
						
							| 
									
										
										
										
											2010-07-08 13:25:52 +00:00
										 |  |  |         if (elem name (attrByPath ["flags"] [] attrSet)) then true else | 
					
						
							|  |  |  |         attrByPath [name] false attrSet ; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Input : attrSet, [ [name default] ... ], name | 
					
						
							|  |  |  |   # Output : its value or default. | 
					
						
							|  |  |  |   getValue = attrSet: argList: name: | 
					
						
							| 
									
										
										
										
											2009-05-24 10:57:41 +00:00
										 |  |  |   ( attrByPath [name] (if checkFlag attrSet name then true else | 
					
						
							| 
									
										
										
										
											2010-07-08 13:25:52 +00:00
										 |  |  |         if argList == [] then null else | 
					
						
							|  |  |  |         let x = builtins.head argList; in | 
					
						
							|  |  |  |                 if (head x) == name then  | 
					
						
							|  |  |  |                         (head (tail x)) | 
					
						
							|  |  |  |                 else (getValue attrSet  | 
					
						
							|  |  |  |                         (tail argList) name)) attrSet ); | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                          | 
					
						
							|  |  |  |   # Input : attrSet, [[name default] ...], [ [flagname reqs..] ... ] | 
					
						
							|  |  |  |   # Output : are reqs satisfied? It's asserted. | 
					
						
							|  |  |  |   checkReqs = attrSet : argList : condList : | 
					
						
							|  |  |  |   ( | 
					
						
							|  |  |  |     fold lib.and true  | 
					
						
							|  |  |  |       (map (x: let name = (head x) ; in | 
					
						
							| 
									
										
										
										
											2010-07-08 13:25:52 +00:00
										 |  |  |          | 
					
						
							|  |  |  |         ((checkFlag attrSet name) ->  | 
					
						
							|  |  |  |         (fold lib.and true | 
					
						
							|  |  |  |         (map (y: let val=(getValue attrSet argList y); in | 
					
						
							|  |  |  |                 (val!=null) && (val!=false))  | 
					
						
							|  |  |  |         (tail x))))) condList)) ; | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2009-05-11 15:21:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-18 11:18:15 +02:00
										 |  |  |   # This function has O(n^2) performance. | 
					
						
							|  |  |  |   uniqList = {inputList, acc ? []} : | 
					
						
							|  |  |  |     let go = xs : acc : | 
					
						
							|  |  |  |              if xs == [] | 
					
						
							|  |  |  |              then [] | 
					
						
							|  |  |  |              else let x = head xs; | 
					
						
							|  |  |  |                       y = if elem x acc then [] else [x]; | 
					
						
							| 
									
										
										
										
											2012-07-18 16:30:57 +02:00
										 |  |  |                   in y ++ go (tail xs) (y ++ acc); | 
					
						
							| 
									
										
										
										
											2012-07-18 11:18:15 +02:00
										 |  |  |     in go inputList acc; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   uniqListExt = {inputList, outputList ? [], | 
					
						
							|  |  |  |     getter ? (x : x), compare ? (x: y: x==y)}: | 
					
						
							| 
									
										
										
										
											2012-12-28 19:54:15 +01:00
										 |  |  |         if inputList == [] then outputList else | 
					
						
							| 
									
										
										
										
											2010-07-08 13:25:52 +00:00
										 |  |  |         let x=head inputList;  | 
					
						
							|  |  |  |         isX = y: (compare (getter y) (getter x)); | 
					
						
							|  |  |  |         newOutputList = outputList ++ | 
					
						
							|  |  |  |          (if any isX outputList then [] else [x]); | 
					
						
							|  |  |  |         in uniqListExt {outputList=newOutputList;  | 
					
						
							|  |  |  |                 inputList = (tail inputList); | 
					
						
							|  |  |  |                 inherit getter compare; | 
					
						
							|  |  |  |                 }; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |   condConcat = name: list: checker: | 
					
						
							| 
									
										
										
										
											2010-07-08 13:25:52 +00:00
										 |  |  |         if list == [] then name else | 
					
						
							|  |  |  |         if checker (head list) then  | 
					
						
							|  |  |  |                 condConcat  | 
					
						
							|  |  |  |                         (name + (head (tail list)))  | 
					
						
							|  |  |  |                         (tail (tail list))  | 
					
						
							|  |  |  |                         checker | 
					
						
							|  |  |  |         else condConcat | 
					
						
							|  |  |  |                 name (tail (tail list)) checker; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-06 16:20:05 +00:00
										 |  |  |   lazyGenericClosure = {startSet, operator}: | 
					
						
							|  |  |  |     let | 
					
						
							|  |  |  |       work = list: doneKeys: result: | 
					
						
							|  |  |  |         if list == [] then | 
					
						
							|  |  |  |           result | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           let x = head list; key = x.key; in | 
					
						
							|  |  |  |           if elem key doneKeys then | 
					
						
							|  |  |  |             work (tail list) doneKeys result | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             work (tail list ++ operator x) ([key] ++ doneKeys) ([x] ++ result); | 
					
						
							|  |  |  |     in | 
					
						
							|  |  |  |       work startSet [] []; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-24 14:48:02 +02:00
										 |  |  |   genericClosure = builtins.genericClosure or lazyGenericClosure; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   innerModifySumArgs = f: x: a: b: if b == null then (f a b) // x else  | 
					
						
							| 
									
										
										
										
											2010-07-08 13:25:52 +00:00
										 |  |  |         innerModifySumArgs f x (a // b); | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |   modifySumArgs = f: x: innerModifySumArgs f x {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-18 11:18:15 +02:00
										 |  |  |   innerClosePropagation = acc : xs : | 
					
						
							|  |  |  |     if xs == [] | 
					
						
							|  |  |  |     then acc | 
					
						
							|  |  |  |     else let y  = head xs; | 
					
						
							|  |  |  |              ys = tail xs; | 
					
						
							|  |  |  |          in if ! isAttrs y | 
					
						
							|  |  |  |             then innerClosePropagation acc ys | 
					
						
							|  |  |  |             else let acc' = [y] ++ acc; | 
					
						
							|  |  |  |                  in innerClosePropagation | 
					
						
							|  |  |  |                       acc' | 
					
						
							|  |  |  |                       (uniqList { inputList = (maybeAttrNullable "propagatedBuildInputs" [] y) | 
					
						
							| 
									
										
										
										
											2012-12-28 19:20:09 +01:00
										 |  |  |                                            ++ (maybeAttrNullable "propagatedNativeBuildInputs" [] y) | 
					
						
							| 
									
										
										
										
											2012-07-18 11:18:15 +02:00
										 |  |  |                                            ++ ys; | 
					
						
							|  |  |  |                                   acc = acc'; | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  |                       ); | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   closePropagation = list: (uniqList {inputList = (innerClosePropagation [] list);}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # calls a function (f attr value ) for each record item. returns a list | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |   mapAttrsFlatten = f : r : map (attr: f attr r.${attr}) (attrNames r); | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   # attribute set containing one attribute | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |   nvs = name : value : listToAttrs [ (nameValuePair name value) ]; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |   # adds / replaces an attribute of an attribute set | 
					
						
							|  |  |  |   setAttr = set : name : v : set // (nvs name v); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # setAttrMerge (similar to mergeAttrsWithFunc but only merges the values of a particular name) | 
					
						
							|  |  |  |   # setAttrMerge "a" [] { a = [2];} (x : x ++ [3]) -> { a = [2 3]; }  | 
					
						
							|  |  |  |   # setAttrMerge "a" [] {         } (x : x ++ [3]) -> { a = [  3]; } | 
					
						
							|  |  |  |   setAttrMerge = name : default : attrs : f : | 
					
						
							|  |  |  |     setAttr attrs name (f (maybeAttr name default attrs)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Using f = a : b = b the result is similar to // | 
					
						
							|  |  |  |   # merge attributes with custom function handling the case that the attribute | 
					
						
							|  |  |  |   # exists in both sets | 
					
						
							|  |  |  |   mergeAttrsWithFunc = f : set1 : set2 : | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |     fold (n: set : if set ? ${n} | 
					
						
							|  |  |  |                         then setAttr set n (f set.${n} set2.${n}) | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |                         else set ) | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |            (set2 // set1) (attrNames set2); | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   # merging two attribute set concatenating the values of same attribute names | 
					
						
							|  |  |  |   # eg { a = 7; } {  a = [ 2 3 ]; } becomes { a = [ 7 2 3 ]; } | 
					
						
							|  |  |  |   mergeAttrsConcatenateValues = mergeAttrsWithFunc ( a : b : (toList a) ++ (toList b) ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # merges attributes using //, if a name exisits in both attributes | 
					
						
							|  |  |  |   # an error will be triggered unless its listed in mergeLists | 
					
						
							|  |  |  |   # so you can mergeAttrsNoOverride { buildInputs = [a]; } { buildInputs = [a]; } {} to get | 
					
						
							|  |  |  |   # { buildInputs = [a b]; } | 
					
						
							|  |  |  |   # merging buildPhase does'nt really make sense. The cases will be rare where appending /prefixing will fit your needs? | 
					
						
							|  |  |  |   # in these cases the first buildPhase will override the second one | 
					
						
							| 
									
										
										
										
											2009-09-22 09:26:18 +00:00
										 |  |  |   # ! deprecated, use mergeAttrByFunc instead | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |   mergeAttrsNoOverride = { mergeLists ? ["buildInputs" "propagatedBuildInputs"], | 
					
						
							|  |  |  |                            overrideSnd ? [ "buildPhase" ] | 
					
						
							|  |  |  |                          } : attrs1 : attrs2 : | 
					
						
							|  |  |  |     fold (n: set :  | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |         setAttr set n ( if set ? ${n} | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |             then # merge  | 
					
						
							|  |  |  |               if elem n mergeLists # attribute contains list, merge them by concatenating | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |                 then attrs2.${n} ++ attrs1.${n} | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |               else if elem n overrideSnd | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |                 then attrs1.${n} | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |               else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined" | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |             else attrs2.${n} # add attribute not existing in attr1 | 
					
						
							|  |  |  |            )) attrs1 (attrNames attrs2); | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # example usage: | 
					
						
							|  |  |  |   # mergeAttrByFunc  { | 
					
						
							|  |  |  |   #   inherit mergeAttrBy; # defined below | 
					
						
							|  |  |  |   #   buildInputs = [ a b ]; | 
					
						
							|  |  |  |   # } { | 
					
						
							|  |  |  |   #  buildInputs = [ c d ]; | 
					
						
							|  |  |  |   # }; | 
					
						
							|  |  |  |   # will result in | 
					
						
							|  |  |  |   # { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; } | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:12 +00:00
										 |  |  |   # is used by prepareDerivationArgs, defaultOverridableDelayableArgs and can be used when composing using | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |   # foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix | 
					
						
							|  |  |  |   mergeAttrByFunc = x : y : | 
					
						
							|  |  |  |     let | 
					
						
							|  |  |  |           mergeAttrBy2 = { mergeAttrBy=lib.mergeAttrs; } | 
					
						
							|  |  |  |                       // (maybeAttr "mergeAttrBy" {} x) | 
					
						
							|  |  |  |                       // (maybeAttr "mergeAttrBy" {} y); in | 
					
						
							|  |  |  |     fold lib.mergeAttrs {} [ | 
					
						
							|  |  |  |       x y | 
					
						
							|  |  |  |       (mapAttrs ( a : v : # merge special names using given functions | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |           if x ? ${a} | 
					
						
							|  |  |  |              then if y ? ${a} | 
					
						
							|  |  |  |                then v x.${a} y.${a} # both have attr, use merge func | 
					
						
							|  |  |  |                else x.${a} # only x has attr | 
					
						
							|  |  |  |              else y.${a} # only y has attr) | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |           ) (removeAttrs mergeAttrBy2 | 
					
						
							|  |  |  |                          # don't merge attrs which are neither in x nor y | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |                          (filter (a: ! x ? ${a} && ! y ? ${a}) | 
					
						
							| 
									
										
										
										
											2009-05-24 10:57:46 +00:00
										 |  |  |                                  (attrNames mergeAttrBy2)) | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |             ) | 
					
						
							|  |  |  |       ) | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  |   mergeAttrsByFuncDefaults = foldl mergeAttrByFunc { inherit mergeAttrBy; }; | 
					
						
							| 
									
										
										
										
											2013-05-29 23:24:20 +02:00
										 |  |  |   mergeAttrsByFuncDefaultsClean = list: removeAttrs (mergeAttrsByFuncDefaults list) ["mergeAttrBy"]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-11 08:12:12 +01:00
										 |  |  |   # merge attrs based on version key into mkDerivation args, see mergeAttrBy to learn about smart merge defaults | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   # This function is best explained by an example: | 
					
						
							|  |  |  |   # | 
					
						
							| 
									
										
										
										
											2013-05-05 17:05:59 +02:00
										 |  |  |   #     {version ? "2.x"} : | 
					
						
							| 
									
										
										
										
											2013-02-11 08:12:12 +01:00
										 |  |  |   # | 
					
						
							|  |  |  |   #     mkDerivation (mergeAttrsByVersion "package-name" version  | 
					
						
							|  |  |  |   #       { # version specific settings | 
					
						
							|  |  |  |   #         "git" = { src = ..; preConfigre = "autogen.sh"; buildInputs = [automake autoconf libtool];  }; | 
					
						
							| 
									
										
										
										
											2013-05-05 17:05:59 +02:00
										 |  |  |   #         "2.x" = { src = ..; }; | 
					
						
							| 
									
										
										
										
											2013-02-11 08:12:12 +01:00
										 |  |  |   #       } | 
					
						
							|  |  |  |   #       {  // shared settings | 
					
						
							|  |  |  |   #          buildInputs = [ common build inputs ]; | 
					
						
							|  |  |  |   #          meta = { .. } | 
					
						
							|  |  |  |   #       } | 
					
						
							|  |  |  |   #     ) | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   # Please note that e.g. Eelco Dolstra usually prefers having one file for | 
					
						
							|  |  |  |   # each version. On the other hand there are valuable additional design goals | 
					
						
							|  |  |  |   #  - readability | 
					
						
							|  |  |  |   #  - do it once only | 
					
						
							|  |  |  |   #  - try to avoid duplication | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   # Marc Weber and Michael Raskin sometimes prefer keeping older | 
					
						
							|  |  |  |   # versions around for testing and regression tests - as long as its cheap to | 
					
						
							|  |  |  |   # do so. | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   # Very often it just happens that the "shared" code is the bigger part. | 
					
						
							|  |  |  |   # Then using this function might be appropriate. | 
					
						
							|  |  |  |   # | 
					
						
							| 
									
										
										
										
											2013-05-05 17:05:59 +02:00
										 |  |  |   # Be aware that its easy to cause recompilations in all versions when using | 
					
						
							|  |  |  |   # this function - also if derivations get too complex splitting into multiple | 
					
						
							|  |  |  |   # files is the way to go. | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   # See misc.nix -> versionedDerivation | 
					
						
							|  |  |  |   # discussion: nixpkgs: pull/310 | 
					
						
							| 
									
										
										
										
											2013-02-11 08:12:12 +01:00
										 |  |  |   mergeAttrsByVersion = name: version: attrsByVersion: base: | 
					
						
							|  |  |  |     mergeAttrsByFuncDefaultsClean [ { name = "${name}-${version}"; } base (maybeAttr version (throw "bad version ${version} for ${name}") attrsByVersion)]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |   # sane defaults (same name as attr name so that inherit can be used) | 
					
						
							|  |  |  |   mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; } | 
					
						
							| 
									
										
										
										
											2013-05-29 23:24:20 +02:00
										 |  |  |     listToAttrs (map (n : nameValuePair n lib.concat) | 
					
						
							|  |  |  |       [ "nativeBuildInputs" "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" "patches" ]) | 
					
						
							| 
									
										
										
										
											2009-08-20 20:18:58 +00:00
										 |  |  |     // listToAttrs (map (n : nameValuePair n lib.mergeAttrs) [ "passthru" "meta" "cfg" "flags" ]) | 
					
						
							| 
									
										
										
										
											2010-05-26 19:01:10 +00:00
										 |  |  |     // listToAttrs (map (n : nameValuePair n (a: b: "${a}\n${b}") ) [ "preConfigure" "postInstall" ]) | 
					
						
							| 
									
										
										
										
											2009-08-20 20:18:58 +00:00
										 |  |  |   ; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   # prepareDerivationArgs tries to make writing configurable derivations easier | 
					
						
							|  |  |  |   # example: | 
					
						
							|  |  |  |   #  prepareDerivationArgs { | 
					
						
							|  |  |  |   #    mergeAttrBy = { | 
					
						
							|  |  |  |   #       myScript = x : y : x ++ "\n" ++ y; | 
					
						
							|  |  |  |   #    }; | 
					
						
							|  |  |  |   #    cfg = { | 
					
						
							|  |  |  |   #      readlineSupport = true; | 
					
						
							|  |  |  |   #    }; | 
					
						
							|  |  |  |   #    flags = { | 
					
						
							|  |  |  |   #      readline = { | 
					
						
							|  |  |  |   #        set = { | 
					
						
							|  |  |  |   #           configureFlags = [ "--with-compiler=${compiler}" ]; | 
					
						
							|  |  |  |   #           buildInputs = [ compiler ]; | 
					
						
							|  |  |  |   #           pass = { inherit compiler; READLINE=1; }; | 
					
						
							|  |  |  |   #           assertion = compiler.dllSupport; | 
					
						
							|  |  |  |   #           myScript = "foo"; | 
					
						
							|  |  |  |   #        }; | 
					
						
							|  |  |  |   #        unset = { configureFlags = ["--without-compiler"]; }; | 
					
						
							|  |  |  |   #      }; | 
					
						
							|  |  |  |   #    }; | 
					
						
							|  |  |  |   #    src = ... | 
					
						
							|  |  |  |   #    buildPhase = '' ... ''; | 
					
						
							|  |  |  |   #    name = ... | 
					
						
							|  |  |  |   #    myScript = "bar"; | 
					
						
							|  |  |  |   #  }; | 
					
						
							|  |  |  |   # if you don't have need for unset you can omit the surrounding set = { .. } attr | 
					
						
							|  |  |  |   # all attrs except flags cfg and mergeAttrBy will be merged with the | 
					
						
							|  |  |  |   # additional data from flags depending on config settings | 
					
						
							|  |  |  |   # It's used in composableDerivation in all-packages.nix. It's also used | 
					
						
							|  |  |  |   # heavily in the new python and libs implementation | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   # should we check for misspelled cfg options? | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:12 +00:00
										 |  |  |   # TODO use args.mergeFun here as well? | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |   prepareDerivationArgs = args: | 
					
						
							|  |  |  |     let args2 = { cfg = {}; flags = {}; } // args; | 
					
						
							|  |  |  |         flagName = name : "${name}Support"; | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |         cfgWithDefaults = (listToAttrs (map (n : nameValuePair (flagName n) false) (attrNames args2.flags))) | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |                           // args2.cfg; | 
					
						
							| 
									
										
										
										
											2012-08-13 18:26:19 -04:00
										 |  |  |         opts = attrValues (mapAttrs (a : v : | 
					
						
							| 
									
										
										
										
											2012-12-28 19:54:15 +01:00
										 |  |  |                 let v2 = if v ? set || v ? unset then v else { set = v; }; | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |                     n = if cfgWithDefaults.${flagName a} then "set" else "unset"; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |                     attr = maybeAttr n {} v2; in | 
					
						
							|  |  |  |                 if (maybeAttr "assertion" true attr) | 
					
						
							|  |  |  |                   then attr | 
					
						
							|  |  |  |                   else throw "assertion of flag ${a} of derivation ${args.name} failed" | 
					
						
							|  |  |  |                ) args2.flags ); | 
					
						
							|  |  |  |     in removeAttrs | 
					
						
							|  |  |  |       (mergeAttrsByFuncDefaults ([args] ++ opts ++ [{ passthru = cfgWithDefaults; }])) | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:12 +00:00
										 |  |  |       ["flags" "cfg" "mergeAttrBy" ]; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-22 21:28:43 +00:00
										 |  |  |   nixType = x: | 
					
						
							|  |  |  |       if isAttrs x then | 
					
						
							|  |  |  |           if x ? outPath then "derivation" | 
					
						
							|  |  |  |           else "aattrs" | 
					
						
							|  |  |  |       else if isFunction x then "function" | 
					
						
							|  |  |  |       else if isList x then "list" | 
					
						
							|  |  |  |       else if x == true then "bool" | 
					
						
							|  |  |  |       else if x == false then "bool" | 
					
						
							|  |  |  |       else if x == null then "null" | 
					
						
							|  |  |  |       else if isInt x then "int" | 
					
						
							|  |  |  |       else "string"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:09 +00:00
										 |  |  | } |