1/**
2 Operations on attribute sets.
3*/
4{ lib }:
5
6let
7 inherit (builtins) head length;
8 inherit (lib.trivial) isInOldestRelease mergeAttrs warn warnIf;
9 inherit (lib.strings) concatStringsSep concatMapStringsSep escapeNixIdentifier sanitizeDerivationName;
10 inherit (lib.lists) foldr foldl' concatMap elemAt all partition groupBy take foldl;
11in
12
13rec {
14 inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr removeAttrs;
15
16
17 /**
18 Return an attribute from nested attribute sets.
19
20 Nix has an [attribute selection operator `. or`](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
21
22 ```nix
23 (x.a.b or 6) == attrByPath ["a" "b"] 6 x
24 # and
25 (x.${f p}."example.com" or 6) == attrByPath [ (f p) "example.com" ] 6 x
26 ```
27
28
29 # Inputs
30
31 `attrPath`
32
33 : A list of strings representing the attribute path to return from `set`
34
35 `default`
36
37 : Default value if `attrPath` does not resolve to an existing value
38
39 `set`
40
41 : The nested attribute set to select values from
42
43 # Type
44
45 ```
46 attrByPath :: [String] -> Any -> AttrSet -> Any
47 ```
48
49 # Examples
50 :::{.example}
51 ## `lib.attrsets.attrByPath` usage example
52
53 ```nix
54 x = { a = { b = 3; }; }
55 # ["a" "b"] is equivalent to x.a.b
56 # 6 is a default value to return if the path does not exist in attrset
57 attrByPath ["a" "b"] 6 x
58 => 3
59 attrByPath ["z" "z"] 6 x
60 => 6
61 ```
62
63 :::
64 */
65 attrByPath =
66 attrPath:
67 default:
68 set:
69 let
70 lenAttrPath = length attrPath;
71 attrByPath' = n: s: (
72 if n == lenAttrPath then s
73 else (
74 let
75 attr = elemAt attrPath n;
76 in
77 if s ? ${attr} then attrByPath' (n + 1) s.${attr}
78 else default
79 )
80 );
81 in
82 attrByPath' 0 set;
83
84 /**
85 Return if an attribute from nested attribute set exists.
86
87 Nix has a [has attribute operator `?`](https://nixos.org/manual/nix/stable/language/operators#has-attribute), which is sufficient for such queries, as long as the number of attributes is static. For example:
88
89 ```nix
90 (x?a.b) == hasAttrByPath ["a" "b"] x
91 # and
92 (x?${f p}."example.com") == hasAttrByPath [ (f p) "example.com" ] x
93 ```
94
95 **Laws**:
96 1. ```nix
97 hasAttrByPath [] x == true
98 ```
99
100
101 # Inputs
102
103 `attrPath`
104
105 : A list of strings representing the attribute path to check from `set`
106
107 `e`
108
109 : The nested attribute set to check
110
111 # Type
112
113 ```
114 hasAttrByPath :: [String] -> AttrSet -> Bool
115 ```
116
117 # Examples
118 :::{.example}
119 ## `lib.attrsets.hasAttrByPath` usage example
120
121 ```nix
122 x = { a = { b = 3; }; }
123 hasAttrByPath ["a" "b"] x
124 => true
125 hasAttrByPath ["z" "z"] x
126 => false
127 hasAttrByPath [] (throw "no need")
128 => true
129 ```
130
131 :::
132 */
133 hasAttrByPath =
134 attrPath:
135 e:
136 let
137 lenAttrPath = length attrPath;
138 hasAttrByPath' = n: s: (
139 n == lenAttrPath || (
140 let
141 attr = elemAt attrPath n;
142 in
143 if s ? ${attr} then hasAttrByPath' (n + 1) s.${attr}
144 else false
145 )
146 );
147 in
148 hasAttrByPath' 0 e;
149
150 /**
151 Return the longest prefix of an attribute path that refers to an existing attribute in a nesting of attribute sets.
152
153 Can be used after [`mapAttrsRecursiveCond`](#function-library-lib.attrsets.mapAttrsRecursiveCond) to apply a condition,
154 although this will evaluate the predicate function on sibling attributes as well.
155
156 Note that the empty attribute path is valid for all values, so this function only throws an exception if any of its inputs does.
157
158 **Laws**:
159 1. ```nix
160 attrsets.longestValidPathPrefix [] x == []
161 ```
162
163 2. ```nix
164 hasAttrByPath (attrsets.longestValidPathPrefix p x) x == true
165 ```
166
167
168 # Inputs
169
170 `attrPath`
171
172 : A list of strings representing the longest possible path that may be returned.
173
174 `v`
175
176 : The nested attribute set to check.
177
178 # Type
179
180 ```
181 attrsets.longestValidPathPrefix :: [String] -> Value -> [String]
182 ```
183
184 # Examples
185 :::{.example}
186 ## `lib.attrsets.longestValidPathPrefix` usage example
187
188 ```nix
189 x = { a = { b = 3; }; }
190 attrsets.longestValidPathPrefix ["a" "b" "c"] x
191 => ["a" "b"]
192 attrsets.longestValidPathPrefix ["a"] x
193 => ["a"]
194 attrsets.longestValidPathPrefix ["z" "z"] x
195 => []
196 attrsets.longestValidPathPrefix ["z" "z"] (throw "no need")
197 => []
198 ```
199
200 :::
201 */
202 longestValidPathPrefix =
203 attrPath:
204 v:
205 let
206 lenAttrPath = length attrPath;
207 getPrefixForSetAtIndex =
208 # The nested attribute set to check, if it is an attribute set, which
209 # is not a given.
210 remainingSet:
211 # The index of the attribute we're about to check, as well as
212 # the length of the prefix we've already checked.
213 remainingPathIndex:
214
215 if remainingPathIndex == lenAttrPath then
216 # All previously checked attributes exist, and no attr names left,
217 # so we return the whole path.
218 attrPath
219 else
220 let
221 attr = elemAt attrPath remainingPathIndex;
222 in
223 if remainingSet ? ${attr} then
224 getPrefixForSetAtIndex
225 remainingSet.${attr} # advance from the set to the attribute value
226 (remainingPathIndex + 1) # advance the path
227 else
228 # The attribute doesn't exist, so we return the prefix up to the
229 # previously checked length.
230 take remainingPathIndex attrPath;
231 in
232 getPrefixForSetAtIndex v 0;
233
234 /**
235 Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
236
237
238 # Inputs
239
240 `attrPath`
241
242 : A list of strings representing the attribute path to set
243
244 `value`
245
246 : The value to set at the location described by `attrPath`
247
248 # Type
249
250 ```
251 setAttrByPath :: [String] -> Any -> AttrSet
252 ```
253
254 # Examples
255 :::{.example}
256 ## `lib.attrsets.setAttrByPath` usage example
257
258 ```nix
259 setAttrByPath ["a" "b"] 3
260 => { a = { b = 3; }; }
261 ```
262
263 :::
264 */
265 setAttrByPath =
266 attrPath:
267 value:
268 let
269 len = length attrPath;
270 atDepth = n:
271 if n == len
272 then value
273 else { ${elemAt attrPath n} = atDepth (n + 1); };
274 in atDepth 0;
275
276 /**
277 Like `attrByPath`, but without a default value. If it doesn't find the
278 path it will throw an error.
279
280 Nix has an [attribute selection operator](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
281
282 ```nix
283 x.a.b == getAttrByPath ["a" "b"] x
284 # and
285 x.${f p}."example.com" == getAttrByPath [ (f p) "example.com" ] x
286 ```
287
288
289 # Inputs
290
291 `attrPath`
292
293 : A list of strings representing the attribute path to get from `set`
294
295 `set`
296
297 : The nested attribute set to find the value in.
298
299 # Type
300
301 ```
302 getAttrFromPath :: [String] -> AttrSet -> Any
303 ```
304
305 # Examples
306 :::{.example}
307 ## `lib.attrsets.getAttrFromPath` usage example
308
309 ```nix
310 x = { a = { b = 3; }; }
311 getAttrFromPath ["a" "b"] x
312 => 3
313 getAttrFromPath ["z" "z"] x
314 => error: cannot find attribute `z.z'
315 ```
316
317 :::
318 */
319 getAttrFromPath =
320 attrPath:
321 set:
322 attrByPath attrPath (abort ("cannot find attribute `" + concatStringsSep "." attrPath + "'")) set;
323
324 /**
325 Map each attribute in the given set and merge them into a new attribute set.
326
327
328 # Inputs
329
330 `f`
331
332 : 1\. Function argument
333
334 `v`
335
336 : 2\. Function argument
337
338 # Type
339
340 ```
341 concatMapAttrs :: (String -> a -> AttrSet) -> AttrSet -> AttrSet
342 ```
343
344 # Examples
345 :::{.example}
346 ## `lib.attrsets.concatMapAttrs` usage example
347
348 ```nix
349 concatMapAttrs
350 (name: value: {
351 ${name} = value;
352 ${name + value} = value;
353 })
354 { x = "a"; y = "b"; }
355 => { x = "a"; xa = "a"; y = "b"; yb = "b"; }
356 ```
357
358 :::
359 */
360 concatMapAttrs = f: v:
361 foldl' mergeAttrs { }
362 (attrValues
363 (mapAttrs f v)
364 );
365
366
367 /**
368 Update or set specific paths of an attribute set.
369
370 Takes a list of updates to apply and an attribute set to apply them to,
371 and returns the attribute set with the updates applied. Updates are
372 represented as `{ path = ...; update = ...; }` values, where `path` is a
373 list of strings representing the attribute path that should be updated,
374 and `update` is a function that takes the old value at that attribute path
375 as an argument and returns the new
376 value it should be.
377
378 Properties:
379
380 - Updates to deeper attribute paths are applied before updates to more
381 shallow attribute paths
382
383 - Multiple updates to the same attribute path are applied in the order
384 they appear in the update list
385
386 - If any but the last `path` element leads into a value that is not an
387 attribute set, an error is thrown
388
389 - If there is an update for an attribute path that doesn't exist,
390 accessing the argument in the update function causes an error, but
391 intermediate attribute sets are implicitly created as needed
392
393 # Type
394
395 ```
396 updateManyAttrsByPath :: [{ path :: [String]; update :: (Any -> Any); }] -> AttrSet -> AttrSet
397 ```
398
399 # Examples
400 :::{.example}
401 ## `lib.attrsets.updateManyAttrsByPath` usage example
402
403 ```nix
404 updateManyAttrsByPath [
405 {
406 path = [ "a" "b" ];
407 update = old: { d = old.c; };
408 }
409 {
410 path = [ "a" "b" "c" ];
411 update = old: old + 1;
412 }
413 {
414 path = [ "x" "y" ];
415 update = old: "xy";
416 }
417 ] { a.b.c = 0; }
418 => { a = { b = { d = 1; }; }; x = { y = "xy"; }; }
419 ```
420
421 :::
422 */
423 updateManyAttrsByPath = let
424 # When recursing into attributes, instead of updating the `path` of each
425 # update using `tail`, which needs to allocate an entirely new list,
426 # we just pass a prefix length to use and make sure to only look at the
427 # path without the prefix length, so that we can reuse the original list
428 # entries.
429 go = prefixLength: hasValue: value: updates:
430 let
431 # Splits updates into ones on this level (split.right)
432 # And ones on levels further down (split.wrong)
433 split = partition (el: length el.path == prefixLength) updates;
434
435 # Groups updates on further down levels into the attributes they modify
436 nested = groupBy (el: elemAt el.path prefixLength) split.wrong;
437
438 # Applies only nested modification to the input value
439 withNestedMods =
440 # Return the value directly if we don't have any nested modifications
441 if split.wrong == [] then
442 if hasValue then value
443 else
444 # Throw an error if there is no value. This `head` call here is
445 # safe, but only in this branch since `go` could only be called
446 # with `hasValue == false` for nested updates, in which case
447 # it's also always called with at least one update
448 let updatePath = (head split.right).path; in
449 throw
450 ( "updateManyAttrsByPath: Path '${showAttrPath updatePath}' does "
451 + "not exist in the given value, but the first update to this "
452 + "path tries to access the existing value.")
453 else
454 # If there are nested modifications, try to apply them to the value
455 if ! hasValue then
456 # But if we don't have a value, just use an empty attribute set
457 # as the value, but simplify the code a bit
458 mapAttrs (name: go (prefixLength + 1) false null) nested
459 else if isAttrs value then
460 # If we do have a value and it's an attribute set, override it
461 # with the nested modifications
462 value //
463 mapAttrs (name: go (prefixLength + 1) (value ? ${name}) value.${name}) nested
464 else
465 # However if it's not an attribute set, we can't apply the nested
466 # modifications, throw an error
467 let updatePath = (head split.wrong).path; in
468 throw
469 ( "updateManyAttrsByPath: Path '${showAttrPath updatePath}' needs to "
470 + "be updated, but path '${showAttrPath (take prefixLength updatePath)}' "
471 + "of the given value is not an attribute set, so we can't "
472 + "update an attribute inside of it.");
473
474 # We get the final result by applying all the updates on this level
475 # after having applied all the nested updates
476 # We use foldl instead of foldl' so that in case of multiple updates,
477 # intermediate values aren't evaluated if not needed
478 in foldl (acc: el: el.update acc) withNestedMods split.right;
479
480 in updates: value: go 0 true value updates;
481
482 /**
483 Return the specified attributes from a set.
484
485
486 # Inputs
487
488 `nameList`
489
490 : The list of attributes to fetch from `set`. Each attribute name must exist on the attrbitue set
491
492 `set`
493
494 : The set to get attribute values from
495
496 # Type
497
498 ```
499 attrVals :: [String] -> AttrSet -> [Any]
500 ```
501
502 # Examples
503 :::{.example}
504 ## `lib.attrsets.attrVals` usage example
505
506 ```nix
507 attrVals ["a" "b" "c"] as
508 => [as.a as.b as.c]
509 ```
510
511 :::
512 */
513 attrVals =
514 nameList:
515 set: map (x: set.${x}) nameList;
516
517
518 /**
519 Return the values of all attributes in the given set, sorted by
520 attribute name.
521
522 # Type
523
524 ```
525 attrValues :: AttrSet -> [Any]
526 ```
527
528 # Examples
529 :::{.example}
530 ## `lib.attrsets.attrValues` usage example
531
532 ```nix
533 attrValues {c = 3; a = 1; b = 2;}
534 => [1 2 3]
535 ```
536
537 :::
538 */
539 attrValues = builtins.attrValues;
540
541
542 /**
543 Given a set of attribute names, return the set of the corresponding
544 attributes from the given set.
545
546
547 # Inputs
548
549 `names`
550
551 : A list of attribute names to get out of `set`
552
553 `attrs`
554
555 : The set to get the named attributes from
556
557 # Type
558
559 ```
560 getAttrs :: [String] -> AttrSet -> AttrSet
561 ```
562
563 # Examples
564 :::{.example}
565 ## `lib.attrsets.getAttrs` usage example
566
567 ```nix
568 getAttrs [ "a" "b" ] { a = 1; b = 2; c = 3; }
569 => { a = 1; b = 2; }
570 ```
571
572 :::
573 */
574 getAttrs =
575 names:
576 attrs: genAttrs names (name: attrs.${name});
577
578 /**
579 Collect each attribute named `attr` from a list of attribute
580 sets. Sets that don't contain the named attribute are ignored.
581
582 # Inputs
583
584 `attr`
585
586 : The attribute name to get out of the sets.
587
588 `list`
589
590 : The list of attribute sets to go through
591
592 # Type
593
594 ```
595 catAttrs :: String -> [AttrSet] -> [Any]
596 ```
597
598 # Examples
599 :::{.example}
600 ## `lib.attrsets.catAttrs` usage example
601
602 ```nix
603 catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
604 => [1 2]
605 ```
606
607 :::
608 */
609 catAttrs = builtins.catAttrs;
610
611
612 /**
613 Filter an attribute set by removing all attributes for which the
614 given predicate return false.
615
616
617 # Inputs
618
619 `pred`
620
621 : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
622
623 `set`
624
625 : The attribute set to filter
626
627 # Type
628
629 ```
630 filterAttrs :: (String -> Any -> Bool) -> AttrSet -> AttrSet
631 ```
632
633 # Examples
634 :::{.example}
635 ## `lib.attrsets.filterAttrs` usage example
636
637 ```nix
638 filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; }
639 => { foo = 1; }
640 ```
641
642 :::
643 */
644 filterAttrs =
645 pred:
646 set:
647 listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set));
648
649
650 /**
651 Filter an attribute set recursively by removing all attributes for
652 which the given predicate return false.
653
654
655 # Inputs
656
657 `pred`
658
659 : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
660
661 `set`
662
663 : The attribute set to filter
664
665 # Type
666
667 ```
668 filterAttrsRecursive :: (String -> Any -> Bool) -> AttrSet -> AttrSet
669 ```
670
671 # Examples
672 :::{.example}
673 ## `lib.attrsets.filterAttrsRecursive` usage example
674
675 ```nix
676 filterAttrsRecursive (n: v: v != null) { foo = { bar = null; }; }
677 => { foo = {}; }
678 ```
679
680 :::
681 */
682 filterAttrsRecursive =
683 pred:
684 set:
685 listToAttrs (
686 concatMap (name:
687 let v = set.${name}; in
688 if pred name v then [
689 (nameValuePair name (
690 if isAttrs v then filterAttrsRecursive pred v
691 else v
692 ))
693 ] else []
694 ) (attrNames set)
695 );
696
697 /**
698 Like [`lib.lists.foldl'`](#function-library-lib.lists.foldl-prime) but for attribute sets.
699 Iterates over every name-value pair in the given attribute set.
700 The result of the callback function is often called `acc` for accumulator. It is passed between callbacks from left to right and the final `acc` is the return value of `foldlAttrs`.
701
702 Attention:
703
704 There is a completely different function `lib.foldAttrs`
705 which has nothing to do with this function, despite the similar name.
706
707
708 # Inputs
709
710 `f`
711
712 : 1\. Function argument
713
714 `init`
715
716 : 2\. Function argument
717
718 `set`
719
720 : 3\. Function argument
721
722 # Type
723
724 ```
725 foldlAttrs :: ( a -> String -> b -> a ) -> a -> { ... :: b } -> a
726 ```
727
728 # Examples
729 :::{.example}
730 ## `lib.attrsets.foldlAttrs` usage example
731
732 ```nix
733 foldlAttrs
734 (acc: name: value: {
735 sum = acc.sum + value;
736 names = acc.names ++ [name];
737 })
738 { sum = 0; names = []; }
739 {
740 foo = 1;
741 bar = 10;
742 }
743 ->
744 {
745 sum = 11;
746 names = ["bar" "foo"];
747 }
748
749 foldlAttrs
750 (throw "function not needed")
751 123
752 {};
753 ->
754 123
755
756 foldlAttrs
757 (acc: _: _: acc)
758 3
759 { z = throw "value not needed"; a = throw "value not needed"; };
760 ->
761 3
762
763 The accumulator doesn't have to be an attrset.
764 It can be as simple as a number or string.
765
766 foldlAttrs
767 (acc: _: v: acc * 10 + v)
768 1
769 { z = 1; a = 2; };
770 ->
771 121
772 ```
773
774 :::
775 */
776 foldlAttrs = f: init: set:
777 foldl'
778 (acc: name: f acc name set.${name})
779 init
780 (attrNames set);
781
782 /**
783 Apply fold functions to values grouped by key.
784
785
786 # Inputs
787
788 `op`
789
790 : A function, given a value and a collector combines the two.
791
792 `nul`
793
794 : The starting value.
795
796 `list_of_attrs`
797
798 : A list of attribute sets to fold together by key.
799
800 # Type
801
802 ```
803 foldAttrs :: (Any -> Any -> Any) -> Any -> [AttrSets] -> Any
804 ```
805
806 # Examples
807 :::{.example}
808 ## `lib.attrsets.foldAttrs` usage example
809
810 ```nix
811 foldAttrs (item: acc: [item] ++ acc) [] [{ a = 2; } { a = 3; }]
812 => { a = [ 2 3 ]; }
813 ```
814
815 :::
816 */
817 foldAttrs =
818 op:
819 nul:
820 list_of_attrs:
821 foldr (n: a:
822 foldr (name: o:
823 o // { ${name} = op n.${name} (a.${name} or nul); }
824 ) a (attrNames n)
825 ) {} list_of_attrs;
826
827
828 /**
829 Recursively collect sets that verify a given predicate named `pred`
830 from the set `attrs`. The recursion is stopped when the predicate is
831 verified.
832
833
834 # Inputs
835
836 `pred`
837
838 : Given an attribute's value, determine if recursion should stop.
839
840 `attrs`
841
842 : The attribute set to recursively collect.
843
844 # Type
845
846 ```
847 collect :: (AttrSet -> Bool) -> AttrSet -> [x]
848 ```
849
850 # Examples
851 :::{.example}
852 ## `lib.attrsets.collect` usage example
853
854 ```nix
855 collect isList { a = { b = ["b"]; }; c = [1]; }
856 => [["b"] [1]]
857
858 collect (x: x ? outPath)
859 { a = { outPath = "a/"; }; b = { outPath = "b/"; }; }
860 => [{ outPath = "a/"; } { outPath = "b/"; }]
861 ```
862
863 :::
864 */
865 collect =
866 pred:
867 attrs:
868 if pred attrs then
869 [ attrs ]
870 else if isAttrs attrs then
871 concatMap (collect pred) (attrValues attrs)
872 else
873 [];
874
875 /**
876 Return the cartesian product of attribute set value combinations.
877
878
879 # Inputs
880
881 `attrsOfLists`
882
883 : Attribute set with attributes that are lists of values
884
885 # Type
886
887 ```
888 cartesianProduct :: AttrSet -> [AttrSet]
889 ```
890
891 # Examples
892 :::{.example}
893 ## `lib.attrsets.cartesianProduct` usage example
894
895 ```nix
896 cartesianProduct { a = [ 1 2 ]; b = [ 10 20 ]; }
897 => [
898 { a = 1; b = 10; }
899 { a = 1; b = 20; }
900 { a = 2; b = 10; }
901 { a = 2; b = 20; }
902 ]
903 ```
904
905 :::
906 */
907 cartesianProduct =
908 attrsOfLists:
909 foldl' (listOfAttrs: attrName:
910 concatMap (attrs:
911 map (listValue: attrs // { ${attrName} = listValue; }) attrsOfLists.${attrName}
912 ) listOfAttrs
913 ) [{}] (attrNames attrsOfLists);
914
915
916 /**
917 Return the result of function f applied to the cartesian product of attribute set value combinations.
918 Equivalent to using cartesianProduct followed by map.
919
920 # Inputs
921
922 `f`
923
924 : A function, given an attribute set, it returns a new value.
925
926 `attrsOfLists`
927
928 : Attribute set with attributes that are lists of values
929
930 # Type
931
932 ```
933 mapCartesianProduct :: (AttrSet -> a) -> AttrSet -> [a]
934 ```
935
936 # Examples
937 :::{.example}
938 ## `lib.attrsets.mapCartesianProduct` usage example
939
940 ```nix
941 mapCartesianProduct ({a, b}: "${a}-${b}") { a = [ "1" "2" ]; b = [ "3" "4" ]; }
942 => [ "1-3" "1-4" "2-3" "2-4" ]
943 ```
944
945 :::
946
947 */
948 mapCartesianProduct = f: attrsOfLists: map f (cartesianProduct attrsOfLists);
949
950 /**
951 Utility function that creates a `{name, value}` pair as expected by `builtins.listToAttrs`.
952
953
954 # Inputs
955
956 `name`
957
958 : Attribute name
959
960 `value`
961
962 : Attribute value
963
964 # Type
965
966 ```
967 nameValuePair :: String -> Any -> { name :: String; value :: Any; }
968 ```
969
970 # Examples
971 :::{.example}
972 ## `lib.attrsets.nameValuePair` usage example
973
974 ```nix
975 nameValuePair "some" 6
976 => { name = "some"; value = 6; }
977 ```
978
979 :::
980 */
981 nameValuePair =
982 name:
983 value:
984 { inherit name value; };
985
986
987 /**
988 Apply a function to each element in an attribute set, creating a new attribute set.
989
990 # Inputs
991
992 `f`
993
994 : A function that takes an attribute name and its value, and returns the new value for the attribute.
995
996 `attrset`
997
998 : The attribute set to iterate through.
999
1000 # Type
1001
1002 ```
1003 mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet
1004 ```
1005
1006 # Examples
1007 :::{.example}
1008 ## `lib.attrsets.mapAttrs` usage example
1009
1010 ```nix
1011 mapAttrs (name: value: name + "-" + value)
1012 { x = "foo"; y = "bar"; }
1013 => { x = "x-foo"; y = "y-bar"; }
1014 ```
1015
1016 :::
1017 */
1018 mapAttrs = builtins.mapAttrs;
1019
1020
1021 /**
1022 Like `mapAttrs`, but allows the name of each attribute to be
1023 changed in addition to the value. The applied function should
1024 return both the new name and value as a `nameValuePair`.
1025
1026
1027 # Inputs
1028
1029 `f`
1030
1031 : A function, given an attribute's name and value, returns a new `nameValuePair`.
1032
1033 `set`
1034
1035 : Attribute set to map over.
1036
1037 # Type
1038
1039 ```
1040 mapAttrs' :: (String -> Any -> { name :: String; value :: Any; }) -> AttrSet -> AttrSet
1041 ```
1042
1043 # Examples
1044 :::{.example}
1045 ## `lib.attrsets.mapAttrs'` usage example
1046
1047 ```nix
1048 mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value))
1049 { x = "a"; y = "b"; }
1050 => { foo_x = "bar-a"; foo_y = "bar-b"; }
1051 ```
1052
1053 :::
1054 */
1055 mapAttrs' =
1056 f:
1057 set:
1058 listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
1059
1060
1061 /**
1062 Call a function for each attribute in the given set and return
1063 the result in a list.
1064
1065 # Inputs
1066
1067 `f`
1068
1069 : A function, given an attribute's name and value, returns a new value.
1070
1071 `attrs`
1072
1073 : Attribute set to map over.
1074
1075 # Type
1076
1077 ```
1078 mapAttrsToList :: (String -> a -> b) -> AttrSet -> [b]
1079 ```
1080
1081 # Examples
1082 :::{.example}
1083 ## `lib.attrsets.mapAttrsToList` usage example
1084
1085 ```nix
1086 mapAttrsToList (name: value: name + value)
1087 { x = "a"; y = "b"; }
1088 => [ "xa" "yb" ]
1089 ```
1090
1091 :::
1092 */
1093 mapAttrsToList =
1094 f:
1095 attrs:
1096 map (name: f name attrs.${name}) (attrNames attrs);
1097
1098 /**
1099 Deconstruct an attrset to a list of name-value pairs as expected by [`builtins.listToAttrs`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-listToAttrs).
1100 Each element of the resulting list is an attribute set with these attributes:
1101 - `name` (string): The name of the attribute
1102 - `value` (any): The value of the attribute
1103
1104 The following is always true:
1105 ```nix
1106 builtins.listToAttrs (attrsToList attrs) == attrs
1107 ```
1108
1109 :::{.warning}
1110 The opposite is not always true. In general expect that
1111 ```nix
1112 attrsToList (builtins.listToAttrs list) != list
1113 ```
1114
1115 This is because the `listToAttrs` removes duplicate names and doesn't preserve the order of the list.
1116 :::
1117
1118 # Inputs
1119
1120 `set`
1121
1122 : The attribute set to deconstruct.
1123
1124 # Type
1125
1126 ```
1127 attrsToList :: AttrSet -> [ { name :: String; value :: Any; } ]
1128 ```
1129
1130 # Examples
1131 :::{.example}
1132 ## `lib.attrsets.attrsToList` usage example
1133
1134 ```nix
1135 attrsToList { foo = 1; bar = "asdf"; }
1136 => [ { name = "bar"; value = "asdf"; } { name = "foo"; value = 1; } ]
1137 ```
1138
1139 :::
1140 */
1141 attrsToList = mapAttrsToList nameValuePair;
1142
1143
1144 /**
1145 Like `mapAttrs`, except that it recursively applies itself to the *leaf* attributes of a potentially-nested attribute set:
1146 the second argument of the function will never be an attrset.
1147 Also, the first argument of the mapping function is a *list* of the attribute names that form the path to the leaf attribute.
1148
1149 For a function that gives you control over what counts as a leaf, see `mapAttrsRecursiveCond`.
1150
1151 :::{#map-attrs-recursive-example .example}
1152 # Map over leaf attributes
1153
1154 ```nix
1155 mapAttrsRecursive (path: value: concatStringsSep "-" (path ++ [value]))
1156 { n = { a = "A"; m = { b = "B"; c = "C"; }; }; d = "D"; }
1157 ```
1158 evaluates to
1159 ```nix
1160 { n = { a = "n-a-A"; m = { b = "n-m-b-B"; c = "n-m-c-C"; }; }; d = "d-D"; }
1161 ```
1162 :::
1163
1164 # Type
1165 ```
1166 mapAttrsRecursive :: ([String] -> a -> b) -> AttrSet -> AttrSet
1167 ```
1168 */
1169 mapAttrsRecursive =
1170 f:
1171 set:
1172 mapAttrsRecursiveCond (as: true) f set;
1173
1174
1175 /**
1176 Like `mapAttrsRecursive`, but it takes an additional predicate that tells it whether to recurse into an attribute set.
1177 If the predicate returns false, `mapAttrsRecursiveCond` does not recurse, but instead applies the mapping function.
1178 If the predicate returns true, it does recurse, and does not apply the mapping function.
1179
1180 :::{#map-attrs-recursive-cond-example .example}
1181 # Map over an leaf attributes defined by a condition
1182
1183 Map derivations to their `name` attribute.
1184 Derivatons are identified as attribute sets that contain `{ type = "derivation"; }`.
1185 ```nix
1186 mapAttrsRecursiveCond
1187 (as: !(as ? "type" && as.type == "derivation"))
1188 (x: x.name)
1189 attrs
1190 ```
1191 :::
1192
1193 # Type
1194 ```
1195 mapAttrsRecursiveCond :: (AttrSet -> Bool) -> ([String] -> a -> b) -> AttrSet -> AttrSet
1196 ```
1197 */
1198 mapAttrsRecursiveCond =
1199 cond:
1200 f:
1201 set:
1202 let
1203 recurse = path:
1204 mapAttrs
1205 (name: value:
1206 if isAttrs value && cond value
1207 then recurse (path ++ [ name ]) value
1208 else f (path ++ [ name ]) value);
1209 in
1210 recurse [ ] set;
1211
1212
1213 /**
1214 Generate an attribute set by mapping a function over a list of
1215 attribute names.
1216
1217
1218 # Inputs
1219
1220 `names`
1221
1222 : Names of values in the resulting attribute set.
1223
1224 `f`
1225
1226 : A function, given the name of the attribute, returns the attribute's value.
1227
1228 # Type
1229
1230 ```
1231 genAttrs :: [ String ] -> (String -> Any) -> AttrSet
1232 ```
1233
1234 # Examples
1235 :::{.example}
1236 ## `lib.attrsets.genAttrs` usage example
1237
1238 ```nix
1239 genAttrs [ "foo" "bar" ] (name: "x_" + name)
1240 => { foo = "x_foo"; bar = "x_bar"; }
1241 ```
1242
1243 :::
1244 */
1245 genAttrs =
1246 names:
1247 f:
1248 listToAttrs (map (n: nameValuePair n (f n)) names);
1249
1250
1251 /**
1252 Check whether the argument is a derivation. Any set with
1253 `{ type = "derivation"; }` counts as a derivation.
1254
1255
1256 # Inputs
1257
1258 `value`
1259
1260 : Value to check.
1261
1262 # Type
1263
1264 ```
1265 isDerivation :: Any -> Bool
1266 ```
1267
1268 # Examples
1269 :::{.example}
1270 ## `lib.attrsets.isDerivation` usage example
1271
1272 ```nix
1273 nixpkgs = import <nixpkgs> {}
1274 isDerivation nixpkgs.ruby
1275 => true
1276 isDerivation "foobar"
1277 => false
1278 ```
1279
1280 :::
1281 */
1282 isDerivation =
1283 value: value.type or null == "derivation";
1284
1285 /**
1286 Converts a store path to a fake derivation.
1287
1288
1289 # Inputs
1290
1291 `path`
1292
1293 : A store path to convert to a derivation.
1294
1295 # Type
1296
1297 ```
1298 toDerivation :: Path -> Derivation
1299 ```
1300 */
1301 toDerivation =
1302 path:
1303 let
1304 path' = builtins.storePath path;
1305 res =
1306 { type = "derivation";
1307 name = sanitizeDerivationName (builtins.substring 33 (-1) (baseNameOf path'));
1308 outPath = path';
1309 outputs = [ "out" ];
1310 out = res;
1311 outputName = "out";
1312 };
1313 in res;
1314
1315
1316 /**
1317 If `cond` is true, return the attribute set `as`,
1318 otherwise an empty attribute set.
1319
1320
1321 # Inputs
1322
1323 `cond`
1324
1325 : Condition under which the `as` attribute set is returned.
1326
1327 `as`
1328
1329 : The attribute set to return if `cond` is `true`.
1330
1331 # Type
1332
1333 ```
1334 optionalAttrs :: Bool -> AttrSet -> AttrSet
1335 ```
1336
1337 # Examples
1338 :::{.example}
1339 ## `lib.attrsets.optionalAttrs` usage example
1340
1341 ```nix
1342 optionalAttrs (true) { my = "set"; }
1343 => { my = "set"; }
1344 optionalAttrs (false) { my = "set"; }
1345 => { }
1346 ```
1347
1348 :::
1349 */
1350 optionalAttrs =
1351 cond:
1352 as:
1353 if cond then as else {};
1354
1355
1356 /**
1357 Merge sets of attributes and use the function `f` to merge attributes
1358 values.
1359
1360
1361 # Inputs
1362
1363 `names`
1364
1365 : List of attribute names to zip.
1366
1367 `f`
1368
1369 : A function, accepts an attribute name, all the values, and returns a combined value.
1370
1371 `sets`
1372
1373 : List of values from the list of attribute sets.
1374
1375 # Type
1376
1377 ```
1378 zipAttrsWithNames :: [ String ] -> (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
1379 ```
1380
1381 # Examples
1382 :::{.example}
1383 ## `lib.attrsets.zipAttrsWithNames` usage example
1384
1385 ```nix
1386 zipAttrsWithNames ["a"] (name: vs: vs) [{a = "x";} {a = "y"; b = "z";}]
1387 => { a = ["x" "y"]; }
1388 ```
1389
1390 :::
1391 */
1392 zipAttrsWithNames =
1393 names:
1394 f:
1395 sets:
1396 listToAttrs (map (name: {
1397 inherit name;
1398 value = f name (catAttrs name sets);
1399 }) names);
1400
1401
1402 /**
1403 Merge sets of attributes and use the function f to merge attribute values.
1404 Like `lib.attrsets.zipAttrsWithNames` with all key names are passed for `names`.
1405
1406 Implementation note: Common names appear multiple times in the list of
1407 names, hopefully this does not affect the system because the maximal
1408 laziness avoid computing twice the same expression and `listToAttrs` does
1409 not care about duplicated attribute names.
1410
1411 # Type
1412
1413 ```
1414 zipAttrsWith :: (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
1415 ```
1416
1417 # Examples
1418 :::{.example}
1419 ## `lib.attrsets.zipAttrsWith` usage example
1420
1421 ```nix
1422 zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}]
1423 => { a = ["x" "y"]; b = ["z"]; }
1424 ```
1425
1426 :::
1427 */
1428 zipAttrsWith =
1429 builtins.zipAttrsWith or (f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets);
1430
1431
1432 /**
1433 Merge sets of attributes and combine each attribute value in to a list.
1434
1435 Like `lib.attrsets.zipAttrsWith` with `(name: values: values)` as the function.
1436
1437 # Type
1438
1439 ```
1440 zipAttrs :: [ AttrSet ] -> AttrSet
1441 ```
1442
1443 # Examples
1444 :::{.example}
1445 ## `lib.attrsets.zipAttrs` usage example
1446
1447 ```nix
1448 zipAttrs [{a = "x";} {a = "y"; b = "z";}]
1449 => { a = ["x" "y"]; b = ["z"]; }
1450 ```
1451
1452 :::
1453 */
1454 zipAttrs = zipAttrsWith (name: values: values);
1455
1456 /**
1457 Merge a list of attribute sets together using the `//` operator.
1458 In case of duplicate attributes, values from later list elements take precedence over earlier ones.
1459 The result is the same as `foldl mergeAttrs { }`, but the performance is better for large inputs.
1460 For n list elements, each with an attribute set containing m unique attributes, the complexity of this operation is O(nm log n).
1461
1462
1463 # Inputs
1464
1465 `list`
1466
1467 : 1\. Function argument
1468
1469 # Type
1470
1471 ```
1472 mergeAttrsList :: [ Attrs ] -> Attrs
1473 ```
1474
1475 # Examples
1476 :::{.example}
1477 ## `lib.attrsets.mergeAttrsList` usage example
1478
1479 ```nix
1480 mergeAttrsList [ { a = 0; b = 1; } { c = 2; d = 3; } ]
1481 => { a = 0; b = 1; c = 2; d = 3; }
1482 mergeAttrsList [ { a = 0; } { a = 1; } ]
1483 => { a = 1; }
1484 ```
1485
1486 :::
1487 */
1488 mergeAttrsList = list:
1489 let
1490 # `binaryMerge start end` merges the elements at indices `index` of `list` such that `start <= index < end`
1491 # Type: Int -> Int -> Attrs
1492 binaryMerge = start: end:
1493 # assert start < end; # Invariant
1494 if end - start >= 2 then
1495 # If there's at least 2 elements, split the range in two, recurse on each part and merge the result
1496 # The invariant is satisfied because each half will have at least 1 element
1497 binaryMerge start (start + (end - start) / 2)
1498 // binaryMerge (start + (end - start) / 2) end
1499 else
1500 # Otherwise there will be exactly 1 element due to the invariant, in which case we just return it directly
1501 elemAt list start;
1502 in
1503 if list == [ ] then
1504 # Calling binaryMerge as below would not satisfy its invariant
1505 { }
1506 else
1507 binaryMerge 0 (length list);
1508
1509
1510 /**
1511 Does the same as the update operator '//' except that attributes are
1512 merged until the given predicate is verified. The predicate should
1513 accept 3 arguments which are the path to reach the attribute, a part of
1514 the first attribute set and a part of the second attribute set. When
1515 the predicate is satisfied, the value of the first attribute set is
1516 replaced by the value of the second attribute set.
1517
1518
1519 # Inputs
1520
1521 `pred`
1522
1523 : Predicate, taking the path to the current attribute as a list of strings for attribute names, and the two values at that path from the original arguments.
1524
1525 `lhs`
1526
1527 : Left attribute set of the merge.
1528
1529 `rhs`
1530
1531 : Right attribute set of the merge.
1532
1533 # Type
1534
1535 ```
1536 recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet
1537 ```
1538
1539 # Examples
1540 :::{.example}
1541 ## `lib.attrsets.recursiveUpdateUntil` usage example
1542
1543 ```nix
1544 recursiveUpdateUntil (path: l: r: path == ["foo"]) {
1545 # first attribute set
1546 foo.bar = 1;
1547 foo.baz = 2;
1548 bar = 3;
1549 } {
1550 #second attribute set
1551 foo.bar = 1;
1552 foo.quz = 2;
1553 baz = 4;
1554 }
1555
1556 => {
1557 foo.bar = 1; # 'foo.*' from the second set
1558 foo.quz = 2; #
1559 bar = 3; # 'bar' from the first set
1560 baz = 4; # 'baz' from the second set
1561 }
1562 ```
1563
1564 :::
1565 */
1566 recursiveUpdateUntil =
1567 pred:
1568 lhs:
1569 rhs:
1570 let f = attrPath:
1571 zipAttrsWith (n: values:
1572 let here = attrPath ++ [n]; in
1573 if length values == 1
1574 || pred here (elemAt values 1) (head values) then
1575 head values
1576 else
1577 f here values
1578 );
1579 in f [] [rhs lhs];
1580
1581
1582 /**
1583 A recursive variant of the update operator ‘//’. The recursion
1584 stops when one of the attribute values is not an attribute set,
1585 in which case the right hand side value takes precedence over the
1586 left hand side value.
1587
1588
1589 # Inputs
1590
1591 `lhs`
1592
1593 : Left attribute set of the merge.
1594
1595 `rhs`
1596
1597 : Right attribute set of the merge.
1598
1599 # Type
1600
1601 ```
1602 recursiveUpdate :: AttrSet -> AttrSet -> AttrSet
1603 ```
1604
1605 # Examples
1606 :::{.example}
1607 ## `lib.attrsets.recursiveUpdate` usage example
1608
1609 ```nix
1610 recursiveUpdate {
1611 boot.loader.grub.enable = true;
1612 boot.loader.grub.device = "/dev/hda";
1613 } {
1614 boot.loader.grub.device = "";
1615 }
1616
1617 returns: {
1618 boot.loader.grub.enable = true;
1619 boot.loader.grub.device = "";
1620 }
1621 ```
1622
1623 :::
1624 */
1625 recursiveUpdate =
1626 lhs:
1627 rhs:
1628 recursiveUpdateUntil (path: lhs: rhs: !(isAttrs lhs && isAttrs rhs)) lhs rhs;
1629
1630
1631 /**
1632 Recurse into every attribute set of the first argument and check that:
1633 - Each attribute path also exists in the second argument.
1634 - If the attribute's value is not a nested attribute set, it must have the same value in the right argument.
1635
1636
1637 # Inputs
1638
1639 `pattern`
1640
1641 : Attribute set structure to match
1642
1643 `attrs`
1644
1645 : Attribute set to check
1646
1647 # Type
1648
1649 ```
1650 matchAttrs :: AttrSet -> AttrSet -> Bool
1651 ```
1652
1653 # Examples
1654 :::{.example}
1655 ## `lib.attrsets.matchAttrs` usage example
1656
1657 ```nix
1658 matchAttrs { cpu = {}; } { cpu = { bits = 64; }; }
1659 => true
1660 ```
1661
1662 :::
1663 */
1664 matchAttrs =
1665 pattern:
1666 attrs:
1667 assert isAttrs pattern;
1668 all
1669 ( # Compare equality between `pattern` & `attrs`.
1670 attr:
1671 # Missing attr, not equal.
1672 attrs ? ${attr} && (
1673 let
1674 lhs = pattern.${attr};
1675 rhs = attrs.${attr};
1676 in
1677 # If attrset check recursively
1678 if isAttrs lhs then isAttrs rhs && matchAttrs lhs rhs
1679 else lhs == rhs
1680 )
1681 )
1682 (attrNames pattern);
1683
1684 /**
1685 Override only the attributes that are already present in the old set
1686 useful for deep-overriding.
1687
1688
1689 # Inputs
1690
1691 `old`
1692
1693 : Original attribute set
1694
1695 `new`
1696
1697 : Attribute set with attributes to override in `old`.
1698
1699 # Type
1700
1701 ```
1702 overrideExisting :: AttrSet -> AttrSet -> AttrSet
1703 ```
1704
1705 # Examples
1706 :::{.example}
1707 ## `lib.attrsets.overrideExisting` usage example
1708
1709 ```nix
1710 overrideExisting {} { a = 1; }
1711 => {}
1712 overrideExisting { b = 2; } { a = 1; }
1713 => { b = 2; }
1714 overrideExisting { a = 3; b = 2; } { a = 1; }
1715 => { a = 1; b = 2; }
1716 ```
1717
1718 :::
1719 */
1720 overrideExisting =
1721 old:
1722 new:
1723 mapAttrs (name: value: new.${name} or value) old;
1724
1725
1726 /**
1727 Turns a list of strings into a human-readable description of those
1728 strings represented as an attribute path. The result of this function is
1729 not intended to be machine-readable.
1730 Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
1731
1732
1733 # Inputs
1734
1735 `path`
1736
1737 : Attribute path to render to a string
1738
1739 # Type
1740
1741 ```
1742 showAttrPath :: [String] -> String
1743 ```
1744
1745 # Examples
1746 :::{.example}
1747 ## `lib.attrsets.showAttrPath` usage example
1748
1749 ```nix
1750 showAttrPath [ "foo" "10" "bar" ]
1751 => "foo.\"10\".bar"
1752 showAttrPath []
1753 => "<root attribute path>"
1754 ```
1755
1756 :::
1757 */
1758 showAttrPath =
1759 path:
1760 if path == [] then "<root attribute path>"
1761 else concatMapStringsSep "." escapeNixIdentifier path;
1762
1763
1764 /**
1765 Get a package output.
1766 If no output is found, fallback to `.out` and then to the default.
1767
1768
1769 # Inputs
1770
1771 `output`
1772
1773 : 1\. Function argument
1774
1775 `pkg`
1776
1777 : 2\. Function argument
1778
1779 # Type
1780
1781 ```
1782 getOutput :: String -> Derivation -> String
1783 ```
1784
1785 # Examples
1786 :::{.example}
1787 ## `lib.attrsets.getOutput` usage example
1788
1789 ```nix
1790 getOutput "dev" pkgs.openssl
1791 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
1792 ```
1793
1794 :::
1795 */
1796 getOutput = output: pkg:
1797 if ! pkg ? outputSpecified || ! pkg.outputSpecified
1798 then pkg.${output} or pkg.out or pkg
1799 else pkg;
1800
1801 /**
1802 Get a package's `bin` output.
1803 If the output does not exist, fallback to `.out` and then to the default.
1804
1805 # Inputs
1806
1807 `pkg`
1808
1809 : The package whose `bin` output will be retrieved.
1810
1811 # Type
1812
1813 ```
1814 getBin :: Derivation -> String
1815 ```
1816
1817 # Examples
1818 :::{.example}
1819 ## `lib.attrsets.getBin` usage example
1820
1821 ```nix
1822 getBin pkgs.openssl
1823 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r"
1824 ```
1825
1826 :::
1827 */
1828 getBin = getOutput "bin";
1829
1830
1831 /**
1832 Get a package's `lib` output.
1833 If the output does not exist, fallback to `.out` and then to the default.
1834
1835 # Inputs
1836
1837 `pkg`
1838
1839 : The package whose `lib` output will be retrieved.
1840
1841 # Type
1842
1843 ```
1844 getLib :: Derivation -> String
1845 ```
1846
1847 # Examples
1848 :::{.example}
1849 ## `lib.attrsets.getLib` usage example
1850
1851 ```nix
1852 getLib pkgs.openssl
1853 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-lib"
1854 ```
1855
1856 :::
1857 */
1858 getLib = getOutput "lib";
1859
1860
1861 /**
1862 Get a package's `dev` output.
1863 If the output does not exist, fallback to `.out` and then to the default.
1864
1865 # Inputs
1866
1867 `pkg`
1868
1869 : The package whose `dev` output will be retrieved.
1870
1871 # Type
1872
1873 ```
1874 getDev :: Derivation -> String
1875 ```
1876
1877 # Examples
1878 :::{.example}
1879 ## `lib.attrsets.getDev` usage example
1880
1881 ```nix
1882 getDev pkgs.openssl
1883 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
1884 ```
1885
1886 :::
1887 */
1888 getDev = getOutput "dev";
1889
1890
1891 /**
1892 Get a package's `man` output.
1893 If the output does not exist, fallback to `.out` and then to the default.
1894
1895 # Inputs
1896
1897 `pkg`
1898
1899 : The package whose `man` output will be retrieved.
1900
1901 # Type
1902
1903 ```
1904 getMan :: Derivation -> String
1905 ```
1906
1907 # Examples
1908 :::{.example}
1909 ## `lib.attrsets.getMan` usage example
1910
1911 ```nix
1912 getMan pkgs.openssl
1913 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-man"
1914 ```
1915
1916 :::
1917 */
1918 getMan = getOutput "man";
1919
1920 /**
1921 Pick the outputs of packages to place in `buildInputs`
1922
1923 # Inputs
1924
1925 `pkgs`
1926
1927 : List of packages.
1928
1929 # Type
1930
1931 ```
1932 chooseDevOutputs :: [Derivation] -> [String]
1933 ```
1934 */
1935 chooseDevOutputs = builtins.map getDev;
1936
1937 /**
1938 Make various Nix tools consider the contents of the resulting
1939 attribute set when looking for what to build, find, etc.
1940
1941 This function only affects a single attribute set; it does not
1942 apply itself recursively for nested attribute sets.
1943
1944
1945 # Inputs
1946
1947 `attrs`
1948
1949 : An attribute set to scan for derivations.
1950
1951 # Type
1952
1953 ```
1954 recurseIntoAttrs :: AttrSet -> AttrSet
1955 ```
1956
1957 # Examples
1958 :::{.example}
1959 ## `lib.attrsets.recurseIntoAttrs` usage example
1960
1961 ```nix
1962 { pkgs ? import <nixpkgs> {} }:
1963 {
1964 myTools = pkgs.lib.recurseIntoAttrs {
1965 inherit (pkgs) hello figlet;
1966 };
1967 }
1968 ```
1969
1970 :::
1971 */
1972 recurseIntoAttrs =
1973 attrs:
1974 attrs // { recurseForDerivations = true; };
1975
1976 /**
1977 Undo the effect of recurseIntoAttrs.
1978
1979
1980 # Inputs
1981
1982 `attrs`
1983
1984 : An attribute set to not scan for derivations.
1985
1986 # Type
1987
1988 ```
1989 dontRecurseIntoAttrs :: AttrSet -> AttrSet
1990 ```
1991 */
1992 dontRecurseIntoAttrs =
1993 attrs:
1994 attrs // { recurseForDerivations = false; };
1995
1996 /**
1997 `unionOfDisjoint x y` is equal to `x // y // z` where the
1998 attrnames in `z` are the intersection of the attrnames in `x` and
1999 `y`, and all values `assert` with an error message. This
2000 operator is commutative, unlike (//).
2001
2002
2003 # Inputs
2004
2005 `x`
2006
2007 : 1\. Function argument
2008
2009 `y`
2010
2011 : 2\. Function argument
2012
2013 # Type
2014
2015 ```
2016 unionOfDisjoint :: AttrSet -> AttrSet -> AttrSet
2017 ```
2018 */
2019 unionOfDisjoint = x: y:
2020 let
2021 intersection = builtins.intersectAttrs x y;
2022 collisions = lib.concatStringsSep " " (builtins.attrNames intersection);
2023 mask = builtins.mapAttrs (name: value: builtins.throw
2024 "unionOfDisjoint: collision on ${name}; complete list: ${collisions}")
2025 intersection;
2026 in
2027 (x // y) // mask;
2028
2029 # DEPRECATED
2030 zipWithNames = warn
2031 "lib.zipWithNames is a deprecated alias of lib.zipAttrsWithNames." zipAttrsWithNames;
2032
2033 # DEPRECATED
2034 zip = warn
2035 "lib.zip is a deprecated alias of lib.zipAttrsWith." zipAttrsWith;
2036
2037 # DEPRECATED
2038 cartesianProductOfSets = warnIf (isInOldestRelease 2405)
2039 "lib.cartesianProductOfSets is a deprecated alias of lib.cartesianProduct." cartesianProduct;
2040}