aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libcmd/installables.cc77
-rw-r--r--src/libstore/derived-path.cc17
-rw-r--r--src/libstore/derived-path.hh2
-rw-r--r--src/nix/nix.md21
4 files changed, 80 insertions, 37 deletions
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc
index d6e62e775..176d655be 100644
--- a/src/libcmd/installables.cc
+++ b/src/libcmd/installables.cc
@@ -399,44 +399,56 @@ static StorePath getDeriver(
struct InstallableStorePath : Installable
{
ref<Store> store;
- StorePath storePath;
+ DerivedPath req;
InstallableStorePath(ref<Store> store, StorePath && storePath)
- : store(store), storePath(std::move(storePath)) { }
+ : store(store),
+ req(storePath.isDerivation()
+ ? (DerivedPath) DerivedPath::Built {
+ .drvPath = std::move(storePath),
+ .outputs = {},
+ }
+ : (DerivedPath) DerivedPath::Opaque {
+ .path = std::move(storePath),
+ })
+ { }
+
+ InstallableStorePath(ref<Store> store, DerivedPath && req)
+ : store(store), req(std::move(req))
+ { }
- std::string what() const override { return store->printStorePath(storePath); }
+ std::string what() const override
+ {
+ return req.to_string(*store);
+ }
DerivedPaths toDerivedPaths() override
{
- if (storePath.isDerivation()) {
- auto drv = store->readDerivation(storePath);
- return {
- DerivedPath::Built {
- .drvPath = storePath,
- .outputs = drv.outputNames(),
- }
- };
- } else {
- return {
- DerivedPath::Opaque {
- .path = storePath,
- }
- };
- }
+ return { req };
}
StorePathSet toDrvPaths(ref<Store> store) override
{
- if (storePath.isDerivation()) {
- return {storePath};
- } else {
- return {getDeriver(store, *this, storePath)};
- }
+ return std::visit(overloaded {
+ [&](const DerivedPath::Built & bfd) -> StorePathSet {
+ return { bfd.drvPath };
+ },
+ [&](const DerivedPath::Opaque & bo) -> StorePathSet {
+ return { getDeriver(store, *this, bo.path) };
+ },
+ }, req.raw());
}
std::optional<StorePath> getStorePath() override
{
- return storePath;
+ return std::visit(overloaded {
+ [&](const DerivedPath::Built & bfd) {
+ return bfd.drvPath;
+ },
+ [&](const DerivedPath::Opaque & bo) {
+ return bo.path;
+ },
+ }, req.raw());
}
};
@@ -802,7 +814,22 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
for (auto & s : ss) {
std::exception_ptr ex;
- if (s.find('/') != std::string::npos) {
+ auto found = s.rfind('^');
+ if (found != std::string::npos) {
+ try {
+ result.push_back(std::make_shared<InstallableStorePath>(
+ store,
+ DerivedPath::Built::parse(*store, 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<InstallableStorePath>(store, store->followLinksToStorePath(s)));
continue;
diff --git a/src/libstore/derived-path.cc b/src/libstore/derived-path.cc
index 88b59f615..7fe797aa1 100644
--- a/src/libstore/derived-path.cc
+++ b/src/libstore/derived-path.cc
@@ -78,24 +78,25 @@ DerivedPath::Opaque DerivedPath::Opaque::parse(const Store & store, std::string_
return {store.parseStorePath(s)};
}
-DerivedPath::Built DerivedPath::Built::parse(const Store & store, std::string_view s)
+DerivedPath::Built DerivedPath::Built::parse(const Store & store, std::string_view drvS, std::string_view outputsS)
{
- size_t n = s.find("!");
- assert(n != s.npos);
- auto drvPath = store.parseStorePath(s.substr(0, n));
- auto outputsS = s.substr(n + 1);
+ auto drvPath = store.parseStorePath(drvS);
std::set<std::string> outputs;
- if (outputsS != "*")
+ if (outputsS != "*") {
outputs = tokenizeString<std::set<std::string>>(outputsS, ",");
+ if (outputs.empty())
+ throw Error(
+ "Explicit list of wanted outputs '%s' must not be empty. Consider using '*' as a wildcard meaning all outputs if no output in particular is wanted.", outputsS);
+ }
return {drvPath, outputs};
}
DerivedPath DerivedPath::parse(const Store & store, std::string_view s)
{
- size_t n = s.find("!");
+ size_t n = s.rfind("!");
return n == s.npos
? (DerivedPath) DerivedPath::Opaque::parse(store, s)
- : (DerivedPath) DerivedPath::Built::parse(store, s);
+ : (DerivedPath) DerivedPath::Built::parse(store, s.substr(0, n), s.substr(n + 1));
}
RealisedPath::Set BuiltPath::toRealisedPaths(Store & store) const
diff --git a/src/libstore/derived-path.hh b/src/libstore/derived-path.hh
index 878696136..706e5dcb4 100644
--- a/src/libstore/derived-path.hh
+++ b/src/libstore/derived-path.hh
@@ -47,7 +47,7 @@ struct DerivedPathBuilt {
std::set<std::string> outputs;
std::string to_string(const Store & store) const;
- static DerivedPathBuilt parse(const Store & store, std::string_view);
+ static DerivedPathBuilt parse(const Store & store, std::string_view, std::string_view);
nlohmann::json toJSON(ref<Store> store) const;
bool operator < (const DerivedPathBuilt & b) const
diff --git a/src/nix/nix.md b/src/nix/nix.md
index d48682a94..811936024 100644
--- a/src/nix/nix.md
+++ b/src/nix/nix.md
@@ -164,6 +164,13 @@ operate are determined as follows:
```
+ and likewise, using a store path to a "drv" file to specify the derivation:
+
+ ```console
+ # nix build '/nix/store/gzaflydcr6sb3567hap9q6srzx8ggdgg-glibc-2.33-78.drv^dev,static'
+ …
+ ```
+
* You can also specify that *all* outputs should be used using the
syntax *installable*`^*`. For example, the following shows the size
of all outputs of the `glibc` package in the binary cache:
@@ -177,9 +184,17 @@ operate are determined as follows:
/nix/store/q6580lr01jpcsqs4r5arlh4ki2c1m9rv-glibc-2.33-123-dev 44200560
```
-* If you didn't specify the desired outputs, but the derivation has an
- attribute `meta.outputsToInstall`, Nix will use those outputs. For
- example, since the package `nixpkgs#libxml2` has this attribute:
+ and likewise, again using a store path to a "drv" file to specify the derivation:
+
+ ```console
+ # nix path-info -S --eval-store auto --store https://cache.nixos.org '/nix/store/gzaflydcr6sb3567hap9q6srzx8ggdgg-glibc-2.33-78.drv^*'
+ …
+ ```
+
+* If you didn't specify the desired outputs, but the derivation comes
+ from an expression which has an attribute `meta.outputsToInstall`, Nix
+ will use those outputs. For example, since the package
+ `nixpkgs#libxml2` has this attribute:
```console
# nix eval 'nixpkgs#libxml2.meta.outputsToInstall'