Merge pull request #270537 from 9999years/packagesFromDirectory
lib.packagesFromDirectoryRecursive: init
This commit is contained in:
commit
cf47b9a5c0
14 changed files with 205 additions and 1 deletions
|
@ -120,7 +120,8 @@ let
|
||||||
inherit (self.meta) addMetaAttrs dontDistribute setName updateName
|
inherit (self.meta) addMetaAttrs dontDistribute setName updateName
|
||||||
appendToName mapDerivationAttrset setPrio lowPrio lowPrioSet hiPrio
|
appendToName mapDerivationAttrset setPrio lowPrio lowPrioSet hiPrio
|
||||||
hiPrioSet getLicenseFromSpdxId getExe getExe';
|
hiPrioSet getLicenseFromSpdxId getExe getExe';
|
||||||
inherit (self.filesystem) pathType pathIsDirectory pathIsRegularFile;
|
inherit (self.filesystem) pathType pathIsDirectory pathIsRegularFile
|
||||||
|
packagesFromDirectoryRecursive;
|
||||||
inherit (self.sources) cleanSourceFilter
|
inherit (self.sources) cleanSourceFilter
|
||||||
cleanSource sourceByRegex sourceFilesBySuffices
|
cleanSource sourceByRegex sourceFilesBySuffices
|
||||||
commitIdFromGitRepo cleanSourceWith pathHasContext
|
commitIdFromGitRepo cleanSourceWith pathHasContext
|
||||||
|
|
|
@ -9,11 +9,22 @@ let
|
||||||
inherit (builtins)
|
inherit (builtins)
|
||||||
readDir
|
readDir
|
||||||
pathExists
|
pathExists
|
||||||
|
toString
|
||||||
|
;
|
||||||
|
|
||||||
|
inherit (lib.attrsets)
|
||||||
|
mapAttrs'
|
||||||
|
filterAttrs
|
||||||
;
|
;
|
||||||
|
|
||||||
inherit (lib.filesystem)
|
inherit (lib.filesystem)
|
||||||
pathType
|
pathType
|
||||||
;
|
;
|
||||||
|
|
||||||
|
inherit (lib.strings)
|
||||||
|
hasSuffix
|
||||||
|
removeSuffix
|
||||||
|
;
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -154,4 +165,147 @@ in
|
||||||
dir + "/${name}"
|
dir + "/${name}"
|
||||||
) (builtins.readDir dir));
|
) (builtins.readDir dir));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Transform a directory tree containing package files suitable for
|
||||||
|
`callPackage` into a matching nested attribute set of derivations.
|
||||||
|
|
||||||
|
For a directory tree like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
my-packages
|
||||||
|
├── a.nix
|
||||||
|
├── b.nix
|
||||||
|
├── c
|
||||||
|
│ ├── my-extra-feature.patch
|
||||||
|
│ ├── package.nix
|
||||||
|
│ └── support-definitions.nix
|
||||||
|
└── my-namespace
|
||||||
|
├── d.nix
|
||||||
|
├── e.nix
|
||||||
|
└── f
|
||||||
|
└── package.nix
|
||||||
|
```
|
||||||
|
|
||||||
|
`packagesFromDirectoryRecursive` will produce an attribute set like this:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
# packagesFromDirectoryRecursive {
|
||||||
|
# callPackage = pkgs.callPackage;
|
||||||
|
# directory = ./my-packages;
|
||||||
|
# }
|
||||||
|
{
|
||||||
|
a = pkgs.callPackage ./my-packages/a.nix { };
|
||||||
|
b = pkgs.callPackage ./my-packages/b.nix { };
|
||||||
|
c = pkgs.callPackage ./my-packages/c/package.nix { };
|
||||||
|
my-namespace = {
|
||||||
|
d = pkgs.callPackage ./my-packages/my-namespace/d.nix { };
|
||||||
|
e = pkgs.callPackage ./my-packages/my-namespace/e.nix { };
|
||||||
|
f = pkgs.callPackage ./my-packages/my-namespace/f/package.nix { };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In particular:
|
||||||
|
- If the input directory contains a `package.nix` file, then
|
||||||
|
`callPackage <directory>/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
|
||||||
|
where:
|
||||||
|
- The attribute name is the file name without the `.nix` extension
|
||||||
|
- The attribute value is `callPackage <file path> { }`
|
||||||
|
- 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
|
||||||
|
`packagesFromDirectoryRecursive { ... }` on the directory.
|
||||||
|
|
||||||
|
As a result, directories with no `.nix` files (including empty
|
||||||
|
directories) will be transformed into empty attribute sets.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
packagesFromDirectoryRecursive {
|
||||||
|
inherit (pkgs) callPackage;
|
||||||
|
directory = ./my-packages;
|
||||||
|
}
|
||||||
|
=> { ... }
|
||||||
|
|
||||||
|
lib.makeScope pkgs.newScope (
|
||||||
|
self: packagesFromDirectoryRecursive {
|
||||||
|
callPackage = self.callPackage;
|
||||||
|
directory = ./my-packages;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
=> { ... }
|
||||||
|
|
||||||
|
Type:
|
||||||
|
packagesFromDirectoryRecursive :: AttrSet -> AttrSet
|
||||||
|
*/
|
||||||
|
packagesFromDirectoryRecursive =
|
||||||
|
# Options.
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
`pkgs.callPackage`
|
||||||
|
|
||||||
|
Type:
|
||||||
|
Path -> AttrSet -> a
|
||||||
|
*/
|
||||||
|
callPackage,
|
||||||
|
/*
|
||||||
|
The directory to read package files from
|
||||||
|
|
||||||
|
Type:
|
||||||
|
Path
|
||||||
|
*/
|
||||||
|
directory,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
# Determine if a directory entry from `readDir` indicates a package or
|
||||||
|
# directory of packages.
|
||||||
|
directoryEntryIsPackage = basename: type:
|
||||||
|
type == "directory" || hasSuffix ".nix" basename;
|
||||||
|
|
||||||
|
# List directory entries that indicate packages in the given `path`.
|
||||||
|
packageDirectoryEntries = path:
|
||||||
|
filterAttrs directoryEntryIsPackage (readDir path);
|
||||||
|
|
||||||
|
# Transform a directory entry (a `basename` and `type` pair) into a
|
||||||
|
# package.
|
||||||
|
directoryEntryToAttrPair = subdirectory: basename: type:
|
||||||
|
let
|
||||||
|
path = subdirectory + "/${basename}";
|
||||||
|
in
|
||||||
|
if type == "regular"
|
||||||
|
then
|
||||||
|
{
|
||||||
|
name = removeSuffix ".nix" basename;
|
||||||
|
value = callPackage path { };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if type == "directory"
|
||||||
|
then
|
||||||
|
{
|
||||||
|
name = basename;
|
||||||
|
value = packagesFromDirectory path;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw
|
||||||
|
''
|
||||||
|
lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString subdirectory}
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Transform a directory into a package (if there's a `package.nix`) or
|
||||||
|
# set of packages (otherwise).
|
||||||
|
packagesFromDirectory = path:
|
||||||
|
let
|
||||||
|
defaultPackagePath = path + "/package.nix";
|
||||||
|
in
|
||||||
|
if pathExists defaultPackagePath
|
||||||
|
then callPackage defaultPackagePath { }
|
||||||
|
else mapAttrs'
|
||||||
|
(directoryEntryToAttrPair path)
|
||||||
|
(packageDirectoryEntries path);
|
||||||
|
in
|
||||||
|
packagesFromDirectory directory;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2055,4 +2055,37 @@ runTests {
|
||||||
expr = meta.platformMatch { } "x86_64-linux";
|
expr = meta.platformMatch { } "x86_64-linux";
|
||||||
expected = false;
|
expected = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
testPackagesFromDirectoryRecursive = {
|
||||||
|
expr = packagesFromDirectoryRecursive {
|
||||||
|
callPackage = path: overrides: import path overrides;
|
||||||
|
directory = ./packages-from-directory;
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
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 = {
|
||||||
|
d = "d";
|
||||||
|
e = "e";
|
||||||
|
f = "f";
|
||||||
|
my-sub-namespace = {
|
||||||
|
g = "g";
|
||||||
|
h = "h";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Check that `packagesFromDirectoryRecursive` can process a directory with a
|
||||||
|
# top-level `package.nix` file into a single package.
|
||||||
|
testPackagesFromDirectoryRecursiveTopLevelPackageNix = {
|
||||||
|
expr = packagesFromDirectoryRecursive {
|
||||||
|
callPackage = path: overrides: import path overrides;
|
||||||
|
directory = ./packages-from-directory/c;
|
||||||
|
};
|
||||||
|
expected = "c";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
2
lib/tests/packages-from-directory/a.nix
Normal file
2
lib/tests/packages-from-directory/a.nix
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
{ }:
|
||||||
|
"a"
|
2
lib/tests/packages-from-directory/b.nix
Normal file
2
lib/tests/packages-from-directory/b.nix
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
{ }:
|
||||||
|
"b"
|
2
lib/tests/packages-from-directory/c/package.nix
Normal file
2
lib/tests/packages-from-directory/c/package.nix
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
{ }:
|
||||||
|
"c"
|
2
lib/tests/packages-from-directory/my-namespace/d.nix
Normal file
2
lib/tests/packages-from-directory/my-namespace/d.nix
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
{ }:
|
||||||
|
"d"
|
2
lib/tests/packages-from-directory/my-namespace/e.nix
Normal file
2
lib/tests/packages-from-directory/my-namespace/e.nix
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
{ }:
|
||||||
|
"e"
|
|
@ -0,0 +1,2 @@
|
||||||
|
{ }:
|
||||||
|
"f"
|
|
@ -0,0 +1,2 @@
|
||||||
|
{ }:
|
||||||
|
"g"
|
|
@ -0,0 +1,2 @@
|
||||||
|
{ }:
|
||||||
|
"h"
|
Loading…
Reference in a new issue