diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/licenses.nix | 11 | ||||
-rw-r--r-- | lib/modules.nix | 6 | ||||
-rw-r--r-- | lib/options.nix | 4 | ||||
-rw-r--r-- | lib/systems/architectures.nix | 2 | ||||
-rw-r--r-- | lib/systems/doubles.nix | 53 | ||||
-rw-r--r-- | lib/systems/examples.nix | 4 | ||||
-rw-r--r-- | lib/tests/misc.nix | 26 | ||||
-rwxr-xr-x | lib/tests/modules.sh | 29 | ||||
-rw-r--r-- | lib/tests/modules/types-anything/attrs-coercible.nix | 12 | ||||
-rw-r--r-- | lib/tests/modules/types-anything/equal-atoms.nix | 26 | ||||
-rw-r--r-- | lib/tests/modules/types-anything/functions.nix | 17 | ||||
-rw-r--r-- | lib/tests/modules/types-anything/lists.nix | 16 | ||||
-rw-r--r-- | lib/tests/modules/types-anything/mk-mods.nix | 44 | ||||
-rw-r--r-- | lib/tests/modules/types-anything/nested-attrs.nix | 22 | ||||
-rw-r--r-- | lib/trivial.nix | 2 | ||||
-rw-r--r-- | lib/types.nix | 74 |
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; }; |