lib.packagesFromDirectoryRecursive: use explicit recursion, support nested scopes

This commit is contained in:
nicoo 2024-11-28 21:42:04 +00:00 committed by Paul Meyer
parent fdd2c6f80f
commit 6b7576b0cf
4 changed files with 50 additions and 35 deletions

View file

@ -116,6 +116,9 @@
"sec-nixpkgs-release-25.05-lib-deprecations": [ "sec-nixpkgs-release-25.05-lib-deprecations": [
"release-notes.html#sec-nixpkgs-release-25.05-lib-deprecations" "release-notes.html#sec-nixpkgs-release-25.05-lib-deprecations"
], ],
"sec-nixpkgs-release-25.05-lib-additions-improvements": [
"release-notes.html#sec-nixpkgs-release-25.05-lib-additions-improvements"
],
"sec-overlays-install": [ "sec-overlays-install": [
"index.html#sec-overlays-install" "index.html#sec-overlays-install"
], ],

View file

@ -84,3 +84,7 @@
- Plasma 5 and Qt 5 based versions of associated software are deprecated in NixOS 25.05, and will be removed in NixOS 25.11. Users are encouraged to upgrade to Plasma 6. - Plasma 5 and Qt 5 based versions of associated software are deprecated in NixOS 25.05, and will be removed in NixOS 25.11. Users are encouraged to upgrade to Plasma 6.
- `rustPlatform.buildRustPackage` stops handling the deprecated argument `cargoSha256`. Out-of-tree packages that haven't migrated from `cargoSha256` to `cargoHash` now receive errors. - `rustPlatform.buildRustPackage` stops handling the deprecated argument `cargoSha256`. Out-of-tree packages that haven't migrated from `cargoSha256` to `cargoHash` now receive errors.
### Other notable changes {#sec-release-25.05-lib-notable-changes}
- `lib.packagesFromDirectoryRecursive` can now construct nested scopes matching the directory tree passed as input.

View file

@ -306,11 +306,12 @@ in
# Type # Type
``` ```
packagesFromDirectoryRecursive :: { packagesFromDirectoryRecursive :: (args :: {
callPackage :: Path -> {} -> a, callPackage :: Path -> {} -> a,
directory :: Path, directory :: Path,
recurseIntoDirectory? :: (args -> AttrSet) -> args -> AttrSet,
... ...
} -> AttrSet }) -> AttrSet
``` ```
# Inputs # Inputs
@ -322,6 +323,10 @@ in
`directory` `directory`
: The directory to read package files from. : 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 # Examples
:::{.example} :::{.example}
@ -342,12 +347,16 @@ in
::::{.example} ::::{.example}
## Create a scope for the nix files found in a directory ## Create a scope for the nix files found in a directory
```nix ```nix
lib.makeScope pkgs.newScope ( packagesFromDirectoryRecursive {
self: packagesFromDirectoryRecursive { inherit (pkgs) callPackage newScope;
inherit (self) callPackage; recurseIntoDirectory = f: { newScope, ... }@args:
directory = ./my-packages; lib.recurseIntoAttrset (lib.makeScope newScope (self:
} f (args // {
) inherit (self) callPackage newScope;
})
));
directory = ./my-packages;
}
=> { ... } => { ... }
``` ```
@ -366,22 +375,15 @@ in
:::{.note} :::{.note}
`a.nix` cannot directly take as inputs packages defined in a child directory, such as `b1`. `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 = packagesFromDirectoryRecursive =
{ {
callPackage, callPackage,
directory, directory,
recurseIntoDirectory ? lib.id,
... ...
}: }@args:
let let
inherit (lib) concatMapAttrs removeSuffix; inherit (lib) concatMapAttrs removeSuffix;
inherit (lib.path) append; inherit (lib.path) append;
@ -390,22 +392,25 @@ in
if pathExists defaultPath then if pathExists defaultPath then
# if `${directory}/package.nix` exists, call it directly # if `${directory}/package.nix` exists, call it directly
callPackage defaultPath {} callPackage defaultPath {}
else concatMapAttrs (name: type: else let
# otherwise, for each directory entry f = { callPackage, ... }@newArgs:
let path = append directory name; in concatMapAttrs (name: type:
if type == "directory" then { # otherwise, for each directory entry
# recurse into directories let path = append directory name; in
"${name}" = packagesFromDirectoryRecursive { if type == "directory" then {
inherit callPackage; # recurse into directories
directory = path; "${name}" = packagesFromDirectoryRecursive (newArgs // {
}; directory = path;
} else if type == "regular" && hasSuffix ".nix" name then { });
# call .nix files } else if type == "regular" && hasSuffix ".nix" name then {
"${removeSuffix ".nix" name}" = callPackage path {}; # call .nix files
} else if type == "regular" then { "${removeSuffix ".nix" name}" = callPackage path {};
# ignore non-nix files } else if type == "regular" then {
} else throw '' # ignore non-nix files
lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path} } else throw ''
'' lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path}
) (builtins.readDir directory); ''
) (builtins.readDir directory);
in
recurseIntoDirectory f args;
} }

View file

@ -1946,6 +1946,9 @@
"sec-nixpkgs-release-25.05-lib-deprecations": [ "sec-nixpkgs-release-25.05-lib-deprecations": [
"release-notes.html#sec-nixpkgs-release-25.05-lib-deprecations" "release-notes.html#sec-nixpkgs-release-25.05-lib-deprecations"
], ],
"sec-nixpkgs-release-25.05-lib-additions-improvements": [
"release-notes.html#sec-nixpkgs-release-25.05-lib-additions-improvements"
],
"sec-release-24.11": [ "sec-release-24.11": [
"release-notes.html#sec-release-24.11" "release-notes.html#sec-release-24.11"
], ],