diff options
author | Alyssa Ross <hi@alyssa.is> | 2023-10-30 13:37:39 +0100 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2023-10-30 13:37:39 +0100 |
commit | 7e0c8fe656bbc2fcbdfc3e03a367d2c6ff389769 (patch) | |
tree | 38e753812c0ceba947d65ec0555a5a66c1a5aa4e /nixpkgs/lib | |
parent | 46cf147fc42b72f68ecd52b3b03a8bfd6077f42b (diff) | |
parent | 63678e9f3d3afecfeafa0acead6239cdb447574c (diff) | |
download | nixlib-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.nix | 88 | ||||
-rw-r--r-- | nixpkgs/lib/fileset/default.nix | 51 | ||||
-rw-r--r-- | nixpkgs/lib/fileset/internal.nix | 26 | ||||
-rwxr-xr-x | nixpkgs/lib/fileset/tests.sh | 67 | ||||
-rw-r--r-- | nixpkgs/lib/systems/parse.nix | 11 |
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 |