at 25.11-pre 47 kB view raw
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}