Merge pull request #168778 from hercules-ci/issue-168767-extendModules-module-dedup-collision
`lib.types.submoduleWith`: Avoid `_key` collisions after `extendModules` (issue #168767)
This commit is contained in:
commit
27a62a9c60
4 changed files with 61 additions and 4 deletions
|
@ -113,6 +113,10 @@ rec {
|
||||||
args ? {}
|
args ? {}
|
||||||
, # This would be remove in the future, Prefer _module.check option instead.
|
, # This would be remove in the future, Prefer _module.check option instead.
|
||||||
check ? true
|
check ? true
|
||||||
|
# Internal variable to avoid `_key` collisions regardless
|
||||||
|
# of `extendModules`. Used in `submoduleWith`.
|
||||||
|
# Test case: lib/tests/modules, "168767"
|
||||||
|
, extensionOffset ? 0
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
withWarnings = x:
|
withWarnings = x:
|
||||||
|
@ -338,15 +342,17 @@ rec {
|
||||||
modules ? [],
|
modules ? [],
|
||||||
specialArgs ? {},
|
specialArgs ? {},
|
||||||
prefix ? [],
|
prefix ? [],
|
||||||
|
extensionOffset ? length modules,
|
||||||
}:
|
}:
|
||||||
evalModules (evalModulesArgs // {
|
evalModules (evalModulesArgs // {
|
||||||
modules = regularModules ++ modules;
|
modules = regularModules ++ modules;
|
||||||
specialArgs = evalModulesArgs.specialArgs or {} // specialArgs;
|
specialArgs = evalModulesArgs.specialArgs or {} // specialArgs;
|
||||||
prefix = extendArgs.prefix or evalModulesArgs.prefix;
|
prefix = extendArgs.prefix or evalModulesArgs.prefix;
|
||||||
|
inherit extensionOffset;
|
||||||
});
|
});
|
||||||
|
|
||||||
type = lib.types.submoduleWith {
|
type = lib.types.submoduleWith {
|
||||||
inherit modules specialArgs;
|
inherit modules specialArgs extensionOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
result = withWarnings {
|
result = withWarnings {
|
||||||
|
|
|
@ -293,7 +293,7 @@ checkConfigOutput '^"a c"$' config.result ./functionTo/merging-attrs.nix
|
||||||
|
|
||||||
# moduleType
|
# moduleType
|
||||||
checkConfigOutput '^"a b"$' config.resultFoo ./declare-variants.nix ./define-variant.nix
|
checkConfigOutput '^"a b"$' config.resultFoo ./declare-variants.nix ./define-variant.nix
|
||||||
checkConfigOutput '^"a y z"$' config.resultFooBar ./declare-variants.nix ./define-variant.nix
|
checkConfigOutput '^"a b y z"$' config.resultFooBar ./declare-variants.nix ./define-variant.nix
|
||||||
checkConfigOutput '^"a b c"$' config.resultFooFoo ./declare-variants.nix ./define-variant.nix
|
checkConfigOutput '^"a b c"$' config.resultFooFoo ./declare-variants.nix ./define-variant.nix
|
||||||
|
|
||||||
## emptyValue's
|
## emptyValue's
|
||||||
|
@ -327,6 +327,10 @@ checkConfigError 'The option .theOption.nested. in .other.nix. is already declar
|
||||||
# Test that types.optionType leaves types untouched as long as they don't need to be merged
|
# Test that types.optionType leaves types untouched as long as they don't need to be merged
|
||||||
checkConfigOutput 'ok' config.freeformItems.foo.bar ./adhoc-freeformType-survives-type-merge.nix
|
checkConfigOutput 'ok' config.freeformItems.foo.bar ./adhoc-freeformType-survives-type-merge.nix
|
||||||
|
|
||||||
|
# Anonymous submodules don't get nixed by import resolution/deduplication
|
||||||
|
# because of an `extendModules` bug, issue 168767.
|
||||||
|
checkConfigOutput '^1$' config.sub.specialisation.value ./extendModules-168767-imports.nix
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
====== module tests ======
|
====== module tests ======
|
||||||
$pass Pass
|
$pass Pass
|
||||||
|
|
41
lib/tests/modules/extendModules-168767-imports.nix
Normal file
41
lib/tests/modules/extendModules-168767-imports.nix
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
{ lib
|
||||||
|
, extendModules
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
with lib;
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
|
||||||
|
{
|
||||||
|
options.sub = mkOption {
|
||||||
|
default = { };
|
||||||
|
type = types.submodule (
|
||||||
|
{ config
|
||||||
|
, extendModules
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
options.value = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
|
||||||
|
options.specialisation = mkOption {
|
||||||
|
default = { };
|
||||||
|
inherit
|
||||||
|
(extendModules {
|
||||||
|
modules = [{
|
||||||
|
specialisation = mkOverride 0 { };
|
||||||
|
}];
|
||||||
|
})
|
||||||
|
type;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
{ config.sub.value = 1; }
|
||||||
|
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
|
@ -568,6 +568,11 @@ rec {
|
||||||
{ modules
|
{ modules
|
||||||
, specialArgs ? {}
|
, specialArgs ? {}
|
||||||
, shorthandOnlyDefinesConfig ? false
|
, shorthandOnlyDefinesConfig ? false
|
||||||
|
|
||||||
|
# Internal variable to avoid `_key` collisions regardless
|
||||||
|
# of `extendModules`. Wired through by `evalModules`.
|
||||||
|
# Test case: lib/tests/modules, "168767"
|
||||||
|
, extensionOffset ? 0
|
||||||
}@attrs:
|
}@attrs:
|
||||||
let
|
let
|
||||||
inherit (lib.modules) evalModules;
|
inherit (lib.modules) evalModules;
|
||||||
|
@ -579,11 +584,11 @@ rec {
|
||||||
allModules = defs: imap1 (n: { value, file }:
|
allModules = defs: imap1 (n: { value, file }:
|
||||||
if isFunction value
|
if isFunction value
|
||||||
then setFunctionArgs
|
then setFunctionArgs
|
||||||
(args: lib.modules.unifyModuleSyntax file "${toString file}-${toString n}" (value args))
|
(args: lib.modules.unifyModuleSyntax file "${toString file}-${toString (n + extensionOffset)}" (value args))
|
||||||
(functionArgs value)
|
(functionArgs value)
|
||||||
else if isAttrs value
|
else if isAttrs value
|
||||||
then
|
then
|
||||||
lib.modules.unifyModuleSyntax file "${toString file}-${toString n}" (shorthandToModule value)
|
lib.modules.unifyModuleSyntax file "${toString file}-${toString (n + extensionOffset)}" (shorthandToModule value)
|
||||||
else value
|
else value
|
||||||
) defs;
|
) defs;
|
||||||
|
|
||||||
|
@ -620,6 +625,7 @@ rec {
|
||||||
(base.extendModules {
|
(base.extendModules {
|
||||||
modules = [ { _module.args.name = last loc; } ] ++ allModules defs;
|
modules = [ { _module.args.name = last loc; } ] ++ allModules defs;
|
||||||
prefix = loc;
|
prefix = loc;
|
||||||
|
extensionOffset = extensionOffset + length defs;
|
||||||
}).config;
|
}).config;
|
||||||
emptyValue = { value = {}; };
|
emptyValue = { value = {}; };
|
||||||
getSubOptions = prefix: (base.extendModules
|
getSubOptions = prefix: (base.extendModules
|
||||||
|
|
Loading…
Reference in a new issue