about summary refs log tree commit diff
path: root/nixpkgs/lib
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2023-10-30 13:37:39 +0100
committerAlyssa Ross <hi@alyssa.is>2023-10-30 13:37:39 +0100
commit7e0c8fe656bbc2fcbdfc3e03a367d2c6ff389769 (patch)
tree38e753812c0ceba947d65ec0555a5a66c1a5aa4e /nixpkgs/lib
parent46cf147fc42b72f68ecd52b3b03a8bfd6077f42b (diff)
parent63678e9f3d3afecfeafa0acead6239cdb447574c (diff)
downloadnixlib-7e0c8fe656bbc2fcbdfc3e03a367d2c6ff389769.tar
nixlib-7e0c8fe656bbc2fcbdfc3e03a367d2c6ff389769.tar.gz
nixlib-7e0c8fe656bbc2fcbdfc3e03a367d2c6ff389769.tar.bz2
nixlib-7e0c8fe656bbc2fcbdfc3e03a367d2c6ff389769.tar.lz
nixlib-7e0c8fe656bbc2fcbdfc3e03a367d2c6ff389769.tar.xz
nixlib-7e0c8fe656bbc2fcbdfc3e03a367d2c6ff389769.tar.zst
nixlib-7e0c8fe656bbc2fcbdfc3e03a367d2c6ff389769.zip
Merge commit '63678e9f3d3afecfeafa0acead6239cdb447574c' into HEAD
Conflicts:
	nixpkgs/pkgs/build-support/rust/build-rust-package/default.nix
Diffstat (limited to 'nixpkgs/lib')
-rw-r--r--nixpkgs/lib/customisation.nix88
-rw-r--r--nixpkgs/lib/fileset/default.nix51
-rw-r--r--nixpkgs/lib/fileset/internal.nix26
-rwxr-xr-xnixpkgs/lib/fileset/tests.sh67
-rw-r--r--nixpkgs/lib/systems/parse.nix11
5 files changed, 223 insertions, 20 deletions
diff --git a/nixpkgs/lib/customisation.nix b/nixpkgs/lib/customisation.nix
index 5ef4f29e6f6a..61bb531d2f62 100644
--- a/nixpkgs/lib/customisation.nix
+++ b/nixpkgs/lib/customisation.nix
@@ -13,16 +13,7 @@ rec {
      scenarios (e.g. in ~/.config/nixpkgs/config.nix).  For instance,
      if you want to "patch" the derivation returned by a package
      function in Nixpkgs to build another version than what the
-     function itself provides, you can do something like this:
-
-       mySed = overrideDerivation pkgs.gnused (oldAttrs: {
-         name = "sed-4.2.2-pre";
-         src = fetchurl {
-           url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2;
-           hash = "sha256-MxBJRcM2rYzQYwJ5XKxhXTQByvSg5jZc5cSHEZoB2IY=";
-         };
-         patches = [];
-       });
+     function itself provides.
 
      For another application, see build-support/vm, where this
      function is used to build arbitrary derivations inside a QEMU
@@ -35,6 +26,19 @@ rec {
 
      You should in general prefer `drv.overrideAttrs` over this function;
      see the nixpkgs manual for more information on overriding.
+
+     Example:
+       mySed = overrideDerivation pkgs.gnused (oldAttrs: {
+         name = "sed-4.2.2-pre";
+         src = fetchurl {
+           url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2;
+           hash = "sha256-MxBJRcM2rYzQYwJ5XKxhXTQByvSg5jZc5cSHEZoB2IY=";
+         };
+         patches = [];
+       });
+
+     Type:
+       overrideDerivation :: Derivation -> ( Derivation -> AttrSet ) -> Derivation
   */
   overrideDerivation = drv: f:
     let
@@ -55,6 +59,10 @@ rec {
      injects `override` attribute which can be used to override arguments of
      the function.
 
+     Please refer to  documentation on [`<pkg>.overrideDerivation`](#sec-pkg-overrideDerivation) to learn about `overrideDerivation` and caveats
+     related to its use.
+
+     Example:
        nix-repl> x = {a, b}: { result = a + b; }
 
        nix-repl> y = lib.makeOverridable x { a = 1; b = 2; }
@@ -65,9 +73,8 @@ rec {
        nix-repl> y.override { a = 10; }
        { override = «lambda»; overrideDerivation = «lambda»; result = 12; }
 
-     Please refer to "Nixpkgs Contributors Guide" section
-     "<pkg>.overrideDerivation" to learn about `overrideDerivation` and caveats
-     related to its use.
+     Type:
+       makeOverridable :: (AttrSet -> a) -> AttrSet -> a
   */
   makeOverridable = f: lib.setFunctionArgs
     (origArgs: let
@@ -105,20 +112,29 @@ rec {
     `autoArgs`.  This function is intended to be partially
     parameterised, e.g.,
 
+      ```nix
       callPackage = callPackageWith pkgs;
       pkgs = {
         libfoo = callPackage ./foo.nix { };
         libbar = callPackage ./bar.nix { };
       };
+      ```
 
     If the `libbar` function expects an argument named `libfoo`, it is
     automatically passed as an argument.  Overrides or missing
     arguments can be supplied in `args`, e.g.
 
+      ```nix
       libbar = callPackage ./bar.nix {
         libfoo = null;
         enableX11 = true;
       };
+      ```
+
+    <!-- TODO: Apply "Example:" tag to the examples above -->
+
+    Type:
+      callPackageWith :: AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a
   */
   callPackageWith = autoArgs: fn: args:
     let
@@ -129,7 +145,7 @@ rec {
       # This includes automatic ones and ones passed explicitly
       allArgs = builtins.intersectAttrs fargs autoArgs // args;
 
-      # A list of argument names that the function requires, but
+      # a list of argument names that the function requires, but
       # wouldn't be passed to it
       missingArgs = lib.attrNames
         # Filter out arguments that have a default value
@@ -176,7 +192,11 @@ rec {
 
   /* Like callPackage, but for a function that returns an attribute
      set of derivations. The override function is added to the
-     individual attributes. */
+     individual attributes.
+
+     Type:
+       callPackagesWith :: AttrSet -> ((AttrSet -> AttrSet) | Path) -> AttrSet -> AttrSet
+  */
   callPackagesWith = autoArgs: fn: args:
     let
       f = if lib.isFunction fn then fn else import fn;
@@ -193,7 +213,11 @@ rec {
 
 
   /* Add attributes to each output of a derivation without changing
-     the derivation itself and check a given condition when evaluating. */
+     the derivation itself and check a given condition when evaluating.
+
+     Type:
+       extendDerivation :: Bool -> Any -> Derivation -> Derivation
+  */
   extendDerivation = condition: passthru: drv:
     let
       outputs = drv.outputs or [ "out" ];
@@ -227,7 +251,11 @@ rec {
   /* Strip a derivation of all non-essential attributes, returning
      only those needed by hydra-eval-jobs. Also strictly evaluate the
      result to ensure that there are no thunks kept alive to prevent
-     garbage collection. */
+     garbage collection.
+
+     Type:
+       hydraJob :: (Derivation | Null) -> (Derivation | Null)
+  */
   hydraJob = drv:
     let
       outputs = drv.outputs or ["out"];
@@ -265,7 +293,11 @@ rec {
      called with the overridden packages. The package sets may be
      hierarchical: the packages in the set are called with the scope
      provided by `newScope` and the set provides a `newScope` attribute
-     which can form the parent scope for later package sets. */
+     which can form the parent scope for later package sets.
+
+     Type:
+       makeScope :: (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a) -> (AttrSet -> AttrSet) -> AttrSet
+  */
   makeScope = newScope: f:
     let self = f self // {
           newScope = scope: newScope (self // scope);
@@ -287,7 +319,25 @@ rec {
     { inherit otherSplices keep extra f; };
 
   /* Like makeScope, but aims to support cross compilation. It's still ugly, but
-     hopefully it helps a little bit. */
+     hopefully it helps a little bit.
+
+     Type:
+       makeScopeWithSplicing' ::
+         { splicePackages :: Splice -> AttrSet
+         , newScope :: AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a
+         }
+         -> { otherSplices :: Splice, keep :: AttrSet -> AttrSet, extra :: AttrSet -> AttrSet }
+         -> AttrSet
+
+       Splice ::
+         { pkgsBuildBuild :: AttrSet
+         , pkgsBuildHost :: AttrSet
+         , pkgsBuildTarget :: AttrSet
+         , pkgsHostHost :: AttrSet
+         , pkgsHostTarget :: AttrSet
+         , pkgsTargetTarget :: AttrSet
+         }
+  */
   makeScopeWithSplicing' =
     { splicePackages
     , newScope
diff --git a/nixpkgs/lib/fileset/default.nix b/nixpkgs/lib/fileset/default.nix
index 7bd701670386..0342be3e0371 100644
--- a/nixpkgs/lib/fileset/default.nix
+++ b/nixpkgs/lib/fileset/default.nix
@@ -6,6 +6,7 @@ let
     _coerceMany
     _toSourceFilter
     _unionMany
+    _fileFilter
     _printFileset
     _intersection
     ;
@@ -41,6 +42,7 @@ let
     ;
 
   inherit (lib.trivial)
+    isFunction
     pipe
     ;
 
@@ -279,6 +281,55 @@ If a directory does not recursively contain any file, it is omitted from the sto
       ];
 
   /*
+    Filter a file set to only contain files matching some predicate.
+
+    Type:
+      fileFilter ::
+        ({
+          name :: String,
+          type :: String,
+          ...
+        } -> Bool)
+        -> FileSet
+        -> FileSet
+
+    Example:
+      # Include all regular `default.nix` files in the current directory
+      fileFilter (file: file.name == "default.nix") ./.
+
+      # Include all non-Nix files from the current directory
+      fileFilter (file: ! hasSuffix ".nix" file.name) ./.
+
+      # Include all files that start with a "." in the current directory
+      fileFilter (file: hasPrefix "." file.name) ./.
+
+      # Include all regular files (not symlinks or others) in the current directory
+      fileFilter (file: file.type == "regular")
+  */
+  fileFilter =
+    /*
+      The predicate function to call on all files contained in given file set.
+      A file is included in the resulting file set if this function returns true for it.
+
+      This function is called with an attribute set containing these attributes:
+
+      - `name` (String): The name of the file
+
+      - `type` (String, one of `"regular"`, `"symlink"` or `"unknown"`): The type of the file.
+        This matches result of calling [`builtins.readFileType`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-readFileType) on the file's path.
+
+      Other attributes may be added in the future.
+    */
+    predicate:
+    # The file set to filter based on the predicate function
+    fileset:
+    if ! isFunction predicate then
+      throw "lib.fileset.fileFilter: Expected the first argument to be a function, but it's a ${typeOf predicate} instead."
+    else
+      _fileFilter predicate
+        (_coerce "lib.fileset.fileFilter: second argument" fileset);
+
+  /*
     The file set containing all files that are in both of two given file sets.
     See also [Intersection (set theory)](https://en.wikipedia.org/wiki/Intersection_(set_theory)).
 
diff --git a/nixpkgs/lib/fileset/internal.nix b/nixpkgs/lib/fileset/internal.nix
index 9892172955c3..2d52a8cb410b 100644
--- a/nixpkgs/lib/fileset/internal.nix
+++ b/nixpkgs/lib/fileset/internal.nix
@@ -638,4 +638,30 @@ rec {
     else
       # In all other cases it's the rhs
       rhs;
+
+  _fileFilter = predicate: fileset:
+    let
+      recurse = path: tree:
+        mapAttrs (name: subtree:
+          if isAttrs subtree || subtree == "directory" then
+            recurse (path + "/${name}") subtree
+          else if
+            predicate {
+              inherit name;
+              type = subtree;
+              # To ensure forwards compatibility with more arguments being added in the future,
+              # adding an attribute which can't be deconstructed :)
+              "lib.fileset.fileFilter: The predicate function passed as the first argument must be able to handle extra attributes for future compatibility. If you're using `{ name, file }:`, use `{ name, file, ... }:` instead." = null;
+            }
+          then
+            subtree
+          else
+            null
+        ) (_directoryEntries path tree);
+    in
+    if fileset._internalIsEmptyWithoutBase then
+      _emptyWithoutBase
+    else
+      _create fileset._internalBase
+        (recurse fileset._internalBase fileset._internalTree);
 }
diff --git a/nixpkgs/lib/fileset/tests.sh b/nixpkgs/lib/fileset/tests.sh
index 529f23ae8871..d8d8dd413189 100755
--- a/nixpkgs/lib/fileset/tests.sh
+++ b/nixpkgs/lib/fileset/tests.sh
@@ -678,6 +678,73 @@ tree=(
 checkFileset 'intersection (unions [ ./a/b ./c/d ./c/e ]) (unions [ ./a ./c/d/f ./c/e ])'
 
 
+## File filter
+
+# The predicate is not called when there's no files
+tree=()
+checkFileset 'fileFilter (file: abort "this is not needed") ./.'
+checkFileset 'fileFilter (file: abort "this is not needed") _emptyWithoutBase'
+
+# The predicate must be able to handle extra attributes
+touch a
+expectFailure 'toSource { root = ./.; fileset = fileFilter ({ name, type }: true) ./.; }' 'called with unexpected argument '\''"lib.fileset.fileFilter: The predicate function passed as the first argument must be able to handle extra attributes for future compatibility. If you'\''re using `\{ name, file \}:`, use `\{ name, file, ... \}:` instead."'\'
+rm -rf -- *
+
+# .name is the name, and it works correctly, even recursively
+tree=(
+    [a]=1
+    [b]=0
+    [c/a]=1
+    [c/b]=0
+    [d/c/a]=1
+    [d/c/b]=0
+)
+checkFileset 'fileFilter (file: file.name == "a") ./.'
+tree=(
+    [a]=0
+    [b]=1
+    [c/a]=0
+    [c/b]=1
+    [d/c/a]=0
+    [d/c/b]=1
+)
+checkFileset 'fileFilter (file: file.name != "a") ./.'
+
+# `.type` is the file type
+mkdir d
+touch d/a
+ln -s d/b d/b
+mkfifo d/c
+expectEqual \
+    'toSource { root = ./.; fileset = fileFilter (file: file.type == "regular") ./.; }' \
+    'toSource { root = ./.; fileset = ./d/a; }'
+expectEqual \
+    'toSource { root = ./.; fileset = fileFilter (file: file.type == "symlink") ./.; }' \
+    'toSource { root = ./.; fileset = ./d/b; }'
+expectEqual \
+    'toSource { root = ./.; fileset = fileFilter (file: file.type == "unknown") ./.; }' \
+    'toSource { root = ./.; fileset = ./d/c; }'
+expectEqual \
+    'toSource { root = ./.; fileset = fileFilter (file: file.type != "regular") ./.; }' \
+    'toSource { root = ./.; fileset = union ./d/b ./d/c; }'
+expectEqual \
+    'toSource { root = ./.; fileset = fileFilter (file: file.type != "symlink") ./.; }' \
+    'toSource { root = ./.; fileset = union ./d/a ./d/c; }'
+expectEqual \
+    'toSource { root = ./.; fileset = fileFilter (file: file.type != "unknown") ./.; }' \
+    'toSource { root = ./.; fileset = union ./d/a ./d/b; }'
+rm -rf -- *
+
+# It's lazy
+tree=(
+    [b]=1
+    [c/a]=1
+)
+# Note that union evaluates the first argument first if necessary, that's why we can use ./c/a here
+checkFileset 'union ./c/a (fileFilter (file: assert file.name != "a"; true) ./.)'
+# but here we need to use ./c
+checkFileset 'union (fileFilter (file: assert file.name != "a"; true) ./.) ./c'
+
 ## Tracing
 
 # The second trace argument is returned
diff --git a/nixpkgs/lib/systems/parse.nix b/nixpkgs/lib/systems/parse.nix
index 34bfd94b3ce5..b69ad669e187 100644
--- a/nixpkgs/lib/systems/parse.nix
+++ b/nixpkgs/lib/systems/parse.nix
@@ -29,6 +29,15 @@ let
       assert type.check value;
       setType type.name ({ inherit name; } // value));
 
+  # gnu-config will ignore the portion of a triple matching the
+  # regex `e?abi.*$` when determining the validity of a triple.  In
+  # other words, `i386-linuxabichickenlips` is a valid triple.
+  removeAbiSuffix = x:
+    let match = builtins.match "(.*)e?abi.*" x;
+    in if match==null
+       then x
+       else lib.elemAt match 0;
+
 in
 
 rec {
@@ -466,7 +475,7 @@ rec {
         else                     vendors.unknown;
       kernel = if hasPrefix "darwin" args.kernel      then getKernel "darwin"
                else if hasPrefix "netbsd" args.kernel then getKernel "netbsd"
-               else                                   getKernel args.kernel;
+               else                                   getKernel (removeAbiSuffix args.kernel);
       abi =
         /**/ if args ? abi       then getAbi args.abi
         else if isLinux parsed || isWindows parsed then