aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/lib
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2020-01-12 01:00:12 +0000
committerKatharina Fey <kookie@spacekookie.de>2020-01-12 01:00:12 +0000
commiteeaf5d25d5f6ae7ae1f5bf8a3dee4559693f8147 (patch)
treeafc41ca8dde96b41089ca324533084aef570322f /nixpkgs/lib
parent63c4c4dda49dc69e5812faa7ef8406180998f3ae (diff)
parente4134747f5666bcab8680aff67fa3b63384f9a0f (diff)
Merge commit 'e4134747f5666bcab8680aff67fa3b63384f9a0f'
Diffstat (limited to 'nixpkgs/lib')
-rw-r--r--nixpkgs/lib/default.nix6
-rw-r--r--nixpkgs/lib/modules.nix152
-rw-r--r--nixpkgs/lib/systems/doubles.nix3
-rwxr-xr-xnixpkgs/lib/tests/modules.sh81
-rw-r--r--nixpkgs/lib/tests/modules/declare-attrsOfSub-any-enable.nix (renamed from nixpkgs/lib/tests/modules/declare-loaOfSub-any-enable.nix)4
-rw-r--r--nixpkgs/lib/tests/modules/declare-submoduleWith-modules.nix30
-rw-r--r--nixpkgs/lib/tests/modules/declare-submoduleWith-noshorthand.nix13
-rw-r--r--nixpkgs/lib/tests/modules/declare-submoduleWith-path.nix12
-rw-r--r--nixpkgs/lib/tests/modules/declare-submoduleWith-shorthand.nix14
-rw-r--r--nixpkgs/lib/tests/modules/declare-submoduleWith-special.nix17
-rw-r--r--nixpkgs/lib/tests/modules/define-attrsOfSub-bar-enable.nix3
-rw-r--r--nixpkgs/lib/tests/modules/define-attrsOfSub-bar.nix3
-rw-r--r--nixpkgs/lib/tests/modules/define-attrsOfSub-foo-enable-force.nix5
-rw-r--r--nixpkgs/lib/tests/modules/define-attrsOfSub-foo-enable-if.nix5
-rw-r--r--nixpkgs/lib/tests/modules/define-attrsOfSub-foo-enable.nix3
-rw-r--r--nixpkgs/lib/tests/modules/define-attrsOfSub-foo-force-enable.nix (renamed from nixpkgs/lib/tests/modules/define-loaOfSub-foo-force-enable.nix)2
-rw-r--r--nixpkgs/lib/tests/modules/define-attrsOfSub-foo-if-enable.nix (renamed from nixpkgs/lib/tests/modules/define-loaOfSub-foo-if-enable.nix)2
-rw-r--r--nixpkgs/lib/tests/modules/define-attrsOfSub-foo.nix3
-rw-r--r--nixpkgs/lib/tests/modules/define-attrsOfSub-force-foo-enable.nix (renamed from nixpkgs/lib/tests/modules/define-loaOfSub-force-foo-enable.nix)2
-rw-r--r--nixpkgs/lib/tests/modules/define-attrsOfSub-if-foo-enable.nix (renamed from nixpkgs/lib/tests/modules/define-loaOfSub-if-foo-enable.nix)2
-rw-r--r--nixpkgs/lib/tests/modules/define-force-attrsOfSub-foo-enable.nix5
-rw-r--r--nixpkgs/lib/tests/modules/define-force-loaOfSub-foo-enable.nix5
-rw-r--r--nixpkgs/lib/tests/modules/define-if-attrsOfSub-foo-enable.nix (renamed from nixpkgs/lib/tests/modules/define-if-loaOfSub-foo-enable.nix)2
-rw-r--r--nixpkgs/lib/tests/modules/define-loaOfSub-bar-enable.nix3
-rw-r--r--nixpkgs/lib/tests/modules/define-loaOfSub-bar.nix3
-rw-r--r--nixpkgs/lib/tests/modules/define-loaOfSub-foo-enable-force.nix5
-rw-r--r--nixpkgs/lib/tests/modules/define-loaOfSub-foo-enable-if.nix5
-rw-r--r--nixpkgs/lib/tests/modules/define-loaOfSub-foo-enable.nix3
-rw-r--r--nixpkgs/lib/tests/modules/define-loaOfSub-foo.nix3
-rw-r--r--nixpkgs/lib/tests/modules/define-submoduleWith-noshorthand.nix3
-rw-r--r--nixpkgs/lib/tests/modules/define-submoduleWith-shorthand.nix3
-rw-r--r--nixpkgs/lib/tests/modules/disable-recursive/bar.nix5
-rw-r--r--nixpkgs/lib/tests/modules/disable-recursive/disable-bar.nix7
-rw-r--r--nixpkgs/lib/tests/modules/disable-recursive/disable-foo.nix7
-rw-r--r--nixpkgs/lib/tests/modules/disable-recursive/foo.nix5
-rw-r--r--nixpkgs/lib/tests/modules/disable-recursive/main.nix8
-rw-r--r--nixpkgs/lib/tests/modules/loaOf-with-long-list.nix19
-rw-r--r--nixpkgs/lib/tests/modules/loaOf-with-many-list-merges.nix19
-rw-r--r--nixpkgs/lib/tests/systems.nix2
-rw-r--r--nixpkgs/lib/types.nix106
40 files changed, 389 insertions, 191 deletions
diff --git a/nixpkgs/lib/default.nix b/nixpkgs/lib/default.nix
index 8af53152586..9f7a088d792 100644
--- a/nixpkgs/lib/default.nix
+++ b/nixpkgs/lib/default.nix
@@ -101,8 +101,8 @@ let
cleanSource sourceByRegex sourceFilesBySuffices
commitIdFromGitRepo cleanSourceWith pathHasContext
canCleanSource;
- inherit (modules) evalModules closeModules unifyModuleSyntax
- applyIfFunction unpackSubmodule packSubmodule mergeModules
+ inherit (modules) evalModules unifyModuleSyntax
+ applyIfFunction mergeModules
mergeModules' mergeOptionDecls evalOptionValue mergeDefinitions
pushDownProperties dischargeProperties filterOverrides
sortProperties fixupOptionType mkIf mkAssert mkMerge mkOverride
@@ -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/nixpkgs/lib/modules.nix b/nixpkgs/lib/modules.nix
index 44db77b5d1c..38d6ac8cd91 100644
--- a/nixpkgs/lib/modules.nix
+++ b/nixpkgs/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,58 +90,103 @@ 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 (unpackSubmodule (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. */
unifyModuleSyntax = file: key: m:
- let metaSet = if m ? meta
- then { meta = m.meta; }
- else {};
+ let addMeta = config: if m ? meta
+ then mkMerge [ config { meta = m.meta; } ]
+ else config;
in
if m ? config || m ? options then
let badAttrs = removeAttrs m ["_file" "key" "disabledModules" "imports" "options" "config" "meta"]; in
if badAttrs != {} then
- throw "Module `${key}' has an unsupported attribute `${head (attrNames badAttrs)}'. This is caused by assignments to the top-level attributes `config' or `options'."
+ throw "Module `${key}' has an unsupported attribute `${head (attrNames badAttrs)}'. This is caused by introducing a top-level `config' or `options' attribute. Add configuration attributes immediately on the top level instead, or move all of them (namely: ${toString (attrNames badAttrs)}) into the explicit `config' attribute."
else
- { file = m._file or file;
+ { _file = m._file or file;
key = toString m.key or key;
disabledModules = m.disabledModules or [];
imports = m.imports or [];
options = m.options or {};
- config = mkMerge [ (m.config or {}) metaSet ];
+ config = addMeta (m.config or {});
}
else
- { file = m._file or file;
+ { _file = m._file or file;
key = toString m.key or key;
disabledModules = m.disabledModules or [];
imports = m.require or [] ++ m.imports or [];
options = {};
- config = mkMerge [ (removeAttrs m ["_file" "key" "disabledModules" "require" "imports"]) metaSet ];
+ config = addMeta (removeAttrs m ["_file" "key" "disabledModules" "require" "imports"]);
};
applyIfFunction = key: f: args@{ config, options, lib, ... }: if isFunction f then
@@ -171,17 +219,6 @@ rec {
else
f;
- /* We have to pack and unpack submodules. We cannot wrap the expected
- result of the function as we would no longer be able to list the arguments
- of the submodule. (see applyIfFunction) */
- unpackSubmodule = unpack: m: args:
- if isType "submodule" m then
- { _file = m.file; } // (unpack m.submodule args)
- else unpack m args;
-
- packSubmodule = file: m:
- { _type = "submodule"; file = file; submodule = m; };
-
/* Merge a list of modules. This will recurse over the option
declarations in all modules, combining them into a single set.
At the same time, for each option declaration, it will merge the
@@ -189,7 +226,7 @@ rec {
in the ā€˜valueā€™ attribute of each option. */
mergeModules = prefix: modules:
mergeModules' prefix modules
- (concatMap (m: map (config: { inherit (m) file; inherit config; }) (pushDownProperties m.config)) modules);
+ (concatMap (m: map (config: { file = m._file; inherit config; }) (pushDownProperties m.config)) modules);
mergeModules' = prefix: options: configs:
let
@@ -223,7 +260,7 @@ rec {
) {} modules;
# an attrset 'name' => list of submodules that declare ā€˜nameā€™.
declsByName = byName "options" (module: option:
- [{ inherit (module) file; options = option; }]
+ [{ inherit (module) _file; options = option; }]
) options;
# an attrset 'name' => list of submodules that define ā€˜nameā€™.
defnsByName = byName "config" (module: value:
@@ -250,7 +287,7 @@ rec {
firstOption = findFirst (m: isOption m.options) "" decls;
firstNonOption = findFirst (m: !isOption m.options) "" decls;
in
- throw "The option `${showOption loc}' in `${firstOption.file}' is a prefix of options in `${firstNonOption.file}'."
+ throw "The option `${showOption loc}' in `${firstOption._file}' is a prefix of options in `${firstNonOption._file}'."
else
mergeModules' loc decls defns
))
@@ -267,7 +304,14 @@ rec {
'opts' is a list of modules. Each module has an options attribute which
correspond to the definition of 'loc' in 'opt.file'. */
- mergeOptionDecls = loc: opts:
+ mergeOptionDecls =
+ let
+ packSubmodule = file: m:
+ { _file = file; imports = [ m ]; };
+ coerceOption = file: opt:
+ if isFunction opt then packSubmodule file opt
+ else packSubmodule file { options = opt; };
+ in loc: opts:
foldl' (res: opt:
let t = res.type;
t' = opt.options.type;
@@ -284,7 +328,7 @@ rec {
bothHave "apply" ||
(bothHave "type" && (! typesMergeable))
then
- throw "The option `${showOption loc}' in `${opt.file}' is already declared in ${showFiles res.declarations}."
+ throw "The option `${showOption loc}' in `${opt._file}' is already declared in ${showFiles res.declarations}."
else
let
/* Add the modules of the current option to the list of modules
@@ -293,16 +337,14 @@ rec {
current option declaration as the file use for the submodule. If the
submodule defines any filename, then we ignore the enclosing option file. */
options' = toList opt.options.options;
- coerceOption = file: opt:
- if isFunction opt then packSubmodule file opt
- else packSubmodule file { options = opt; };
+
getSubModules = opt.options.type.getSubModules or null;
submodules =
- if getSubModules != null then map (packSubmodule opt.file) getSubModules ++ res.options
- else if opt.options ? options then map (coerceOption opt.file) options' ++ res.options
+ if getSubModules != null then map (packSubmodule opt._file) getSubModules ++ res.options
+ else if opt.options ? options then map (coerceOption opt._file) options' ++ res.options
else res.options;
in opt.options // res //
- { declarations = res.declarations ++ [opt.file];
+ { declarations = res.declarations ++ [opt._file];
options = submodules;
} // typeSet
) { inherit loc; declarations = []; options = []; } opts;
diff --git a/nixpkgs/lib/systems/doubles.nix b/nixpkgs/lib/systems/doubles.nix
index 700c895b3ab..96e602d0e16 100644
--- a/nixpkgs/lib/systems/doubles.nix
+++ b/nixpkgs/lib/systems/doubles.nix
@@ -27,6 +27,8 @@ let
"riscv32-linux" "riscv64-linux"
"aarch64-none" "avr-none" "arm-none" "i686-none" "x86_64-none" "powerpc-none" "msp430-none" "riscv64-none" "riscv32-none" "vc4-none"
+
+ "js-ghcjs"
];
allParsed = map parse.mkSystemFromString all;
@@ -46,6 +48,7 @@ in {
mips = filterDoubles predicates.isMips;
riscv = filterDoubles predicates.isRiscV;
vc4 = filterDoubles predicates.isVc4;
+ js = filterDoubles predicates.isJavaScript;
cygwin = filterDoubles predicates.isCygwin;
darwin = filterDoubles predicates.isDarwin;
diff --git a/nixpkgs/lib/tests/modules.sh b/nixpkgs/lib/tests/modules.sh
index cf344122cf4..2997fb1ada1 100755
--- a/nixpkgs/lib/tests/modules.sh
+++ b/nixpkgs/lib/tests/modules.sh
@@ -87,36 +87,36 @@ checkConfigOutput "false" "$@" ./define-force-enable.nix
checkConfigOutput "false" "$@" ./define-enable-force.nix
# Check mkForce with option and submodules.
-checkConfigError 'attribute .*foo.* .* not found' config.loaOfSub.foo.enable ./declare-loaOfSub-any-enable.nix
-checkConfigOutput 'false' config.loaOfSub.foo.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix
-set -- config.loaOfSub.foo.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo-enable.nix
+checkConfigError 'attribute .*foo.* .* not found' config.attrsOfSub.foo.enable ./declare-attrsOfSub-any-enable.nix
+checkConfigOutput 'false' config.attrsOfSub.foo.enable ./declare-attrsOfSub-any-enable.nix ./define-attrsOfSub-foo.nix
+set -- config.attrsOfSub.foo.enable ./declare-attrsOfSub-any-enable.nix ./define-attrsOfSub-foo-enable.nix
checkConfigOutput 'true' "$@"
-checkConfigOutput 'false' "$@" ./define-force-loaOfSub-foo-enable.nix
-checkConfigOutput 'false' "$@" ./define-loaOfSub-force-foo-enable.nix
-checkConfigOutput 'false' "$@" ./define-loaOfSub-foo-force-enable.nix
-checkConfigOutput 'false' "$@" ./define-loaOfSub-foo-enable-force.nix
+checkConfigOutput 'false' "$@" ./define-force-attrsOfSub-foo-enable.nix
+checkConfigOutput 'false' "$@" ./define-attrsOfSub-force-foo-enable.nix
+checkConfigOutput 'false' "$@" ./define-attrsOfSub-foo-force-enable.nix
+checkConfigOutput 'false' "$@" ./define-attrsOfSub-foo-enable-force.nix
# Check overriding effect of mkForce on submodule definitions.
-checkConfigError 'attribute .*bar.* .* not found' config.loaOfSub.bar.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix
-checkConfigOutput 'false' config.loaOfSub.bar.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix ./define-loaOfSub-bar.nix
-set -- config.loaOfSub.bar.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix ./define-loaOfSub-bar-enable.nix
+checkConfigError 'attribute .*bar.* .* not found' config.attrsOfSub.bar.enable ./declare-attrsOfSub-any-enable.nix ./define-attrsOfSub-foo.nix
+checkConfigOutput 'false' config.attrsOfSub.bar.enable ./declare-attrsOfSub-any-enable.nix ./define-attrsOfSub-foo.nix ./define-attrsOfSub-bar.nix
+set -- config.attrsOfSub.bar.enable ./declare-attrsOfSub-any-enable.nix ./define-attrsOfSub-foo.nix ./define-attrsOfSub-bar-enable.nix
checkConfigOutput 'true' "$@"
-checkConfigError 'attribute .*bar.* .* not found' "$@" ./define-force-loaOfSub-foo-enable.nix
-checkConfigError 'attribute .*bar.* .* not found' "$@" ./define-loaOfSub-force-foo-enable.nix
-checkConfigOutput 'true' "$@" ./define-loaOfSub-foo-force-enable.nix
-checkConfigOutput 'true' "$@" ./define-loaOfSub-foo-enable-force.nix
+checkConfigError 'attribute .*bar.* .* not found' "$@" ./define-force-attrsOfSub-foo-enable.nix
+checkConfigError 'attribute .*bar.* .* not found' "$@" ./define-attrsOfSub-force-foo-enable.nix
+checkConfigOutput 'true' "$@" ./define-attrsOfSub-foo-force-enable.nix
+checkConfigOutput 'true' "$@" ./define-attrsOfSub-foo-enable-force.nix
# Check mkIf with submodules.
-checkConfigError 'attribute .*foo.* .* not found' config.loaOfSub.foo.enable ./declare-enable.nix ./declare-loaOfSub-any-enable.nix
-set -- config.loaOfSub.foo.enable ./declare-enable.nix ./declare-loaOfSub-any-enable.nix
-checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-if-loaOfSub-foo-enable.nix
-checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-loaOfSub-if-foo-enable.nix
-checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-loaOfSub-foo-if-enable.nix
-checkConfigOutput 'false' "$@" ./define-loaOfSub-foo-enable-if.nix
-checkConfigOutput 'true' "$@" ./define-enable.nix ./define-if-loaOfSub-foo-enable.nix
-checkConfigOutput 'true' "$@" ./define-enable.nix ./define-loaOfSub-if-foo-enable.nix
-checkConfigOutput 'true' "$@" ./define-enable.nix ./define-loaOfSub-foo-if-enable.nix
-checkConfigOutput 'true' "$@" ./define-enable.nix ./define-loaOfSub-foo-enable-if.nix
+checkConfigError 'attribute .*foo.* .* not found' config.attrsOfSub.foo.enable ./declare-enable.nix ./declare-attrsOfSub-any-enable.nix
+set -- config.attrsOfSub.foo.enable ./declare-enable.nix ./declare-attrsOfSub-any-enable.nix
+checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-if-attrsOfSub-foo-enable.nix
+checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-attrsOfSub-if-foo-enable.nix
+checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-attrsOfSub-foo-if-enable.nix
+checkConfigOutput 'false' "$@" ./define-attrsOfSub-foo-enable-if.nix
+checkConfigOutput 'true' "$@" ./define-enable.nix ./define-if-attrsOfSub-foo-enable.nix
+checkConfigOutput 'true' "$@" ./define-enable.nix ./define-attrsOfSub-if-foo-enable.nix
+checkConfigOutput 'true' "$@" ./define-enable.nix ./define-attrsOfSub-foo-if-enable.nix
+checkConfigOutput 'true' "$@" ./define-enable.nix ./define-attrsOfSub-foo-enable-if.nix
# Check disabledModules with config definitions and option declarations.
set -- config.enable ./define-enable.nix ./declare-enable.nix
@@ -138,7 +138,7 @@ checkConfigError 'while evaluating the module argument .*custom.* in .*import-cu
checkConfigError 'infinite recursion encountered' "$@"
# Check _module.check.
-set -- config.enable ./declare-enable.nix ./define-enable.nix ./define-loaOfSub-foo.nix
+set -- config.enable ./declare-enable.nix ./define-enable.nix ./define-attrsOfSub-foo.nix
checkConfigError 'The option .* defined in .* does not exist.' "$@"
checkConfigOutput "true" "$@" ./define-module-check.nix
@@ -152,18 +152,37 @@ checkConfigOutput "12" config.value ./declare-coerced-value-unsound.nix
checkConfigError 'The option value .* in .* is not.*8 bit signed integer.* or string convertible to it' config.value ./declare-coerced-value-unsound.nix ./define-value-string-bigint.nix
checkConfigError 'unrecognised JSON value' config.value ./declare-coerced-value-unsound.nix ./define-value-string-arbitrary.nix
-# Check loaOf with long list.
-checkConfigOutput "1 2 3 4 5 6 7 8 9 10" config.result ./loaOf-with-long-list.nix
-
-# Check loaOf with many merges of lists.
-checkConfigOutput "1 2 3 4 5 6 7 8 9 10" config.result ./loaOf-with-many-list-merges.nix
-
# Check mkAliasOptionModule.
checkConfigOutput "true" config.enable ./alias-with-priority.nix
checkConfigOutput "true" config.enableAlias ./alias-with-priority.nix
checkConfigOutput "false" config.enable ./alias-with-priority-can-override.nix
checkConfigOutput "false" config.enableAlias ./alias-with-priority-can-override.nix
+# submoduleWith
+
+## specialArgs should work
+checkConfigOutput "foo" config.submodule.foo ./declare-submoduleWith-special.nix
+
+## shorthandOnlyDefines config behaves as expected
+checkConfigOutput "true" config.submodule.config ./declare-submoduleWith-shorthand.nix ./define-submoduleWith-shorthand.nix
+checkConfigError 'is not of type `boolean' config.submodule.config ./declare-submoduleWith-shorthand.nix ./define-submoduleWith-noshorthand.nix
+checkConfigError 'value is a boolean while a set was expected' config.submodule.config ./declare-submoduleWith-noshorthand.nix ./define-submoduleWith-shorthand.nix
+checkConfigOutput "true" config.submodule.config ./declare-submoduleWith-noshorthand.nix ./define-submoduleWith-noshorthand.nix
+
+## submoduleWith should merge all modules in one swoop
+checkConfigOutput "true" config.submodule.inner ./declare-submoduleWith-modules.nix
+checkConfigOutput "true" config.submodule.outer ./declare-submoduleWith-modules.nix
+
+## Paths should be allowed as values and work as expected
+# 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
diff --git a/nixpkgs/lib/tests/modules/declare-loaOfSub-any-enable.nix b/nixpkgs/lib/tests/modules/declare-attrsOfSub-any-enable.nix
index 71dad1c9135..986d07227e1 100644
--- a/nixpkgs/lib/tests/modules/declare-loaOfSub-any-enable.nix
+++ b/nixpkgs/lib/tests/modules/declare-attrsOfSub-any-enable.nix
@@ -17,10 +17,10 @@ in
{
options = {
- loaOfSub = lib.mkOption {
+ attrsOfSub = lib.mkOption {
default = {};
example = {};
- type = lib.types.loaOf (lib.types.submodule [ submod ]);
+ type = lib.types.attrsOf (lib.types.submodule [ submod ]);
description = ''
Some descriptive text
'';
diff --git a/nixpkgs/lib/tests/modules/declare-submoduleWith-modules.nix b/nixpkgs/lib/tests/modules/declare-submoduleWith-modules.nix
new file mode 100644
index 00000000000..4736ab41751
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/declare-submoduleWith-modules.nix
@@ -0,0 +1,30 @@
+{ lib, ... }: {
+ options.submodule = lib.mkOption {
+ type = lib.types.submoduleWith {
+ modules = [
+ {
+ options.inner = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+ }
+ {
+ outer = true;
+ }
+ ];
+ };
+ default = {};
+ };
+
+ config.submodule = lib.mkMerge [
+ ({ lib, ... }: {
+ options.outer = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+ })
+ {
+ inner = true;
+ }
+ ];
+}
diff --git a/nixpkgs/lib/tests/modules/declare-submoduleWith-noshorthand.nix b/nixpkgs/lib/tests/modules/declare-submoduleWith-noshorthand.nix
new file mode 100644
index 00000000000..af3b4ba470f
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/declare-submoduleWith-noshorthand.nix
@@ -0,0 +1,13 @@
+{ lib, ... }: let
+ sub.options.config = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+in {
+ options.submodule = lib.mkOption {
+ type = lib.types.submoduleWith {
+ modules = [ sub ];
+ };
+ default = {};
+ };
+}
diff --git a/nixpkgs/lib/tests/modules/declare-submoduleWith-path.nix b/nixpkgs/lib/tests/modules/declare-submoduleWith-path.nix
new file mode 100644
index 00000000000..477647f3212
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/declare-submoduleWith-path.nix
@@ -0,0 +1,12 @@
+{ lib, ... }: {
+ options.submodule = lib.mkOption {
+ type = lib.types.submoduleWith {
+ modules = [
+ ./declare-enable.nix
+ ];
+ };
+ default = {};
+ };
+
+ config.submodule = ./define-enable.nix;
+}
diff --git a/nixpkgs/lib/tests/modules/declare-submoduleWith-shorthand.nix b/nixpkgs/lib/tests/modules/declare-submoduleWith-shorthand.nix
new file mode 100644
index 00000000000..63ac16293e2
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/declare-submoduleWith-shorthand.nix
@@ -0,0 +1,14 @@
+{ lib, ... }: let
+ sub.options.config = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+in {
+ options.submodule = lib.mkOption {
+ type = lib.types.submoduleWith {
+ modules = [ sub ];
+ shorthandOnlyDefinesConfig = true;
+ };
+ default = {};
+ };
+}
diff --git a/nixpkgs/lib/tests/modules/declare-submoduleWith-special.nix b/nixpkgs/lib/tests/modules/declare-submoduleWith-special.nix
new file mode 100644
index 00000000000..6b15c5bde20
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/declare-submoduleWith-special.nix
@@ -0,0 +1,17 @@
+{ lib, ... }: {
+ options.submodule = lib.mkOption {
+ type = lib.types.submoduleWith {
+ modules = [
+ ({ lib, ... }: {
+ options.foo = lib.mkOption {
+ default = lib.foo;
+ };
+ })
+ ];
+ specialArgs.lib = lib // {
+ foo = "foo";
+ };
+ };
+ default = {};
+ };
+}
diff --git a/nixpkgs/lib/tests/modules/define-attrsOfSub-bar-enable.nix b/nixpkgs/lib/tests/modules/define-attrsOfSub-bar-enable.nix
new file mode 100644
index 00000000000..99c55d8b360
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/define-attrsOfSub-bar-enable.nix
@@ -0,0 +1,3 @@
+{
+ attrsOfSub.bar.enable = true;
+}
diff --git a/nixpkgs/lib/tests/modules/define-attrsOfSub-bar.nix b/nixpkgs/lib/tests/modules/define-attrsOfSub-bar.nix
new file mode 100644
index 00000000000..2a33068a568
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/define-attrsOfSub-bar.nix
@@ -0,0 +1,3 @@
+{
+ attrsOfSub.bar = {};
+}
diff --git a/nixpkgs/lib/tests/modules/define-attrsOfSub-foo-enable-force.nix b/nixpkgs/lib/tests/modules/define-attrsOfSub-foo-enable-force.nix
new file mode 100644
index 00000000000..c9ee36446f1
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/define-attrsOfSub-foo-enable-force.nix
@@ -0,0 +1,5 @@
+{ lib, ... }:
+
+{
+ attrsOfSub.foo.enable = lib.mkForce false;
+}
diff --git a/nixpkgs/lib/tests/modules/define-attrsOfSub-foo-enable-if.nix b/nixpkgs/lib/tests/modules/define-attrsOfSub-foo-enable-if.nix
new file mode 100644
index 00000000000..0b3baddb5ec
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/define-attrsOfSub-foo-enable-if.nix
@@ -0,0 +1,5 @@
+{ config, lib, ... }:
+
+{
+ attrsOfSub.foo.enable = lib.mkIf config.enable true;
+}
diff --git a/nixpkgs/lib/tests/modules/define-attrsOfSub-foo-enable.nix b/nixpkgs/lib/tests/modules/define-attrsOfSub-foo-enable.nix
new file mode 100644
index 00000000000..39cd63cef72
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/define-attrsOfSub-foo-enable.nix
@@ -0,0 +1,3 @@
+{
+ attrsOfSub.foo.enable = true;
+}
diff --git a/nixpkgs/lib/tests/modules/define-loaOfSub-foo-force-enable.nix b/nixpkgs/lib/tests/modules/define-attrsOfSub-foo-force-enable.nix
index dce0ef547b3..009da7c77cd 100644
--- a/nixpkgs/lib/tests/modules/define-loaOfSub-foo-force-enable.nix
+++ b/nixpkgs/lib/tests/modules/define-attrsOfSub-foo-force-enable.nix
@@ -1,7 +1,7 @@
{ lib, ... }:
{
- loaOfSub.foo = lib.mkForce {
+ attrsOfSub.foo = lib.mkForce {
enable = false;
};
}
diff --git a/nixpkgs/lib/tests/modules/define-loaOfSub-foo-if-enable.nix b/nixpkgs/lib/tests/modules/define-attrsOfSub-foo-if-enable.nix
index 236b2840ee5..93702dfa86f 100644
--- a/nixpkgs/lib/tests/modules/define-loaOfSub-foo-if-enable.nix
+++ b/nixpkgs/lib/tests/modules/define-attrsOfSub-foo-if-enable.nix
@@ -1,7 +1,7 @@
{ config, lib, ... }:
{
- loaOfSub.foo = lib.mkIf config.enable {
+ attrsOfSub.foo = lib.mkIf config.enable {
enable = true;
};
}
diff --git a/nixpkgs/lib/tests/modules/define-attrsOfSub-foo.nix b/nixpkgs/lib/tests/modules/define-attrsOfSub-foo.nix
new file mode 100644
index 00000000000..e6bb531dedd
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/define-attrsOfSub-foo.nix
@@ -0,0 +1,3 @@
+{
+ attrsOfSub.foo = {};
+}
diff --git a/nixpkgs/lib/tests/modules/define-loaOfSub-force-foo-enable.nix b/nixpkgs/lib/tests/modules/define-attrsOfSub-force-foo-enable.nix
index df5722274ee..5c02dd34314 100644
--- a/nixpkgs/lib/tests/modules/define-loaOfSub-force-foo-enable.nix
+++ b/nixpkgs/lib/tests/modules/define-attrsOfSub-force-foo-enable.nix
@@ -1,7 +1,7 @@
{ lib, ... }:
{
- loaOfSub = lib.mkForce {
+ attrsOfSub = lib.mkForce {
foo.enable = false;
};
}
diff --git a/nixpkgs/lib/tests/modules/define-loaOfSub-if-foo-enable.nix b/nixpkgs/lib/tests/modules/define-attrsOfSub-if-foo-enable.nix
index bd2d068d31a..a3fe6051d41 100644
--- a/nixpkgs/lib/tests/modules/define-loaOfSub-if-foo-enable.nix
+++ b/nixpkgs/lib/tests/modules/define-attrsOfSub-if-foo-enable.nix
@@ -1,7 +1,7 @@
{ config, lib, ... }:
{
- loaOfSub = lib.mkIf config.enable {
+ attrsOfSub = lib.mkIf config.enable {
foo.enable = true;
};
}
diff --git a/nixpkgs/lib/tests/modules/define-force-attrsOfSub-foo-enable.nix b/nixpkgs/lib/tests/modules/define-force-attrsOfSub-foo-enable.nix
new file mode 100644
index 00000000000..dafb2360e1f
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/define-force-attrsOfSub-foo-enable.nix
@@ -0,0 +1,5 @@
+{ lib, ... }:
+
+lib.mkForce {
+ attrsOfSub.foo.enable = false;
+}
diff --git a/nixpkgs/lib/tests/modules/define-force-loaOfSub-foo-enable.nix b/nixpkgs/lib/tests/modules/define-force-loaOfSub-foo-enable.nix
deleted file mode 100644
index bfd8e084b59..00000000000
--- a/nixpkgs/lib/tests/modules/define-force-loaOfSub-foo-enable.nix
+++ /dev/null
@@ -1,5 +0,0 @@
-{ lib, ... }:
-
-lib.mkForce {
- loaOfSub.foo.enable = false;
-}
diff --git a/nixpkgs/lib/tests/modules/define-if-loaOfSub-foo-enable.nix b/nixpkgs/lib/tests/modules/define-if-attrsOfSub-foo-enable.nix
index 4288d74dec0..6a8e32e802a 100644
--- a/nixpkgs/lib/tests/modules/define-if-loaOfSub-foo-enable.nix
+++ b/nixpkgs/lib/tests/modules/define-if-attrsOfSub-foo-enable.nix
@@ -1,5 +1,5 @@
{ config, lib, ... }:
lib.mkIf config.enable {
- loaOfSub.foo.enable = true;
+ attrsOfSub.foo.enable = true;
}
diff --git a/nixpkgs/lib/tests/modules/define-loaOfSub-bar-enable.nix b/nixpkgs/lib/tests/modules/define-loaOfSub-bar-enable.nix
deleted file mode 100644
index 422bb0a600b..00000000000
--- a/nixpkgs/lib/tests/modules/define-loaOfSub-bar-enable.nix
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- loaOfSub.bar.enable = true;
-}
diff --git a/nixpkgs/lib/tests/modules/define-loaOfSub-bar.nix b/nixpkgs/lib/tests/modules/define-loaOfSub-bar.nix
deleted file mode 100644
index c24315e09b6..00000000000
--- a/nixpkgs/lib/tests/modules/define-loaOfSub-bar.nix
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- loaOfSub.bar = {};
-}
diff --git a/nixpkgs/lib/tests/modules/define-loaOfSub-foo-enable-force.nix b/nixpkgs/lib/tests/modules/define-loaOfSub-foo-enable-force.nix
deleted file mode 100644
index c1d7b198be5..00000000000
--- a/nixpkgs/lib/tests/modules/define-loaOfSub-foo-enable-force.nix
+++ /dev/null
@@ -1,5 +0,0 @@
-{ lib, ... }:
-
-{
- loaOfSub.foo.enable = lib.mkForce false;
-}
diff --git a/nixpkgs/lib/tests/modules/define-loaOfSub-foo-enable-if.nix b/nixpkgs/lib/tests/modules/define-loaOfSub-foo-enable-if.nix
deleted file mode 100644
index 44b2c96cd02..00000000000
--- a/nixpkgs/lib/tests/modules/define-loaOfSub-foo-enable-if.nix
+++ /dev/null
@@ -1,5 +0,0 @@
-{ config, lib, ... }:
-
-{
- loaOfSub.foo.enable = lib.mkIf config.enable true;
-}
diff --git a/nixpkgs/lib/tests/modules/define-loaOfSub-foo-enable.nix b/nixpkgs/lib/tests/modules/define-loaOfSub-foo-enable.nix
deleted file mode 100644
index 822425c71bb..00000000000
--- a/nixpkgs/lib/tests/modules/define-loaOfSub-foo-enable.nix
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- loaOfSub.foo.enable = true;
-}
diff --git a/nixpkgs/lib/tests/modules/define-loaOfSub-foo.nix b/nixpkgs/lib/tests/modules/define-loaOfSub-foo.nix
deleted file mode 100644
index e9b2e631f2e..00000000000
--- a/nixpkgs/lib/tests/modules/define-loaOfSub-foo.nix
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- loaOfSub.foo = {};
-}
diff --git a/nixpkgs/lib/tests/modules/define-submoduleWith-noshorthand.nix b/nixpkgs/lib/tests/modules/define-submoduleWith-noshorthand.nix
new file mode 100644
index 00000000000..35e1607b6f1
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/define-submoduleWith-noshorthand.nix
@@ -0,0 +1,3 @@
+{
+ submodule.config.config = true;
+}
diff --git a/nixpkgs/lib/tests/modules/define-submoduleWith-shorthand.nix b/nixpkgs/lib/tests/modules/define-submoduleWith-shorthand.nix
new file mode 100644
index 00000000000..17df248db8e
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/define-submoduleWith-shorthand.nix
@@ -0,0 +1,3 @@
+{
+ submodule.config = true;
+}
diff --git a/nixpkgs/lib/tests/modules/disable-recursive/bar.nix b/nixpkgs/lib/tests/modules/disable-recursive/bar.nix
new file mode 100644
index 00000000000..4d9240a432d
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/disable-recursive/bar.nix
@@ -0,0 +1,5 @@
+{
+ imports = [
+ ../declare-enable.nix
+ ];
+}
diff --git a/nixpkgs/lib/tests/modules/disable-recursive/disable-bar.nix b/nixpkgs/lib/tests/modules/disable-recursive/disable-bar.nix
new file mode 100644
index 00000000000..987b2802ae8
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/disable-recursive/disable-bar.nix
@@ -0,0 +1,7 @@
+{
+
+ disabledModules = [
+ ./bar.nix
+ ];
+
+}
diff --git a/nixpkgs/lib/tests/modules/disable-recursive/disable-foo.nix b/nixpkgs/lib/tests/modules/disable-recursive/disable-foo.nix
new file mode 100644
index 00000000000..5b68a3c4610
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/disable-recursive/disable-foo.nix
@@ -0,0 +1,7 @@
+{
+
+ disabledModules = [
+ ./foo.nix
+ ];
+
+}
diff --git a/nixpkgs/lib/tests/modules/disable-recursive/foo.nix b/nixpkgs/lib/tests/modules/disable-recursive/foo.nix
new file mode 100644
index 00000000000..4d9240a432d
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/disable-recursive/foo.nix
@@ -0,0 +1,5 @@
+{
+ imports = [
+ ../declare-enable.nix
+ ];
+}
diff --git a/nixpkgs/lib/tests/modules/disable-recursive/main.nix b/nixpkgs/lib/tests/modules/disable-recursive/main.nix
new file mode 100644
index 00000000000..48a3c6218cf
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/disable-recursive/main.nix
@@ -0,0 +1,8 @@
+{
+ imports = [
+ ./foo.nix
+ ./bar.nix
+ ];
+
+ enable = true;
+}
diff --git a/nixpkgs/lib/tests/modules/loaOf-with-long-list.nix b/nixpkgs/lib/tests/modules/loaOf-with-long-list.nix
deleted file mode 100644
index f30903c47e5..00000000000
--- a/nixpkgs/lib/tests/modules/loaOf-with-long-list.nix
+++ /dev/null
@@ -1,19 +0,0 @@
-{ config, lib, ... }:
-
-{
- options = {
- loaOfInt = lib.mkOption {
- type = lib.types.loaOf lib.types.int;
- };
-
- result = lib.mkOption {
- type = lib.types.str;
- };
- };
-
- config = {
- loaOfInt = [ 1 2 3 4 5 6 7 8 9 10 ];
-
- result = toString (lib.attrValues config.loaOfInt);
- };
-}
diff --git a/nixpkgs/lib/tests/modules/loaOf-with-many-list-merges.nix b/nixpkgs/lib/tests/modules/loaOf-with-many-list-merges.nix
deleted file mode 100644
index f8f8a8da82b..00000000000
--- a/nixpkgs/lib/tests/modules/loaOf-with-many-list-merges.nix
+++ /dev/null
@@ -1,19 +0,0 @@
-{ config, lib, ... }:
-
-{
- options = {
- loaOfInt = lib.mkOption {
- type = lib.types.loaOf lib.types.int;
- };
-
- result = lib.mkOption {
- type = lib.types.str;
- };
- };
-
- config = {
- loaOfInt = lib.mkMerge (map lib.singleton [ 1 2 3 4 5 6 7 8 9 10 ]);
-
- result = toString (lib.attrValues config.loaOfInt);
- };
-}
diff --git a/nixpkgs/lib/tests/systems.nix b/nixpkgs/lib/tests/systems.nix
index 818749442f9..6f52912994d 100644
--- a/nixpkgs/lib/tests/systems.nix
+++ b/nixpkgs/lib/tests/systems.nix
@@ -12,7 +12,7 @@ let
expected = lib.sort lib.lessThan y;
};
in with lib.systems.doubles; lib.runTests {
- testall = mseteq all (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ wasi ++ windows ++ embedded);
+ testall = mseteq all (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ wasi ++ windows ++ embedded ++ js);
testarm = mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv7a-linux" "armv7l-linux" "arm-none" "armv7a-darwin" ];
testi686 = mseteq i686 [ "i686-linux" "i686-freebsd" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" "i686-none" "i686-darwin" ];
diff --git a/nixpkgs/lib/types.nix b/nixpkgs/lib/types.nix
index 5e9a28ac4f0..4872a676657 100644
--- a/nixpkgs/lib/types.nix
+++ b/nixpkgs/lib/types.nix
@@ -242,8 +242,7 @@ rec {
path = mkOptionType {
name = "path";
- # Hacky: there is no ā€˜isPathā€™ primop.
- check = x: builtins.substring 0 1 (toString x) == "/";
+ check = x: isCoercibleToString x && builtins.substring 0 1 (toString x) == "/";
merge = mergeEqualOption;
};
@@ -295,26 +294,43 @@ rec {
# List or attribute set of ...
loaOf = elemType:
let
- convertAllLists = defs:
+ convertAllLists = loc: defs:
let
padWidth = stringLength (toString (length defs));
unnamedPrefix = i: "unnamed-" + fixedWidthNumber padWidth i + ".";
in
- imap1 (i: convertIfList (unnamedPrefix i)) defs;
-
- convertIfList = unnamedPrefix: def:
+ imap1 (i: convertIfList loc (unnamedPrefix i)) defs;
+ convertIfList = loc: unnamedPrefix: def:
if isList def.value then
let
padWidth = stringLength (toString (length def.value));
unnamed = i: unnamedPrefix + fixedWidthNumber padWidth i;
+ res =
+ { inherit (def) file;
+ value = listToAttrs (
+ imap1 (elemIdx: elem:
+ { name = elem.name or (unnamed elemIdx);
+ value = elem;
+ }) def.value);
+ };
+ option = concatStringsSep "." loc;
+ sample = take 3 def.value;
+ list = concatMapStrings (x: ''{ name = "${x.name or "unnamed"}"; ...} '') sample;
+ set = concatMapStrings (x: ''${x.name or "unnamed"} = {...}; '') sample;
+ msg = ''
+ In file ${def.file}
+ a list is being assigned to the option config.${option}.
+ This will soon be an error as type loaOf is deprecated.
+ See https://git.io/fj2zm for more information.
+ Do
+ ${option} =
+ { ${set}...}
+ instead of
+ ${option} =
+ [ ${list}...]
+ '';
in
- { inherit (def) file;
- value = listToAttrs (
- imap1 (elemIdx: elem:
- { name = elem.name or (unnamed elemIdx);
- value = elem;
- }) def.value);
- }
+ lib.warn msg res
else
def;
attrOnly = attrsOf elemType;
@@ -322,7 +338,7 @@ rec {
name = "loaOf";
description = "list or attribute set of ${elemType.description}s";
check = x: isList x || isAttrs x;
- merge = loc: defs: attrOnly.merge loc (convertAllLists defs);
+ merge = loc: defs: attrOnly.merge loc (convertAllLists loc defs);
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]);
getSubModules = elemType.getSubModules;
substSubModules = m: loaOf (elemType.substSubModules m);
@@ -358,25 +374,41 @@ rec {
};
# A submodule (like typed attribute set). See NixOS manual.
- submodule = opts:
+ submodule = modules: submoduleWith {
+ shorthandOnlyDefinesConfig = true;
+ modules = toList modules;
+ };
+
+ submoduleWith =
+ { modules
+ , specialArgs ? {}
+ , shorthandOnlyDefinesConfig ? false
+ }@attrs:
let
- opts' = toList opts;
inherit (lib.modules) evalModules;
+
+ coerce = unify: value: if isFunction value
+ then setFunctionArgs (args: unify (value args)) (functionArgs value)
+ else unify (if shorthandOnlyDefinesConfig then { config = value; } else value);
+
+ allModules = defs: modules ++ imap1 (n: { value, file }:
+ # Annotate the value with the location of its definition for better error messages
+ coerce (lib.modules.unifyModuleSyntax file "${toString file}-${toString n}") value
+ ) defs;
+
in
mkOptionType rec {
name = "submodule";
check = x: isAttrs x || isFunction x;
merge = loc: defs:
- let
- coerce = def: if isFunction def then def else { config = def; };
- modules = opts' ++ map (def: { _file = def.file; imports = [(coerce def.value)]; }) defs;
- in (evalModules {
- inherit modules;
+ (evalModules {
+ modules = allModules defs;
+ inherit specialArgs;
args.name = last loc;
prefix = loc;
}).config;
getSubOptions = prefix: (evalModules
- { modules = opts'; inherit prefix;
+ { inherit modules prefix specialArgs;
# This is a work-around due to the fact that some sub-modules,
# such as the one included in an attribute set, expects a "args"
# attribute to be given to the sub-module. As the option
@@ -394,13 +426,29 @@ rec {
# It shouldn't cause an issue since this is cosmetic for the manual.
args.name = "ā€¹nameā€ŗ";
}).options;
- getSubModules = opts';
- substSubModules = m: submodule m;
- functor = (defaultFunctor name) // {
- # Merging of submodules is done as part of mergeOptionDecls, as we have to annotate
- # each submodule with its location.
- payload = [];
- binOp = lhs: rhs: [];
+ getSubModules = modules;
+ substSubModules = m: submoduleWith (attrs // {
+ modules = m;
+ });
+ functor = defaultFunctor name // {
+ type = types.submoduleWith;
+ payload = {
+ modules = modules;
+ specialArgs = specialArgs;
+ shorthandOnlyDefinesConfig = shorthandOnlyDefinesConfig;
+ };
+ binOp = lhs: rhs: {
+ modules = lhs.modules ++ rhs.modules;
+ specialArgs =
+ let intersecting = builtins.intersectAttrs lhs.specialArgs rhs.specialArgs;
+ in if intersecting == {}
+ then lhs.specialArgs // rhs.specialArgs
+ else throw "A submoduleWith option is declared multiple times with the same specialArgs \"${toString (attrNames intersecting)}\"";
+ shorthandOnlyDefinesConfig =
+ if lhs.shorthandOnlyDefinesConfig == rhs.shorthandOnlyDefinesConfig
+ then lhs.shorthandOnlyDefinesConfig
+ else throw "A submoduleWith option is declared multiple times with conflicting shorthandOnlyDefinesConfig values";
+ };
};
};