aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/lib
diff options
context:
space:
mode:
authorKaiden Fey <kookie@spacekookie.de>2020-09-19 15:00:33 +0200
committerKatharina Fey <kookie@spacekookie.de>2020-09-19 15:00:33 +0200
commite0800985dab8f8ebb4cebdfd7e361fd1fafdb2a7 (patch)
tree289f43c72dd1fffeec4eb18ced05ae91e50c179a /nixpkgs/lib
parent5581b5521e14317c3507a6e8451a3f14996e5c4d (diff)
parent441a7da8080352881bb52f85e910d8855e83fc55 (diff)
Merge commit '441a7da8080352881bb52f85e910d8855e83fc55'
Diffstat (limited to 'nixpkgs/lib')
-rw-r--r--nixpkgs/lib/licenses.nix22
-rw-r--r--nixpkgs/lib/modules.nix171
-rw-r--r--nixpkgs/lib/strings.nix17
-rw-r--r--nixpkgs/lib/systems/architectures.nix77
-rw-r--r--nixpkgs/lib/systems/default.nix3
-rw-r--r--nixpkgs/lib/systems/doubles.nix2
-rw-r--r--nixpkgs/lib/systems/examples.nix8
-rw-r--r--nixpkgs/lib/tests/misc.nix26
-rwxr-xr-xnixpkgs/lib/tests/modules.sh23
-rw-r--r--nixpkgs/lib/tests/modules/define-value-string-properties.nix12
-rw-r--r--nixpkgs/lib/tests/modules/freeform-attrsOf.nix3
-rw-r--r--nixpkgs/lib/tests/modules/freeform-lazyAttrsOf.nix3
-rw-r--r--nixpkgs/lib/tests/modules/freeform-nested.nix7
-rw-r--r--nixpkgs/lib/tests/modules/freeform-str-dep-unstr.nix8
-rw-r--r--nixpkgs/lib/tests/modules/freeform-unstr-dep-str.nix8
-rw-r--r--nixpkgs/lib/tests/release.nix1
-rw-r--r--nixpkgs/lib/tests/systems.nix4
-rw-r--r--nixpkgs/lib/trivial.nix2
-rw-r--r--nixpkgs/lib/types.nix141
19 files changed, 359 insertions, 179 deletions
diff --git a/nixpkgs/lib/licenses.nix b/nixpkgs/lib/licenses.nix
index 2f9fc04cb7c..a704a6884c7 100644
--- a/nixpkgs/lib/licenses.nix
+++ b/nixpkgs/lib/licenses.nix
@@ -85,6 +85,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = ''Beerware License'';
};
+ blueOak100 = spdx {
+ spdxId = "BlueOak-1.0.0";
+ fullName = "Blue Oak Model License 1.0.0";
+ };
+
bsd0 = spdx {
spdxId = "0BSD";
fullName = "BSD Zero Clause License";
@@ -431,17 +436,18 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
};
# Proprietary binaries; free to redistribute without modification.
+ databricks = {
+ fullName = "Databricks Proprietary License";
+ url = "https://pypi.org/project/databricks-connect";
+ free = false;
+ };
+
issl = {
fullName = "Intel Simplified Software License";
url = "https://software.intel.com/en-us/license/intel-simplified-software-license";
free = false;
};
- jasper = spdx {
- spdxId = "JasPer-2.0";
- fullName = "JasPer License";
- };
-
lgpl2Only = spdx {
spdxId = "LGPL-2.0-only";
fullName = "GNU Library General Public License v2 only";
@@ -638,6 +644,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
url = "https://enterprise.dejacode.com/licenses/public/purdue-bsd";
};
+ prosperity30 = {
+ fullName = "Prosperity-3.0.0";
+ free = false;
+ url = "https://prosperitylicense.com/versions/3.0.0.html";
+ };
+
qhull = spdx {
spdxId = "Qhull";
fullName = "Qhull License";
diff --git a/nixpkgs/lib/modules.nix b/nixpkgs/lib/modules.nix
index c18fec66c70..412c7f1df71 100644
--- a/nixpkgs/lib/modules.nix
+++ b/nixpkgs/lib/modules.nix
@@ -58,6 +58,23 @@ rec {
default = check;
description = "Whether to check whether all option definitions have matching declarations.";
};
+
+ _module.freeformType = mkOption {
+ # Disallow merging for now, but could be implemented nicely with a `types.optionType`
+ type = types.nullOr (types.uniq types.attrs);
+ internal = true;
+ default = null;
+ description = ''
+ If set, merge all definitions that don't have an associated option
+ together using this type. The result then gets combined with the
+ values of all declared options to produce the final <literal>
+ config</literal> value.
+
+ If this is <literal>null</literal>, definitions without an option
+ will throw an error unless <option>_module.check</option> is
+ turned off.
+ '';
+ };
};
config = {
@@ -65,35 +82,55 @@ rec {
};
};
- collected = collectModules
- (specialArgs.modulesPath or "")
- (modules ++ [ internalModule ])
- ({ inherit config options lib; } // specialArgs);
-
- 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
- # definitions have matching declarations.
- # !!! _module.check's value can't depend on any other config values
- # without an infinite recursion. One way around this is to make the
- # 'config' passed around to the modules be unconditionally unchecked,
- # and only do the check in 'result'.
- config = yieldConfig prefix options;
- yieldConfig = prefix: set:
- let res = removeAttrs (mapAttrs (n: v:
- if isOption v then v.value
- else yieldConfig (prefix ++ [n]) v) set) ["_definedNames"];
- in
- if options._module.check.value && set ? _definedNames then
- foldl' (res: m:
- foldl' (res: name:
- if set ? ${name} then res else throw "The option `${showOption (prefix ++ [name])}' defined in `${m.file}' does not exist.")
- res m.names)
- res set._definedNames
- else
- res;
- result = {
+ merged =
+ let collected = collectModules
+ (specialArgs.modulesPath or "")
+ (modules ++ [ internalModule ])
+ ({ inherit lib options config; } // specialArgs);
+ in mergeModules prefix (reverseList collected);
+
+ options = merged.matchedOptions;
+
+ config =
+ let
+
+ # For definitions that have an associated option
+ declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
+
+ # If freeformType is set, this is for definitions that don't have an associated option
+ freeformConfig =
+ let
+ defs = map (def: {
+ file = def.file;
+ value = setAttrByPath def.prefix def.value;
+ }) merged.unmatchedDefns;
+ in if defs == [] then {}
+ else declaredConfig._module.freeformType.merge prefix defs;
+
+ in if declaredConfig._module.freeformType == null then declaredConfig
+ # Because all definitions that had an associated option ended in
+ # declaredConfig, freeformConfig can only contain the non-option
+ # paths, meaning recursiveUpdate will never override any value
+ else recursiveUpdate freeformConfig declaredConfig;
+
+ checkUnmatched =
+ if config._module.check && config._module.freeformType == null && merged.unmatchedDefns != [] then
+ let
+ firstDef = head merged.unmatchedDefns;
+ baseMsg = "The option `${showOption (prefix ++ firstDef.prefix)}' defined in `${firstDef.file}' does not exist.";
+ in
+ if attrNames options == [ "_module" ]
+ then throw ''
+ ${baseMsg}
+
+ However there are no options defined in `${showOption prefix}'. Are you sure you've
+ declared your options properly? This can happen if you e.g. declared your options in `types.submodule'
+ under `config' rather than `options'.
+ ''
+ else throw baseMsg
+ else null;
+
+ result = builtins.seq checkUnmatched {
inherit options;
config = removeAttrs config [ "_module" ];
inherit (config) _module;
@@ -174,12 +211,16 @@ rec {
/* Massage a module into canonical form, that is, a set consisting
of ā€˜optionsā€™, ā€˜configā€™ and ā€˜importsā€™ attributes. */
unifyModuleSyntax = file: key: m:
- let addMeta = config: if m ? meta
- then mkMerge [ config { meta = m.meta; } ]
- else config;
+ let
+ addMeta = config: if m ? meta
+ then mkMerge [ config { meta = m.meta; } ]
+ else config;
+ addFreeformType = config: if m ? freeformType
+ then mkMerge [ config { _module.freeformType = m.freeformType; } ]
+ else config;
in
if m ? config || m ? options then
- let badAttrs = removeAttrs m ["_file" "key" "disabledModules" "imports" "options" "config" "meta"]; in
+ let badAttrs = removeAttrs m ["_file" "key" "disabledModules" "imports" "options" "config" "meta" "freeformType"]; in
if badAttrs != {} then
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
@@ -188,7 +229,7 @@ rec {
disabledModules = m.disabledModules or [];
imports = m.imports or [];
options = m.options or {};
- config = addMeta (m.config or {});
+ config = addFreeformType (addMeta (m.config or {}));
}
else
{ _file = m._file or file;
@@ -196,7 +237,7 @@ rec {
disabledModules = m.disabledModules or [];
imports = m.require or [] ++ m.imports or [];
options = {};
- config = addMeta (removeAttrs m ["_file" "key" "disabledModules" "require" "imports"]);
+ config = addFreeformType (addMeta (removeAttrs m ["_file" "key" "disabledModules" "require" "imports" "freeformType"]));
};
applyIfFunction = key: f: args@{ config, options, lib, ... }: if isFunction f then
@@ -233,7 +274,23 @@ rec {
declarations in all modules, combining them into a single set.
At the same time, for each option declaration, it will merge the
corresponding option definitions in all machines, returning them
- in the ā€˜valueā€™ attribute of each option. */
+ in the ā€˜valueā€™ attribute of each option.
+
+ This returns a set like
+ {
+ # A recursive set of options along with their final values
+ matchedOptions = {
+ foo = { _type = "option"; value = "option value of foo"; ... };
+ bar.baz = { _type = "option"; value = "option value of bar.baz"; ... };
+ ...
+ };
+ # A list of definitions that weren't matched by any option
+ unmatchedDefns = [
+ { file = "file.nix"; prefix = [ "qux" ]; value = "qux"; }
+ ...
+ ];
+ }
+ */
mergeModules = prefix: modules:
mergeModules' prefix modules
(concatMap (m: map (config: { file = m._file; inherit config; }) (pushDownProperties m.config)) modules);
@@ -280,9 +337,9 @@ rec {
defnsByName' = byName "config" (module: value:
[{ inherit (module) file; inherit value; }]
) configs;
- in
- (flip mapAttrs declsByName (name: decls:
- # We're descending into attribute ā€˜nameā€™.
+
+ resultsByName = flip mapAttrs declsByName (name: decls:
+ # We're descending into attribute ā€˜nameā€™.
let
loc = prefix ++ [name];
defns = defnsByName.${name} or [];
@@ -291,7 +348,10 @@ rec {
in
if nrOptions == length decls then
let opt = fixupOptionType loc (mergeOptionDecls loc decls);
- in evalOptionValue loc opt defns'
+ in {
+ matchedOptions = evalOptionValue loc opt defns';
+ unmatchedDefns = [];
+ }
else if nrOptions != 0 then
let
firstOption = findFirst (m: isOption m.options) "" decls;
@@ -299,9 +359,27 @@ rec {
in
throw "The option `${showOption loc}' in `${firstOption._file}' is a prefix of options in `${firstNonOption._file}'."
else
- mergeModules' loc decls defns
- ))
- // { _definedNames = map (m: { inherit (m) file; names = attrNames m.config; }) configs; };
+ mergeModules' loc decls defns);
+
+ matchedOptions = mapAttrs (n: v: v.matchedOptions) resultsByName;
+
+ # an attrset 'name' => list of unmatched definitions for 'name'
+ unmatchedDefnsByName =
+ # Propagate all unmatched definitions from nested option sets
+ mapAttrs (n: v: v.unmatchedDefns) resultsByName
+ # Plus the definitions for the current prefix that don't have a matching option
+ // removeAttrs defnsByName' (attrNames matchedOptions);
+ in {
+ inherit matchedOptions;
+
+ # Transforms unmatchedDefnsByName into a list of definitions
+ unmatchedDefns = concatLists (mapAttrsToList (name: defs:
+ map (def: def // {
+ # Set this so we know when the definition first left unmatched territory
+ prefix = [name] ++ (def.prefix or []);
+ }) defs
+ ) unmatchedDefnsByName);
+ };
/* Merge multiple option declarations into a single declaration. In
general, there should be only one declaration of each option.
@@ -379,7 +457,11 @@ rec {
# yield a value computed from the definitions
value = if opt ? apply then opt.apply res.mergedValue else res.mergedValue;
- in opt //
+ warnDeprecation =
+ if opt.type.deprecationMessage == null then id
+ else warn "The type `types.${opt.type.name}' of option `${showOption loc}' defined in ${showFiles opt.declarations} is deprecated. ${opt.type.deprecationMessage}";
+
+ in warnDeprecation opt //
{ value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
inherit (res.defsFinal') highestPrio;
definitions = map (def: def.value) res.defsFinal;
@@ -535,7 +617,6 @@ rec {
if tp.name == "option set" || tp.name == "submodule" then
throw "The option ${showOption loc} uses submodules without a wrapping type, in ${showFiles opt.declarations}."
else if optionSetIn "attrsOf" then types.attrsOf (types.submodule options)
- else if optionSetIn "loaOf" then types.loaOf (types.submodule options)
else if optionSetIn "listOf" then types.listOf (types.submodule options)
else if optionSetIn "nullOr" then types.nullOr (types.submodule options)
else tp;
diff --git a/nixpkgs/lib/strings.nix b/nixpkgs/lib/strings.nix
index 0baa942355c..9fa9f023561 100644
--- a/nixpkgs/lib/strings.nix
+++ b/nixpkgs/lib/strings.nix
@@ -689,14 +689,15 @@ rec {
"/prefix/nix-profiles-library-paths.patch"
"/prefix/compose-search-path.patch" ]
*/
- readPathsFromFile = rootPath: file:
- let
- lines = lib.splitString "\n" (builtins.readFile file);
- removeComments = lib.filter (line: line != "" && !(lib.hasPrefix "#" line));
- relativePaths = removeComments lines;
- absolutePaths = builtins.map (path: rootPath + "/${path}") relativePaths;
- in
- absolutePaths;
+ readPathsFromFile = lib.warn "lib.readPathsFromFile is deprecated, use a list instead"
+ (rootPath: file:
+ let
+ lines = lib.splitString "\n" (builtins.readFile file);
+ removeComments = lib.filter (line: line != "" && !(lib.hasPrefix "#" line));
+ relativePaths = removeComments lines;
+ absolutePaths = builtins.map (path: rootPath + "/${path}") relativePaths;
+ in
+ absolutePaths);
/* Read the contents of a file removing the trailing \n
diff --git a/nixpkgs/lib/systems/architectures.nix b/nixpkgs/lib/systems/architectures.nix
new file mode 100644
index 00000000000..bfecaec1ae8
--- /dev/null
+++ b/nixpkgs/lib/systems/architectures.nix
@@ -0,0 +1,77 @@
+{ lib }:
+
+rec {
+ # platform.gcc.arch to its features (as in /proc/cpuinfo)
+ features = {
+ default = [ ];
+ # x86_64 Intel
+ westmere = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" ];
+ sandybridge = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
+ ivybridge = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
+ haswell = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
+ broadwell = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
+ skylake = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
+ skylake-avx512 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "avx512" "fma" ];
+ # x86_64 AMD
+ btver1 = [ "sse3" "ssse3" "sse4_1" "sse4_2" ];
+ btver2 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
+ bdver1 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "fma" "fma4" ];
+ bdver2 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "fma" "fma4" ];
+ bdver3 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "fma" "fma4" ];
+ bdver4 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "fma" "fma4" ];
+ znver1 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "fma" ];
+ znver2 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "fma" ];
+ # other
+ armv5te = [ ];
+ armv6 = [ ];
+ armv7-a = [ ];
+ armv8-a = [ ];
+ mips32 = [ ];
+ loongson2f = [ ];
+ };
+
+ # a superior CPU has all the features of an inferior and is able to build and test code for it
+ inferiors = {
+ # x86_64 Intel
+ default = [ ];
+ westmere = [ ];
+ sandybridge = [ "westmere" ] ++ inferiors.westmere;
+ ivybridge = [ "sandybridge" ] ++ inferiors.sandybridge;
+ haswell = [ "ivybridge" ] ++ inferiors.ivybridge;
+ broadwell = [ "haswell" ] ++ inferiors.haswell;
+ skylake = [ "broadwell" ] ++ inferiors.broadwell;
+ skylake-avx512 = [ "skylake" ] ++ inferiors.skylake;
+ # x86_64 AMD
+ btver1 = [ ];
+ btver2 = [ ]; # TODO: fill this (need testing)
+ bdver1 = [ ]; # TODO: fill this (need testing)
+ bdver2 = [ ]; # TODO: fill this (need testing)
+ bdver3 = [ ]; # TODO: fill this (need testing)
+ bdver4 = [ ]; # TODO: fill this (need testing)
+ znver1 = [ ]; # TODO: fill this (need testing)
+ znver2 = [ ]; # TODO: fill this (need testing)
+ # other
+ armv5te = [ ];
+ armv6 = [ ];
+ armv7-a = [ ];
+ armv8-a = [ ];
+ mips32 = [ ];
+ loongson2f = [ ];
+ };
+
+ predicates = let
+ featureSupport = feature: x: builtins.elem feature features.${x} or [];
+ in {
+ sse3Support = featureSupport "sse3";
+ ssse3Support = featureSupport "ssse3";
+ sse4_1Support = featureSupport "sse4_1";
+ sse4_2Support = featureSupport "sse4_2";
+ sse4_aSupport = featureSupport "sse4a";
+ avxSupport = featureSupport "avx";
+ avx2Support = featureSupport "avx2";
+ avx512Support = featureSupport "avx512";
+ aesSupport = featureSupport "aes";
+ fmaSupport = featureSupport "fma";
+ fma4Support = featureSupport "fma4";
+ };
+}
diff --git a/nixpkgs/lib/systems/default.nix b/nixpkgs/lib/systems/default.nix
index c929781dd8f..9939743157e 100644
--- a/nixpkgs/lib/systems/default.nix
+++ b/nixpkgs/lib/systems/default.nix
@@ -7,6 +7,7 @@ rec {
inspect = import ./inspect.nix { inherit lib; };
platforms = import ./platforms.nix { inherit lib; };
examples = import ./examples.nix { inherit lib; };
+ architectures = import ./architectures.nix { inherit lib; };
# Elaborate a `localSystem` or `crossSystem` so that it contains everything
# necessary.
@@ -76,6 +77,7 @@ rec {
# uname -r
release = null;
};
+ isStatic = final.isWasm || final.isRedox;
kernelArch =
if final.isAarch32 then "arm"
@@ -125,6 +127,7 @@ rec {
else throw "Don't know how to run ${final.config} executables.";
} // mapAttrs (n: v: v final.parsed) inspect.predicates
+ // mapAttrs (n: v: v final.platform.gcc.arch or "default") architectures.predicates
// args;
in assert final.useAndroidPrebuilt -> final.isAndroid;
assert lib.foldl
diff --git a/nixpkgs/lib/systems/doubles.nix b/nixpkgs/lib/systems/doubles.nix
index c0e78595d85..fb7d722e737 100644
--- a/nixpkgs/lib/systems/doubles.nix
+++ b/nixpkgs/lib/systems/doubles.nix
@@ -38,7 +38,7 @@ let
"js-ghcjs"
- "aarch64-genode" "x86_64-genode"
+ "aarch64-genode" "i686-genode" "x86_64-genode"
];
allParsed = map parse.mkSystemFromString all;
diff --git a/nixpkgs/lib/systems/examples.nix b/nixpkgs/lib/systems/examples.nix
index ca562d2e456..5403f73405c 100644
--- a/nixpkgs/lib/systems/examples.nix
+++ b/nixpkgs/lib/systems/examples.nix
@@ -46,16 +46,16 @@ rec {
armv7a-android-prebuilt = {
config = "armv7a-unknown-linux-androideabi";
- sdkVer = "24";
- ndkVer = "18b";
+ sdkVer = "29";
+ ndkVer = "21";
platform = platforms.armv7a-android;
useAndroidPrebuilt = true;
};
aarch64-android-prebuilt = {
config = "aarch64-unknown-linux-android";
- sdkVer = "24";
- ndkVer = "18b";
+ sdkVer = "29";
+ ndkVer = "21";
platform = platforms.aarch64-multiplatform;
useAndroidPrebuilt = true;
};
diff --git a/nixpkgs/lib/tests/misc.nix b/nixpkgs/lib/tests/misc.nix
index b066f577f32..03eff4ce48b 100644
--- a/nixpkgs/lib/tests/misc.nix
+++ b/nixpkgs/lib/tests/misc.nix
@@ -542,4 +542,30 @@ runTests {
name = "";
expected = "unknown";
};
+
+ testFreeformOptions = {
+ expr =
+ let
+ submodule = { lib, ... }: {
+ freeformType = lib.types.attrsOf (lib.types.submodule {
+ options.bar = lib.mkOption {};
+ });
+ options.bar = lib.mkOption {};
+ };
+
+ module = { lib, ... }: {
+ options.foo = lib.mkOption {
+ type = lib.types.submodule submodule;
+ };
+ };
+
+ options = (evalModules {
+ modules = [ module ];
+ }).options;
+
+ locs = filter (o: ! o.internal) (optionAttrSetToDocList options);
+ in map (o: o.loc) locs;
+ expected = [ [ "foo" ] [ "foo" "<name>" "bar" ] [ "foo" "bar" ] ];
+ };
+
}
diff --git a/nixpkgs/lib/tests/modules.sh b/nixpkgs/lib/tests/modules.sh
index 6258244457a..943deebe3c0 100755
--- a/nixpkgs/lib/tests/modules.sh
+++ b/nixpkgs/lib/tests/modules.sh
@@ -210,6 +210,29 @@ checkConfigOutput "empty" config.value.foo ./declare-lazyAttrsOf.nix ./attrsOf-c
checkConfigError 'The option value .* in .* is not of type .*' \
config.value ./declare-int-unsigned-value.nix ./define-value-list.nix ./define-value-int-positive.nix
+## Freeform modules
+# Assigning without a declared option should work
+checkConfigOutput 24 config.value ./freeform-attrsOf.nix ./define-value-string.nix
+# No freeform assigments shouldn't make it error
+checkConfigOutput '{ }' config ./freeform-attrsOf.nix
+# but only if the type matches
+checkConfigError 'The option value .* in .* is not of type .*' config.value ./freeform-attrsOf.nix ./define-value-list.nix
+# and properties should be applied
+checkConfigOutput yes config.value ./freeform-attrsOf.nix ./define-value-string-properties.nix
+# Options should still be declarable, and be able to have a type that doesn't match the freeform type
+checkConfigOutput false config.enable ./freeform-attrsOf.nix ./define-value-string.nix ./declare-enable.nix
+checkConfigOutput 24 config.value ./freeform-attrsOf.nix ./define-value-string.nix ./declare-enable.nix
+# and this should work too with nested values
+checkConfigOutput false config.nest.foo ./freeform-attrsOf.nix ./freeform-nested.nix
+checkConfigOutput bar config.nest.bar ./freeform-attrsOf.nix ./freeform-nested.nix
+# Check whether a declared option can depend on an freeform-typed one
+checkConfigOutput null config.foo ./freeform-attrsOf.nix ./freeform-str-dep-unstr.nix
+checkConfigOutput 24 config.foo ./freeform-attrsOf.nix ./freeform-str-dep-unstr.nix ./define-value-string.nix
+# Check whether an freeform-typed value can depend on a declared option, this can only work with lazyAttrsOf
+checkConfigError 'infinite recursion encountered' config.foo ./freeform-attrsOf.nix ./freeform-unstr-dep-str.nix
+checkConfigError 'The option .* is used but not defined' config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix
+checkConfigOutput 24 config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix ./define-value-string.nix
+
cat <<EOF
====== module tests ======
$pass Pass
diff --git a/nixpkgs/lib/tests/modules/define-value-string-properties.nix b/nixpkgs/lib/tests/modules/define-value-string-properties.nix
new file mode 100644
index 00000000000..972304c0112
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/define-value-string-properties.nix
@@ -0,0 +1,12 @@
+{ lib, ... }: {
+
+ imports = [{
+ value = lib.mkDefault "def";
+ }];
+
+ value = lib.mkMerge [
+ (lib.mkIf false "nope")
+ "yes"
+ ];
+
+}
diff --git a/nixpkgs/lib/tests/modules/freeform-attrsOf.nix b/nixpkgs/lib/tests/modules/freeform-attrsOf.nix
new file mode 100644
index 00000000000..8cc577f38a6
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/freeform-attrsOf.nix
@@ -0,0 +1,3 @@
+{ lib, ... }: {
+ freeformType = with lib.types; attrsOf (either str (attrsOf str));
+}
diff --git a/nixpkgs/lib/tests/modules/freeform-lazyAttrsOf.nix b/nixpkgs/lib/tests/modules/freeform-lazyAttrsOf.nix
new file mode 100644
index 00000000000..36d6c0b13fc
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/freeform-lazyAttrsOf.nix
@@ -0,0 +1,3 @@
+{ lib, ... }: {
+ freeformType = with lib.types; lazyAttrsOf (either str (lazyAttrsOf str));
+}
diff --git a/nixpkgs/lib/tests/modules/freeform-nested.nix b/nixpkgs/lib/tests/modules/freeform-nested.nix
new file mode 100644
index 00000000000..5da27f5a8b4
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/freeform-nested.nix
@@ -0,0 +1,7 @@
+{ lib, ... }: {
+ options.nest.foo = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+ config.nest.bar = "bar";
+}
diff --git a/nixpkgs/lib/tests/modules/freeform-str-dep-unstr.nix b/nixpkgs/lib/tests/modules/freeform-str-dep-unstr.nix
new file mode 100644
index 00000000000..a2dfbc80cfa
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/freeform-str-dep-unstr.nix
@@ -0,0 +1,8 @@
+{ lib, config, ... }: {
+ options.foo = lib.mkOption {
+ type = lib.types.nullOr lib.types.str;
+ default = null;
+ };
+
+ config.foo = lib.mkIf (config ? value) config.value;
+}
diff --git a/nixpkgs/lib/tests/modules/freeform-unstr-dep-str.nix b/nixpkgs/lib/tests/modules/freeform-unstr-dep-str.nix
new file mode 100644
index 00000000000..549d89afeca
--- /dev/null
+++ b/nixpkgs/lib/tests/modules/freeform-unstr-dep-str.nix
@@ -0,0 +1,8 @@
+{ lib, config, ... }: {
+ options.value = lib.mkOption {
+ type = lib.types.nullOr lib.types.str;
+ default = null;
+ };
+
+ config.foo = lib.mkIf (config.value != null) config.value;
+}
diff --git a/nixpkgs/lib/tests/release.nix b/nixpkgs/lib/tests/release.nix
index eebee1b49bc..800d8a65c14 100644
--- a/nixpkgs/lib/tests/release.nix
+++ b/nixpkgs/lib/tests/release.nix
@@ -17,7 +17,6 @@ pkgs.runCommandNoCC "nixpkgs-lib-tests" {
export TEST_ROOT=$(pwd)/test-tmp
export NIX_BUILD_HOOK=
export NIX_CONF_DIR=$TEST_ROOT/etc
- export NIX_DB_DIR=$TEST_ROOT/db
export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
export NIX_STATE_DIR=$TEST_ROOT/var/nix
diff --git a/nixpkgs/lib/tests/systems.nix b/nixpkgs/lib/tests/systems.nix
index ea8ceedd43f..f691b2da316 100644
--- a/nixpkgs/lib/tests/systems.nix
+++ b/nixpkgs/lib/tests/systems.nix
@@ -15,14 +15,14 @@ in with lib.systems.doubles; lib.runTests {
testall = mseteq all (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ wasi ++ windows ++ embedded ++ js ++ genode ++ redox);
testarm = mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv6l-none" "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" ];
+ testi686 = mseteq i686 [ "i686-linux" "i686-freebsd" "i686-genode" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" "i686-none" "i686-darwin" ];
testmips = mseteq mips [ "mipsel-linux" ];
testx86_64 = mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-genode" "x86_64-redox" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" "x86_64-windows" "x86_64-none" ];
testcygwin = mseteq cygwin [ "i686-cygwin" "x86_64-cygwin" ];
testdarwin = mseteq darwin [ "x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin" ];
testfreebsd = mseteq freebsd [ "i686-freebsd" "x86_64-freebsd" ];
- testgenode = mseteq genode [ "aarch64-genode" "x86_64-genode" ];
+ testgenode = mseteq genode [ "aarch64-genode" "i686-genode" "x86_64-genode" ];
testredox = mseteq redox [ "x86_64-redox" ];
testgnu = mseteq gnu (linux /* ++ kfreebsd ++ ... */);
testillumos = mseteq illumos [ "x86_64-solaris" ];
diff --git a/nixpkgs/lib/trivial.nix b/nixpkgs/lib/trivial.nix
index 6eb1fb3a5b1..9501a2906ca 100644
--- a/nixpkgs/lib/trivial.nix
+++ b/nixpkgs/lib/trivial.nix
@@ -171,7 +171,7 @@ rec {
On each release the first letter is bumped and a new animal is chosen
starting with that new letter.
*/
- codeName = "Nightingale";
+ codeName = "Okapi";
/* Returns the current nixpkgs version suffix as string. */
versionSuffix =
diff --git a/nixpkgs/lib/types.nix b/nixpkgs/lib/types.nix
index 6fd6de7e1fd..ef2c78082f8 100644
--- a/nixpkgs/lib/types.nix
+++ b/nixpkgs/lib/types.nix
@@ -91,9 +91,12 @@ rec {
# combinable with the binOp binary operation.
# binOp: binary operation that merge two payloads of the same type.
functor ? defaultFunctor name
+ , # The deprecation message to display when this type is used by an option
+ # If null, the type isn't deprecated
+ deprecationMessage ? null
}:
{ _type = "option-type";
- inherit name check merge emptyValue getSubOptions getSubModules substSubModules typeMerge functor;
+ inherit name check merge emptyValue getSubOptions getSubModules substSubModules typeMerge functor deprecationMessage;
description = if description == null then name else description;
};
@@ -222,8 +225,10 @@ rec {
# Deprecated; should not be used because it quietly concatenates
# strings, which is usually not what you want.
- string = warn "types.string is deprecated because it quietly concatenates strings"
- (separatedString "");
+ string = separatedString "" // {
+ name = "string";
+ deprecationMessage = "See https://github.com/NixOS/nixpkgs/pull/66346 for better alternative types.";
+ };
attrs = mkOptionType {
name = "attrs";
@@ -252,9 +257,6 @@ rec {
merge = mergeEqualOption;
};
- # drop this in the future:
- list = builtins.trace "`types.list` is deprecated; use `types.listOf` instead" types.listOf;
-
listOf = elemType: mkOptionType rec {
name = "listOf";
description = "list of ${elemType.description}s";
@@ -326,110 +328,13 @@ rec {
functor = (defaultFunctor name) // { wrapped = elemType; };
};
- # List or attribute set of ...
- loaOf = elemType:
- let
- convertAllLists = loc: defs:
- let
- padWidth = stringLength (toString (length defs));
- unnamedPrefix = i: "unnamed-" + fixedWidthNumber padWidth i + ".";
- in
- 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;
- anyString = placeholder "name";
- nameAttrs = [
- { path = [ "environment" "etc" ];
- name = "target";
- }
- { path = [ "containers" anyString "bindMounts" ];
- name = "mountPoint";
- }
- { path = [ "programs" "ssh" "knownHosts" ];
- # hostNames is actually a list so we would need to handle it only when singleton
- name = "hostNames";
- }
- { path = [ "fileSystems" ];
- name = "mountPoint";
- }
- { path = [ "boot" "specialFileSystems" ];
- name = "mountPoint";
- }
- { path = [ "services" "znapzend" "zetup" ];
- name = "dataset";
- }
- { path = [ "services" "znapzend" "zetup" anyString "destinations" ];
- name = "label";
- }
- { path = [ "services" "geoclue2" "appConfig" ];
- name = "desktopID";
- }
- ];
- matched = let
- equals = a: b: b == anyString || a == b;
- fallback = { name = "name"; };
- in findFirst ({ path, ... }: all (v: v == true) (zipListsWith equals loc path)) fallback nameAttrs;
- nameAttr = matched.name;
- nameValueOld = value:
- if isList value then
- if length value > 0 then
- "[ " + concatMapStringsSep " " escapeNixString value + " ]"
- else
- "[ ]"
- else
- escapeNixString value;
- nameValueNew = value: unnamed:
- if isList value then
- if length value > 0 then
- head value
- else
- unnamed
- else
- value;
- res =
- { inherit (def) file;
- value = listToAttrs (
- imap1 (elemIdx: elem:
- { name = nameValueNew (elem.${nameAttr} or (unnamed elemIdx)) (unnamed elemIdx);
- value = elem;
- }) def.value);
- };
- option = concatStringsSep "." loc;
- sample = take 3 def.value;
- more = lib.optionalString (length def.value > 3) "... ";
- list = concatMapStrings (x: ''{ ${nameAttr} = ${nameValueOld (x.${nameAttr} or "unnamed")}; ...} '') sample;
- set = concatMapStrings (x: ''${nameValueNew (x.${nameAttr} or "unnamed") "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://github.com/NixOS/nixpkgs/pull/63103 for more information.
- Do
- ${option} =
- { ${set}${more}}
- instead of
- ${option} =
- [ ${list}${more}]
- '';
- in
- lib.warn msg res
- else
- def;
- attrOnly = attrsOf elemType;
- in mkOptionType 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 loc defs);
- emptyValue = { value = {}; };
- getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]);
- getSubModules = elemType.getSubModules;
- substSubModules = m: loaOf (elemType.substSubModules m);
- functor = (defaultFunctor name) // { wrapped = elemType; };
- };
+ # TODO: drop this in the future:
+ loaOf = elemType: types.attrsOf elemType // {
+ name = "loaOf";
+ deprecationMessage = "Mixing lists with attribute values is no longer"
+ + " possible; please use `types.attrsOf` instead. See"
+ + " https://github.com/NixOS/nixpkgs/issues/1800 for the motivation.";
+ };
# Value of given type but with no merging (i.e. `uniq list`s are not concatenated).
uniq = elemType: mkOptionType rec {
@@ -486,9 +391,15 @@ rec {
else value
) defs;
+ freeformType = (evalModules {
+ inherit modules specialArgs;
+ args.name = "ā€¹nameā€ŗ";
+ })._module.freeformType;
+
in
mkOptionType rec {
name = "submodule";
+ description = freeformType.description or name;
check = x: isAttrs x || isFunction x || path.check x;
merge = loc: defs:
(evalModules {
@@ -516,7 +427,12 @@ rec {
# would be used, and use of `<` and `>` would break the XML document.
# It shouldn't cause an issue since this is cosmetic for the manual.
args.name = "ā€¹nameā€ŗ";
- }).options;
+ }).options // optionalAttrs (freeformType != null) {
+ # Expose the sub options of the freeform type. Note that the option
+ # discovery doesn't care about the attribute name used here, so this
+ # is just to avoid conflicts with potential options from the submodule
+ _freeformOptions = freeformType.getSubOptions prefix;
+ };
getSubModules = modules;
substSubModules = m: submoduleWith (attrs // {
modules = m;
@@ -618,8 +534,9 @@ rec {
# declarations from the ā€˜optionsā€™ attribute of containing option
# declaration.
optionSet = mkOptionType {
- name = builtins.trace "types.optionSet is deprecated; use types.submodule instead" "optionSet";
+ name = "optionSet";
description = "option set";
+ deprecationMessage = "Use `types.submodule' instead";
};
# Augment the given type with an additional type check function.
addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; };