Allow options with type "package" to be store paths

For example, this allows writing

nix.package = /nix/store/786mlvhd17xvcp2r4jmmay6jj4wj6b7f-nix-1.10pre4206_896428c;

Also, document types.package in the manual.

Changed files
+30 -4
lib
nixos
doc
manual
+10
lib/attrsets.nix
···
isDerivation = x: isAttrs x && x ? type && x.type == "derivation";
+
/* Convert a store path to a fake derivation. */
+
toDerivation = path:
+
let path' = builtins.storePath path; in
+
{ type = "derivation";
+
name = builtins.unsafeDiscardStringContext (builtins.substring 33 (-1) (baseNameOf path'));
+
outPath = path';
+
outputs = [ "out" ];
+
};
+
+
/* If the Boolean `cond' is true, return the attribute set `as',
otherwise an empty attribute set. */
optionalAttrs = cond: as: if cond then as else {};
+5
lib/strings.nix
···
# Format a number adding leading zeroes up to fixed width.
fixedWidthNumber = width: n: fixedWidthString width "0" (toString n);
+
+
+
# Check whether a value is a store path.
+
isStorePath = x: builtins.substring 0 1 (toString x) == "/" && dirOf (builtins.toPath x) == builtins.storeDir;
+
}
+5 -3
lib/types.nix
···
# derivation is a reserved keyword.
package = mkOptionType {
name = "derivation";
-
check = isDerivation;
-
merge = mergeOneOption;
+
check = x: isDerivation x || isStorePath x;
+
merge = loc: defs:
+
let res = mergeOneOption loc defs;
+
in if isDerivation res then res else toDerivation res;
};
path = mkOptionType {
name = "path";
# Hacky: there is no ‘isPath’ primop.
-
check = x: builtins.unsafeDiscardStringContext (builtins.substring 0 1 (toString x)) == "/";
+
check = x: builtins.substring 0 1 (toString x) == "/";
merge = mergeOneOption;
};
+10 -1
nixos/doc/manual/development/option-declarations.xml
···
</varlistentry>
<varlistentry>
+
<term><varname>types.package</varname></term>
+
<listitem>
+
<para>A derivation (such as <literal>pkgs.hello</literal>) or a
+
store path (such as
+
<filename>/nix/store/1ifi1cfbfs5iajmvwgrbmrnrw3a147h9-hello-2.10</filename>).</para>
+
</listitem>
+
</varlistentry>
+
+
<varlistentry>
<term><varname>types.listOf</varname> <replaceable>t</replaceable></term>
<listitem>
<para>A list of elements of type <replaceable>t</replaceable>
···
<varname>mkOptionType</varname>. See
<filename>lib/types.nix</filename> in Nixpkgs for details.</para>
-
</section>
+
</section>