0
0
Fork 0
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-07-13 21:50:33 +03:00

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 # Type
``` ```
packagesFromDirectoryRecursive :: (args :: { packagesFromDirectoryRecursive :: {
callPackage :: Path -> {} -> a, callPackage :: Path -> {} -> a,
newScope? :: AttrSet -> scope, newScope? :: AttrSet -> scope,
directory :: Path, directory :: Path,
recurseIntoDirectory? :: (args -> AttrSet) -> args -> AttrSet, } -> AttrSet
recurseArgs? :: Any
}) -> AttrSet
``` ```
# Inputs # Inputs
@ -323,36 +321,13 @@ in
It is typically the `callPackage` function, taken from either `pkgs` or a new scope corresponding to the `directory`. It is typically the `callPackage` function, taken from either `pkgs` or a new scope corresponding to the `directory`.
`newScope` `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 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. anything in their scope, or in an ancestor of their scope.
This argument has no effect when `recurseIntoDirectory` is provided.
`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`).
:::{.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 # Examples
:::{.example} :::{.example}
## Basic use of `lib.packagesFromDirectoryRecursive` ## 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`. `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 = packagesFromDirectoryRecursive =
let let
@ -454,15 +397,25 @@ in
lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path} lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path}
'' ''
) (builtins.readDir directory); ) (builtins.readDir directory);
in
defaultRecurse = processDir: args: {
if args ? newScope then callPackage,
newScope ? throw "lib.packagesFromDirectoryRecursive: newScope wasn't passed in args",
directory,
}@args:
let
defaultPath = append directory "package.nix";
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`. # Create a new scope and mark it `recurseForDerivations`.
# This lets the packages refer to each other. # This lets the packages refer to each other.
# See: # See:
# [lib.makeScope](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) and # [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) # [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` # generate the attrset representing the directory, using the new scope's `callPackage` and `newScope`
processDir (args // { processDir (args // {
inherit (self) callPackage newScope; inherit (self) callPackage newScope;
@ -471,22 +424,4 @@ in
else else
processDir args 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";
in
if pathExists defaultPath then
# if `${directory}/package.nix` exists, call it directly
callPackage defaultPath {}
else
recurseIntoDirectory processDir args;
} }