mirror of
https://github.com/divnix/digga.git
synced 2024-12-23 08:02:21 +03:00
rakeLeaves: create and use standard auto-importer
The function picks up `.nix` files and stops recursing when it hits a folder with a `default.nix` This allows it to be used to collect hosts, overlays, and profiles
This commit is contained in:
parent
8065740c86
commit
237e0bce9b
@ -40,9 +40,9 @@
|
||||
};
|
||||
|
||||
inherit (attrs) mapFilterAttrs genAttrs' safeReadDir concatAttrs;
|
||||
inherit (lists) profileMap collectProfiles unifyOverlays;
|
||||
inherit (lists) unifyOverlays;
|
||||
inherit (strings) rgxToString;
|
||||
inherit (importers) mkProfileAttrs pathsIn importHosts;
|
||||
inherit (importers) profileMap rakeLeaves;
|
||||
inherit (generators) mkSuites mkDeployNodes mkHomeConfigurations;
|
||||
}
|
||||
);
|
||||
|
@ -37,14 +37,14 @@
|
||||
let
|
||||
profileSet = lib.genAttrs' profiles (path: {
|
||||
name = baseNameOf path;
|
||||
value = lib.mkProfileAttrs (toString path);
|
||||
value = lib.rakeLeaves (toString path);
|
||||
});
|
||||
|
||||
definedSuites = suites profileSet;
|
||||
definedSuites = lib.mapAttrs (_: v: lib.profileMap v) (suites profileSet);
|
||||
|
||||
allProfiles = lib.collectProfiles profileSet;
|
||||
allProfiles = lib.foldl (lhs: rhs: lhs ++ rhs) [ ] (builtins.attrValues definedSuites);
|
||||
in
|
||||
lib.mapAttrs (_: v: lib.profileMap v) definedSuites // {
|
||||
definedSuites // {
|
||||
inherit allProfiles;
|
||||
};
|
||||
}
|
||||
|
@ -1,73 +1,84 @@
|
||||
{ lib }:
|
||||
let
|
||||
recImport = { dir, _import ? base: import "${dir}/${base}.nix" }:
|
||||
lib.mapFilterAttrs
|
||||
(_: v: v != null)
|
||||
(n: v:
|
||||
if n != "default.nix" && lib.hasSuffix ".nix" n && v == "regular"
|
||||
then
|
||||
let name = lib.removeSuffix ".nix" n; in lib.nameValuePair (name) (_import name)
|
||||
else
|
||||
lib.nameValuePair ("") (null))
|
||||
(lib.safeReadDir dir);
|
||||
|
||||
mkProfileAttrs =
|
||||
rakeLeaves =
|
||||
/**
|
||||
Synopsis: mkProfileAttrs _path_
|
||||
Synopsis: rakeLeaves _path_
|
||||
|
||||
Recursively collect the subdirs of _path_ containing a default.nix into attrs.
|
||||
This sets a contract, eliminating ambiguity for _default.nix_ living under the
|
||||
profile directory.
|
||||
Recursively collect the nix files of _path_ into attrs.
|
||||
|
||||
Example:
|
||||
let profiles = mkProfileAttrs ./profiles; in
|
||||
assert profiles ? core.default; 0
|
||||
Output Format:
|
||||
An attribute set where all `.nix` files and directories with `default.nix` in them
|
||||
are mapped to keys(file with .nix stripped or folder name. All other directories
|
||||
are recursed further into nested attribute sets with the same format.
|
||||
|
||||
Example file structure:
|
||||
```
|
||||
./core/default.nix
|
||||
./base.nix
|
||||
./main/dev.nix
|
||||
./main/os/default.nix
|
||||
```
|
||||
Example output:
|
||||
```
|
||||
{
|
||||
core = ./core;
|
||||
base = base.nix;
|
||||
main = {
|
||||
dev = ./main/dev.nix;
|
||||
os = ./main/os;
|
||||
};
|
||||
}
|
||||
```
|
||||
**/
|
||||
dir:
|
||||
dirPath:
|
||||
let
|
||||
imports =
|
||||
let
|
||||
files = lib.safeReadDir dir;
|
||||
# Relative paths cause issues, so convert to string immediately
|
||||
dir = toString dirPath;
|
||||
|
||||
p = n: v:
|
||||
v == "directory"
|
||||
&& n != "profiles";
|
||||
in
|
||||
lib.filterAttrs p files;
|
||||
collect = file: type: {
|
||||
name = lib.removeSuffix ".nix" file;
|
||||
value = let path = "${dir}/${file}"; in
|
||||
if (type == "regular")
|
||||
|| (type == "directory" && builtins.pathExists "${path}/default.nix")
|
||||
then path
|
||||
else rakeLeaves path;
|
||||
};
|
||||
|
||||
f = n: _:
|
||||
lib.optionalAttrs
|
||||
(lib.pathExists "${dir}/${n}/default.nix")
|
||||
{ default = "${dir}/${n}"; }
|
||||
// mkProfileAttrs "${dir}/${n}";
|
||||
files = lib.filterAttrs
|
||||
(file: type:
|
||||
# Only include `.nix` files or directories
|
||||
(type == "regular" && lib.hasSuffix ".nix" file) || (type == "directory")
|
||||
)
|
||||
(lib.safeReadDir dir);
|
||||
in
|
||||
lib.mapAttrs f imports;
|
||||
|
||||
pathsIn = dir:
|
||||
let
|
||||
fullPath = name: "${toString dir}/${name}";
|
||||
in
|
||||
map fullPath (lib.attrNames (lib.safeReadDir dir));
|
||||
lib.mapAttrs' collect files;
|
||||
|
||||
getProfilePath = fallback: item:
|
||||
if lib.isString item then item else fallback;
|
||||
in
|
||||
{
|
||||
inherit pathsIn recImport mkProfileAttrs;
|
||||
inherit rakeLeaves;
|
||||
|
||||
profileMap = list: map
|
||||
(p: getProfilePath (throw "passed profile ${builtins.toJSON p} isn't a path") p)
|
||||
(lib.flatten list);
|
||||
|
||||
overlays = dir:
|
||||
{
|
||||
# Meant to output a module that sets the overlays option
|
||||
overlays = pathsIn dir;
|
||||
# Only get top-level .nix files or default.nix from directories
|
||||
overlays = map (getProfilePath (_: _: { })) (builtins.attrValues (rakeLeaves dir));
|
||||
};
|
||||
|
||||
hosts = dir:
|
||||
{
|
||||
# Meant to output a module that sets the hosts option
|
||||
hosts = recImport {
|
||||
inherit dir;
|
||||
_import = base: {
|
||||
modules = import "${toString dir}/${base}.nix";
|
||||
};
|
||||
};
|
||||
hosts = lib.mapAttrs
|
||||
(n: p: {
|
||||
# Only get top-level .nix files or default.nix from directories
|
||||
modules = getProfilePath { } p;
|
||||
})
|
||||
(rakeLeaves dir);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,4 @@
|
||||
{ lib }:
|
||||
{
|
||||
collectProfiles = set:
|
||||
let
|
||||
collectNestedProfiles = set:
|
||||
lib.mapAttrsToList
|
||||
(n: v:
|
||||
if builtins.isAttrs v then
|
||||
[ v.default or null ] ++ collectNestedProfiles v
|
||||
else null
|
||||
)
|
||||
set;
|
||||
in
|
||||
builtins.filter (x: x != null) (lib.flatten (collectNestedProfiles set));
|
||||
|
||||
profileMap = list: map (profile: profile.default) (lib.flatten list);
|
||||
|
||||
unifyOverlays = channels: map (o: if builtins.isFunction (o null null) then o channels else o);
|
||||
}
|
||||
|
@ -1,93 +0,0 @@
|
||||
{ pkgs, lib, ... }:
|
||||
with lib;
|
||||
lib.runTests {
|
||||
testConcatAttrs = {
|
||||
expr = concatAttrs [{ foo = 1; } { bar = 2; } { baz = 3; }];
|
||||
|
||||
expected = { foo = 1; bar = 2; baz = 3; };
|
||||
};
|
||||
|
||||
testGenAttrs' = {
|
||||
expr = genAttrs'
|
||||
[ "/foo/bar" "/baz/buzz" ]
|
||||
(path: {
|
||||
name = baseNameOf path;
|
||||
value = "${path}/fizz";
|
||||
});
|
||||
|
||||
expected = { bar = "/foo/bar/fizz"; buzz = "/baz/buzz/fizz"; };
|
||||
};
|
||||
|
||||
testMapFilterAttrs = {
|
||||
expr = mapFilterAttrs
|
||||
(n: v: n == "foobar" && v == 1)
|
||||
(n: v: lib.nameValuePair ("${n}bar") (v + 1))
|
||||
{ foo = 0; bar = 2; };
|
||||
|
||||
expected = { foobar = 1; };
|
||||
};
|
||||
|
||||
testPathsIn = {
|
||||
expr = pathsIn (toString ./testPathsIn);
|
||||
|
||||
expected = map toString [
|
||||
./testPathsIn/bar
|
||||
./testPathsIn/baz
|
||||
./testPathsIn/foo
|
||||
];
|
||||
};
|
||||
|
||||
testPathsToImportedAttrs = {
|
||||
expr =
|
||||
pathsToImportedAttrs [
|
||||
(toString ./testPathsToImportedAttrs/dir)
|
||||
./testPathsToImportedAttrs/foo.nix
|
||||
./testPathsToImportedAttrs/bar.nix
|
||||
./testPathsToImportedAttrs/t.nix
|
||||
./testPathsToImportedAttrs/f.nix
|
||||
];
|
||||
|
||||
expected = {
|
||||
dir = { a = 5; };
|
||||
foo = { bar = 1; };
|
||||
bar = { foo = 2; };
|
||||
t = true;
|
||||
f = false;
|
||||
};
|
||||
};
|
||||
|
||||
testRgxToString = lib.testAllTrue [
|
||||
(rgxToString ".+x" "vxk" == "vx")
|
||||
(rgxToString "^fo" "foo" == "fo")
|
||||
(rgxToString "a?" "a" == "a")
|
||||
(rgxToString "hat" "foohatbar" == "hat")
|
||||
];
|
||||
|
||||
testSafeReadDir = {
|
||||
expr = safeReadDir ./profiles // safeReadDir ./nonexistentdir;
|
||||
expected = {
|
||||
foo = "directory";
|
||||
t = "directory";
|
||||
};
|
||||
};
|
||||
|
||||
testSuites =
|
||||
let
|
||||
profiles = os.mkProfileAttrs (toString ./profiles);
|
||||
users = "";
|
||||
userProfiles = "";
|
||||
suites = { profiles, ... }: {
|
||||
system.bar = [ profiles.foo ];
|
||||
};
|
||||
in
|
||||
{
|
||||
expr = os.mkSuites { inherit profiles users userProfiles suites; };
|
||||
expected = {
|
||||
system = {
|
||||
bar = [ profiles.foo.default ];
|
||||
allProfiles = [ profiles.foo.default profiles.t.default ];
|
||||
allUsers = [ ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
{ users, profiles, userProfiles, ... }:
|
||||
|
||||
{
|
||||
system = with profiles; rec {
|
||||
base = [ core users.nixos users.root ];
|
||||
};
|
||||
user = with userProfiles; rec {
|
||||
base = [ direnv git ];
|
||||
};
|
||||
}
|
@ -27,16 +27,6 @@ lib.runTests {
|
||||
expected = { foobar = 1; };
|
||||
};
|
||||
|
||||
testPathsIn = {
|
||||
expr = pathsIn (toString ./testPathsIn);
|
||||
|
||||
expected = map toString [
|
||||
./testPathsIn/bar
|
||||
./testPathsIn/baz
|
||||
./testPathsIn/foo
|
||||
];
|
||||
};
|
||||
|
||||
testRgxToString = lib.testAllTrue [
|
||||
(rgxToString ".+x" "vxk" == "vx")
|
||||
(rgxToString "^fo" "foo" == "fo")
|
||||
@ -49,21 +39,22 @@ lib.runTests {
|
||||
expected = {
|
||||
foo = "directory";
|
||||
t = "directory";
|
||||
"f.nix" = "regular";
|
||||
};
|
||||
};
|
||||
|
||||
testSuites = {
|
||||
expr = mkSuites {
|
||||
suites = { profiles, ... }: with profiles; {
|
||||
bar = [ foo ];
|
||||
bar = [ foo f ];
|
||||
};
|
||||
profiles = [ (./profiles) ];
|
||||
};
|
||||
expected = {
|
||||
bar = [ (toString ./profiles/foo) ];
|
||||
bar = [ (toString ./profiles/foo) (toString ./profiles/f.nix) ];
|
||||
allProfiles = [
|
||||
(toString ./profiles/foo)
|
||||
(toString ./profiles/t)
|
||||
(toString ./profiles/f.nix)
|
||||
];
|
||||
};
|
||||
};
|
||||
|
0
tests/profiles/f.nix
Normal file
0
tests/profiles/f.nix
Normal file
Loading…
Reference in New Issue
Block a user