lib.types.package: only call toDerivation when necessary

The current logic assumes that everything that isn't a derivation is a
store path, but it can also be something that's *coercible* to a store
path, like a flake input.

Unnecessary uses of `lib.toDerivation` result in errors in pure evaluation
mode when `builtins.storePath` is disabled.

Also document what a `package` is.
This commit is contained in:
Naïm Favier 2022-03-09 13:14:22 +01:00
parent a782fa14c8
commit 9c2266c031
No known key found for this signature in database
GPG Key ID: 49B07322580B7EE2
3 changed files with 15 additions and 4 deletions

View File

@ -368,13 +368,21 @@ rec {
emptyValue = { value = {}; };
};
# derivation is a reserved keyword.
# A package is a top-level store path (/nix/store/hash-name). This includes:
# - derivations
# - more generally, attribute sets with an `outPath` or `__toString` attribute
# pointing to a store path, e.g. flake inputs
# - strings with context, e.g. "${pkgs.foo}" or (toString pkgs.foo)
# - hardcoded store path literals (/nix/store/hash-foo) or strings without context
# ("/nix/store/hash-foo"). These get a context added to them using builtins.storePath.
package = mkOptionType {
name = "package";
check = x: isDerivation x || isStorePath x;
merge = loc: defs:
let res = mergeOneOption loc defs;
in if isDerivation res then res else toDerivation res;
in if builtins.isPath res || (builtins.isString res && ! builtins.hasContext res)
then toDerivation res
else res;
};
shellPackage = package // {

View File

@ -22,7 +22,8 @@ merging is handled.
`types.package`
: A derivation or a store path.
: A top-level store path. This can be an attribute set pointing
to a store path, like a derivation or a flake input.
`types.anything`

View File

@ -43,7 +43,9 @@
</term>
<listitem>
<para>
A derivation or a store path.
A top-level store path. This can be an attribute set
pointing to a store path, like a derivation or a flake
input.
</para>
</listitem>
</varlistentry>