Merge pull request #211855 from hercules-ci/lib-modules-disabledModules-module-with-key
lib/modules: Allow an "anonymous" module with key in disabledModules
This commit is contained in:
commit
6b79fe8cdc
@ -21,6 +21,7 @@ let
|
||||
isBool
|
||||
isFunction
|
||||
isList
|
||||
isPath
|
||||
isString
|
||||
length
|
||||
mapAttrs
|
||||
@ -45,6 +46,9 @@ let
|
||||
showOption
|
||||
unknownModule
|
||||
;
|
||||
inherit (lib.strings)
|
||||
isConvertibleWithToString
|
||||
;
|
||||
|
||||
showDeclPrefix = loc: decl: prefix:
|
||||
" - option(s) with prefix `${showOption (loc ++ [prefix])}' in module `${decl._file}'";
|
||||
@ -403,7 +407,7 @@ rec {
|
||||
key = module.key;
|
||||
module = module;
|
||||
modules = collectedImports.modules;
|
||||
disabled = module.disabledModules ++ collectedImports.disabled;
|
||||
disabled = (if module.disabledModules != [] then [{ file = module._file; disabled = module.disabledModules; }] else []) ++ collectedImports.disabled;
|
||||
}) initialModules);
|
||||
|
||||
# filterModules :: String -> { disabled, modules } -> [ Module ]
|
||||
@ -412,10 +416,30 @@ rec {
|
||||
# modules recursively. It returns the final list of unique-by-key modules
|
||||
filterModules = modulesPath: { disabled, modules }:
|
||||
let
|
||||
moduleKey = m: if isString m && (builtins.substring 0 1 m != "/")
|
||||
then toString modulesPath + "/" + m
|
||||
else toString m;
|
||||
disabledKeys = map moduleKey disabled;
|
||||
moduleKey = file: m:
|
||||
if isString m
|
||||
then
|
||||
if builtins.substring 0 1 m == "/"
|
||||
then m
|
||||
else toString modulesPath + "/" + m
|
||||
|
||||
else if isConvertibleWithToString m
|
||||
then
|
||||
if m?key && m.key != toString m
|
||||
then
|
||||
throw "Module `${file}` contains a disabledModules item that is an attribute set that can be converted to a string (${toString m}) but also has a `.key` attribute (${m.key}) with a different value. This makes it ambiguous which module should be disabled."
|
||||
else
|
||||
toString m
|
||||
|
||||
else if m?key
|
||||
then
|
||||
m.key
|
||||
|
||||
else if isAttrs m
|
||||
then throw "Module `${file}` contains a disabledModules item that is an attribute set, presumably a module, that does not have a `key` attribute. This means that the module system doesn't have any means to identify the module that should be disabled. Make sure that you've put the correct value in disabledModules: a string path relative to modulesPath, a path value, or an attribute set with a `key` attribute."
|
||||
else throw "Each disabledModules item must be a path, string, or a attribute set with a key attribute, or a value supported by toString. However, one of the disabledModules items in `${toString file}` is none of that, but is of type ${builtins.typeOf m}.";
|
||||
|
||||
disabledKeys = concatMap ({ file, disabled }: map (moduleKey file) disabled) disabled;
|
||||
keyFilter = filter (attrs: ! elem attrs.key disabledKeys);
|
||||
in map (attrs: attrs.module) (builtins.genericClosure {
|
||||
startSet = keyFilter modules;
|
||||
|
@ -141,6 +141,14 @@ checkConfigError "The option .*enable.* does not exist. Definition values:\n\s*-
|
||||
checkConfigError "attribute .*enable.* in selection path .*config.enable.* not found" "$@" ./disable-define-enable.nix ./disable-declare-enable.nix
|
||||
checkConfigError "attribute .*enable.* in selection path .*config.enable.* not found" "$@" ./disable-enable-modules.nix
|
||||
|
||||
checkConfigOutput '^true$' 'config.positive.enable' ./disable-module-with-key.nix
|
||||
checkConfigOutput '^false$' 'config.negative.enable' ./disable-module-with-key.nix
|
||||
checkConfigError 'Module ..*disable-module-bad-key.nix. contains a disabledModules item that is an attribute set, presumably a module, that does not have a .key. attribute. .*' 'config.enable' ./disable-module-bad-key.nix
|
||||
|
||||
# Not sure if we want to keep supporting module keys that aren't strings, paths or v?key, but we shouldn't remove support accidentally.
|
||||
checkConfigOutput '^true$' 'config.positive.enable' ./disable-module-with-toString-key.nix
|
||||
checkConfigOutput '^false$' 'config.negative.enable' ./disable-module-with-toString-key.nix
|
||||
|
||||
# Check _module.args.
|
||||
set -- config.enable ./declare-enable.nix ./define-enable-with-custom-arg.nix
|
||||
checkConfigError 'while evaluating the module argument .*custom.* in .*define-enable-with-custom-arg.nix.*:' "$@"
|
||||
@ -358,6 +366,10 @@ checkConfigOutput '^"The option `a\.b. defined in `.*/doRename-warnings\.nix. ha
|
||||
config.result \
|
||||
./doRename-warnings.nix
|
||||
|
||||
# Anonymous modules get deduplicated by key
|
||||
checkConfigOutput '^"pear"$' config.once.raw ./merge-module-with-key.nix
|
||||
checkConfigOutput '^"pear\\npear"$' config.twice.raw ./merge-module-with-key.nix
|
||||
|
||||
cat <<EOF
|
||||
====== module tests ======
|
||||
$pass Pass
|
||||
|
16
lib/tests/modules/disable-module-bad-key.nix
Normal file
16
lib/tests/modules/disable-module-bad-key.nix
Normal file
@ -0,0 +1,16 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
|
||||
moduleWithKey = { config, ... }: {
|
||||
config = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./declare-enable.nix
|
||||
];
|
||||
disabledModules = [ { } ];
|
||||
}
|
34
lib/tests/modules/disable-module-with-key.nix
Normal file
34
lib/tests/modules/disable-module-with-key.nix
Normal file
@ -0,0 +1,34 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
|
||||
moduleWithKey = {
|
||||
key = "disable-module-with-key.nix#moduleWithKey";
|
||||
config = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options = {
|
||||
positive = mkOption {
|
||||
type = types.submodule {
|
||||
imports = [
|
||||
./declare-enable.nix
|
||||
moduleWithKey
|
||||
];
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
negative = mkOption {
|
||||
type = types.submodule {
|
||||
imports = [
|
||||
./declare-enable.nix
|
||||
moduleWithKey
|
||||
];
|
||||
disabledModules = [ moduleWithKey ];
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
}
|
34
lib/tests/modules/disable-module-with-toString-key.nix
Normal file
34
lib/tests/modules/disable-module-with-toString-key.nix
Normal file
@ -0,0 +1,34 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
|
||||
moduleWithKey = {
|
||||
key = 123;
|
||||
config = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options = {
|
||||
positive = mkOption {
|
||||
type = types.submodule {
|
||||
imports = [
|
||||
./declare-enable.nix
|
||||
moduleWithKey
|
||||
];
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
negative = mkOption {
|
||||
type = types.submodule {
|
||||
imports = [
|
||||
./declare-enable.nix
|
||||
moduleWithKey
|
||||
];
|
||||
disabledModules = [ 123 ];
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
}
|
49
lib/tests/modules/merge-module-with-key.nix
Normal file
49
lib/tests/modules/merge-module-with-key.nix
Normal file
@ -0,0 +1,49 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
|
||||
moduleWithoutKey = {
|
||||
config = {
|
||||
raw = "pear";
|
||||
};
|
||||
};
|
||||
|
||||
moduleWithKey = {
|
||||
key = __curPos.file + "#moduleWithKey";
|
||||
config = {
|
||||
raw = "pear";
|
||||
};
|
||||
};
|
||||
|
||||
decl = {
|
||||
options = {
|
||||
raw = mkOption {
|
||||
type = types.lines;
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options = {
|
||||
once = mkOption {
|
||||
type = types.submodule {
|
||||
imports = [
|
||||
decl
|
||||
moduleWithKey
|
||||
moduleWithKey
|
||||
];
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
twice = mkOption {
|
||||
type = types.submodule {
|
||||
imports = [
|
||||
decl
|
||||
moduleWithoutKey
|
||||
moduleWithoutKey
|
||||
];
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
}
|
@ -8,8 +8,15 @@ the system on a stable release.
|
||||
|
||||
`disabledModules` is a top level attribute like `imports`, `options` and
|
||||
`config`. It contains a list of modules that will be disabled. This can
|
||||
either be the full path to the module or a string with the filename
|
||||
relative to the modules path (eg. \<nixpkgs/nixos/modules> for nixos).
|
||||
either be:
|
||||
- the full path to the module,
|
||||
- or a string with the filename relative to the modules path (eg. \<nixpkgs/nixos/modules> for nixos),
|
||||
- or an attribute set containing a specific `key` attribute.
|
||||
|
||||
The latter allows some modules to be disabled, despite them being distributed
|
||||
via attributes instead of file paths. The `key` should be globally unique, so
|
||||
it is recommended to include a file path in it, or rely on a framework to do it
|
||||
for you.
|
||||
|
||||
This example will replace the existing postgresql module with the
|
||||
version defined in the nixos-unstable channel while keeping the rest of
|
||||
|
Loading…
Reference in New Issue
Block a user