aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2021-02-12 21:51:36 +0000
committerJohn Ericson <John.Ericson@Obsidian.Systems>2021-04-06 10:25:09 -0400
commit8499f32fb2e7fdf09e97d0beb1fe78bef5900d93 (patch)
tree3bddff8d3894439335707652c4e3653a0b751615
parent4bf3eb27e6e2c0cdac862d188b23342793180999 (diff)
New "indexed" installable syntax: `<drvPath>!<outputName>`
Being conservative and only doing a single output name for now.
-rw-r--r--src/libcmd/installables.cc42
-rw-r--r--src/nix/nix.md10
-rw-r--r--tests/build-explicit-output.sh17
-rw-r--r--tests/build.sh5
-rw-r--r--tests/local.mk1
5 files changed, 72 insertions, 3 deletions
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc
index 5d3026c1a..cf7681d0d 100644
--- a/src/libcmd/installables.cc
+++ b/src/libcmd/installables.cc
@@ -349,6 +349,31 @@ struct InstallableStorePath : Installable
}
};
+struct InstallableIndexedStorePath : Installable
+{
+ ref<Store> store;
+ DerivedPath::Built req;
+
+ InstallableIndexedStorePath(ref<Store> store, DerivedPath::Built && req)
+ : store(store), req(std::move(req))
+ { }
+
+ std::string what() override
+ {
+ return req.to_string(*store);
+ }
+
+ DerivedPathsWithHints toDerivedPathsWithHints() override
+ {
+ std::map<std::string, std::optional<StorePath>> outputs;
+ for (auto & output : req.outputs)
+ outputs.insert_or_assign(output, std::nullopt);
+ return {
+ DerivedPathWithHints { DerivedPathWithHints::Built { req.drvPath, std::move(outputs) } }
+ };
+ }
+};
+
DerivedPathsWithHints InstallableValue::toDerivedPathsWithHints()
{
DerivedPathsWithHints res;
@@ -638,7 +663,22 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
ex = std::current_exception();
}
- if (s.find('/') != std::string::npos) {
+ auto found = s.rfind('!');
+ if (found != std::string::npos) {
+ try {
+ result.push_back(std::make_shared<InstallableIndexedStorePath>(
+ store,
+ DerivedPath::Built::parse(*store, s)));
+ continue;
+ } catch (BadStorePath &) {
+ } catch (...) {
+ if (!ex)
+ ex = std::current_exception();
+ }
+ }
+
+ found = s.find('/');
+ if (found != std::string::npos) {
try {
result.push_back(std::make_shared<InstallableStorePath>(store, store->followLinksToStorePath(s)));
continue;
diff --git a/src/nix/nix.md b/src/nix/nix.md
index d10de7c01..22cc9d476 100644
--- a/src/nix/nix.md
+++ b/src/nix/nix.md
@@ -94,6 +94,16 @@ the Nix store. Here are the recognised types of installables:
If you want to operate on the store derivation itself, pass the
`--derivation` flag.
+* **Indexed store derivations**: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv!out`
+
+ Store derivations can be indexed with a specific output name. This
+ allows finer control versus just specifying a derivation (without
+ `--derivation`) and getting all the outputs.
+
+ This is especially useful for (currently unstable) floating content
+ addressed derivations, which do not have precomputed output paths that
+ can be used instead.
+
* **Nix attributes**: `--file /path/to/nixpkgs hello`
When the `-f` / `--file` *path* option is given, installables are
diff --git a/tests/build-explicit-output.sh b/tests/build-explicit-output.sh
new file mode 100644
index 000000000..17930c2c0
--- /dev/null
+++ b/tests/build-explicit-output.sh
@@ -0,0 +1,17 @@
+source common.sh
+
+drv=$(nix eval -f multiple-outputs.nix --raw a.drvPath)
+if nix build "$drv!not-an-output" --json; then
+ fail "'not-an-output' should fail to build"
+fi
+
+nix build "$drv!first" --json | jq --exit-status '
+ (.[0] |
+ (.drvPath | match(".*multiple-outputs-a.drv")) and
+ (.outputs |
+ .first and
+ (has("second") | not)))
+'
+# TODO use
+# (.first | match(".*multiple-outputs-a-first")) and
+# once we make it put the result paths in the buildables.
diff --git a/tests/build.sh b/tests/build.sh
index aa54b88eb..5a2819336 100644
--- a/tests/build.sh
+++ b/tests/build.sh
@@ -4,8 +4,9 @@ expectedJSONRegex='\[\{"drvPath":".*multiple-outputs-a.drv","outputs":\{"first":
nix build -f multiple-outputs.nix --json a.all b.all | jq --exit-status '
(.[0] |
(.drvPath | match(".*multiple-outputs-a.drv")) and
- (.outputs.first | match(".*multiple-outputs-a-first")) and
- (.outputs.second | match(".*multiple-outputs-a-second")))
+ (.outputs |
+ (.first | match(".*multiple-outputs-a-first")) and
+ (.second | match(".*multiple-outputs-a-second"))))
and (.[1] |
(.drvPath | match(".*multiple-outputs-b.drv")) and
(.outputs.out | match(".*multiple-outputs-b")))
diff --git a/tests/local.mk b/tests/local.mk
index e7e85f97e..1d3e89499 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -41,6 +41,7 @@ nix_tests = \
describe-stores.sh \
flakes.sh \
build.sh \
+ build-explicit-output.sh \
compute-levels.sh \
ca/build.sh \
ca/substitute.sh \