about summary refs log tree commit diff
path: root/nixpkgs/lib
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2024-03-01 11:40:12 +0100
committerAlyssa Ross <hi@alyssa.is>2024-03-01 11:40:12 +0100
commitbf6d657e5dbcb5e39fda280ef7e86b2a7794ca86 (patch)
tree8eb035cbab19794f6415cc460fac7226f7a58afc /nixpkgs/lib
parent66f707d69f1e423db5a35c2fe43b32781125a9af (diff)
parent09c1497ce5d4ed4a0edfdd44450d3048074cb300 (diff)
downloadnixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.tar
nixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.tar.gz
nixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.tar.bz2
nixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.tar.lz
nixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.tar.xz
nixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.tar.zst
nixlib-bf6d657e5dbcb5e39fda280ef7e86b2a7794ca86.zip
Merge branch 'nixos-unstable-small' of https://github.com/NixOS/nixpkgs
Diffstat (limited to 'nixpkgs/lib')
-rw-r--r--nixpkgs/lib/attrsets.nix15
-rw-r--r--nixpkgs/lib/default.nix4
-rw-r--r--nixpkgs/lib/fileset/default.nix37
-rw-r--r--nixpkgs/lib/fileset/internal.nix23
-rwxr-xr-xnixpkgs/lib/fileset/tests.sh124
-rw-r--r--nixpkgs/lib/fixed-points.nix13
-rw-r--r--nixpkgs/lib/lists.nix31
-rw-r--r--nixpkgs/lib/meta.nix8
-rw-r--r--nixpkgs/lib/strings.nix3
-rw-r--r--nixpkgs/lib/tests/release.nix55
-rw-r--r--nixpkgs/lib/tests/test-with-nix.nix70
-rw-r--r--nixpkgs/lib/trivial.nix19
-rw-r--r--nixpkgs/lib/versions.nix2
-rw-r--r--nixpkgs/lib/zip-int-bits.nix39
14 files changed, 236 insertions, 207 deletions
diff --git a/nixpkgs/lib/attrsets.nix b/nixpkgs/lib/attrsets.nix
index 0e896a93156d..4f7d795c397f 100644
--- a/nixpkgs/lib/attrsets.nix
+++ b/nixpkgs/lib/attrsets.nix
@@ -2,10 +2,10 @@
 { lib }:
 
 let
-  inherit (builtins) head tail length;
-  inherit (lib.trivial) id mergeAttrs warn;
+  inherit (builtins) head length;
+  inherit (lib.trivial) mergeAttrs warn;
   inherit (lib.strings) concatStringsSep concatMapStringsSep escapeNixIdentifier sanitizeDerivationName;
-  inherit (lib.lists) foldr foldl' concatMap concatLists elemAt all partition groupBy take foldl;
+  inherit (lib.lists) foldr foldl' concatMap elemAt all partition groupBy take foldl;
 in
 
 rec {
@@ -369,7 +369,7 @@ rec {
      Type:
        attrValues :: AttrSet -> [Any]
   */
-  attrValues = builtins.attrValues or (attrs: attrVals (attrNames attrs) attrs);
+  attrValues = builtins.attrValues;
 
 
   /* Given a set of attribute names, return the set of the corresponding
@@ -398,8 +398,7 @@ rec {
      Type:
        catAttrs :: String -> [AttrSet] -> [Any]
   */
-  catAttrs = builtins.catAttrs or
-    (attr: l: concatLists (map (s: if s ? ${attr} then [s.${attr}] else []) l));
+  catAttrs = builtins.catAttrs;
 
 
   /* Filter an attribute set by removing all attributes for which the
@@ -608,9 +607,7 @@ rec {
      Type:
        mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet
   */
-  mapAttrs = builtins.mapAttrs or
-    (f: set:
-      listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)));
+  mapAttrs = builtins.mapAttrs;
 
 
   /* Like `mapAttrs`, but allows the name of each attribute to be
diff --git a/nixpkgs/lib/default.nix b/nixpkgs/lib/default.nix
index a17307be6e07..668c29640f9f 100644
--- a/nixpkgs/lib/default.nix
+++ b/nixpkgs/lib/default.nix
@@ -84,8 +84,8 @@ let
       mapAttrs' mapAttrsToList attrsToList concatMapAttrs mapAttrsRecursive
       mapAttrsRecursiveCond genAttrs isDerivation toDerivation optionalAttrs
       zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
-      recursiveUpdate matchAttrs overrideExisting showAttrPath getOutput getBin
-      getLib getDev getMan chooseDevOutputs zipWithNames zip
+      recursiveUpdate matchAttrs mergeAttrsList overrideExisting showAttrPath getOutput
+      getBin getLib getDev getMan chooseDevOutputs zipWithNames zip
       recurseIntoAttrs dontRecurseIntoAttrs cartesianProductOfSets
       updateManyAttrsByPath;
     inherit (self.lists) singleton forEach foldr fold foldl foldl' imap0 imap1
diff --git a/nixpkgs/lib/fileset/default.nix b/nixpkgs/lib/fileset/default.nix
index c007b60def0a..ce9afc796a3f 100644
--- a/nixpkgs/lib/fileset/default.nix
+++ b/nixpkgs/lib/fileset/default.nix
@@ -23,6 +23,10 @@
 
     Add files in file sets to the store to use as derivation sources.
 
+  - [`lib.fileset.toList`](#function-library-lib.fileset.toList):
+
+    The list of files contained in a file set.
+
   Combinators:
   - [`lib.fileset.union`](#function-library-lib.fileset.union)/[`lib.fileset.unions`](#function-library-lib.fileset.unions):
 
@@ -102,6 +106,7 @@ let
     _coerceMany
     _toSourceFilter
     _fromSourceFilter
+    _toList
     _unionMany
     _fileFilter
     _printFileset
@@ -412,6 +417,38 @@ in {
         filter = sourceFilter;
       };
 
+
+  /*
+    The list of file paths contained in the given file set.
+
+    :::{.note}
+    This function is strict in the entire file set.
+    This is in contrast with combinators [`lib.fileset.union`](#function-library-lib.fileset.union),
+    [`lib.fileset.intersection`](#function-library-lib.fileset.intersection) and [`lib.fileset.difference`](#function-library-lib.fileset.difference).
+
+    Thus it is recommended to call `toList` on file sets created using the combinators,
+    instead of doing list processing on the result of `toList`.
+    :::
+
+    The resulting list of files can be turned back into a file set using [`lib.fileset.unions`](#function-library-lib.fileset.unions).
+
+    Type:
+      toList :: FileSet -> [ Path ]
+
+    Example:
+      toList ./.
+      [ ./README.md ./Makefile ./src/main.c ./src/main.h ]
+
+      toList (difference ./. ./src)
+      [ ./README.md ./Makefile ]
+  */
+  toList =
+    # The file set whose file paths to return.
+    # This argument can also be a path,
+    # which gets [implicitly coerced to a file set](#sec-fileset-path-coercion).
+    fileset:
+    _toList (_coerce "lib.fileset.toList: Argument" fileset);
+
   /*
     The file set containing all files that are in either of two given file sets.
     This is the same as [`unions`](#function-library-lib.fileset.unions),
diff --git a/nixpkgs/lib/fileset/internal.nix b/nixpkgs/lib/fileset/internal.nix
index f4fcc83e1012..0d97ef174568 100644
--- a/nixpkgs/lib/fileset/internal.nix
+++ b/nixpkgs/lib/fileset/internal.nix
@@ -18,6 +18,7 @@ let
     attrNames
     attrValues
     mapAttrs
+    mapAttrsToList
     optionalAttrs
     zipAttrsWith
     ;
@@ -29,6 +30,7 @@ let
   inherit (lib.lists)
     all
     commonPrefix
+    concatLists
     elemAt
     filter
     findFirst
@@ -539,6 +541,27 @@ rec {
           ${baseNameOf root} = rootPathType;
         };
 
+  # Turns a file set into the list of file paths it includes.
+  # Type: fileset -> [ Path ]
+  _toList = fileset:
+    let
+      recurse = path: tree:
+        if isAttrs tree then
+          concatLists (mapAttrsToList (name: value:
+            recurse (path + "/${name}") value
+          ) tree)
+        else if tree == "directory" then
+          recurse path (readDir path)
+        else if tree == null then
+          [ ]
+        else
+          [ path ];
+    in
+    if fileset._internalIsEmptyWithoutBase then
+      [ ]
+    else
+      recurse fileset._internalBase fileset._internalTree;
+
   # Transforms the filesetTree of a file set to a shorter base path, e.g.
   # _shortenTreeBase [ "foo" ] (_create /foo/bar null)
   # => { bar = null; }
diff --git a/nixpkgs/lib/fileset/tests.sh b/nixpkgs/lib/fileset/tests.sh
index af8338eb7855..405fa04d8e06 100755
--- a/nixpkgs/lib/fileset/tests.sh
+++ b/nixpkgs/lib/fileset/tests.sh
@@ -275,7 +275,6 @@ createTree() {
 # )
 # checkFileset './a' # Pass the fileset as the argument
 checkFileset() {
-    # New subshell so that we can have a separate trap handler, see `trap` below
     local fileset=$1
 
     # Create the tree
@@ -283,16 +282,20 @@ checkFileset() {
 
     # Process the tree into separate arrays for included paths, excluded paths and excluded files.
     local -a included=()
+    local -a includedFiles=()
     local -a excluded=()
     local -a excludedFiles=()
     for p in "${!tree[@]}"; do
         case "${tree[$p]}" in
             1)
                 included+=("$p")
+                # If keys end with a `/` we treat them as directories, otherwise files
+                if [[ ! "$p" =~ /$ ]]; then
+                    includedFiles+=("$p")
+                fi
                 ;;
             0)
                 excluded+=("$p")
-                # If keys end with a `/` we treat them as directories, otherwise files
                 if [[ ! "$p" =~ /$ ]]; then
                     excludedFiles+=("$p")
                 fi
@@ -302,6 +305,10 @@ checkFileset() {
         esac
     done
 
+    # Test that lib.fileset.toList contains exactly the included files.
+    # The /#/./ part prefixes each element with `./`
+    expectEqual "toList ($fileset)" "sort lessThan [ ${includedFiles[*]/#/./} ]"
+
     expression="toSource { root = ./.; fileset = $fileset; }"
 
     # We don't have lambda's in bash unfortunately,
@@ -338,13 +345,17 @@ checkFileset() {
 
 #### Error messages #####
 
+# We're using [[:blank:]] here instead of \s, because only the former is POSIX
+# (see https://pubs.opengroup.org/onlinepubs/007908799/xbd/re.html#tag_007_003_005).
+# And indeed, Darwin's bash only supports the former
+
 # Absolute paths in strings cannot be passed as `root`
 expectFailure 'toSource { root = "/nix/store/foobar"; fileset = ./.; }' 'lib.fileset.toSource: `root` \(/nix/store/foobar\) is a string-like value, but it should be a path instead.
-\s*Paths in strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
+[[:blank:]]*Paths in strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
 
 expectFailure 'toSource { root = cleanSourceWith { src = ./.; }; fileset = ./.; }' 'lib.fileset.toSource: `root` is a `lib.sources`-based value, but it should be a path instead.
-\s*To use a `lib.sources`-based value, convert it to a file set using `lib.fileset.fromSource` and pass it as `fileset`.
-\s*Note that this only works for sources created from paths.'
+[[:blank:]]*To use a `lib.sources`-based value, convert it to a file set using `lib.fileset.fromSource` and pass it as `fileset`.
+[[:blank:]]*Note that this only works for sources created from paths.'
 
 # Only paths are accepted as `root`
 expectFailure 'toSource { root = 10; fileset = ./.; }' 'lib.fileset.toSource: `root` is of type int, but it should be a path instead.'
@@ -354,9 +365,9 @@ mkdir -p {foo,bar}/mock-root
 expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
   toSource { root = ./foo/mock-root; fileset = ./bar/mock-root; }
 ' 'lib.fileset.toSource: Filesystem roots are not the same for `fileset` and `root` \('"$work"'/foo/mock-root\):
-\s*`root`: Filesystem root is "'"$work"'/foo/mock-root"
-\s*`fileset`: Filesystem root is "'"$work"'/bar/mock-root"
-\s*Different filesystem roots are not supported.'
+[[:blank:]]*`root`: Filesystem root is "'"$work"'/foo/mock-root"
+[[:blank:]]*`fileset`: Filesystem root is "'"$work"'/bar/mock-root"
+[[:blank:]]*Different filesystem roots are not supported.'
 rm -rf -- *
 
 # `root` needs to exist
@@ -365,8 +376,8 @@ expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `
 # `root` needs to be a file
 touch a
 expectFailure 'toSource { root = ./a; fileset = ./a; }' 'lib.fileset.toSource: `root` \('"$work"'/a\) is a file, but it should be a directory instead. Potential solutions:
-\s*- If you want to import the file into the store _without_ a containing directory, use string interpolation or `builtins.path` instead of this function.
-\s*- If you want to import the file into the store _with_ a containing directory, set `root` to the containing directory, such as '"$work"', and set `fileset` to the file path.'
+[[:blank:]]*- If you want to import the file into the store _without_ a containing directory, use string interpolation or `builtins.path` instead of this function.
+[[:blank:]]*- If you want to import the file into the store _with_ a containing directory, set `root` to the containing directory, such as '"$work"', and set `fileset` to the file path.'
 rm -rf -- *
 
 # The fileset argument should be evaluated, even if the directory is empty
@@ -375,36 +386,36 @@ expectFailure 'toSource { root = ./.; fileset = abort "This should be evaluated"
 # Only paths under `root` should be able to influence the result
 mkdir a
 expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `fileset` could contain files in '"$work"', which is not under the `root` \('"$work"'/a\). Potential solutions:
-\s*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
-\s*- Set `fileset` to a file set that cannot contain files outside the `root` \('"$work"'/a\). This could change the files included in the result.'
+[[:blank:]]*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
+[[:blank:]]*- Set `fileset` to a file set that cannot contain files outside the `root` \('"$work"'/a\). This could change the files included in the result.'
 rm -rf -- *
 
 # non-regular and non-symlink files cannot be added to the Nix store
 mkfifo a
 expectFailure 'toSource { root = ./.; fileset = ./a; }' 'lib.fileset.toSource: `fileset` contains a file that cannot be added to the store: '"$work"'/a
-\s*This file is neither a regular file nor a symlink, the only file types supported by the Nix store.
-\s*Therefore the file set cannot be added to the Nix store as is. Make sure to not include that file to avoid this error.'
+[[:blank:]]*This file is neither a regular file nor a symlink, the only file types supported by the Nix store.
+[[:blank:]]*Therefore the file set cannot be added to the Nix store as is. Make sure to not include that file to avoid this error.'
 rm -rf -- *
 
 # Path coercion only works for paths
 expectFailure 'toSource { root = ./.; fileset = 10; }' 'lib.fileset.toSource: `fileset` is of type int, but it should be a file set or a path instead.'
 expectFailure 'toSource { root = ./.; fileset = "/some/path"; }' 'lib.fileset.toSource: `fileset` \("/some/path"\) is a string-like value, but it should be a file set or a path instead.
-\s*Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
+[[:blank:]]*Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
 expectFailure 'toSource { root = ./.; fileset = cleanSourceWith { src = ./.; }; }' 'lib.fileset.toSource: `fileset` is a `lib.sources`-based value, but it should be a file set or a path instead.
-\s*To convert a `lib.sources`-based value to a file set you can use `lib.fileset.fromSource`.
-\s*Note that this only works for sources created from paths.'
+[[:blank:]]*To convert a `lib.sources`-based value to a file set you can use `lib.fileset.fromSource`.
+[[:blank:]]*Note that this only works for sources created from paths.'
 
 # Path coercion errors for non-existent paths
 expectFailure 'toSource { root = ./.; fileset = ./a; }' 'lib.fileset.toSource: `fileset` \('"$work"'/a\) is a path that does not exist.
-\s*To create a file set from a path that may not exist, use `lib.fileset.maybeMissing`.'
+[[:blank:]]*To create a file set from a path that may not exist, use `lib.fileset.maybeMissing`.'
 
 # File sets cannot be evaluated directly
 expectFailure 'union ./. ./.' 'lib.fileset: Directly evaluating a file set is not supported.
-\s*To turn it into a usable source, use `lib.fileset.toSource`.
-\s*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
+[[:blank:]]*To turn it into a usable source, use `lib.fileset.toSource`.
+[[:blank:]]*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
 expectFailure '_emptyWithoutBase' 'lib.fileset: Directly evaluating a file set is not supported.
-\s*To turn it into a usable source, use `lib.fileset.toSource`.
-\s*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
+[[:blank:]]*To turn it into a usable source, use `lib.fileset.toSource`.
+[[:blank:]]*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
 
 # Past versions of the internal representation are supported
 expectEqual '_coerce "<tests>: value" { _type = "fileset"; _internalVersion = 0; _internalBase = ./.; }' \
@@ -416,9 +427,9 @@ expectEqual '_coerce "<tests>: value" { _type = "fileset"; _internalVersion = 2;
 
 # Future versions of the internal representation are unsupported
 expectFailure '_coerce "<tests>: value" { _type = "fileset"; _internalVersion = 4; }' '<tests>: value is a file set created from a future version of the file set library with a different internal representation:
-\s*- Internal version of the file set: 4
-\s*- Internal version of the library: 3
-\s*Make sure to update your Nixpkgs to have a newer version of `lib.fileset`.'
+[[:blank:]]*- Internal version of the file set: 4
+[[:blank:]]*- Internal version of the library: 3
+[[:blank:]]*Make sure to update your Nixpkgs to have a newer version of `lib.fileset`.'
 
 # _create followed by _coerce should give the inputs back without any validation
 expectEqual '{
@@ -511,6 +522,19 @@ expectEqual '_toSourceFilter (_create /. { foo = "regular"; }) "/foo" ""' 'true'
 expectEqual '_toSourceFilter (_create /. { foo = null; }) "/foo" ""' 'false'
 
 
+## lib.fileset.toList
+# This function is mainly tested in checkFileset
+
+# The error context for an invalid argument must be correct
+expectFailure 'toList null' 'lib.fileset.toList: Argument is of type null, but it should be a file set or a path instead.'
+
+# Works for the empty fileset
+expectEqual 'toList _emptyWithoutBase' '[ ]'
+
+# Works on empty paths
+expectEqual 'toList ./.' '[ ]'
+
+
 ## lib.fileset.union, lib.fileset.unions
 
 
@@ -519,16 +543,16 @@ mkdir -p {foo,bar}/mock-root
 expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
   toSource { root = ./.; fileset = union ./foo/mock-root ./bar/mock-root; }
 ' 'lib.fileset.union: Filesystem roots are not the same:
-\s*First argument: Filesystem root is "'"$work"'/foo/mock-root"
-\s*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
-\s*Different filesystem roots are not supported.'
+[[:blank:]]*First argument: Filesystem root is "'"$work"'/foo/mock-root"
+[[:blank:]]*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
+[[:blank:]]*Different filesystem roots are not supported.'
 
 expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
   toSource { root = ./.; fileset = unions [ ./foo/mock-root ./bar/mock-root ]; }
 ' 'lib.fileset.unions: Filesystem roots are not the same:
-\s*Element 0: Filesystem root is "'"$work"'/foo/mock-root"
-\s*Element 1: Filesystem root is "'"$work"'/bar/mock-root"
-\s*Different filesystem roots are not supported.'
+[[:blank:]]*Element 0: Filesystem root is "'"$work"'/foo/mock-root"
+[[:blank:]]*Element 1: Filesystem root is "'"$work"'/bar/mock-root"
+[[:blank:]]*Different filesystem roots are not supported.'
 rm -rf -- *
 
 # Coercion errors show the correct context
@@ -632,9 +656,9 @@ mkdir -p {foo,bar}/mock-root
 expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
   toSource { root = ./.; fileset = intersection ./foo/mock-root ./bar/mock-root; }
 ' 'lib.fileset.intersection: Filesystem roots are not the same:
-\s*First argument: Filesystem root is "'"$work"'/foo/mock-root"
-\s*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
-\s*Different filesystem roots are not supported.'
+[[:blank:]]*First argument: Filesystem root is "'"$work"'/foo/mock-root"
+[[:blank:]]*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
+[[:blank:]]*Different filesystem roots are not supported.'
 rm -rf -- *
 
 # Coercion errors show the correct context
@@ -741,8 +765,8 @@ rm -rf -- *
 # Also not the other way around
 mkdir a
 expectFailure 'toSource { root = ./a; fileset = difference ./. ./a; }' 'lib.fileset.toSource: `fileset` could contain files in '"$work"', which is not under the `root` \('"$work"'/a\). Potential solutions:
-\s*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
-\s*- Set `fileset` to a file set that cannot contain files outside the `root` \('"$work"'/a\). This could change the files included in the result.'
+[[:blank:]]*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
+[[:blank:]]*- Set `fileset` to a file set that cannot contain files outside the `root` \('"$work"'/a\). This could change the files included in the result.'
 rm -rf -- *
 
 # Difference actually works
@@ -819,7 +843,7 @@ expectFailure 'fileFilter null (abort "this is not needed")' 'lib.fileset.fileFi
 
 # The second argument needs to be an existing path
 expectFailure 'fileFilter (file: abort "this is not needed") _emptyWithoutBase' 'lib.fileset.fileFilter: Second argument is a file set, but it should be a path instead.
-\s*If you need to filter files in a file set, use `intersection fileset \(fileFilter pred \./\.\)` instead.'
+[[:blank:]]*If you need to filter files in a file set, use `intersection fileset \(fileFilter pred \./\.\)` instead.'
 expectFailure 'fileFilter (file: abort "this is not needed") null' 'lib.fileset.fileFilter: Second argument is of type null, but it should be a path instead.'
 expectFailure 'fileFilter (file: abort "this is not needed") ./a' 'lib.fileset.fileFilter: Second argument \('"$work"'/a\) is a path that does not exist.'
 
@@ -1083,7 +1107,7 @@ rm -rf -- *
 
 # String-like values are not supported
 expectFailure 'fromSource (lib.cleanSource "")' 'lib.fileset.fromSource: The source origin of the argument is a string-like value \(""\), but it should be a path instead.
-\s*Sources created from paths in strings cannot be turned into file sets, use `lib.sources` or derivations instead.'
+[[:blank:]]*Sources created from paths in strings cannot be turned into file sets, use `lib.sources` or derivations instead.'
 
 # Wrong type
 expectFailure 'fromSource null' 'lib.fileset.fromSource: The source origin of the argument is of type null, but it should be a path instead.'
@@ -1400,10 +1424,10 @@ expectEqual '(import '"$storePath"' { fs = lib.fileset; }).outPath' \""$storePat
 
 ## But it fails if the path is imported with a fetcher that doesn't remove .git (like just using "${./.}")
 expectFailure 'import "${./.}" { fs = lib.fileset; }' 'lib.fileset.gitTracked: The argument \(.*\) is a store path within a working tree of a Git repository.
-\s*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
-\s*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
-\s*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
-\s*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
+[[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
+[[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
+[[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
+[[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
 
 ## Even with submodules
 if [[ -n "$fetchGitSupportsSubmodules" ]]; then
@@ -1427,15 +1451,15 @@ if [[ -n "$fetchGitSupportsSubmodules" ]]; then
 
     ## But it fails if the path is imported with a fetcher that doesn't remove .git (like just using "${./.}")
     expectFailure 'import "${./.}" { fs = lib.fileset; }' 'lib.fileset.gitTrackedWith: The second argument \(.*\) is a store path within a working tree of a Git repository.
-    \s*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
-    \s*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
-    \s*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
-    \s*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
+    [[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
+    [[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
+    [[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
+    [[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
     expectFailure 'import "${./.}/sub" { fs = lib.fileset; }' 'lib.fileset.gitTracked: The argument \(.*/sub\) is a store path within a working tree of a Git repository.
-    \s*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
-    \s*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
-    \s*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
-    \s*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
+    [[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
+    [[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
+    [[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
+    [[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
 fi
 rm -rf -- *
 
diff --git a/nixpkgs/lib/fixed-points.nix b/nixpkgs/lib/fixed-points.nix
index 3370b55a4ab9..3bd18fdd2a5a 100644
--- a/nixpkgs/lib/fixed-points.nix
+++ b/nixpkgs/lib/fixed-points.nix
@@ -145,6 +145,12 @@ rec {
     in fix g
     ```
 
+    :::{.note}
+    The argument to the given fixed-point function after applying an overlay will *not* refer to its own return value, but rather to the value after evaluating the overlay function.
+
+    The given fixed-point function is called with a separate argument than if it was evaluated with `lib.fix`.
+    :::
+
     :::{.example}
 
     # Extend a fixed-point function with an overlay
@@ -230,13 +236,6 @@ rec {
 
       fix (extends (final: prev: { c = final.a + final.b; }) f)
       => { a = 1; b = 3; c = 4; }
-
-    :::{.note}
-    The argument to the given fixed-point function after applying an overlay will *not* refer to its own return value, but rather to the value after evaluating the overlay function.
-
-    The given fixed-point function is called with a separate argument than if it was evaluated with `lib.fix`.
-    The new argument
-    :::
   */
   extends =
     # The overlay to apply to the fixed-point function
diff --git a/nixpkgs/lib/lists.nix b/nixpkgs/lib/lists.nix
index b612bc16697e..05216c1a66eb 100644
--- a/nixpkgs/lib/lists.nix
+++ b/nixpkgs/lib/lists.nix
@@ -4,7 +4,6 @@ let
   inherit (lib.strings) toInt;
   inherit (lib.trivial) compare min id warn;
   inherit (lib.attrsets) mapAttrs;
-  inherit (lib.lists) sort;
 in
 rec {
 
@@ -172,7 +171,7 @@ rec {
        concatMap (x: [x] ++ ["z"]) ["a" "b"]
        => [ "a" "z" "b" "z" ]
   */
-  concatMap = builtins.concatMap or (f: list: concatLists (map f list));
+  concatMap = builtins.concatMap;
 
   /* Flatten the argument into a single list; that is, nested lists are
      spliced into the top-level lists.
@@ -316,7 +315,7 @@ rec {
        any isString [ 1 { } ]
        => false
   */
-  any = builtins.any or (pred: foldr (x: y: if pred x then true else y) false);
+  any = builtins.any;
 
   /* Return true if function `pred` returns true for all elements of
      `list`.
@@ -329,7 +328,7 @@ rec {
        all (x: x < 3) [ 1 2 3 ]
        => false
   */
-  all = builtins.all or (pred: foldr (x: y: if pred x then y else false) true);
+  all = builtins.all;
 
   /* Count how many elements of `list` match the supplied predicate
      function.
@@ -428,12 +427,7 @@ rec {
        partition (x: x > 2) [ 5 1 2 3 4 ]
        => { right = [ 5 3 4 ]; wrong = [ 1 2 ]; }
   */
-  partition = builtins.partition or (pred:
-    foldr (h: t:
-      if pred h
-      then { right = [h] ++ t.right; wrong = t.wrong; }
-      else { right = t.right; wrong = [h] ++ t.wrong; }
-    ) { right = []; wrong = []; });
+  partition = builtins.partition;
 
   /* Splits the elements of a list into many lists, using the return value of a predicate.
      Predicate should return a string which becomes keys of attrset `groupBy` returns.
@@ -602,22 +596,7 @@ rec {
      Type:
        sort :: (a -> a -> Bool) -> [a] -> [a]
   */
-  sort = builtins.sort or (
-    strictLess: list:
-    let
-      len = length list;
-      first = head list;
-      pivot' = n: acc@{ left, right }: let el = elemAt list n; next = pivot' (n + 1); in
-        if n == len
-          then acc
-        else if strictLess first el
-          then next { inherit left; right = [ el ] ++ right; }
-        else
-          next { left = [ el ] ++ left; inherit right; };
-      pivot = pivot' 1 { left = []; right = []; };
-    in
-      if len < 2 then list
-      else (sort strictLess pivot.left) ++  [ first ] ++  (sort strictLess pivot.right));
+  sort = builtins.sort;
 
   /*
     Sort a list based on the default comparison of a derived property `b`.
diff --git a/nixpkgs/lib/meta.nix b/nixpkgs/lib/meta.nix
index 5d5f71d6c3cb..675e1912d4be 100644
--- a/nixpkgs/lib/meta.nix
+++ b/nixpkgs/lib/meta.nix
@@ -87,6 +87,10 @@ rec {
 
      We can inject these into a pattern for the whole of a structured platform,
      and then match that.
+
+     Example:
+      lib.meta.platformMatch { system = "aarch64-darwin"; } "aarch64-darwin"
+      => true
   */
   platformMatch = platform: elem: (
     # Check with simple string comparison if elem was a string.
@@ -112,6 +116,10 @@ rec {
           platform, or `meta.platforms` is not present.
 
        2. None of `meta.badPlatforms` pattern matches the given platform.
+
+     Example:
+       lib.meta.availableOn { system = "aarch64-darwin"; } pkg.zsh
+       => true
   */
   availableOn = platform: pkg:
     ((!pkg?meta.platforms) || any (platformMatch platform) pkg.meta.platforms) &&
diff --git a/nixpkgs/lib/strings.nix b/nixpkgs/lib/strings.nix
index 7083576dd529..47ee095f1b68 100644
--- a/nixpkgs/lib/strings.nix
+++ b/nixpkgs/lib/strings.nix
@@ -95,8 +95,7 @@ rec {
         concatStringsSep "/" ["usr" "local" "bin"]
         => "usr/local/bin"
   */
-  concatStringsSep = builtins.concatStringsSep or (separator: list:
-    lib.foldl' (x: y: x + y) "" (intersperse separator list));
+  concatStringsSep = builtins.concatStringsSep;
 
   /* Maps a function over a list of strings and then concatenates the
      result with the specified separator interspersed between
diff --git a/nixpkgs/lib/tests/release.nix b/nixpkgs/lib/tests/release.nix
index 96d34be8c2d3..5b2a9df1635c 100644
--- a/nixpkgs/lib/tests/release.nix
+++ b/nixpkgs/lib/tests/release.nix
@@ -9,60 +9,7 @@
 let
   lib = import ../.;
   testWithNix = nix:
-    pkgs.runCommand "nixpkgs-lib-tests-nix-${nix.version}" {
-      buildInputs = [
-        (import ./check-eval.nix)
-        (import ./maintainers.nix {
-          inherit pkgs;
-          lib = import ../.;
-        })
-        (import ./teams.nix {
-          inherit pkgs;
-          lib = import ../.;
-        })
-        (import ../path/tests {
-          inherit pkgs;
-        })
-      ];
-      nativeBuildInputs = [
-        nix
-        pkgs.gitMinimal
-      ] ++ lib.optional pkgs.stdenv.isLinux pkgs.inotify-tools;
-      strictDeps = true;
-    } ''
-      datadir="${nix}/share"
-      export TEST_ROOT=$(pwd)/test-tmp
-      export HOME=$(mktemp -d)
-      export NIX_BUILD_HOOK=
-      export NIX_CONF_DIR=$TEST_ROOT/etc
-      export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
-      export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
-      export NIX_STATE_DIR=$TEST_ROOT/var/nix
-      export NIX_STORE_DIR=$TEST_ROOT/store
-      export PAGER=cat
-      cacheDir=$TEST_ROOT/binary-cache
-
-      nix-store --init
-
-      cp -r ${../.} lib
-      echo "Running lib/tests/modules.sh"
-      bash lib/tests/modules.sh
-
-      echo "Running lib/tests/filesystem.sh"
-      TEST_LIB=$PWD/lib bash lib/tests/filesystem.sh
-
-      echo "Running lib/tests/sources.sh"
-      TEST_LIB=$PWD/lib bash lib/tests/sources.sh
-
-      echo "Running lib/fileset/tests.sh"
-      TEST_LIB=$PWD/lib bash lib/fileset/tests.sh
-
-      echo "Running lib/tests/systems.nix"
-      [[ $(nix-instantiate --eval --strict lib/tests/systems.nix | tee /dev/stderr) == '[ ]' ]];
-
-      mkdir $out
-      echo success > $out/${nix.version}
-    '';
+    import ./test-with-nix.nix { inherit lib nix pkgs; };
 
 in
   pkgs.symlinkJoin {
diff --git a/nixpkgs/lib/tests/test-with-nix.nix b/nixpkgs/lib/tests/test-with-nix.nix
new file mode 100644
index 000000000000..fd2e7532e697
--- /dev/null
+++ b/nixpkgs/lib/tests/test-with-nix.nix
@@ -0,0 +1,70 @@
+/**
+ * Instantiate the library tests for a given Nix version.
+ *
+ * IMPORTANT:
+ * This is used by the github.com/NixOS/nix CI.
+ *
+ * Try not to change the interface of this file, or if you need to, ping the
+ * Nix maintainers for help. Thank you!
+ */
+{
+  pkgs,
+  lib,
+  # Only ever use this nix; see comment at top
+  nix,
+}:
+
+pkgs.runCommand "nixpkgs-lib-tests-nix-${nix.version}" {
+  buildInputs = [
+    (import ./check-eval.nix)
+    (import ./maintainers.nix {
+      inherit pkgs;
+      lib = import ../.;
+    })
+    (import ./teams.nix {
+      inherit pkgs;
+      lib = import ../.;
+    })
+    (import ../path/tests {
+      inherit pkgs;
+    })
+  ];
+  nativeBuildInputs = [
+    nix
+    pkgs.gitMinimal
+  ] ++ lib.optional pkgs.stdenv.isLinux pkgs.inotify-tools;
+  strictDeps = true;
+} ''
+  datadir="${nix}/share"
+  export TEST_ROOT=$(pwd)/test-tmp
+  export HOME=$(mktemp -d)
+  export NIX_BUILD_HOOK=
+  export NIX_CONF_DIR=$TEST_ROOT/etc
+  export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
+  export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
+  export NIX_STATE_DIR=$TEST_ROOT/var/nix
+  export NIX_STORE_DIR=$TEST_ROOT/store
+  export PAGER=cat
+  cacheDir=$TEST_ROOT/binary-cache
+
+  nix-store --init
+
+  cp -r ${../.} lib
+  echo "Running lib/tests/modules.sh"
+  bash lib/tests/modules.sh
+
+  echo "Running lib/tests/filesystem.sh"
+  TEST_LIB=$PWD/lib bash lib/tests/filesystem.sh
+
+  echo "Running lib/tests/sources.sh"
+  TEST_LIB=$PWD/lib bash lib/tests/sources.sh
+
+  echo "Running lib/fileset/tests.sh"
+  TEST_LIB=$PWD/lib bash lib/fileset/tests.sh
+
+  echo "Running lib/tests/systems.nix"
+  [[ $(nix-instantiate --eval --strict lib/tests/systems.nix | tee /dev/stderr) == '[ ]' ]];
+
+  mkdir $out
+  echo success > $out/${nix.version}
+''
diff --git a/nixpkgs/lib/trivial.nix b/nixpkgs/lib/trivial.nix
index 58620006de15..fa499cbbf028 100644
--- a/nixpkgs/lib/trivial.nix
+++ b/nixpkgs/lib/trivial.nix
@@ -95,21 +95,6 @@ in {
   /* boolean “and” */
   and = x: y: x && y;
 
-  /* bitwise “and” */
-  bitAnd = builtins.bitAnd
-    or (import ./zip-int-bits.nix
-        (a: b: if a==1 && b==1 then 1 else 0));
-
-  /* bitwise “or” */
-  bitOr = builtins.bitOr
-    or (import ./zip-int-bits.nix
-        (a: b: if a==1 || b==1 then 1 else 0));
-
-  /* bitwise “xor” */
-  bitXor = builtins.bitXor
-    or (import ./zip-int-bits.nix
-        (a: b: if a!=b then 1 else 0));
-
   /* bitwise “not” */
   bitNot = builtins.sub (-1);
 
@@ -165,8 +150,8 @@ in {
   inherit (builtins)
     pathExists readFile isBool
     isInt isFloat add sub lessThan
-    seq deepSeq genericClosure;
-
+    seq deepSeq genericClosure
+    bitAnd bitOr bitXor;
 
   ## nixpkgs version strings
 
diff --git a/nixpkgs/lib/versions.nix b/nixpkgs/lib/versions.nix
index 986e7e5f9b37..720d19e8ca29 100644
--- a/nixpkgs/lib/versions.nix
+++ b/nixpkgs/lib/versions.nix
@@ -9,7 +9,7 @@ rec {
        splitVersion "1.2.3"
        => ["1" "2" "3"]
   */
-  splitVersion = builtins.splitVersion or (lib.splitString ".");
+  splitVersion = builtins.splitVersion;
 
   /* Get the major version string from a string.
 
diff --git a/nixpkgs/lib/zip-int-bits.nix b/nixpkgs/lib/zip-int-bits.nix
deleted file mode 100644
index 53efd2bb0a04..000000000000
--- a/nixpkgs/lib/zip-int-bits.nix
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Helper function to implement a fallback for the bit operators
-   `bitAnd`, `bitOr` and `bitXor` on older nix version.
-   See ./trivial.nix
-*/
-f: x: y:
-  let
-    # (intToBits 6) -> [ 0 1 1 ]
-    intToBits = x:
-      if x == 0 || x == -1 then
-        []
-      else
-        let
-          headbit  = if (x / 2) * 2 != x then 1 else 0;          # x & 1
-          tailbits = if x < 0 then ((x + 1) / 2) - 1 else x / 2; # x >> 1
-        in
-          [headbit] ++ (intToBits tailbits);
-
-    # (bitsToInt [ 0 1 1 ] 0) -> 6
-    # (bitsToInt [ 0 1 0 ] 1) -> -6
-    bitsToInt = l: signum:
-      if l == [] then
-        (if signum == 0 then 0 else -1)
-      else
-        (builtins.head l) + (2 * (bitsToInt (builtins.tail l) signum));
-
-    xsignum = if x < 0 then 1 else 0;
-    ysignum = if y < 0 then 1 else 0;
-    zipListsWith' = fst: snd:
-      if fst==[] && snd==[] then
-        []
-      else if fst==[] then
-        [(f xsignum             (builtins.head snd))] ++ (zipListsWith' []                  (builtins.tail snd))
-      else if snd==[] then
-        [(f (builtins.head fst) ysignum            )] ++ (zipListsWith' (builtins.tail fst) []                 )
-      else
-        [(f (builtins.head fst) (builtins.head snd))] ++ (zipListsWith' (builtins.tail fst) (builtins.tail snd));
-  in
-    assert (builtins.isInt x) && (builtins.isInt y);
-    bitsToInt (zipListsWith' (intToBits x) (intToBits y)) (f xsignum ysignum)