From b377da6ef8f45e44fc88d6a8dc360ba60b05d63a Mon Sep 17 00:00:00 2001 From: nicoo Date: Sat, 28 Dec 2024 21:38:17 +0000 Subject: [PATCH 01/18] lib.filesystem: remove dead `let`-bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found by `deadnix` 🖤 --- lib/filesystem.nix | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index 620ab54024dc4..5dfdde85b9d23 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -12,11 +12,6 @@ let toString ; - inherit (lib.attrsets) - mapAttrs' - filterAttrs - ; - inherit (lib.filesystem) pathIsDirectory pathIsRegularFile @@ -26,7 +21,6 @@ let inherit (lib.strings) hasSuffix - removeSuffix ; in From 3eb6c8c0652671c070addc40fd7b272e42012e11 Mon Sep 17 00:00:00 2001 From: nicoo Date: Thu, 28 Nov 2024 21:01:51 +0000 Subject: [PATCH 02/18] lib/tests: move `packages-from-directory/*` into a subdir in preparation for adding more tests for `lib.packagesFromDirectoryRecursive` --- lib/tests/misc.nix | 4 ++-- lib/tests/packages-from-directory/{ => plain}/a.nix | 0 lib/tests/packages-from-directory/{ => plain}/b.nix | 0 .../{ => plain}/c/my-extra-feature.patch | 0 .../{ => plain}/c/not-a-namespace/not-a-package.nix | 0 lib/tests/packages-from-directory/{ => plain}/c/package.nix | 0 .../{ => plain}/c/support-definitions.nix | 0 .../packages-from-directory/{ => plain}/my-namespace/d.nix | 0 .../packages-from-directory/{ => plain}/my-namespace/e.nix | 0 .../{ => plain}/my-namespace/f/package.nix | 0 .../{ => plain}/my-namespace/my-sub-namespace/g.nix | 0 .../{ => plain}/my-namespace/my-sub-namespace/h.nix | 0 12 files changed, 2 insertions(+), 2 deletions(-) rename lib/tests/packages-from-directory/{ => plain}/a.nix (100%) rename lib/tests/packages-from-directory/{ => plain}/b.nix (100%) rename lib/tests/packages-from-directory/{ => plain}/c/my-extra-feature.patch (100%) rename lib/tests/packages-from-directory/{ => plain}/c/not-a-namespace/not-a-package.nix (100%) rename lib/tests/packages-from-directory/{ => plain}/c/package.nix (100%) rename lib/tests/packages-from-directory/{ => plain}/c/support-definitions.nix (100%) rename lib/tests/packages-from-directory/{ => plain}/my-namespace/d.nix (100%) rename lib/tests/packages-from-directory/{ => plain}/my-namespace/e.nix (100%) rename lib/tests/packages-from-directory/{ => plain}/my-namespace/f/package.nix (100%) rename lib/tests/packages-from-directory/{ => plain}/my-namespace/my-sub-namespace/g.nix (100%) rename lib/tests/packages-from-directory/{ => plain}/my-namespace/my-sub-namespace/h.nix (100%) diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index f0c4b6f2c5e1c..89f2d6152db1d 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -2559,7 +2559,7 @@ runTests { testPackagesFromDirectoryRecursive = { expr = packagesFromDirectoryRecursive { callPackage = path: overrides: import path overrides; - directory = ./packages-from-directory; + directory = ./packages-from-directory/plain; }; expected = { a = "a"; @@ -2584,7 +2584,7 @@ runTests { testPackagesFromDirectoryRecursiveTopLevelPackageNix = { expr = packagesFromDirectoryRecursive { callPackage = path: overrides: import path overrides; - directory = ./packages-from-directory/c; + directory = ./packages-from-directory/plain/c; }; expected = "c"; }; diff --git a/lib/tests/packages-from-directory/a.nix b/lib/tests/packages-from-directory/plain/a.nix similarity index 100% rename from lib/tests/packages-from-directory/a.nix rename to lib/tests/packages-from-directory/plain/a.nix diff --git a/lib/tests/packages-from-directory/b.nix b/lib/tests/packages-from-directory/plain/b.nix similarity index 100% rename from lib/tests/packages-from-directory/b.nix rename to lib/tests/packages-from-directory/plain/b.nix diff --git a/lib/tests/packages-from-directory/c/my-extra-feature.patch b/lib/tests/packages-from-directory/plain/c/my-extra-feature.patch similarity index 100% rename from lib/tests/packages-from-directory/c/my-extra-feature.patch rename to lib/tests/packages-from-directory/plain/c/my-extra-feature.patch diff --git a/lib/tests/packages-from-directory/c/not-a-namespace/not-a-package.nix b/lib/tests/packages-from-directory/plain/c/not-a-namespace/not-a-package.nix similarity index 100% rename from lib/tests/packages-from-directory/c/not-a-namespace/not-a-package.nix rename to lib/tests/packages-from-directory/plain/c/not-a-namespace/not-a-package.nix diff --git a/lib/tests/packages-from-directory/c/package.nix b/lib/tests/packages-from-directory/plain/c/package.nix similarity index 100% rename from lib/tests/packages-from-directory/c/package.nix rename to lib/tests/packages-from-directory/plain/c/package.nix diff --git a/lib/tests/packages-from-directory/c/support-definitions.nix b/lib/tests/packages-from-directory/plain/c/support-definitions.nix similarity index 100% rename from lib/tests/packages-from-directory/c/support-definitions.nix rename to lib/tests/packages-from-directory/plain/c/support-definitions.nix diff --git a/lib/tests/packages-from-directory/my-namespace/d.nix b/lib/tests/packages-from-directory/plain/my-namespace/d.nix similarity index 100% rename from lib/tests/packages-from-directory/my-namespace/d.nix rename to lib/tests/packages-from-directory/plain/my-namespace/d.nix diff --git a/lib/tests/packages-from-directory/my-namespace/e.nix b/lib/tests/packages-from-directory/plain/my-namespace/e.nix similarity index 100% rename from lib/tests/packages-from-directory/my-namespace/e.nix rename to lib/tests/packages-from-directory/plain/my-namespace/e.nix diff --git a/lib/tests/packages-from-directory/my-namespace/f/package.nix b/lib/tests/packages-from-directory/plain/my-namespace/f/package.nix similarity index 100% rename from lib/tests/packages-from-directory/my-namespace/f/package.nix rename to lib/tests/packages-from-directory/plain/my-namespace/f/package.nix diff --git a/lib/tests/packages-from-directory/my-namespace/my-sub-namespace/g.nix b/lib/tests/packages-from-directory/plain/my-namespace/my-sub-namespace/g.nix similarity index 100% rename from lib/tests/packages-from-directory/my-namespace/my-sub-namespace/g.nix rename to lib/tests/packages-from-directory/plain/my-namespace/my-sub-namespace/g.nix diff --git a/lib/tests/packages-from-directory/my-namespace/my-sub-namespace/h.nix b/lib/tests/packages-from-directory/plain/my-namespace/my-sub-namespace/h.nix similarity index 100% rename from lib/tests/packages-from-directory/my-namespace/my-sub-namespace/h.nix rename to lib/tests/packages-from-directory/plain/my-namespace/my-sub-namespace/h.nix From 03968c43afa80fa6c215dfbee050f5c54f7245d8 Mon Sep 17 00:00:00 2001 From: nicoo Date: Thu, 28 Nov 2024 21:42:04 +0000 Subject: [PATCH 03/18] lib.packagesFromDirectoryRecursive: use explicit recursion, support nested scopes --- lib/filesystem.nix | 75 ++++++++++--------- nixos/doc/manual/redirects.json | 3 + .../manual/release-notes/rl-2505.section.md | 4 + 3 files changed, 47 insertions(+), 35 deletions(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index 5dfdde85b9d23..866eff710a20c 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -306,11 +306,12 @@ in # Type ``` - packagesFromDirectoryRecursive :: { + packagesFromDirectoryRecursive :: (args :: { callPackage :: Path -> {} -> a, directory :: Path, + recurseIntoDirectory? :: (args -> AttrSet) -> args -> AttrSet, ... - } -> AttrSet + }) -> AttrSet ``` # Inputs @@ -322,6 +323,10 @@ in `directory` : The directory to read package files from. + `recurseIntoDirectory` + : This argument is applied to the function which processes directories. + : Equivalently, this function takes `processDir` and `args`, and can modify arguments passed to `processDir` + (same as above) before calling it, as well as modify its output (which is then returned by `recurseIntoDirectory`). # Examples :::{.example} @@ -342,12 +347,16 @@ in ::::{.example} ## Create a scope for the nix files found in a directory ```nix - lib.makeScope pkgs.newScope ( - self: packagesFromDirectoryRecursive { - inherit (self) callPackage; - directory = ./my-packages; - } - ) + packagesFromDirectoryRecursive { + inherit (pkgs) callPackage newScope; + recurseIntoDirectory = f: { newScope, ... }@args: + lib.recurseIntoAttrset (lib.makeScope newScope (self: + f (args // { + inherit (self) callPackage newScope; + }) + )); + directory = ./my-packages; + } => { ... } ``` @@ -366,22 +375,15 @@ in :::{.note} `a.nix` cannot directly take as inputs packages defined in a child directory, such as `b1`. ::: - - :::{.warning} - As of now, `lib.packagesFromDirectoryRecursive` cannot create nested scopes for sub-directories. - - In particular, files under `b/` can only require (as inputs) other files under `my-packages`, - but not to those in the same directory, nor those in a parent directory; e.g, `b2.nix` cannot directly - require `b1`. - ::: :::: */ packagesFromDirectoryRecursive = { callPackage, directory, + recurseIntoDirectory ? lib.id, ... - }: + }@args: let inherit (lib) concatMapAttrs removeSuffix; inherit (lib.path) append; @@ -390,22 +392,25 @@ in if pathExists defaultPath then # if `${directory}/package.nix` exists, call it directly callPackage defaultPath {} - else concatMapAttrs (name: type: - # otherwise, for each directory entry - let path = append directory name; in - if type == "directory" then { - # recurse into directories - "${name}" = packagesFromDirectoryRecursive { - inherit callPackage; - directory = path; - }; - } else if type == "regular" && hasSuffix ".nix" name then { - # call .nix files - "${removeSuffix ".nix" name}" = callPackage path {}; - } else if type == "regular" then { - # ignore non-nix files - } else throw '' - lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path} - '' - ) (builtins.readDir directory); + else let + f = { callPackage, ... }@newArgs: + concatMapAttrs (name: type: + # otherwise, for each directory entry + let path = append directory name; in + if type == "directory" then { + # recurse into directories + "${name}" = packagesFromDirectoryRecursive (newArgs // { + directory = path; + }); + } else if type == "regular" && hasSuffix ".nix" name then { + # call .nix files + "${removeSuffix ".nix" name}" = callPackage path {}; + } else if type == "regular" then { + # ignore non-nix files + } else throw '' + lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path} + '' + ) (builtins.readDir directory); + in + recurseIntoDirectory f args; } diff --git a/nixos/doc/manual/redirects.json b/nixos/doc/manual/redirects.json index 428dbdcc54c29..fb27dde0ffeca 100644 --- a/nixos/doc/manual/redirects.json +++ b/nixos/doc/manual/redirects.json @@ -149,6 +149,9 @@ "sec-changing-config": [ "index.html#sec-changing-config" ], + "sec-release-25.05-lib-notable-changes": [ + "release-notes.html#sec-release-25.05-lib-notable-changes" + ], "sec-upgrading": [ "index.html#sec-upgrading" ], diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index 39e75a30446ea..c711a9644119c 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -310,3 +310,7 @@ - Structure of the `functor` of some types has changed. `functor` is an implementation detail and should not be relied upon. If you did rely on it let us know in this [PR](https://github.com/NixOS/nixpkgs/pull/363565). - [`lib.types.enum`](https://nixos.org/manual/nixos/unstable/#sec-option-types-basic): Previously the `functor.payload` was the list of enum values directly. Now it is an attribute set containing the values in the `values` attribute. - [`lib.types.separatedString`](https://nixos.org/manual/nixos/unstable/#sec-option-types-string): Previously the `functor.payload` was the seperator directly. Now it is an attribute set containing the seperator in the `sep` attribute. + +### Other notable changes {#sec-release-25.05-lib-notable-changes} + +- `lib.packagesFromDirectoryRecursive` can now construct nested scopes matching the directory tree passed as input. From b0df85bb5c02cb03d75049d40538069356410a7e Mon Sep 17 00:00:00 2001 From: nicoo Date: Thu, 28 Nov 2024 21:42:35 +0000 Subject: [PATCH 04/18] lib.packagesFromDirectoryRecursive: add tests for nested scopes --- lib/tests/misc.nix | 34 +++++++++++++++++++ lib/tests/packages-from-directory/scope/a.nix | 1 + lib/tests/packages-from-directory/scope/b.nix | 3 ++ .../scope/c/my-extra-feature.patch | 0 .../scope/c/not-a-namespace/not-a-package.nix | 1 + .../scope/c/package.nix | 1 + .../scope/c/support-definitions.nix | 1 + .../scope/my-namespace/d.nix | 5 +++ .../scope/my-namespace/e.nix | 3 ++ .../scope/my-namespace/f/package.nix | 1 + .../scope/my-namespace/my-sub-namespace/g.nix | 7 ++++ .../scope/my-namespace/my-sub-namespace/h.nix | 1 + 12 files changed, 58 insertions(+) create mode 100644 lib/tests/packages-from-directory/scope/a.nix create mode 100644 lib/tests/packages-from-directory/scope/b.nix create mode 100644 lib/tests/packages-from-directory/scope/c/my-extra-feature.patch create mode 100644 lib/tests/packages-from-directory/scope/c/not-a-namespace/not-a-package.nix create mode 100644 lib/tests/packages-from-directory/scope/c/package.nix create mode 100644 lib/tests/packages-from-directory/scope/c/support-definitions.nix create mode 100644 lib/tests/packages-from-directory/scope/my-namespace/d.nix create mode 100644 lib/tests/packages-from-directory/scope/my-namespace/e.nix create mode 100644 lib/tests/packages-from-directory/scope/my-namespace/f/package.nix create mode 100644 lib/tests/packages-from-directory/scope/my-namespace/my-sub-namespace/g.nix create mode 100644 lib/tests/packages-from-directory/scope/my-namespace/my-sub-namespace/h.nix diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index 89f2d6152db1d..613fe1e069a57 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -2588,4 +2588,38 @@ runTests { }; expected = "c"; }; + + # Check that `packagesFromDirectoryRecursive` can be used to create scopes + # for sub-directories + testPackagesFromDirectoryNestedScopes = let + inherit (lib) makeScope recurseIntoAttrs; + emptyScope = makeScope lib.callPackageWith (_: {}); + in { + expr = lib.filterAttrsRecursive (name: value: !lib.elem name [ "callPackage" "newScope" "overrideScope" "packages" ]) (packagesFromDirectoryRecursive { + inherit (emptyScope) callPackage newScope; + recurseIntoDirectory = f: { newScope, ... }@args: + recurseIntoAttrs (makeScope newScope (self: + f (args // { + inherit (self) callPackage newScope; + }) + )); + directory = ./packages-from-directory/scope; + }); + expected = lib.recurseIntoAttrs { + a = "a"; + b = "b"; + # Note: Other files/directories in `./test-data/c/` are ignored and can be + # used by `package.nix`. + c = "c"; + my-namespace = lib.recurseIntoAttrs { + d = "d"; + e = "e"; + f = "f"; + my-sub-namespace = lib.recurseIntoAttrs { + g = "g"; + h = "h"; + }; + }; + }; + }; } diff --git a/lib/tests/packages-from-directory/scope/a.nix b/lib/tests/packages-from-directory/scope/a.nix new file mode 100644 index 0000000000000..0ba3be1fa5a5c --- /dev/null +++ b/lib/tests/packages-from-directory/scope/a.nix @@ -0,0 +1 @@ +{ }: "a" diff --git a/lib/tests/packages-from-directory/scope/b.nix b/lib/tests/packages-from-directory/scope/b.nix new file mode 100644 index 0000000000000..4201bac5693eb --- /dev/null +++ b/lib/tests/packages-from-directory/scope/b.nix @@ -0,0 +1,3 @@ +{ a }: +assert a == "a"; +"b" diff --git a/lib/tests/packages-from-directory/scope/c/my-extra-feature.patch b/lib/tests/packages-from-directory/scope/c/my-extra-feature.patch new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/lib/tests/packages-from-directory/scope/c/not-a-namespace/not-a-package.nix b/lib/tests/packages-from-directory/scope/c/not-a-namespace/not-a-package.nix new file mode 100644 index 0000000000000..ffcd4415b08f8 --- /dev/null +++ b/lib/tests/packages-from-directory/scope/c/not-a-namespace/not-a-package.nix @@ -0,0 +1 @@ +{ } diff --git a/lib/tests/packages-from-directory/scope/c/package.nix b/lib/tests/packages-from-directory/scope/c/package.nix new file mode 100644 index 0000000000000..33caddbec8808 --- /dev/null +++ b/lib/tests/packages-from-directory/scope/c/package.nix @@ -0,0 +1 @@ +{ }: "c" diff --git a/lib/tests/packages-from-directory/scope/c/support-definitions.nix b/lib/tests/packages-from-directory/scope/c/support-definitions.nix new file mode 100644 index 0000000000000..ffcd4415b08f8 --- /dev/null +++ b/lib/tests/packages-from-directory/scope/c/support-definitions.nix @@ -0,0 +1 @@ +{ } diff --git a/lib/tests/packages-from-directory/scope/my-namespace/d.nix b/lib/tests/packages-from-directory/scope/my-namespace/d.nix new file mode 100644 index 0000000000000..9496d021a94c1 --- /dev/null +++ b/lib/tests/packages-from-directory/scope/my-namespace/d.nix @@ -0,0 +1,5 @@ +{ a, e }: +# Check we can get parameter from the parent scope(s) as well as the current one +assert a == "a"; +assert e == "e"; +"d" diff --git a/lib/tests/packages-from-directory/scope/my-namespace/e.nix b/lib/tests/packages-from-directory/scope/my-namespace/e.nix new file mode 100644 index 0000000000000..276b80deab406 --- /dev/null +++ b/lib/tests/packages-from-directory/scope/my-namespace/e.nix @@ -0,0 +1,3 @@ +{ d }: +# Check that mutual recursion is possible +"e" diff --git a/lib/tests/packages-from-directory/scope/my-namespace/f/package.nix b/lib/tests/packages-from-directory/scope/my-namespace/f/package.nix new file mode 100644 index 0000000000000..d58cfe01d606b --- /dev/null +++ b/lib/tests/packages-from-directory/scope/my-namespace/f/package.nix @@ -0,0 +1 @@ +{ }: "f" diff --git a/lib/tests/packages-from-directory/scope/my-namespace/my-sub-namespace/g.nix b/lib/tests/packages-from-directory/scope/my-namespace/my-sub-namespace/g.nix new file mode 100644 index 0000000000000..77a79907a1511 --- /dev/null +++ b/lib/tests/packages-from-directory/scope/my-namespace/my-sub-namespace/g.nix @@ -0,0 +1,7 @@ +{ + a, + d, + h, +}: +# Check we can get parameters from ancestral scopes (e.g. the scope's grandparent) +"g" diff --git a/lib/tests/packages-from-directory/scope/my-namespace/my-sub-namespace/h.nix b/lib/tests/packages-from-directory/scope/my-namespace/my-sub-namespace/h.nix new file mode 100644 index 0000000000000..34a0416e95772 --- /dev/null +++ b/lib/tests/packages-from-directory/scope/my-namespace/my-sub-namespace/h.nix @@ -0,0 +1 @@ +{ }: "h" From 3ae1e97478b6141cba8127a6e343cac3b23977d1 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sun, 1 Dec 2024 10:44:54 +0000 Subject: [PATCH 05/18] lib.packagesFromDirectoryRecursive: default to creating new scopes when `newScope` is provided Co-authored-by: Rebecca Turner --- lib/filesystem.nix | 58 +++++++++++++++++++++++++++++++++++++--------- lib/tests/misc.nix | 6 ----- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index 866eff710a20c..afc8468730cff 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -308,6 +308,7 @@ in ``` packagesFromDirectoryRecursive :: (args :: { callPackage :: Path -> {} -> a, + newScope? :: AttrSet -> scope, directory :: Path, recurseIntoDirectory? :: (args -> AttrSet) -> args -> AttrSet, ... @@ -320,6 +321,12 @@ in : The function used to convert a Nix file's path into a leaf of the attribute set. It is typically the `callPackage` function, taken from either `pkgs` or a new scope corresponding to the `directory`. + `newScope` + : If present, this function is used by the default `recurseIntoDirectory` to generate a new scope. + The arguments are updated with the scope's `callPackage` and `newScope` functions, so packages can require + anything in their scope, or in an ancestor of their scope. + This argument has no effect when `recurseIntoDirectory` is provided. + `directory` : The directory to read package files from. @@ -328,6 +335,20 @@ in : Equivalently, this function takes `processDir` and `args`, and can modify arguments passed to `processDir` (same as above) before calling it, as well as modify its output (which is then returned by `recurseIntoDirectory`). + :::{.note} + When `newScope` is set, the default `recurseIntoDirectory` is equivalent to: + ```nix + processDir: { newScope, ... }@args: + # create a new scope and mark it `recurseForDerivations` + lib.recurseIntoAttrs (lib.makeScope newScope (self: + # generate the attrset representing the directory, using the new scope's `callPackage` and `newScope` + processDir (args // { + inherit (self) callPackage newScope; + }) + )) + ``` + ::: + # Examples :::{.example} ## Basic use of `lib.packagesFromDirectoryRecursive` @@ -349,12 +370,6 @@ in ```nix packagesFromDirectoryRecursive { inherit (pkgs) callPackage newScope; - recurseIntoDirectory = f: { newScope, ... }@args: - lib.recurseIntoAttrset (lib.makeScope newScope (self: - f (args // { - inherit (self) callPackage newScope; - }) - )); directory = ./my-packages; } => { ... } @@ -378,22 +393,43 @@ in :::: */ packagesFromDirectoryRecursive = + let + inherit (lib) concatMapAttrs id makeScope recurseIntoAttrs removeSuffix; + inherit (lib.path) append; + in { callPackage, directory, - recurseIntoDirectory ? lib.id, + # recurseIntoDirectory can modify the function used when processing directory entries; see nixdoc above + recurseIntoDirectory ? + if args ? newScope then + # `processDir` is the same function as defined below, + # `args` are the arguments passed to (this recursive call of) `packagesFromDirectoryRecursive` + processDir: { newScope, ... }@args: + # Create a new scope and mark it `recurseForDerivations`. + # This lets the packages refer to each other. + # See: + # [lib.makeScope](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) and + # [lib.recurseIntoAttrs](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) + recurseIntoAttrs (makeScope newScope (self: + # generate the attrset representing the directory, using the new scope's `callPackage` and `newScope` + processDir (args // { + inherit (self) callPackage newScope; + }) + )) + else + # otherwise, no modification is necessary + id, ... }@args: let - inherit (lib) concatMapAttrs removeSuffix; - inherit (lib.path) append; defaultPath = append directory "package.nix"; in if pathExists defaultPath then # if `${directory}/package.nix` exists, call it directly callPackage defaultPath {} else let - f = { callPackage, ... }@newArgs: + processDir = { callPackage, ... }@newArgs: concatMapAttrs (name: type: # otherwise, for each directory entry let path = append directory name; in @@ -412,5 +448,5 @@ in '' ) (builtins.readDir directory); in - recurseIntoDirectory f args; + recurseIntoDirectory processDir args; } diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index 613fe1e069a57..fbc68419ebfb3 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -2597,12 +2597,6 @@ runTests { in { expr = lib.filterAttrsRecursive (name: value: !lib.elem name [ "callPackage" "newScope" "overrideScope" "packages" ]) (packagesFromDirectoryRecursive { inherit (emptyScope) callPackage newScope; - recurseIntoDirectory = f: { newScope, ... }@args: - recurseIntoAttrs (makeScope newScope (self: - f (args // { - inherit (self) callPackage newScope; - }) - )); directory = ./packages-from-directory/scope; }); expected = lib.recurseIntoAttrs { From 1ca4a58a3b8e33447a2c892ce62abffd3e95e36e Mon Sep 17 00:00:00 2001 From: nicoo Date: Tue, 3 Dec 2024 14:36:00 +0000 Subject: [PATCH 06/18] lib.packagesFromDirectoryRecursive: hoist `processDir` out of the lambda Fixes a bug preventing `recurseIntoDirectory` from changing the `directory` argument. Moreover, `processDir` now cannot capture arguments from the `packagesFromDirectoryRecursive` call, entirely preventing this class of bug from reoccurring should new parameters be added etc. --- lib/filesystem.nix | 47 ++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index afc8468730cff..5453160a18465 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -396,6 +396,28 @@ in let inherit (lib) concatMapAttrs id makeScope recurseIntoAttrs removeSuffix; inherit (lib.path) append; + + # Generate an attrset corresponding to a given directory. + # This function is outside `packagesFromDirectoryRecursive`'s lambda expression, + # to prevent accidentally using its parameters. + processDir = { callPackage, directory, ... }@args: + concatMapAttrs (name: type: + # for each directory entry + let path = append directory name; in + if type == "directory" then { + # recurse into directories + "${name}" = packagesFromDirectoryRecursive (args // { + directory = path; + }); + } else if type == "regular" && hasSuffix ".nix" name then { + # call .nix files + "${removeSuffix ".nix" name}" = callPackage path {}; + } else if type == "regular" then { + # ignore non-nix files + } else throw '' + lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path} + '' + ) (builtins.readDir directory); in { callPackage, @@ -403,7 +425,7 @@ in # recurseIntoDirectory can modify the function used when processing directory entries; see nixdoc above recurseIntoDirectory ? if args ? newScope then - # `processDir` is the same function as defined below, + # `processDir` is the same function as defined above # `args` are the arguments passed to (this recursive call of) `packagesFromDirectoryRecursive` processDir: { newScope, ... }@args: # Create a new scope and mark it `recurseForDerivations`. @@ -428,25 +450,6 @@ in if pathExists defaultPath then # if `${directory}/package.nix` exists, call it directly callPackage defaultPath {} - else let - processDir = { callPackage, ... }@newArgs: - concatMapAttrs (name: type: - # otherwise, for each directory entry - let path = append directory name; in - if type == "directory" then { - # recurse into directories - "${name}" = packagesFromDirectoryRecursive (newArgs // { - directory = path; - }); - } else if type == "regular" && hasSuffix ".nix" name then { - # call .nix files - "${removeSuffix ".nix" name}" = callPackage path {}; - } else if type == "regular" then { - # ignore non-nix files - } else throw '' - lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path} - '' - ) (builtins.readDir directory); - in - recurseIntoDirectory processDir args; + else + recurseIntoDirectory processDir args; } From bf5cd41edb033709ac14f9c45f04ff2070ccc542 Mon Sep 17 00:00:00 2001 From: nicoo Date: Tue, 3 Dec 2024 16:27:30 +0000 Subject: [PATCH 07/18] lib.packagesFromDirectoryRecursive: reject unknown arguments see [discussion](https://github.com/NixOS/nixpkgs/pull/270537#discussion_r1862458435) --- lib/filesystem.nix | 11 ++++++++--- nixos/doc/manual/release-notes/rl-2505.section.md | 6 +++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index 5453160a18465..a9fd19525a16e 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -311,7 +311,7 @@ in newScope? :: AttrSet -> scope, directory :: Path, recurseIntoDirectory? :: (args -> AttrSet) -> args -> AttrSet, - ... + recurseArgs? :: Any }) -> AttrSet ``` @@ -349,6 +349,9 @@ in ``` ::: + `recurseArgs` + : Optional argument, which can be hold data used by `recurseIntoDirectory` + # Examples :::{.example} ## Basic use of `lib.packagesFromDirectoryRecursive` @@ -421,8 +424,11 @@ in in { callPackage, + newScope ? throw "lib.packagesFromDirectoryRecursive: newScope wasn't passed in args", directory, - # recurseIntoDirectory can modify the function used when processing directory entries; see nixdoc above + # recurseIntoDirectory can modify the function used when processing directory entries + # and recurseArgs can (optionally) hold data for its use ; see nixdoc above + recurseArgs ? throw "lib.packagesFromDirectoryRecursive: recurseArgs wasn't passed in args", recurseIntoDirectory ? if args ? newScope then # `processDir` is the same function as defined above @@ -442,7 +448,6 @@ in else # otherwise, no modification is necessary id, - ... }@args: let defaultPath = append directory "package.nix"; diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index c711a9644119c..099015c27b7f9 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -311,6 +311,10 @@ - [`lib.types.enum`](https://nixos.org/manual/nixos/unstable/#sec-option-types-basic): Previously the `functor.payload` was the list of enum values directly. Now it is an attribute set containing the values in the `values` attribute. - [`lib.types.separatedString`](https://nixos.org/manual/nixos/unstable/#sec-option-types-string): Previously the `functor.payload` was the seperator directly. Now it is an attribute set containing the seperator in the `sep` attribute. +- [`lib.packagesFromDirectoryRecursive`] now rejects unknown arguments, and applies [`lib.recurseIntoAttrs`] when recursing into a directory. + [`lib.packagesFromDirectoryRecursive`]: https://nixos.org/manual/nixpkgs/stable/#function-library-lib.filesystem.packagesFromDirectoryRecursive + [`lib.recurseIntoAttrs`]: https://nixos.org/manual/nixpkgs/stable/#function-library-lib.attrsets.recurseIntoAttrs + ### Other notable changes {#sec-release-25.05-lib-notable-changes} -- `lib.packagesFromDirectoryRecursive` can now construct nested scopes matching the directory tree passed as input. +- [`lib.packagesFromDirectoryRecursive`] can now construct nested scopes matching the directory tree passed as input. From 0fe9ad2c52b785b55df4786c6ce0d2a1f433afe1 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sat, 28 Dec 2024 22:29:34 +0000 Subject: [PATCH 08/18] lib.packagesFromDirectoryRecursive: Add example use of `recurseIntoDirectory` --- lib/filesystem.nix | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index a9fd19525a16e..55e3e02d8514d 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -394,6 +394,38 @@ in `a.nix` cannot directly take as inputs packages defined in a child directory, such as `b1`. ::: :::: + + :::{.example} + ## Mark with `recurseIntoAttrs` when recursing into a directory + ```nix + packagesFromDirectoryRecursive { + inherit (pkgs) callPackage; + directory = ./my-packages; + + recurseIntoDirectory = processDir: args: lib.recurseIntoAttrs (processDir args); + } + ``` + ::: + + :::{.example} + ## Express custom recursion behaviour with `recurseIntoDirectory` + For instance, only mark attrsets produced by `packagesFromDirectoryRecursive` with `recurseForDerivations` + if they (transitively) contain derivations. + + ```nix + packagesFromDirectoryRecursive { + inherit (pkgs) callPackage; + directory = ./my-packages; + + recurseIntoDirectory = processDir: args: let + result = processDir args; + in result // { + recurseForDerivations = with lib; + any (child: isDerivation child || child.recurseForDerivations or false) result; + }; + } + ``` + ::: */ packagesFromDirectoryRecursive = let From 6b9379f4eb54db982611ff2d41dba3338cd1c336 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sun, 12 Jan 2025 09:58:59 +0000 Subject: [PATCH 09/18] fixup! lib.packagesFromDirectoryRecursive: use explicit recursion, support nested scopes --- nixos/doc/manual/redirects.json | 6 +++--- nixos/doc/manual/release-notes/rl-2505.section.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nixos/doc/manual/redirects.json b/nixos/doc/manual/redirects.json index fb27dde0ffeca..ef1c4ff3599b2 100644 --- a/nixos/doc/manual/redirects.json +++ b/nixos/doc/manual/redirects.json @@ -149,9 +149,6 @@ "sec-changing-config": [ "index.html#sec-changing-config" ], - "sec-release-25.05-lib-notable-changes": [ - "release-notes.html#sec-release-25.05-lib-notable-changes" - ], "sec-upgrading": [ "index.html#sec-upgrading" ], @@ -1895,6 +1892,9 @@ "sec-release-25.05-lib-breaking": [ "release-notes.html#sec-release-25.05-lib-breaking" ], + "sec-release-25.05-lib-additions-improvements": [ + "release-notes.html#sec-release-25.05-lib-additions-improvements" + ], "sec-release-24.11": [ "release-notes.html#sec-release-24.11" ], diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index 099015c27b7f9..4dec1f2bdf79f 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -315,6 +315,6 @@ [`lib.packagesFromDirectoryRecursive`]: https://nixos.org/manual/nixpkgs/stable/#function-library-lib.filesystem.packagesFromDirectoryRecursive [`lib.recurseIntoAttrs`]: https://nixos.org/manual/nixpkgs/stable/#function-library-lib.attrsets.recurseIntoAttrs -### Other notable changes {#sec-release-25.05-lib-notable-changes} +### Additions and Improvements {#sec-release-25.05-lib-additions-improvements} - [`lib.packagesFromDirectoryRecursive`] can now construct nested scopes matching the directory tree passed as input. From 8e448eec5443a0bab83cf3291bec5ca789bce4e0 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sun, 12 Jan 2025 10:07:06 +0000 Subject: [PATCH 10/18] fixup! lib.packagesFromDirectoryRecursive: default to creating new scopes when `newScope` is provided --- lib/filesystem.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index 55e3e02d8514d..041151c121d47 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -459,7 +459,7 @@ in newScope ? throw "lib.packagesFromDirectoryRecursive: newScope wasn't passed in args", directory, # recurseIntoDirectory can modify the function used when processing directory entries - # and recurseArgs can (optionally) hold data for its use ; see nixdoc above + # and recurseArgs can (optionally) hold data for its use ; see function documentation recurseArgs ? throw "lib.packagesFromDirectoryRecursive: recurseArgs wasn't passed in args", recurseIntoDirectory ? if args ? newScope then From b3977a7e39b70f518e4de3d85ce076eddd65b389 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sun, 12 Jan 2025 12:52:25 +0000 Subject: [PATCH 11/18] lib.packagesFromDirectoryRecursive: document that symlinks are ignored MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was implicit in the previous “other files are ignored.” --- lib/filesystem.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index 041151c121d47..e359b57f73632 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -290,11 +290,10 @@ in `callPackage /package.nix { }` is returned. - Otherwise, the input directory's contents are listed and transformed into an attribute set. - - If a file name has the `.nix` extension, it is turned into attribute + - If a regular file's name has the `.nix` extension, it is turned into attribute where: - The attribute name is the file name without the `.nix` extension - The attribute value is `callPackage { }` - - Other files are ignored. - Directories are turned into an attribute where: - The attribute name is the name of the directory - The attribute value is the result of calling @@ -302,6 +301,8 @@ in As a result, directories with no `.nix` files (including empty directories) will be transformed into empty attribute sets. + - Other files are ignored, including symbolic links to directories and to regular `.nix` + files; this is because nixlang code cannot distinguish the type of a link's target. # Type From 91f94d89d39cfb099eeaf9c7695f04147b68e030 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sun, 12 Jan 2025 12:54:29 +0000 Subject: [PATCH 12/18] fixup! lib.packagesFromDirectoryRecursive: Add example use of `recurseIntoDirectory` --- lib/filesystem.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index e359b57f73632..7443c87b81292 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -421,8 +421,8 @@ in recurseIntoDirectory = processDir: args: let result = processDir args; in result // { - recurseForDerivations = with lib; - any (child: isDerivation child || child.recurseForDerivations or false) result; + recurseForDerivations = + lib.any (child: lib.isDerivation child || child.recurseForDerivations or false) result; }; } ``` From d742f77521a8fdf2007c8ea0ee26b3ac174f9235 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sun, 12 Jan 2025 13:02:51 +0000 Subject: [PATCH 13/18] squash! lib.packagesFromDirectoryRecursive: hoist `processDir` out of the lambda also hoisted the default `recurseIntoDirectory`, as requested during review --- lib/filesystem.nix | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index 7443c87b81292..e60cb4c0ba96a 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -454,6 +454,23 @@ in lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path} '' ) (builtins.readDir directory); + + defaultRecurse = processDir: args: + if args ? newScope then + # Create a new scope and mark it `recurseForDerivations`. + # This lets the packages refer to each other. + # See: + # [lib.makeScope](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) and + # [lib.recurseIntoAttrs](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) + recurseIntoAttrs (makeScope args.newScope (self: + # generate the attrset representing the directory, using the new scope's `callPackage` and `newScope` + processDir (args // { + inherit (self) callPackage newScope; + }) + )) + else + processDir args + ; in { callPackage, @@ -462,25 +479,7 @@ in # recurseIntoDirectory can modify the function used when processing directory entries # and recurseArgs can (optionally) hold data for its use ; see function documentation recurseArgs ? throw "lib.packagesFromDirectoryRecursive: recurseArgs wasn't passed in args", - recurseIntoDirectory ? - if args ? newScope then - # `processDir` is the same function as defined above - # `args` are the arguments passed to (this recursive call of) `packagesFromDirectoryRecursive` - processDir: { newScope, ... }@args: - # Create a new scope and mark it `recurseForDerivations`. - # This lets the packages refer to each other. - # See: - # [lib.makeScope](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) and - # [lib.recurseIntoAttrs](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) - recurseIntoAttrs (makeScope newScope (self: - # generate the attrset representing the directory, using the new scope's `callPackage` and `newScope` - processDir (args // { - inherit (self) callPackage newScope; - }) - )) - else - # otherwise, no modification is necessary - id, + recurseIntoDirectory ? defaultRecurse, }@args: let defaultPath = append directory "package.nix"; From 22feb4cc023d62cce81cb3020264c588ee027404 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sat, 18 Jan 2025 20:45:05 +0000 Subject: [PATCH 14/18] lib.packagesFromDirectoryRecursive: drop open recursion from API surface --- lib/filesystem.nix | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index e60cb4c0ba96a..39cfd809f758d 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -454,32 +454,11 @@ in lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path} '' ) (builtins.readDir directory); - - defaultRecurse = processDir: args: - if args ? newScope then - # Create a new scope and mark it `recurseForDerivations`. - # This lets the packages refer to each other. - # See: - # [lib.makeScope](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) and - # [lib.recurseIntoAttrs](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) - recurseIntoAttrs (makeScope args.newScope (self: - # generate the attrset representing the directory, using the new scope's `callPackage` and `newScope` - processDir (args // { - inherit (self) callPackage newScope; - }) - )) - else - processDir args - ; in { callPackage, newScope ? throw "lib.packagesFromDirectoryRecursive: newScope wasn't passed in args", directory, - # recurseIntoDirectory can modify the function used when processing directory entries - # and recurseArgs can (optionally) hold data for its use ; see function documentation - recurseArgs ? throw "lib.packagesFromDirectoryRecursive: recurseArgs wasn't passed in args", - recurseIntoDirectory ? defaultRecurse, }@args: let defaultPath = append directory "package.nix"; @@ -487,6 +466,19 @@ in if pathExists defaultPath then # if `${directory}/package.nix` exists, call it directly callPackage defaultPath {} + else if args ? newScope then + # Create a new scope and mark it `recurseForDerivations`. + # This lets the packages refer to each other. + # See: + # [lib.makeScope](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) and + # [lib.recurseIntoAttrs](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) + recurseIntoAttrs (makeScope args.newScope (self: + # generate the attrset representing the directory, using the new scope's `callPackage` and `newScope` + processDir (args // { + inherit (self) callPackage newScope; + }) + )) else - recurseIntoDirectory processDir args; + processDir args + ; } From 25c495e61c88ec9c35c200843ea61254f67de331 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sat, 18 Jan 2025 20:49:08 +0000 Subject: [PATCH 15/18] fixup! lib.packagesFromDirectoryRecursive: drop open recursion from API surface --- lib/filesystem.nix | 59 +--------------------------------------------- 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index 39cfd809f758d..bf34e3c603ba7 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -311,8 +311,6 @@ in callPackage :: Path -> {} -> a, newScope? :: AttrSet -> scope, directory :: Path, - recurseIntoDirectory? :: (args -> AttrSet) -> args -> AttrSet, - recurseArgs? :: Any }) -> AttrSet ``` @@ -323,36 +321,13 @@ in It is typically the `callPackage` function, taken from either `pkgs` or a new scope corresponding to the `directory`. `newScope` - : If present, this function is used by the default `recurseIntoDirectory` to generate a new scope. + : If present, this function is used when recursing into a directory, to generate a new scope. The arguments are updated with the scope's `callPackage` and `newScope` functions, so packages can require anything in their scope, or in an ancestor of their scope. - This argument has no effect when `recurseIntoDirectory` is provided. `directory` : The directory to read package files from. - `recurseIntoDirectory` - : This argument is applied to the function which processes directories. - : Equivalently, this function takes `processDir` and `args`, and can modify arguments passed to `processDir` - (same as above) before calling it, as well as modify its output (which is then returned by `recurseIntoDirectory`). - - :::{.note} - When `newScope` is set, the default `recurseIntoDirectory` is equivalent to: - ```nix - processDir: { newScope, ... }@args: - # create a new scope and mark it `recurseForDerivations` - lib.recurseIntoAttrs (lib.makeScope newScope (self: - # generate the attrset representing the directory, using the new scope's `callPackage` and `newScope` - processDir (args // { - inherit (self) callPackage newScope; - }) - )) - ``` - ::: - - `recurseArgs` - : Optional argument, which can be hold data used by `recurseIntoDirectory` - # Examples :::{.example} ## Basic use of `lib.packagesFromDirectoryRecursive` @@ -395,38 +370,6 @@ in `a.nix` cannot directly take as inputs packages defined in a child directory, such as `b1`. ::: :::: - - :::{.example} - ## Mark with `recurseIntoAttrs` when recursing into a directory - ```nix - packagesFromDirectoryRecursive { - inherit (pkgs) callPackage; - directory = ./my-packages; - - recurseIntoDirectory = processDir: args: lib.recurseIntoAttrs (processDir args); - } - ``` - ::: - - :::{.example} - ## Express custom recursion behaviour with `recurseIntoDirectory` - For instance, only mark attrsets produced by `packagesFromDirectoryRecursive` with `recurseForDerivations` - if they (transitively) contain derivations. - - ```nix - packagesFromDirectoryRecursive { - inherit (pkgs) callPackage; - directory = ./my-packages; - - recurseIntoDirectory = processDir: args: let - result = processDir args; - in result // { - recurseForDerivations = - lib.any (child: lib.isDerivation child || child.recurseForDerivations or false) result; - }; - } - ``` - ::: */ packagesFromDirectoryRecursive = let From 7477abe6390e5ceee48a4beeab54d6a7479a2cf4 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sat, 18 Jan 2025 21:14:03 +0000 Subject: [PATCH 16/18] fixup! lib.packagesFromDirectoryRecursive: drop open recursion from API surface --- lib/filesystem.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index bf34e3c603ba7..fd257c30c034b 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -307,11 +307,11 @@ in # Type ``` - packagesFromDirectoryRecursive :: (args :: { + packagesFromDirectoryRecursive :: { callPackage :: Path -> {} -> a, newScope? :: AttrSet -> scope, directory :: Path, - }) -> AttrSet + } -> AttrSet ``` # Inputs From 168b2ab6838ad590c01a1e7a4a7d089fa1475f44 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sat, 18 Jan 2025 21:17:05 +0000 Subject: [PATCH 17/18] fixup! lib.packagesFromDirectoryRecursive: drop open recursion from API surface --- lib/filesystem.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index fd257c30c034b..c3e44137c42d5 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -415,7 +415,7 @@ in # See: # [lib.makeScope](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) and # [lib.recurseIntoAttrs](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) - recurseIntoAttrs (makeScope args.newScope (self: + recurseIntoAttrs (makeScope newScope (self: # generate the attrset representing the directory, using the new scope's `callPackage` and `newScope` processDir (args // { inherit (self) callPackage newScope; From ab992bac83dd856aeb45cb8bcec9164dab505ea9 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sun, 19 Jan 2025 09:29:30 +0000 Subject: [PATCH 18/18] fixup! lib.packagesFromDirectoryRecursive: reject unknown arguments --- nixos/doc/manual/release-notes/rl-2505.section.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index 4dec1f2bdf79f..5c353e37c2f22 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -311,9 +311,8 @@ - [`lib.types.enum`](https://nixos.org/manual/nixos/unstable/#sec-option-types-basic): Previously the `functor.payload` was the list of enum values directly. Now it is an attribute set containing the values in the `values` attribute. - [`lib.types.separatedString`](https://nixos.org/manual/nixos/unstable/#sec-option-types-string): Previously the `functor.payload` was the seperator directly. Now it is an attribute set containing the seperator in the `sep` attribute. -- [`lib.packagesFromDirectoryRecursive`] now rejects unknown arguments, and applies [`lib.recurseIntoAttrs`] when recursing into a directory. +- [`lib.packagesFromDirectoryRecursive`] now rejects unknown arguments. [`lib.packagesFromDirectoryRecursive`]: https://nixos.org/manual/nixpkgs/stable/#function-library-lib.filesystem.packagesFromDirectoryRecursive - [`lib.recurseIntoAttrs`]: https://nixos.org/manual/nixpkgs/stable/#function-library-lib.attrsets.recurseIntoAttrs ### Additions and Improvements {#sec-release-25.05-lib-additions-improvements}