Allow a \n character at the end of the string and remove it during the
merge function.
An option of this type will resolve to the value "foo" whether it is set
to "foo" or "foo\n".
This is useful when using 'builtins.readFile' or ''-strings, which might
add an unintended newline (for example, bash trim the final newline from
a subshell).
Add a new type, inheriting 'types.str' but checking whether the value
doesn't contain any newline characters.
The motivation comes from a problem with the
'users.users.${u}.openssh.authorizedKeys' option.
It is easy to unintentionally insert a newline character at the end of a
string, or even in the middle, for example:
restricted_ssh_keys = command: keys:
let
prefix = ''
command="${command}",no-pty,no-agent-forwarding,no-port-forwarding,no-X11-forwarding
'';
in map (key: "${prefix} ${key}") keys;
The 'prefix' string ends with a newline, which ends up in the middle of
a key entry after a few manipulations.
This is problematic because the key file is built by concatenating all
the keys with 'concatStringsSep "\n"', with result in two entries for
the faulty key:
''
command="...",options...
MY_KEY
''
This is hard to debug and might be dangerous. This is now caught at
build time.
This will be used to issue deprecation warnings recursively in the next
commit
In addition, this allows easily getting nested types of other options, which
is useful when you want to create an option that aliases a part of
another one.
Since shellPackage actually requires the value to be an attribute set
(i. e. an derivation in this case), we cannot re-use the package.check
type checker since it also allows strings or things that are coercible
to strings as long as they look like store paths.
Now type checks the resulting function values and allows mkMerge and co.
Also indicates that the type check is done in the function body
Co-Authored-By: Robert Hensing <robert@roberthensing.nl>
This reverts commit 4ff1ab5a56.
We need this to type options like:
services.xserver.windowManager.xmonad.extraPackages that specify functions that
take an attribute set containing packages / plugins and return a list containing
a selection of the values in this set.
The reason we need a dedicated type for this is to have the correct merge
behaviour. Without the functionTo type merging multiple function option
definitions results in an evaluation error. The functionTo type merges
definitions by returning a new function that applies the functions of all the
definitions to the given input and merges the result.
(cherry picked from commit 7ed41ff5e7e633dd64866398ee497ac02736a3a5)
I think there was a silent (i.e. semantic) merge conflict between PR #101139 and
PR #100456. This commit should fix the error, which manifests as follows:
error: undefined variable 'boolToString' at /home/kkini/src/nixpkgs/lib/types.nix:552:42
Nix can perform static scope checking, but whenever code is inside
a `with` expression, the analysis breaks down, because it can't
know statically what's in the attribute set whose attributes were
brought into scope. In those cases, Nix has to assume that
everything works out.
Except it doesnt. Removing `with` from lib/ revealed an undefined
variable in an error message.
If that doesn't convince you that we're better off without `with`,
I can tell you that this PR results in a 3% evaluation performance
improvement because Nix can look up local variables by index.
This adds up with applications like the module system.
Furthermore, removing `with` makes the binding site of each
variable obvious, which helps with comprehension.
This new type has unsurprising merge behavior: Only attribute sets are
merged together (recursively), and only if they don't conflict.
This is in contrast to the existing types:
- types.attrs is problematic because later definitions completely
override attributes of earlier definitions, and it doesn't support
mkIf and co.
- types.unspecified is very similar to types.attrs, but it has smart
merging behavior that often doesn't make sense, and it doesn't support
all types
Previously the only way to deprecate a type was using
theType = lib.warn "deprecated" (mkOptionType ...)
This caused the warning to be emitted when the type was evaluated, but
the error didn't include which option actually used that type.
With this commit, types can specify a deprecationMessage, which when
non-null, is printed along with the option that uses the type
Submodules that have a freeform type set behave as if that was the type
of the option itself (for values that don't have an option). Since the
submodules options are shown as separate entries in the manual, it makes
sense to show the freeform type as the submodule type.
Not all modules use name attribute as the name of the submodule, for example,
environment.etc uses target. We will need to maintain a list of exceptions.
The standard attrsOf is strict in its *values*, meaning it's impossible to
access only one attribute value without evaluating all others as well.
lazyAttrsOf is a version that doesn't have that problem, at the expense
of conditional definitions not properly working anymore.
Previously when this function was called without a value coercible to a
string it would throw an error instead of returning false. Now it does.
As a result this now allows the use of a type like `either path attrs`
without it erroring out when a definition is an attribute set.
The warning about there not being a isPath primop was removed because
this is not the case anymore, there is builtins.isPath. But also there
always was `builtins.typeOf x == "path"` that could've been used
instead. However the path type now stands for more than just path types,
but absolute paths in general.
This reverts commit eec83d41e3.
This broke hydra evaluation because with this commit submodule values
are allowed to be paths, however the certmgr module uses `either
(submodule ...) path` in its type, meaning it already used paths for
something else which would now be interpreted as a submodule.
The explicit remove helped to uncover some hidden uses of `optionSet`
in NixOps. However it makes life harder for end-users of NixOps - it will
be impossible to deploy 19.03 systems with old NixOps, but there is no
new release of NixOps with `optionSet` fixes.
Also, "deprecation" process isn't well defined. Even that `optionSet` was
declared "deprecated" for many years, it was never announced. Hence, I
leave "deprecation" announce. Then, 3 releases after announce,
we can announce removal of this feature.
This type has to be removed, not `throw`-ed in runtime, because it makes
some perfectly fine code to fail. For example:
```
$ nix-instantiate --eval -E '(import <nixpkgs/lib>).types' --strict
trace: `types.list` is deprecated; use `types.listOf` instead
error: types.optionSet is deprecated; use types.submodule instead
(use '--show-trace' to show detailed location information)
```
The previous description "string" is misleading in the full options
manual pages; they are actually concatenated strings, with a specific
character.
The empty string version ("types.string") has been special-cased to
provide a better message.
Assigning a list of 10 or more elements to an option having the type
`loaOf a` produces a configuration value that is not honoring the
order of the original list. This commit fixes this and a related issue
arising when 10 or more lists are merged into this type of option.
Without this change
(coercedTo str toInt int).check "foo"
would evaluate to true, even though
(coercedTo str toInt int).merge {} [{ value = "foo"; }]
will throw an error because "foo" can't be coerced to an int.
This file doesn't evaluate in 32-bit versions of Nix because the integer
type is a signed 32-bit integer there, so 4294967296 causes an 'invalid
integer' error. I see no other way around than commenting this out :(
(s32 could be made to work by tweaking the expressions a bit, but didn't
do that for now since it'd be asymmetric to have s32 but no u32).
This does break the API of being able to import any lib file and get
its libs, however I'm not sure people did this.
I made this while exploring being able to swap out docFn with a stub
in #2305, to avoid functor performance problems. I don't know if that
is going to move forward (or if it is a problem or not,) but after
doing all this work figured I'd put it up anyway :)
Two notable advantages to this approach:
1. when a lib inherits another lib's functions, it doesn't
automatically get put in to the scope of lib
2. when a lib implements a new obscure functions, it doesn't
automatically get put in to the scope of lib
Using the test script (later in this commit) I got the following diff
on the API:
+ diff master fixed-lib
11764a11765,11766
> .types.defaultFunctor
> .types.defaultTypeMerge
11774a11777,11778
> .types.isOptionType
> .types.isType
11781a11786
> .types.mkOptionType
11788a11794
> .types.setType
11795a11802
> .types.types
This means that this commit _adds_ to the API, however I can't find a
way to fix these last remaining discrepancies. At least none are
_removed_.
Test script (run with nix-repl in the PATH):
#!/bin/sh
set -eux
repl() {
suff=${1:-}
echo "(import ./lib)$suff" \
| nix-repl 2>&1
}
attrs_to_check() {
repl "${1:-}" \
| tr ';' $'\n' \
| grep "\.\.\." \
| cut -d' ' -f2 \
| sed -e "s/^/${1:-}./" \
| sort
}
summ() {
repl "${1:-}" \
| tr ' ' $'\n' \
| sort \
| uniq
}
deep_summ() {
suff="${1:-}"
depth="${2:-4}"
depth=$((depth - 1))
summ "$suff"
for attr in $(attrs_to_check "$suff" | grep -v "types.types"); do
if [ $depth -eq 0 ]; then
summ "$attr" | sed -e "s/^/$attr./"
else
deep_summ "$attr" "$depth" | sed -e "s/^/$attr./"
fi
done
}
(
cd nixpkgs
#git add .
#git commit -m "Auto-commit, sorry" || true
git checkout fixed-lib
deep_summ > ../fixed-lib
git checkout master
deep_summ > ../master
)
if diff master fixed-lib; then
echo "SHALLOW MATCH!"
fi
(
cd nixpkgs
git checkout fixed-lib
repl .types
)
* lib: introduce imap0, imap1
For historical reasons, imap starts counting at 1 and it's not
consistent with the rest of the lib.
So for now we split imap into imap0 that starts counting at zero and
imap1 that starts counting at 1. And imap is marked as deprecated.
See c71e2d4235 (commitcomment-21873221)
* replace uses of lib.imap
* lib: move imap to deprecated.nix
The old forms presumably predates, or were made in ignorance of,
`let inherit`. This way is better style as the scoping as more lexical,
something which Nix can (or might already!) take advantage of.
Nix style seems to have settled on not using spaces between bound
variable names and the lambda : so I also tried to make those somewhat
more consistent throughout.