forked from mirrors/nixpkgs
Merge pull request #76857 from Infinisil/recursive-disableModules
Apply `disabledModules` recursively
This commit is contained in:
commit
e9c16ec186
|
@ -101,7 +101,7 @@ let
|
|||
cleanSource sourceByRegex sourceFilesBySuffices
|
||||
commitIdFromGitRepo cleanSourceWith pathHasContext
|
||||
canCleanSource;
|
||||
inherit (modules) evalModules closeModules unifyModuleSyntax
|
||||
inherit (modules) evalModules unifyModuleSyntax
|
||||
applyIfFunction mergeModules
|
||||
mergeModules' mergeOptionDecls evalOptionValue mergeDefinitions
|
||||
pushDownProperties dischargeProperties filterOverrides
|
||||
|
@ -110,7 +110,7 @@ let
|
|||
mkFixStrictness mkOrder mkBefore mkAfter mkAliasDefinitions
|
||||
mkAliasAndWrapDefinitions fixMergeModules mkRemovedOptionModule
|
||||
mkRenamedOptionModule mkMergedOptionModule mkChangedOptionModule
|
||||
mkAliasOptionModule doRename filterModules;
|
||||
mkAliasOptionModule doRename;
|
||||
inherit (options) isOption mkEnableOption mkSinkUndeclaredOptions
|
||||
mergeDefaultOption mergeOneOption mergeEqualOption getValues
|
||||
getFiles optionAttrSetToDocList optionAttrSetToDocList'
|
||||
|
|
|
@ -59,9 +59,12 @@ rec {
|
|||
};
|
||||
};
|
||||
|
||||
closed = closeModules (modules ++ [ internalModule ]) ({ inherit config options lib; } // specialArgs);
|
||||
collected = collectModules
|
||||
(specialArgs.modulesPath or "")
|
||||
(modules ++ [ internalModule ])
|
||||
({ inherit config options lib; } // specialArgs);
|
||||
|
||||
options = mergeModules prefix (reverseList (filterModules (specialArgs.modulesPath or "") closed));
|
||||
options = mergeModules prefix (reverseList collected);
|
||||
|
||||
# Traverse options and extract the option values into the final
|
||||
# config set. At the same time, check whether all option
|
||||
|
@ -87,31 +90,76 @@ rec {
|
|||
result = { inherit options config; };
|
||||
in result;
|
||||
|
||||
# collectModules :: (modulesPath: String) -> (modules: [ Module ]) -> (args: Attrs) -> [ Module ]
|
||||
#
|
||||
# Collects all modules recursively through `import` statements, filtering out
|
||||
# all modules in disabledModules.
|
||||
collectModules = let
|
||||
|
||||
# Filter disabled modules. Modules can be disabled allowing
|
||||
# their implementation to be replaced.
|
||||
filterModules = modulesPath: modules:
|
||||
let
|
||||
moduleKey = m: if isString m then toString modulesPath + "/" + m else toString m;
|
||||
disabledKeys = map moduleKey (concatMap (m: m.disabledModules) modules);
|
||||
in
|
||||
filter (m: !(elem m.key disabledKeys)) modules;
|
||||
# Like unifyModuleSyntax, but also imports paths and calls functions if necessary
|
||||
loadModule = args: fallbackFile: fallbackKey: m:
|
||||
if isFunction m || isAttrs m then
|
||||
unifyModuleSyntax fallbackFile fallbackKey (applyIfFunction fallbackKey m args)
|
||||
else unifyModuleSyntax (toString m) (toString m) (applyIfFunction (toString m) (import m) args);
|
||||
|
||||
/* Close a set of modules under the ‘imports’ relation. */
|
||||
closeModules = modules: args:
|
||||
let
|
||||
toClosureList = file: parentKey: imap1 (n: x:
|
||||
if isAttrs x || isFunction x then
|
||||
let key = "${parentKey}:anon-${toString n}"; in
|
||||
unifyModuleSyntax file key (applyIfFunction key x args)
|
||||
else
|
||||
let file = toString x; key = toString x; in
|
||||
unifyModuleSyntax file key (applyIfFunction key (import x) args));
|
||||
in
|
||||
builtins.genericClosure {
|
||||
startSet = toClosureList unknownModule "" modules;
|
||||
operator = m: toClosureList m._file m.key m.imports;
|
||||
};
|
||||
/*
|
||||
Collects all modules recursively into the form
|
||||
|
||||
{
|
||||
disabled = [ <list of disabled modules> ];
|
||||
# All modules of the main module list
|
||||
modules = [
|
||||
{
|
||||
key = <key1>;
|
||||
module = <module for key1>;
|
||||
# All modules imported by the module for key1
|
||||
modules = [
|
||||
{
|
||||
key = <key1-1>;
|
||||
module = <module for key1-1>;
|
||||
# All modules imported by the module for key1-1
|
||||
modules = [ ... ];
|
||||
}
|
||||
...
|
||||
];
|
||||
}
|
||||
...
|
||||
];
|
||||
}
|
||||
*/
|
||||
collectStructuredModules =
|
||||
let
|
||||
collectResults = modules: {
|
||||
disabled = concatLists (catAttrs "disabled" modules);
|
||||
inherit modules;
|
||||
};
|
||||
in parentFile: parentKey: initialModules: args: collectResults (imap1 (n: x:
|
||||
let
|
||||
module = loadModule args parentFile "${parentKey}:anon-${toString n}" x;
|
||||
collectedImports = collectStructuredModules module._file module.key module.imports args;
|
||||
in {
|
||||
key = module.key;
|
||||
module = module;
|
||||
modules = collectedImports.modules;
|
||||
disabled = module.disabledModules ++ collectedImports.disabled;
|
||||
}) initialModules);
|
||||
|
||||
# filterModules :: String -> { disabled, modules } -> [ Module ]
|
||||
#
|
||||
# Filters a structure as emitted by collectStructuredModules by removing all disabled
|
||||
# modules recursively. It returns the final list of unique-by-key modules
|
||||
filterModules = modulesPath: { disabled, modules }:
|
||||
let
|
||||
moduleKey = m: if isString m then toString modulesPath + "/" + m else toString m;
|
||||
disabledKeys = listToAttrs (map (k: nameValuePair (moduleKey k) null) disabled);
|
||||
keyFilter = filter (attrs: ! disabledKeys ? ${attrs.key});
|
||||
in map (attrs: attrs.module) (builtins.genericClosure {
|
||||
startSet = keyFilter modules;
|
||||
operator = attrs: keyFilter attrs.modules;
|
||||
});
|
||||
|
||||
in modulesPath: initialModules: args:
|
||||
filterModules modulesPath (collectStructuredModules unknownModule "" initialModules args);
|
||||
|
||||
/* Massage a module into canonical form, that is, a set consisting
|
||||
of ‘options’, ‘config’ and ‘imports’ attributes. */
|
||||
|
|
|
@ -177,6 +177,12 @@ checkConfigOutput "true" config.submodule.outer ./declare-submoduleWith-modules.
|
|||
# Temporarily disabled until https://github.com/NixOS/nixpkgs/pull/76861
|
||||
#checkConfigOutput "true" config.submodule.enable ./declare-submoduleWith-path.nix
|
||||
|
||||
# Check that disabledModules works recursively and correctly
|
||||
checkConfigOutput "true" config.enable ./disable-recursive/main.nix
|
||||
checkConfigOutput "true" config.enable ./disable-recursive/{main.nix,disable-foo.nix}
|
||||
checkConfigOutput "true" config.enable ./disable-recursive/{main.nix,disable-bar.nix}
|
||||
checkConfigError 'The option .* defined in .* does not exist' config.enable ./disable-recursive/{main.nix,disable-foo.nix,disable-bar.nix}
|
||||
|
||||
cat <<EOF
|
||||
====== module tests ======
|
||||
$pass Pass
|
||||
|
|
5
lib/tests/modules/disable-recursive/bar.nix
Normal file
5
lib/tests/modules/disable-recursive/bar.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
../declare-enable.nix
|
||||
];
|
||||
}
|
7
lib/tests/modules/disable-recursive/disable-bar.nix
Normal file
7
lib/tests/modules/disable-recursive/disable-bar.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
|
||||
disabledModules = [
|
||||
./bar.nix
|
||||
];
|
||||
|
||||
}
|
7
lib/tests/modules/disable-recursive/disable-foo.nix
Normal file
7
lib/tests/modules/disable-recursive/disable-foo.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
|
||||
disabledModules = [
|
||||
./foo.nix
|
||||
];
|
||||
|
||||
}
|
5
lib/tests/modules/disable-recursive/foo.nix
Normal file
5
lib/tests/modules/disable-recursive/foo.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
../declare-enable.nix
|
||||
];
|
||||
}
|
8
lib/tests/modules/disable-recursive/main.nix
Normal file
8
lib/tests/modules/disable-recursive/main.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
imports = [
|
||||
./foo.nix
|
||||
./bar.nix
|
||||
];
|
||||
|
||||
enable = true;
|
||||
}
|
|
@ -6,8 +6,8 @@
|
|||
<title>Replace Modules</title>
|
||||
|
||||
<para>
|
||||
Modules that are imported can also be disabled. The option declarations and
|
||||
config implementation of a disabled module will be ignored, allowing another
|
||||
Modules that are imported can also be disabled. The option declarations,
|
||||
config implementation and the imports of a disabled module will be ignored, allowing another
|
||||
to take it's place. This can be used to import a set of modules from another
|
||||
channel while keeping the rest of the system on a stable release.
|
||||
</para>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs, baseModules, extraModules, modules, ... }:
|
||||
{ config, lib, pkgs, baseModules, extraModules, modules, modulesPath, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -22,7 +22,10 @@ let
|
|||
scrubbedEval = evalModules {
|
||||
modules = [ { nixpkgs.localSystem = config.nixpkgs.localSystem; } ] ++ manualModules;
|
||||
args = (config._module.args) // { modules = [ ]; };
|
||||
specialArgs = { pkgs = scrubDerivations "pkgs" pkgs; };
|
||||
specialArgs = {
|
||||
pkgs = scrubDerivations "pkgs" pkgs;
|
||||
inherit modulesPath;
|
||||
};
|
||||
};
|
||||
scrubDerivations = namePrefix: pkgSet: mapAttrs
|
||||
(name: value:
|
||||
|
|
Loading…
Reference in a new issue