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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user