| 
									
										
										
										
											2017-07-28 20:05:35 -04:00
										 |  |  |  | { lib }: | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |  | # Operations on attribute sets. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-08 20:52:13 -05:00
										 |  |  |  | let | 
					
						
							| 
									
										
										
										
											2014-12-30 15:07:29 -08:00
										 |  |  |  |   inherit (builtins) head tail length; | 
					
						
							| 
									
										
										
										
											2017-07-28 20:05:35 -04:00
										 |  |  |  |   inherit (lib.trivial) and or; | 
					
						
							|  |  |  |  |   inherit (lib.strings) concatStringsSep; | 
					
						
							|  |  |  |  |   inherit (lib.lists) fold concatMap concatLists all deepSeqList; | 
					
						
							| 
									
										
										
										
											2017-02-08 20:52:13 -05:00
										 |  |  |  | in | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | rec { | 
					
						
							| 
									
										
										
										
											2012-08-13 00:08:21 -04:00
										 |  |  |  |   inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |   /* Return an attribute from nested attribute sets.
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        x = { a = { b = 3; }; } | 
					
						
							|  |  |  |  |        attrByPath ["a" "b"] 6 x | 
					
						
							|  |  |  |  |        => 3 | 
					
						
							|  |  |  |  |        attrByPath ["z" "z"] 6 x | 
					
						
							|  |  |  |  |        => 6 | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2009-05-24 10:57:41 +00:00
										 |  |  |  |   attrByPath = attrPath: default: e: | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |  |     let attr = head attrPath; | 
					
						
							|  |  |  |  |     in | 
					
						
							|  |  |  |  |       if attrPath == [] then e | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |  |       else if e ? ${attr} | 
					
						
							|  |  |  |  |       then attrByPath (tail attrPath) default e.${attr} | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |  |       else default; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-04 16:17:45 +01:00
										 |  |  |  |   /* Return if an attribute from nested attribute set exists.
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        x = { a = { b = 3; }; } | 
					
						
							|  |  |  |  |        hasAttrByPath ["a" "b"] x | 
					
						
							|  |  |  |  |        => true | 
					
						
							|  |  |  |  |        hasAttrByPath ["z" "z"] x | 
					
						
							|  |  |  |  |        => false | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2015-12-04 16:17:45 +01:00
										 |  |  |  |   hasAttrByPath = attrPath: e: | 
					
						
							|  |  |  |  |     let attr = head attrPath; | 
					
						
							|  |  |  |  |     in | 
					
						
							|  |  |  |  |       if attrPath == [] then true | 
					
						
							|  |  |  |  |       else if e ? ${attr} | 
					
						
							|  |  |  |  |       then hasAttrByPath (tail attrPath) e.${attr} | 
					
						
							|  |  |  |  |       else false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 15:35:48 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |   /* Return nested attribute set in which an attribute is set.
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        setAttrByPath ["a" "b"] 3 | 
					
						
							|  |  |  |  |        => { a = { b = 3; }; } | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2009-09-28 18:22:44 +00:00
										 |  |  |  |   setAttrByPath = attrPath: value: | 
					
						
							|  |  |  |  |     if attrPath == [] then value | 
					
						
							| 
									
										
										
										
											2013-10-28 07:51:46 +01:00
										 |  |  |  |     else listToAttrs | 
					
						
							|  |  |  |  |       [ { name = head attrPath; value = setAttrByPath (tail attrPath) value; } ]; | 
					
						
							| 
									
										
										
										
											2009-09-28 18:22:44 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:14 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |   /* Like `getAttrPath' without a default value. If it doesn't find the
 | 
					
						
							|  |  |  |  |      path it will throw. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        x = { a = { b = 3; }; } | 
					
						
							|  |  |  |  |        getAttrFromPath ["a" "b"] x | 
					
						
							|  |  |  |  |        => 3 | 
					
						
							|  |  |  |  |        getAttrFromPath ["z" "z"] x | 
					
						
							|  |  |  |  |        => error: cannot find attribute `z.z' | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  |   getAttrFromPath = attrPath: set: | 
					
						
							|  |  |  |  |     let errorMsg = "cannot find attribute `" + concatStringsSep "." attrPath + "'"; | 
					
						
							| 
									
										
										
										
											2009-05-24 10:57:41 +00:00
										 |  |  |  |     in attrByPath attrPath (abort errorMsg) set; | 
					
						
							| 
									
										
										
										
											2012-10-23 15:35:48 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:14 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  |   /* Return the specified attributes from a set.
 | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:14 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  |      Example: | 
					
						
							|  |  |  |  |        attrVals ["a" "b" "c"] as | 
					
						
							|  |  |  |  |        => [as.a as.b as.c] | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |  |   attrVals = nameList: set: map (x: set.${x}) nameList; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Return the values of all attributes in the given set, sorted by
 | 
					
						
							|  |  |  |  |      attribute name. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        attrValues {c = 3; a = 1; b = 2;} | 
					
						
							|  |  |  |  |        => [1 2 3] | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2014-10-04 18:30:35 +02:00
										 |  |  |  |   attrValues = builtins.attrValues or (attrs: attrVals (attrNames attrs) attrs); | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Collect each attribute named `attr' from a list of attribute
 | 
					
						
							|  |  |  |  |      sets.  Sets that don't contain the named attribute are ignored. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}] | 
					
						
							|  |  |  |  |        => [1 2] | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2014-10-04 18:30:35 +02:00
										 |  |  |  |   catAttrs = builtins.catAttrs or | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |  |     (attr: l: concatLists (map (s: if s ? ${attr} then [s.${attr}] else []) l)); | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-05 15:37:52 +00:00
										 |  |  |  |   /* Filter an attribute set by removing all attributes for which the
 | 
					
						
							|  |  |  |  |      given predicate return false. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; } | 
					
						
							|  |  |  |  |        => { foo = 1; } | 
					
						
							|  |  |  |  |   */ | 
					
						
							|  |  |  |  |   filterAttrs = pred: set: | 
					
						
							| 
									
										
										
										
											2015-07-23 16:12:25 +02:00
										 |  |  |  |     listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set)); | 
					
						
							| 
									
										
										
										
											2012-04-05 15:37:52 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 15:35:48 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-19 14:41:28 -05:00
										 |  |  |  |   /* Filter an attribute set recursively by removing all attributes for
 | 
					
						
							| 
									
										
										
										
											2015-09-19 00:16:06 +02:00
										 |  |  |  |      which the given predicate return false. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        filterAttrsRecursive (n: v: v != null) { foo = { bar = null; }; } | 
					
						
							|  |  |  |  |        => { foo = {}; } | 
					
						
							|  |  |  |  |   */ | 
					
						
							|  |  |  |  |   filterAttrsRecursive = pred: set: | 
					
						
							|  |  |  |  |     listToAttrs ( | 
					
						
							|  |  |  |  |       concatMap (name: | 
					
						
							|  |  |  |  |         let v = set.${name}; in | 
					
						
							|  |  |  |  |         if pred name v then [ | 
					
						
							|  |  |  |  |           (nameValuePair name ( | 
					
						
							|  |  |  |  |             if isAttrs v then filterAttrsRecursive pred v | 
					
						
							|  |  |  |  |             else v | 
					
						
							|  |  |  |  |           )) | 
					
						
							|  |  |  |  |         ] else [] | 
					
						
							|  |  |  |  |       ) (attrNames set) | 
					
						
							|  |  |  |  |     ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |   /* Apply fold functions to values grouped by key.
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        foldAttrs (n: a: [n] ++ a) [] [{ a = 2; } { a = 3; }] | 
					
						
							|  |  |  |  |        => { a = [ 2 3 ]; } | 
					
						
							| 
									
										
										
										
											2012-08-28 14:40:24 +02:00
										 |  |  |  |   */ | 
					
						
							|  |  |  |  |   foldAttrs = op: nul: list_of_attrs: | 
					
						
							|  |  |  |  |     fold (n: a: | 
					
						
							|  |  |  |  |         fold (name: o: | 
					
						
							| 
									
										
										
										
											2015-07-23 17:41:35 +02:00
										 |  |  |  |           o // (listToAttrs [{inherit name; value = op n.${name} (a.${name} or nul); }]) | 
					
						
							| 
									
										
										
										
											2012-08-28 14:40:24 +02:00
										 |  |  |  |         ) a (attrNames n) | 
					
						
							|  |  |  |  |     ) {} list_of_attrs; | 
					
						
							| 
									
										
										
										
											2012-04-05 15:37:52 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 15:35:48 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-11 16:03:33 +00:00
										 |  |  |  |   /* Recursively collect sets that verify a given predicate named `pred'
 | 
					
						
							|  |  |  |  |      from the set `attrs'.  The recursion is stopped when the predicate is | 
					
						
							|  |  |  |  |      verified. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Type: | 
					
						
							|  |  |  |  |        collect :: | 
					
						
							| 
									
										
										
										
											2015-10-23 13:04:10 +02:00
										 |  |  |  |          (AttrSet -> Bool) -> AttrSet -> [x] | 
					
						
							| 
									
										
										
										
											2009-06-11 16:03:33 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							| 
									
										
										
										
											2013-11-12 13:48:19 +01:00
										 |  |  |  |        collect isList { a = { b = ["b"]; }; c = [1]; } | 
					
						
							| 
									
										
										
										
											2009-09-29 15:34:19 +00:00
										 |  |  |  |        => [["b"] [1]] | 
					
						
							| 
									
										
										
										
											2009-06-11 16:03:33 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |        collect (x: x ? outPath) | 
					
						
							|  |  |  |  |           { a = { outPath = "a/"; }; b = { outPath = "b/"; }; } | 
					
						
							|  |  |  |  |        => [{ outPath = "a/"; } { outPath = "b/"; }] | 
					
						
							|  |  |  |  |   */ | 
					
						
							|  |  |  |  |   collect = pred: attrs: | 
					
						
							|  |  |  |  |     if pred attrs then | 
					
						
							|  |  |  |  |       [ attrs ] | 
					
						
							| 
									
										
										
										
											2013-11-12 13:50:45 +01:00
										 |  |  |  |     else if isAttrs attrs then | 
					
						
							| 
									
										
										
										
											2009-06-11 16:03:33 +00:00
										 |  |  |  |       concatMap (collect pred) (attrValues attrs) | 
					
						
							|  |  |  |  |     else | 
					
						
							|  |  |  |  |       []; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  |   /* Utility function that creates a {name, value} pair as expected by
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |      builtins.listToAttrs. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        nameValuePair "some" 6 | 
					
						
							|  |  |  |  |        => { name = "some"; value = 6; } | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  |   nameValuePair = name: value: { inherit name value; }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 15:35:48 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  |   /* Apply a function to each element in an attribute set.  The
 | 
					
						
							|  |  |  |  |      function takes two arguments --- the attribute name and its value | 
					
						
							|  |  |  |  |      --- and returns the new value for the attribute.  The result is a | 
					
						
							|  |  |  |  |      new attribute set. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        mapAttrs (name: value: name + "-" + value) | 
					
						
							| 
									
										
										
										
											2012-05-25 17:01:58 +00:00
										 |  |  |  |           { x = "foo"; y = "bar"; } | 
					
						
							|  |  |  |  |        => { x = "x-foo"; y = "y-bar"; } | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  |   */ | 
					
						
							|  |  |  |  |   mapAttrs = f: set: | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |  |     listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)); | 
					
						
							| 
									
										
										
										
											2012-05-25 17:01:58 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Like `mapAttrs', but allows the name of each attribute to be
 | 
					
						
							|  |  |  |  |      changed in addition to the value.  The applied function should | 
					
						
							|  |  |  |  |      return both the new name and value as a `nameValuePair'. | 
					
						
							| 
									
										
										
										
											2012-10-23 15:35:48 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-25 17:01:58 +00:00
										 |  |  |  |      Example: | 
					
						
							|  |  |  |  |        mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value)) | 
					
						
							|  |  |  |  |           { x = "a"; y = "b"; } | 
					
						
							|  |  |  |  |        => { foo_x = "bar-a"; foo_y = "bar-b"; } | 
					
						
							|  |  |  |  |   */ | 
					
						
							|  |  |  |  |   mapAttrs' = f: set: | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |  |     listToAttrs (map (attr: f attr set.${attr}) (attrNames set)); | 
					
						
							| 
									
										
										
										
											2012-10-23 15:35:48 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-14 19:07:01 +00:00
										 |  |  |  |   /* Call a function for each attribute in the given set and return
 | 
					
						
							|  |  |  |  |      the result in a list. | 
					
						
							| 
									
										
										
										
											2012-10-23 15:35:48 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-14 19:07:01 +00:00
										 |  |  |  |      Example: | 
					
						
							|  |  |  |  |        mapAttrsToList (name: value: name + value) | 
					
						
							|  |  |  |  |           { x = "a"; y = "b"; } | 
					
						
							|  |  |  |  |        => [ "xa" "yb" ] | 
					
						
							|  |  |  |  |   */ | 
					
						
							|  |  |  |  |   mapAttrsToList = f: attrs: | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |  |     map (name: f name attrs.${name}) (attrNames attrs); | 
					
						
							| 
									
										
										
										
											2012-10-23 15:35:48 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-14 19:07:01 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  |   /* Like `mapAttrs', except that it recursively applies itself to
 | 
					
						
							| 
									
										
										
										
											2009-03-30 13:19:57 +00:00
										 |  |  |  |      attribute sets.  Also, the first argument of the argument | 
					
						
							|  |  |  |  |      function is a *list* of the names of the containing attributes. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Type: | 
					
						
							|  |  |  |  |        mapAttrsRecursive :: | 
					
						
							|  |  |  |  |          ([String] -> a -> b) -> AttrSet -> AttrSet | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        mapAttrsRecursive (path: value: concatStringsSep "-" (path ++ [value])) | 
					
						
							|  |  |  |  |          { n = { a = "A"; m = { b = "B"; c = "C"; }; }; d = "D"; } | 
					
						
							|  |  |  |  |        => { n = { a = "n-a-A"; m = { b = "n-m-b-B"; c = "n-m-c-C"; }; }; d = "d-D"; } | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2009-03-30 13:19:57 +00:00
										 |  |  |  |   mapAttrsRecursive = mapAttrsRecursiveCond (as: true); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 15:35:48 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-30 13:19:57 +00:00
										 |  |  |  |   /* Like `mapAttrsRecursive', but it takes an additional predicate
 | 
					
						
							| 
									
										
										
										
											2016-02-03 12:16:33 +01:00
										 |  |  |  |      function that tells it whether to recursive into an attribute | 
					
						
							| 
									
										
										
										
											2009-03-30 13:19:57 +00:00
										 |  |  |  |      set.  If it returns false, `mapAttrsRecursiveCond' does not | 
					
						
							|  |  |  |  |      recurse, but does apply the map function.  It is returns true, it | 
					
						
							|  |  |  |  |      does recurse, and does not apply the map function. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Type: | 
					
						
							|  |  |  |  |        mapAttrsRecursiveCond :: | 
					
						
							|  |  |  |  |          (AttrSet -> Bool) -> ([String] -> a -> b) -> AttrSet -> AttrSet | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        # To prevent recursing into derivations (which are attribute | 
					
						
							|  |  |  |  |        # sets with the attribute "type" equal to "derivation"): | 
					
						
							|  |  |  |  |        mapAttrsRecursiveCond | 
					
						
							|  |  |  |  |          (as: !(as ? "type" && as.type == "derivation")) | 
					
						
							|  |  |  |  |          (x: ... do something ...) | 
					
						
							|  |  |  |  |          attrs | 
					
						
							| 
									
										
										
										
											2013-03-06 16:33:01 +01:00
										 |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2009-03-30 13:19:57 +00:00
										 |  |  |  |   mapAttrsRecursiveCond = cond: f: set: | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  |     let | 
					
						
							| 
									
										
										
										
											2009-03-30 13:19:57 +00:00
										 |  |  |  |       recurse = path: set: | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  |         let | 
					
						
							|  |  |  |  |           g = | 
					
						
							|  |  |  |  |             name: value: | 
					
						
							| 
									
										
										
										
											2009-03-30 13:19:57 +00:00
										 |  |  |  |             if isAttrs value && cond value | 
					
						
							|  |  |  |  |               then recurse (path ++ [name]) value | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  |               else f (path ++ [name]) value; | 
					
						
							|  |  |  |  |         in mapAttrs g set; | 
					
						
							| 
									
										
										
										
											2009-03-30 13:19:57 +00:00
										 |  |  |  |     in recurse [] set; | 
					
						
							| 
									
										
										
										
											2009-04-25 14:08:29 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-06 16:33:01 +01:00
										 |  |  |  |   /* Generate an attribute set by mapping a function over a list of
 | 
					
						
							|  |  |  |  |      attribute names. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        genAttrs [ "foo" "bar" ] (name: "x_" + name) | 
					
						
							|  |  |  |  |        => { foo = "x_foo"; bar = "x_bar"; } | 
					
						
							|  |  |  |  |   */ | 
					
						
							|  |  |  |  |   genAttrs = names: f: | 
					
						
							|  |  |  |  |     listToAttrs (map (n: nameValuePair n (f n)) names); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |   /* Check whether the argument is a derivation. Any set with
 | 
					
						
							|  |  |  |  |      { type = "derivation"; } counts as a derivation. | 
					
						
							| 
									
										
										
										
											2009-04-25 14:08:29 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |      Example: | 
					
						
							|  |  |  |  |        nixpkgs = import <nixpkgs> {} | 
					
						
							|  |  |  |  |        isDerivation nixpkgs.ruby | 
					
						
							|  |  |  |  |        => true | 
					
						
							|  |  |  |  |        isDerivation "foobar" | 
					
						
							|  |  |  |  |        => false | 
					
						
							|  |  |  |  |   */ | 
					
						
							|  |  |  |  |   isDerivation = x: isAttrs x && x ? type && x.type == "derivation"; | 
					
						
							| 
									
										
										
										
											2009-09-10 10:52:51 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |   /* Converts a store path to a fake derivation. */ | 
					
						
							| 
									
										
										
										
											2015-08-06 19:55:42 +02:00
										 |  |  |  |   toDerivation = path: | 
					
						
							| 
									
										
										
										
											2016-09-19 11:51:11 +02:00
										 |  |  |  |     let | 
					
						
							|  |  |  |  |       path' = builtins.storePath path; | 
					
						
							|  |  |  |  |       res = | 
					
						
							|  |  |  |  |         { type = "derivation"; | 
					
						
							|  |  |  |  |           name = builtins.unsafeDiscardStringContext (builtins.substring 33 (-1) (baseNameOf path')); | 
					
						
							|  |  |  |  |           outPath = path'; | 
					
						
							|  |  |  |  |           outputs = [ "out" ]; | 
					
						
							|  |  |  |  |           out = res; | 
					
						
							|  |  |  |  |           outputName = "out"; | 
					
						
							|  |  |  |  |         }; | 
					
						
							|  |  |  |  |     in res; | 
					
						
							| 
									
										
										
										
											2015-08-06 19:55:42 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |   /* If `cond' is true, return the attribute set `as',
 | 
					
						
							|  |  |  |  |      otherwise an empty attribute set. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        optionalAttrs (true) { my = "set"; } | 
					
						
							|  |  |  |  |        => { my = "set"; } | 
					
						
							|  |  |  |  |        optionalAttrs (false) { my = "set"; } | 
					
						
							|  |  |  |  |        => { } | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2009-09-10 10:52:51 +00:00
										 |  |  |  |   optionalAttrs = cond: as: if cond then as else {}; | 
					
						
							| 
									
										
										
										
											2009-09-29 14:57:00 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Merge sets of attributes and use the function f to merge attributes
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |      values. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        zipAttrsWithNames ["a"] (name: vs: vs) [{a = "x";} {a = "y"; b = "z";}] | 
					
						
							|  |  |  |  |        => { a = ["x" "y"]; } | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2009-09-29 14:57:00 +00:00
										 |  |  |  |   zipAttrsWithNames = names: f: sets: | 
					
						
							|  |  |  |  |     listToAttrs (map (name: { | 
					
						
							|  |  |  |  |       inherit name; | 
					
						
							|  |  |  |  |       value = f name (catAttrs name sets); | 
					
						
							|  |  |  |  |     }) names); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-19 14:41:28 -05:00
										 |  |  |  |   /* Implementation note: Common names  appear multiple times in the list of
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |      names, hopefully this does not affect the system because the maximal | 
					
						
							|  |  |  |  |      laziness avoid computing twice the same expression and listToAttrs does | 
					
						
							|  |  |  |  |      not care about duplicated attribute names. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}] | 
					
						
							|  |  |  |  |        => { a = ["x" "y"]; b = ["z"] } | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |   zipAttrsWith = f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets; | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |   /* Like `zipAttrsWith' with `(name: values: value)' as the function.
 | 
					
						
							| 
									
										
										
										
											2009-09-29 14:57:00 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |     Example: | 
					
						
							|  |  |  |  |       zipAttrs [{a = "x";} {a = "y"; b = "z";}] | 
					
						
							|  |  |  |  |       => { a = ["x" "y"]; b = ["z"] } | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2009-09-29 14:57:00 +00:00
										 |  |  |  |   zipAttrs = zipAttrsWith (name: values: values); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Does the same as the update operator '//' except that attributes are
 | 
					
						
							| 
									
										
										
										
											2017-04-19 14:41:28 -05:00
										 |  |  |  |      merged until the given predicate is verified.  The predicate should | 
					
						
							| 
									
										
										
										
											2009-11-19 16:07:47 +00:00
										 |  |  |  |      accept 3 arguments which are the path to reach the attribute, a part of | 
					
						
							| 
									
										
										
										
											2009-09-29 14:57:00 +00:00
										 |  |  |  |      the first attribute set and a part of the second attribute set.  When | 
					
						
							|  |  |  |  |      the predicate is verified, the value of the first attribute set is | 
					
						
							|  |  |  |  |      replaced by the value of the second attribute set. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        recursiveUpdateUntil (path: l: r: path == ["foo"]) { | 
					
						
							|  |  |  |  |          # first attribute set | 
					
						
							|  |  |  |  |          foo.bar = 1; | 
					
						
							|  |  |  |  |          foo.baz = 2; | 
					
						
							|  |  |  |  |          bar = 3; | 
					
						
							|  |  |  |  |        } { | 
					
						
							|  |  |  |  |          #second attribute set | 
					
						
							|  |  |  |  |          foo.bar = 1; | 
					
						
							|  |  |  |  |          foo.quz = 2; | 
					
						
							|  |  |  |  |          baz = 4; | 
					
						
							|  |  |  |  |        } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |        returns: { | 
					
						
							|  |  |  |  |          foo.bar = 1; # 'foo.*' from the second set | 
					
						
							| 
									
										
										
										
											2012-10-23 15:35:48 +02:00
										 |  |  |  |          foo.quz = 2; # | 
					
						
							| 
									
										
										
										
											2009-09-29 14:57:00 +00:00
										 |  |  |  |          bar = 3;     # 'bar' from the first set | 
					
						
							|  |  |  |  |          baz = 4;     # 'baz' from the second set | 
					
						
							|  |  |  |  |        } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      */ | 
					
						
							|  |  |  |  |   recursiveUpdateUntil = pred: lhs: rhs: | 
					
						
							|  |  |  |  |     let f = attrPath: | 
					
						
							|  |  |  |  |       zipAttrsWith (n: values: | 
					
						
							|  |  |  |  |         if tail values == [] | 
					
						
							|  |  |  |  |         || pred attrPath (head (tail values)) (head values) then | 
					
						
							|  |  |  |  |           head values | 
					
						
							|  |  |  |  |         else | 
					
						
							|  |  |  |  |           f (attrPath ++ [n]) values | 
					
						
							|  |  |  |  |       ); | 
					
						
							|  |  |  |  |     in f [] [rhs lhs]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-04 01:39:03 +01:00
										 |  |  |  |   /* A recursive variant of the update operator ‘//’.  The recursion
 | 
					
						
							| 
									
										
										
										
											2012-11-14 11:38:47 +01:00
										 |  |  |  |      stops when one of the attribute values is not an attribute set, | 
					
						
							|  |  |  |  |      in which case the right hand side value takes precedence over the | 
					
						
							| 
									
										
										
										
											2009-09-29 14:57:00 +00:00
										 |  |  |  |      left hand side value. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        recursiveUpdate { | 
					
						
							|  |  |  |  |          boot.loader.grub.enable = true; | 
					
						
							|  |  |  |  |          boot.loader.grub.device = "/dev/hda"; | 
					
						
							|  |  |  |  |        } { | 
					
						
							|  |  |  |  |          boot.loader.grub.device = ""; | 
					
						
							|  |  |  |  |        } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |        returns: { | 
					
						
							|  |  |  |  |          boot.loader.grub.enable = true; | 
					
						
							|  |  |  |  |          boot.loader.grub.device = ""; | 
					
						
							|  |  |  |  |        } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      */ | 
					
						
							|  |  |  |  |   recursiveUpdate = lhs: rhs: | 
					
						
							|  |  |  |  |     recursiveUpdateUntil (path: lhs: rhs: | 
					
						
							|  |  |  |  |       !(isAttrs lhs && isAttrs rhs) | 
					
						
							|  |  |  |  |     ) lhs rhs; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |   /* Returns true if the pattern is contained in the set. False otherwise.
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							| 
									
										
										
										
											2017-04-01 15:34:38 -04:00
										 |  |  |  |        matchAttrs { cpu = {}; } { cpu = { bits = 64; }; } | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |        => true | 
					
						
							|  |  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-04-01 15:34:38 -04:00
										 |  |  |  |   matchAttrs = pattern: attrs: assert isAttrs pattern; | 
					
						
							|  |  |  |  |     fold and true (attrValues (zipAttrsWithNames (attrNames pattern) (n: values: | 
					
						
							| 
									
										
										
										
											2009-11-19 17:19:39 +00:00
										 |  |  |  |       let pat = head values; val = head (tail values); in | 
					
						
							| 
									
										
										
										
											2012-08-13 18:08:35 -04:00
										 |  |  |  |       if length values == 1 then false | 
					
						
							| 
									
										
										
										
											2017-04-01 15:34:38 -04:00
										 |  |  |  |       else if isAttrs pat then isAttrs val && matchAttrs pat val | 
					
						
							| 
									
										
										
										
											2012-08-13 18:08:35 -04:00
										 |  |  |  |       else pat == val | 
					
						
							| 
									
										
										
										
											2009-11-19 17:19:39 +00:00
										 |  |  |  |     ) [pattern attrs])); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  |   /* Override only the attributes that are already present in the old set
 | 
					
						
							|  |  |  |  |     useful for deep-overriding. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     Example: | 
					
						
							|  |  |  |  |       x = { a = { b = 4; c = 3; }; } | 
					
						
							|  |  |  |  |       overrideExisting x { a = { b = 6; d = 2; }; } | 
					
						
							|  |  |  |  |       => { a = { b = 6; d = 2; }; } | 
					
						
							|  |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2010-07-08 15:31:59 +00:00
										 |  |  |  |   overrideExisting = old: new: | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |  |     old // listToAttrs (map (attr: nameValuePair attr (attrByPath [attr] old.${attr} new)) (attrNames old)); | 
					
						
							| 
									
										
										
										
											2010-07-08 15:31:59 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-14 18:13:50 +03:00
										 |  |  |  |   /* Get a package output.
 | 
					
						
							|  |  |  |  |      If no output is found, fallback to `.out` and then to the default. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      Example: | 
					
						
							|  |  |  |  |        getOutput "dev" pkgs.openssl | 
					
						
							|  |  |  |  |        => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev" | 
					
						
							|  |  |  |  |   */ | 
					
						
							|  |  |  |  |   getOutput = output: pkg: | 
					
						
							|  |  |  |  |     if pkg.outputUnspecified or false | 
					
						
							|  |  |  |  |       then pkg.${output} or pkg.out or pkg | 
					
						
							|  |  |  |  |       else pkg; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-14 19:00:39 +03:00
										 |  |  |  |   getBin = getOutput "bin"; | 
					
						
							|  |  |  |  |   getLib = getOutput "lib"; | 
					
						
							|  |  |  |  |   getDev = getOutput "dev"; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-24 00:18:38 +02:00
										 |  |  |  |   /* Pick the outputs of packages to place in buildInputs */ | 
					
						
							| 
									
										
										
										
											2016-09-01 18:31:26 +03:00
										 |  |  |  |   chooseDevOutputs = drvs: builtins.map getDev drvs; | 
					
						
							| 
									
										
										
										
											2016-02-28 21:49:42 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   /*** deprecated stuff ***/ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   zipWithNames = zipAttrsWithNames; | 
					
						
							|  |  |  |  |   zip = builtins.trace | 
					
						
							|  |  |  |  |     "lib.zip is deprecated, use lib.zipAttrsWith instead" zipAttrsWith; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-10 15:18:38 +00:00
										 |  |  |  | } |