lib.evalModules: add graph attribute
Co-authored-by: Ali Jamadi <jamadi1377@gmail.com>
This commit is contained in:
parent
2c1ec14d12
commit
5186921ded
@ -116,6 +116,16 @@ A nominal type marker, always `"configuration"`.
|
|||||||
|
|
||||||
The [`class` argument](#module-system-lib-evalModules-param-class).
|
The [`class` argument](#module-system-lib-evalModules-param-class).
|
||||||
|
|
||||||
|
#### `graph` {#module-system-lib-evalModules-return-value-graph}
|
||||||
|
|
||||||
|
Represents all the modules that took part in the evaluation.
|
||||||
|
It is a list of `ModuleGraph` where `ModuleGraph` is defined as an attribute set with the following attributes:
|
||||||
|
|
||||||
|
- `key`: `string` for the purpose of module deduplication and `disabledModules`
|
||||||
|
- `file`: `string` for the purpose of error messages and warnings
|
||||||
|
- `imports`: `[ ModuleGraph ]`
|
||||||
|
- `disabled`: `bool`
|
||||||
|
|
||||||
## Module arguments {#module-system-module-arguments}
|
## Module arguments {#module-system-module-arguments}
|
||||||
|
|
||||||
Module arguments are the attribute values passed to modules when they are evaluated.
|
Module arguments are the attribute values passed to modules when they are evaluated.
|
||||||
|
@ -487,6 +487,9 @@
|
|||||||
"module-system-lib-evalModules-return-value-_configurationClass": [
|
"module-system-lib-evalModules-return-value-_configurationClass": [
|
||||||
"index.html#module-system-lib-evalModules-return-value-_configurationClass"
|
"index.html#module-system-lib-evalModules-return-value-_configurationClass"
|
||||||
],
|
],
|
||||||
|
"module-system-lib-evalModules-return-value-graph": [
|
||||||
|
"index.html#module-system-lib-evalModules-return-value-graph"
|
||||||
|
],
|
||||||
"part-stdenv": [
|
"part-stdenv": [
|
||||||
"index.html#part-stdenv"
|
"index.html#part-stdenv"
|
||||||
],
|
],
|
||||||
|
@ -245,11 +245,12 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
merged =
|
# This function takes an empty attrset as an argument.
|
||||||
let
|
# It could theoretically be replaced with its body,
|
||||||
collected =
|
# but such a binding is avoided to allow for earlier grabage collection.
|
||||||
collectModules class (specialArgs.modulesPath or "") (regularModules ++ [ internalModule ])
|
doCollect =
|
||||||
(
|
{ }:
|
||||||
|
collectModules class (specialArgs.modulesPath or "") (regularModules ++ [ internalModule ]) (
|
||||||
{
|
{
|
||||||
inherit
|
inherit
|
||||||
lib
|
lib
|
||||||
@ -262,8 +263,8 @@ let
|
|||||||
}
|
}
|
||||||
// specialArgs
|
// specialArgs
|
||||||
);
|
);
|
||||||
in
|
|
||||||
mergeModules prefix (reverseList collected);
|
merged = mergeModules prefix (reverseList (doCollect { }).modules);
|
||||||
|
|
||||||
options = merged.matchedOptions;
|
options = merged.matchedOptions;
|
||||||
|
|
||||||
@ -359,12 +360,13 @@ let
|
|||||||
options = checked options;
|
options = checked options;
|
||||||
config = checked (removeAttrs config [ "_module" ]);
|
config = checked (removeAttrs config [ "_module" ]);
|
||||||
_module = checked (config._module);
|
_module = checked (config._module);
|
||||||
|
inherit (doCollect { }) graph;
|
||||||
inherit extendModules type class;
|
inherit extendModules type class;
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
result;
|
result;
|
||||||
|
|
||||||
# collectModules :: (class: String) -> (modulesPath: String) -> (modules: [ Module ]) -> (args: Attrs) -> [ Module ]
|
# collectModules :: (class: String) -> (modulesPath: String) -> (modules: [ Module ]) -> (args: Attrs) -> ModulesTree
|
||||||
#
|
#
|
||||||
# Collects all modules recursively through `import` statements, filtering out
|
# Collects all modules recursively through `import` statements, filtering out
|
||||||
# all modules in disabledModules.
|
# all modules in disabledModules.
|
||||||
@ -529,9 +531,25 @@ let
|
|||||||
operator = attrs: keyFilter attrs.modules;
|
operator = attrs: keyFilter attrs.modules;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
toGraph =
|
||||||
|
modulesPath:
|
||||||
|
{ disabled, modules }:
|
||||||
|
let
|
||||||
|
isDisabledModule = isDisabled modulesPath disabled;
|
||||||
|
|
||||||
|
toModuleGraph = structuredModule: {
|
||||||
|
disabled = isDisabledModule structuredModule;
|
||||||
|
inherit (structuredModule) key;
|
||||||
|
file = structuredModule.module._file;
|
||||||
|
imports = map toModuleGraph structuredModule.modules;
|
||||||
|
};
|
||||||
in
|
in
|
||||||
modulesPath: initialModules: args:
|
map toModuleGraph (filter (x: x.key != "lib/modules.nix") modules);
|
||||||
filterModules modulesPath (collectStructuredModules unknownModule "" initialModules args);
|
in
|
||||||
|
modulesPath: initialModules: args: {
|
||||||
|
modules = filterModules modulesPath (collectStructuredModules unknownModule "" initialModules args);
|
||||||
|
graph = toGraph modulesPath (collectStructuredModules unknownModule "" initialModules args);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Wrap a module with a default location for reporting errors.
|
Wrap a module with a default location for reporting errors.
|
||||||
|
@ -20,6 +20,10 @@ cd "$DIR"/modules
|
|||||||
pass=0
|
pass=0
|
||||||
fail=0
|
fail=0
|
||||||
|
|
||||||
|
local-nix-instantiate() {
|
||||||
|
nix-instantiate --timeout 1 --eval-only --show-trace --read-write-mode --json "$@"
|
||||||
|
}
|
||||||
|
|
||||||
# loc
|
# loc
|
||||||
# prints the location of the call of to the function that calls it
|
# prints the location of the call of to the function that calls it
|
||||||
# loc n
|
# loc n
|
||||||
@ -55,7 +59,7 @@ evalConfig() {
|
|||||||
local attr=$1
|
local attr=$1
|
||||||
shift
|
shift
|
||||||
local script="import ./default.nix { modules = [ $* ];}"
|
local script="import ./default.nix { modules = [ $* ];}"
|
||||||
nix-instantiate --timeout 1 -E "$script" -A "$attr" --eval-only --show-trace --read-write-mode --json
|
local-nix-instantiate -E "$script" -A "$attr"
|
||||||
}
|
}
|
||||||
|
|
||||||
reportFailure() {
|
reportFailure() {
|
||||||
@ -106,6 +110,20 @@ globalErrorLogCheck() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkExpression() {
|
||||||
|
local path=$1
|
||||||
|
local output
|
||||||
|
{
|
||||||
|
output="$(local-nix-instantiate --strict "$path" 2>&1)" && ((++pass))
|
||||||
|
} || {
|
||||||
|
logStartFailure
|
||||||
|
echo "$output"
|
||||||
|
((++fail))
|
||||||
|
logFailure
|
||||||
|
logEndFailure
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
checkConfigError() {
|
checkConfigError() {
|
||||||
local errorContains=$1
|
local errorContains=$1
|
||||||
local err=""
|
local err=""
|
||||||
@ -337,6 +355,9 @@ checkConfigOutput '^12$' config.value ./declare-coerced-value-unsound.nix
|
|||||||
checkConfigError 'A definition for option .* is not of type .*. Definition values:\n\s*- In .*: "1000"' config.value ./declare-coerced-value-unsound.nix ./define-value-string-bigint.nix
|
checkConfigError 'A definition for option .* is not of type .*. Definition values:\n\s*- In .*: "1000"' config.value ./declare-coerced-value-unsound.nix ./define-value-string-bigint.nix
|
||||||
checkConfigError 'toInt: Could not convert .* to int' config.value ./declare-coerced-value-unsound.nix ./define-value-string-arbitrary.nix
|
checkConfigError 'toInt: Could not convert .* to int' config.value ./declare-coerced-value-unsound.nix ./define-value-string-arbitrary.nix
|
||||||
|
|
||||||
|
# Check `graph` attribute
|
||||||
|
checkExpression './graph/test.nix'
|
||||||
|
|
||||||
# Check mkAliasOptionModule.
|
# Check mkAliasOptionModule.
|
||||||
checkConfigOutput '^true$' config.enable ./alias-with-priority.nix
|
checkConfigOutput '^true$' config.enable ./alias-with-priority.nix
|
||||||
checkConfigOutput '^true$' config.enableAlias ./alias-with-priority.nix
|
checkConfigOutput '^true$' config.enableAlias ./alias-with-priority.nix
|
||||||
|
8
lib/tests/modules/graph/a.nix
Normal file
8
lib/tests/modules/graph/a.nix
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
imports = [
|
||||||
|
{
|
||||||
|
imports = [ { } ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
disabledModules = [ ./b.nix ];
|
||||||
|
}
|
3
lib/tests/modules/graph/b.nix
Normal file
3
lib/tests/modules/graph/b.nix
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
args: {
|
||||||
|
imports = [ { key = "explicit-key"; } ];
|
||||||
|
}
|
64
lib/tests/modules/graph/test.nix
Normal file
64
lib/tests/modules/graph/test.nix
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
let
|
||||||
|
lib = import ../../..;
|
||||||
|
|
||||||
|
evaluation = lib.evalModules {
|
||||||
|
modules = [
|
||||||
|
{ }
|
||||||
|
(args: { })
|
||||||
|
./a.nix
|
||||||
|
./b.nix
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
actual = evaluation.graph;
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
{
|
||||||
|
key = ":anon-1";
|
||||||
|
file = "<unknown-file>";
|
||||||
|
imports = [ ];
|
||||||
|
disabled = false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
key = ":anon-2";
|
||||||
|
file = "<unknown-file>";
|
||||||
|
imports = [ ];
|
||||||
|
disabled = false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
key = toString ./a.nix;
|
||||||
|
file = toString ./a.nix;
|
||||||
|
imports = [
|
||||||
|
{
|
||||||
|
key = "${toString ./a.nix}:anon-1";
|
||||||
|
file = toString ./a.nix;
|
||||||
|
imports = [
|
||||||
|
{
|
||||||
|
key = "${toString ./a.nix}:anon-1:anon-1";
|
||||||
|
file = toString ./a.nix;
|
||||||
|
imports = [ ];
|
||||||
|
disabled = false;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
disabled = false;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
disabled = false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
key = toString ./b.nix;
|
||||||
|
file = toString ./b.nix;
|
||||||
|
imports = [
|
||||||
|
{
|
||||||
|
key = "explicit-key";
|
||||||
|
file = toString ./b.nix;
|
||||||
|
imports = [ ];
|
||||||
|
disabled = false;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
in
|
||||||
|
assert actual == expected;
|
||||||
|
null
|
Loading…
x
Reference in New Issue
Block a user