summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorFrederik Rietdijk <fridh@fridh.nl>2020-01-10 10:34:04 +0100
committerFrederik Rietdijk <fridh@fridh.nl>2020-01-10 10:34:04 +0100
commit5ad16cb27fd81cb67db4da80283e147bea4e1c25 (patch)
treead648118454028113d3b5236b27754151dc498b5 /lib
parenteb1369670b5a4e616ff0cf4100616479b1fa3064 (diff)
parent773494d0ea6fdf3a40561b44b805b90ae1949292 (diff)
downloadnixpkgs-5ad16cb27fd81cb67db4da80283e147bea4e1c25.tar
nixpkgs-5ad16cb27fd81cb67db4da80283e147bea4e1c25.tar.gz
nixpkgs-5ad16cb27fd81cb67db4da80283e147bea4e1c25.tar.bz2
nixpkgs-5ad16cb27fd81cb67db4da80283e147bea4e1c25.tar.lz
nixpkgs-5ad16cb27fd81cb67db4da80283e147bea4e1c25.tar.xz
nixpkgs-5ad16cb27fd81cb67db4da80283e147bea4e1c25.tar.zst
nixpkgs-5ad16cb27fd81cb67db4da80283e147bea4e1c25.zip
Merge master into staging-next
Diffstat (limited to 'lib')
-rw-r--r--lib/default.nix4
-rw-r--r--lib/modules.nix98
-rwxr-xr-xlib/tests/modules.sh11
-rw-r--r--lib/tests/modules/disable-recursive/bar.nix5
-rw-r--r--lib/tests/modules/disable-recursive/disable-bar.nix7
-rw-r--r--lib/tests/modules/disable-recursive/disable-foo.nix7
-rw-r--r--lib/tests/modules/disable-recursive/foo.nix5
-rw-r--r--lib/tests/modules/disable-recursive/main.nix8
-rw-r--r--lib/tests/modules/import-from-store.nix17
9 files changed, 134 insertions, 28 deletions
diff --git a/lib/default.nix b/lib/default.nix
index e31edeaaf9e..9f7a088d792 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -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'
diff --git a/lib/modules.nix b/lib/modules.nix
index aebc9874aa4..559697b3d57 100644
--- a/lib/modules.nix
+++ b/lib/modules.nix
@@ -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 = map moduleKey disabled;
+          keyFilter = filter (attrs: ! elem attrs.key disabledKeys);
+        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. */
diff --git a/lib/tests/modules.sh b/lib/tests/modules.sh
index f69befd15c6..79d90670fb5 100755
--- a/lib/tests/modules.sh
+++ b/lib/tests/modules.sh
@@ -12,7 +12,7 @@ evalConfig() {
     local attr=$1
     shift;
     local script="import ./default.nix { modules = [ $@ ];}"
-    nix-instantiate --timeout 1 -E "$script" -A "$attr" --eval-only --show-trace
+    nix-instantiate --timeout 1 -E "$script" -A "$attr" --eval-only --show-trace --read-write-mode
 }
 
 reportFailure() {
@@ -177,6 +177,15 @@ 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}
+
+# Check that imports can depend on derivations
+checkConfigOutput "true" config.enable ./import-from-store.nix
+
 cat <<EOF
 ====== module tests ======
 $pass Pass
diff --git a/lib/tests/modules/disable-recursive/bar.nix b/lib/tests/modules/disable-recursive/bar.nix
new file mode 100644
index 00000000000..4d9240a432d
--- /dev/null
+++ b/lib/tests/modules/disable-recursive/bar.nix
@@ -0,0 +1,5 @@
+{
+  imports = [
+    ../declare-enable.nix
+  ];
+}
diff --git a/lib/tests/modules/disable-recursive/disable-bar.nix b/lib/tests/modules/disable-recursive/disable-bar.nix
new file mode 100644
index 00000000000..987b2802ae8
--- /dev/null
+++ b/lib/tests/modules/disable-recursive/disable-bar.nix
@@ -0,0 +1,7 @@
+{
+
+  disabledModules = [
+    ./bar.nix
+  ];
+
+}
diff --git a/lib/tests/modules/disable-recursive/disable-foo.nix b/lib/tests/modules/disable-recursive/disable-foo.nix
new file mode 100644
index 00000000000..5b68a3c4610
--- /dev/null
+++ b/lib/tests/modules/disable-recursive/disable-foo.nix
@@ -0,0 +1,7 @@
+{
+
+  disabledModules = [
+    ./foo.nix
+  ];
+
+}
diff --git a/lib/tests/modules/disable-recursive/foo.nix b/lib/tests/modules/disable-recursive/foo.nix
new file mode 100644
index 00000000000..4d9240a432d
--- /dev/null
+++ b/lib/tests/modules/disable-recursive/foo.nix
@@ -0,0 +1,5 @@
+{
+  imports = [
+    ../declare-enable.nix
+  ];
+}
diff --git a/lib/tests/modules/disable-recursive/main.nix b/lib/tests/modules/disable-recursive/main.nix
new file mode 100644
index 00000000000..48a3c6218cf
--- /dev/null
+++ b/lib/tests/modules/disable-recursive/main.nix
@@ -0,0 +1,8 @@
+{
+  imports = [
+    ./foo.nix
+    ./bar.nix
+  ];
+
+  enable = true;
+}
diff --git a/lib/tests/modules/import-from-store.nix b/lib/tests/modules/import-from-store.nix
new file mode 100644
index 00000000000..64e7ec2e388
--- /dev/null
+++ b/lib/tests/modules/import-from-store.nix
@@ -0,0 +1,17 @@
+{ lib, ... }:
+let
+  drv = derivation {
+    name = "derivation";
+    system = builtins.currentSystem;
+    builder = "/bin/sh";
+    args = [ "-c" "echo {} > $out" ];
+  };
+in {
+
+  imports = [
+    "${drv}"
+    ./declare-enable.nix
+    ./define-enable.nix
+  ];
+
+}