summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/licenses.nix11
-rw-r--r--lib/modules.nix6
-rw-r--r--lib/options.nix4
-rw-r--r--lib/systems/architectures.nix2
-rw-r--r--lib/systems/doubles.nix53
-rw-r--r--lib/systems/examples.nix4
-rw-r--r--lib/tests/misc.nix26
-rwxr-xr-xlib/tests/modules.sh29
-rw-r--r--lib/tests/modules/types-anything/attrs-coercible.nix12
-rw-r--r--lib/tests/modules/types-anything/equal-atoms.nix26
-rw-r--r--lib/tests/modules/types-anything/functions.nix17
-rw-r--r--lib/tests/modules/types-anything/lists.nix16
-rw-r--r--lib/tests/modules/types-anything/mk-mods.nix44
-rw-r--r--lib/tests/modules/types-anything/nested-attrs.nix22
-rw-r--r--lib/trivial.nix2
-rw-r--r--lib/types.nix74
16 files changed, 297 insertions, 51 deletions
diff --git a/lib/licenses.nix b/lib/licenses.nix
index ee11966b0d53..a704a6884c7d 100644
--- a/lib/licenses.nix
+++ b/lib/licenses.nix
@@ -448,11 +448,6 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
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";
@@ -649,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/lib/modules.nix b/lib/modules.nix
index decb96ffe111..412c7f1df712 100644
--- a/lib/modules.nix
+++ b/lib/modules.nix
@@ -457,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;
diff --git a/lib/options.nix b/lib/options.nix
index 38f4f1329f21..0494a597ab80 100644
--- a/lib/options.nix
+++ b/lib/options.nix
@@ -107,6 +107,10 @@ rec {
/* "Merge" option definitions by checking that they all have the same value. */
mergeEqualOption = loc: defs:
if defs == [] then abort "This case should never happen."
+ # Return early if we only have one element
+ # This also makes it work for functions, because the foldl' below would try
+ # to compare the first element with itself, which is false for functions
+ else if length defs == 1 then (elemAt defs 0).value
else foldl' (val: def:
if def.value != val then
throw "The option `${showOption loc}' has conflicting definitions, in ${showFiles (getFiles defs)}."
diff --git a/lib/systems/architectures.nix b/lib/systems/architectures.nix
index 9d1c29fd9f0b..bfecaec1ae88 100644
--- a/lib/systems/architectures.nix
+++ b/lib/systems/architectures.nix
@@ -60,7 +60,7 @@ rec {
};
predicates = let
- featureSupport = feature: x: builtins.elem feature features.${x};
+ featureSupport = feature: x: builtins.elem feature features.${x} or [];
in {
sse3Support = featureSupport "sse3";
ssse3Support = featureSupport "ssse3";
diff --git a/lib/systems/doubles.nix b/lib/systems/doubles.nix
index fb7d722e737e..517a7296afd2 100644
--- a/lib/systems/doubles.nix
+++ b/lib/systems/doubles.nix
@@ -50,32 +50,35 @@ in {
none = [];
- arm = filterDoubles predicates.isAarch32;
- aarch64 = filterDoubles predicates.isAarch64;
- x86 = filterDoubles predicates.isx86;
- i686 = filterDoubles predicates.isi686;
- x86_64 = filterDoubles predicates.isx86_64;
- mips = filterDoubles predicates.isMips;
- riscv = filterDoubles predicates.isRiscV;
- vc4 = filterDoubles predicates.isVc4;
- js = filterDoubles predicates.isJavaScript;
-
- cygwin = filterDoubles predicates.isCygwin;
- darwin = filterDoubles predicates.isDarwin;
- freebsd = filterDoubles predicates.isFreeBSD;
+ arm = filterDoubles predicates.isAarch32;
+ aarch64 = filterDoubles predicates.isAarch64;
+ x86 = filterDoubles predicates.isx86;
+ i686 = filterDoubles predicates.isi686;
+ x86_64 = filterDoubles predicates.isx86_64;
+ mips = filterDoubles predicates.isMips;
+ riscv = filterDoubles predicates.isRiscV;
+ vc4 = filterDoubles predicates.isVc4;
+ js = filterDoubles predicates.isJavaScript;
+
+ bigEndian = filterDoubles predicates.isBigEndian;
+ littleEndian = filterDoubles predicates.isLittleEndian;
+
+ cygwin = filterDoubles predicates.isCygwin;
+ darwin = filterDoubles predicates.isDarwin;
+ freebsd = filterDoubles predicates.isFreeBSD;
# Should be better, but MinGW is unclear.
- gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabi; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabihf; });
- illumos = filterDoubles predicates.isSunOS;
- linux = filterDoubles predicates.isLinux;
- netbsd = filterDoubles predicates.isNetBSD;
- openbsd = filterDoubles predicates.isOpenBSD;
- unix = filterDoubles predicates.isUnix;
- wasi = filterDoubles predicates.isWasi;
- redox = filterDoubles predicates.isRedox;
- windows = filterDoubles predicates.isWindows;
- genode = filterDoubles predicates.isGenode;
-
- embedded = filterDoubles predicates.isNone;
+ gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabi; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabihf; });
+ illumos = filterDoubles predicates.isSunOS;
+ linux = filterDoubles predicates.isLinux;
+ netbsd = filterDoubles predicates.isNetBSD;
+ openbsd = filterDoubles predicates.isOpenBSD;
+ unix = filterDoubles predicates.isUnix;
+ wasi = filterDoubles predicates.isWasi;
+ redox = filterDoubles predicates.isRedox;
+ windows = filterDoubles predicates.isWindows;
+ genode = filterDoubles predicates.isGenode;
+
+ embedded = filterDoubles predicates.isNone;
mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "armv7a-linux" "aarch64-linux" "powerpc64le-linux"];
}
diff --git a/lib/systems/examples.nix b/lib/systems/examples.nix
index 40e2b8fcefbc..5403f73405c2 100644
--- a/lib/systems/examples.nix
+++ b/lib/systems/examples.nix
@@ -47,7 +47,7 @@ rec {
armv7a-android-prebuilt = {
config = "armv7a-unknown-linux-androideabi";
sdkVer = "29";
- ndkVer = "18b";
+ ndkVer = "21";
platform = platforms.armv7a-android;
useAndroidPrebuilt = true;
};
@@ -55,7 +55,7 @@ rec {
aarch64-android-prebuilt = {
config = "aarch64-unknown-linux-android";
sdkVer = "29";
- ndkVer = "18b";
+ ndkVer = "21";
platform = platforms.aarch64-multiplatform;
useAndroidPrebuilt = true;
};
diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix
index f60e6ad17870..3a6db53c276d 100644
--- a/lib/tests/misc.nix
+++ b/lib/tests/misc.nix
@@ -600,4 +600,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/lib/tests/modules.sh b/lib/tests/modules.sh
index 943deebe3c09..cfe474d4ded2 100755
--- a/lib/tests/modules.sh
+++ b/lib/tests/modules.sh
@@ -233,6 +233,35 @@ checkConfigError 'infinite recursion encountered' config.foo ./freeform-attrsOf.
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
+## types.anything
+# Check that attribute sets are merged recursively
+checkConfigOutput null config.value.foo ./types-anything/nested-attrs.nix
+checkConfigOutput null config.value.l1.foo ./types-anything/nested-attrs.nix
+checkConfigOutput null config.value.l1.l2.foo ./types-anything/nested-attrs.nix
+checkConfigOutput null config.value.l1.l2.l3.foo ./types-anything/nested-attrs.nix
+# Attribute sets that are coercible to strings shouldn't be recursed into
+checkConfigOutput foo config.value.outPath ./types-anything/attrs-coercible.nix
+# Multiple lists aren't concatenated together
+checkConfigError 'The option .* has conflicting definitions' config.value ./types-anything/lists.nix
+# Check that all equalizable atoms can be used as long as all definitions are equal
+checkConfigOutput 0 config.value.int ./types-anything/equal-atoms.nix
+checkConfigOutput false config.value.bool ./types-anything/equal-atoms.nix
+checkConfigOutput '""' config.value.string ./types-anything/equal-atoms.nix
+checkConfigOutput / config.value.path ./types-anything/equal-atoms.nix
+checkConfigOutput null config.value.null ./types-anything/equal-atoms.nix
+checkConfigOutput 0.1 config.value.float ./types-anything/equal-atoms.nix
+# Functions can't be merged together
+checkConfigError "The option .* has conflicting definitions" config.value.multiple-lambdas ./types-anything/functions.nix
+checkConfigOutput '<LAMBDA>' config.value.single-lambda ./types-anything/functions.nix
+# Check that all mk* modifiers are applied
+checkConfigError 'attribute .* not found' config.value.mkiffalse ./types-anything/mk-mods.nix
+checkConfigOutput '{ }' config.value.mkiftrue ./types-anything/mk-mods.nix
+checkConfigOutput 1 config.value.mkdefault ./types-anything/mk-mods.nix
+checkConfigOutput '{ }' config.value.mkmerge ./types-anything/mk-mods.nix
+checkConfigOutput true config.value.mkbefore ./types-anything/mk-mods.nix
+checkConfigOutput 1 config.value.nested.foo ./types-anything/mk-mods.nix
+checkConfigOutput baz config.value.nested.bar.baz ./types-anything/mk-mods.nix
+
cat <<EOF
====== module tests ======
$pass Pass
diff --git a/lib/tests/modules/types-anything/attrs-coercible.nix b/lib/tests/modules/types-anything/attrs-coercible.nix
new file mode 100644
index 000000000000..085cbd638f17
--- /dev/null
+++ b/lib/tests/modules/types-anything/attrs-coercible.nix
@@ -0,0 +1,12 @@
+{ lib, ... }: {
+
+ options.value = lib.mkOption {
+ type = lib.types.anything;
+ };
+
+ config.value = {
+ outPath = "foo";
+ err = throw "err";
+ };
+
+}
diff --git a/lib/tests/modules/types-anything/equal-atoms.nix b/lib/tests/modules/types-anything/equal-atoms.nix
new file mode 100644
index 000000000000..972711201a09
--- /dev/null
+++ b/lib/tests/modules/types-anything/equal-atoms.nix
@@ -0,0 +1,26 @@
+{ lib, ... }: {
+
+ options.value = lib.mkOption {
+ type = lib.types.anything;
+ };
+
+ config = lib.mkMerge [
+ {
+ value.int = 0;
+ value.bool = false;
+ value.string = "";
+ value.path = /.;
+ value.null = null;
+ value.float = 0.1;
+ }
+ {
+ value.int = 0;
+ value.bool = false;
+ value.string = "";
+ value.path = /.;
+ value.null = null;
+ value.float = 0.1;
+ }
+ ];
+
+}
diff --git a/lib/tests/modules/types-anything/functions.nix b/lib/tests/modules/types-anything/functions.nix
new file mode 100644
index 000000000000..079518913918
--- /dev/null
+++ b/lib/tests/modules/types-anything/functions.nix
@@ -0,0 +1,17 @@
+{ lib, ... }: {
+
+ options.value = lib.mkOption {
+ type = lib.types.anything;
+ };
+
+ config = lib.mkMerge [
+ {
+ value.single-lambda = x: x;
+ value.multiple-lambdas = x: x;
+ }
+ {
+ value.multiple-lambdas = x: x;
+ }
+ ];
+
+}
diff --git a/lib/tests/modules/types-anything/lists.nix b/lib/tests/modules/types-anything/lists.nix
new file mode 100644
index 000000000000..bd846afd3d18
--- /dev/null
+++ b/lib/tests/modules/types-anything/lists.nix
@@ -0,0 +1,16 @@
+{ lib, ... }: {
+
+ options.value = lib.mkOption {
+ type = lib.types.anything;
+ };
+
+ config = lib.mkMerge [
+ {
+ value = [ null ];
+ }
+ {
+ value = [ null ];
+ }
+ ];
+
+}
diff --git a/lib/tests/modules/types-anything/mk-mods.nix b/lib/tests/modules/types-anything/mk-mods.nix
new file mode 100644
index 000000000000..f84ad01df017
--- /dev/null
+++ b/lib/tests/modules/types-anything/mk-mods.nix
@@ -0,0 +1,44 @@
+{ lib, ... }: {
+
+ options.value = lib.mkOption {
+ type = lib.types.anything;
+ };
+
+ config = lib.mkMerge [
+ {
+ value.mkiffalse = lib.mkIf false {};
+ }
+ {
+ value.mkiftrue = lib.mkIf true {};
+ }
+ {
+ value.mkdefault = lib.mkDefault 0;
+ }
+ {
+ value.mkdefault = 1;
+ }
+ {
+ value.mkmerge = lib.mkMerge [
+ {}
+ ];
+ }
+ {
+ value.mkbefore = lib.mkBefore true;
+ }
+ {
+ value.nested = lib.mkMerge [
+ {
+ foo = lib.mkDefault 0;
+ bar = lib.mkIf false 0;
+ }
+ (lib.mkIf true {
+ foo = lib.mkIf true (lib.mkForce 1);
+ bar = {
+ baz = lib.mkDefault "baz";
+ };
+ })
+ ];
+ }
+ ];
+
+}
diff --git a/lib/tests/modules/types-anything/nested-attrs.nix b/lib/tests/modules/types-anything/nested-attrs.nix
new file mode 100644
index 000000000000..e57d33ef8717
--- /dev/null
+++ b/lib/tests/modules/types-anything/nested-attrs.nix
@@ -0,0 +1,22 @@
+{ lib, ... }: {
+
+ options.value = lib.mkOption {
+ type = lib.types.anything;
+ };
+
+ config = lib.mkMerge [
+ {
+ value.foo = null;
+ }
+ {
+ value.l1.foo = null;
+ }
+ {
+ value.l1.l2.foo = null;
+ }
+ {
+ value.l1.l2.l3.foo = null;
+ }
+ ];
+
+}
diff --git a/lib/trivial.nix b/lib/trivial.nix
index 6eb1fb3a5b11..9501a2906cae 100644
--- a/lib/trivial.nix
+++ b/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/lib/types.nix b/lib/types.nix
index 17e7a939fe3d..aae45366b8fb 100644
--- a/lib/types.nix
+++ b/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;
};
@@ -101,6 +104,42 @@ rec {
# When adding new types don't forget to document them in
# nixos/doc/manual/development/option-types.xml!
types = rec {
+
+ anything = mkOptionType {
+ name = "anything";
+ description = "anything";
+ check = value: true;
+ merge = loc: defs:
+ let
+ getType = value:
+ if isAttrs value && isCoercibleToString value
+ then "stringCoercibleSet"
+ else builtins.typeOf value;
+
+ # Returns the common type of all definitions, throws an error if they
+ # don't have the same type
+ commonType = foldl' (type: def:
+ if getType def.value == type
+ then type
+ else throw "The option `${showOption loc}' has conflicting option types in ${showFiles (getFiles defs)}"
+ ) (getType (head defs).value) defs;
+
+ mergeFunction = {
+ # Recursively merge attribute sets
+ set = (attrsOf anything).merge;
+ # Safe and deterministic behavior for lists is to only accept one definition
+ # listOf only used to apply mkIf and co.
+ list =
+ if length defs > 1
+ then throw "The option `${showOption loc}' has conflicting definitions, in ${showFiles (getFiles defs)}."
+ else (listOf anything).merge;
+ # This is the type of packages, only accept a single definition
+ stringCoercibleSet = mergeOneOption;
+ # Otherwise fall back to only allowing all equal definitions
+ }.${commonType} or mergeEqualOption;
+ in mergeFunction loc defs;
+ };
+
unspecified = mkOptionType {
name = "unspecified";
};
@@ -222,8 +261,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 +293,6 @@ rec {
merge = mergeEqualOption;
};
- # TODO: drop this in the future:
- list = builtins.trace "`types.list` has been removed; please use `types.listOf` instead" types.listOf;
-
listOf = elemType: mkOptionType rec {
name = "listOf";
description = "list of ${elemType.description}s";
@@ -327,14 +365,12 @@ rec {
};
# TODO: drop this in the future:
- loaOf =
- let msg =
- ''
- `types.loaOf` has been removed and 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.
- '';
- in builtins.trace msg types.attrsOf;
+ 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 {
@@ -427,7 +463,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;
@@ -529,8 +570,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; };