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