lib.packagesFromDirectoryRecursive: drop open recursion from API surface

This commit is contained in:
nicoo 2025-01-18 20:45:05 +00:00 committed by Paul Meyer
parent 151b6e431a
commit 05d528b56b

View file

@ -307,13 +307,11 @@ in
# Type
```
packagesFromDirectoryRecursive :: (args :: {
packagesFromDirectoryRecursive :: {
callPackage :: Path -> {} -> a,
newScope? :: AttrSet -> scope,
directory :: Path,
recurseIntoDirectory? :: (args -> AttrSet) -> args -> AttrSet,
recurseArgs? :: Any
}) -> AttrSet
} -> AttrSet
```
# Inputs
@ -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
@ -454,32 +397,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 +409,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 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
;
}