From 093a8eeaa06249109dc98c4ffe6444a0186e5ede Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 12 Feb 2021 21:51:36 +0000 Subject: [PATCH] New "indexed" installable syntax: `!` Being conservative and only doing a single output name for now. --- src/libcmd/installables.cc | 45 +++++++++++++++++++++++++++++++++- src/nix/nix.md | 10 ++++++++ tests/build-explicit-output.sh | 17 +++++++++++++ tests/build.sh | 5 ++-- tests/local.mk | 3 ++- 5 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 tests/build-explicit-output.sh diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 4739dc974bc3..3dfdfe451aeb 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -367,6 +367,33 @@ struct InstallableStorePath : Installable } }; +struct InstallableIndexedStorePath : Installable +{ + ref store; + StorePath storePath; + std::string outputName; + + InstallableIndexedStorePath(ref store, StorePath && storePath, std::string && outputName) + : store(store), storePath(std::move(storePath)), outputName(std::move(outputName)) { } + + std::string what() override + { + return store->printStorePath(storePath) + "!" + outputName; + } + + Buildables toBuildables() override + { + return { + BuildableFromDrv { + .drvPath = storePath, + .outputs = { + { outputName, {} }, + }, + } + }; + } +}; + Buildables InstallableValue::toBuildables() { Buildables res; @@ -656,7 +683,23 @@ std::vector> SourceExprCommand::parseInstallables( ex = std::current_exception(); } - if (s.find('/') != std::string::npos) { + auto found = s.find('!'); + if (found != std::string::npos) { + try { + result.push_back(std::make_shared( + store, + store->followLinksToStorePath(s.substr(0, found)), + s.substr(found + 1))); + 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(store, store->followLinksToStorePath(s))); continue; diff --git a/src/nix/nix.md b/src/nix/nix.md index d10de7c01b11..22cc9d4767df 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 000000000000..6c76e3e95ae3 --- /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 aa54b88eb8ab..5ffc39ac5f43 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 aa8b4f9bf913..636ccd680584 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -38,7 +38,8 @@ nix_tests = \ describe-stores.sh \ flakes.sh \ content-addressed.sh \ - build.sh + build.sh \ + build-explicit-output.sh # parallel.sh # build-remote-content-addressed-fixed.sh \