From 3876238546c82e4cda4f257b9b1e3e6d53d07658 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 18 Jan 2022 17:28:18 +0100 Subject: [PATCH] Add Installable::toDrvPaths() This is needed to get the path of a derivation that might not exist (e.g. for 'nix store copy-log'). InstallableStorePath::toDerivedPaths() cannot be used for this because it calls readDerivation(), so it fails if the store doesn't have the derivation. --- src/libcmd/installables.cc | 39 +++++++++++++++++++++++++++++++------- src/libcmd/installables.hh | 11 +++++++++-- src/nix/app.cc | 2 +- src/nix/store-copy-log.cc | 14 ++++++++++---- 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 6c20bb7b1..0c2db0399 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -345,6 +345,18 @@ Installable::getCursor(EvalState & state) return cursors[0]; } +static StorePath getDeriver( + ref store, + const Installable & i, + const StorePath & drvPath) +{ + auto derivers = store->queryValidDerivers(drvPath); + if (derivers.empty()) + throw Error("'%s' does not have a known deriver", i.what()); + // FIXME: use all derivers? + return *derivers.begin(); +} + struct InstallableStorePath : Installable { ref store; @@ -353,7 +365,7 @@ struct InstallableStorePath : Installable InstallableStorePath(ref store, StorePath && storePath) : store(store), storePath(std::move(storePath)) { } - std::string what() override { return store->printStorePath(storePath); } + std::string what() const override { return store->printStorePath(storePath); } DerivedPaths toDerivedPaths() override { @@ -374,6 +386,15 @@ struct InstallableStorePath : Installable } } + StorePathSet toDrvPaths(ref store) override + { + if (storePath.isDerivation()) { + return {storePath}; + } else { + return {getDeriver(store, *this, storePath)}; + } + } + std::optional getStorePath() override { return storePath; @@ -402,6 +423,14 @@ DerivedPaths InstallableValue::toDerivedPaths() return res; } +StorePathSet InstallableValue::toDrvPaths(ref store) +{ + StorePathSet res; + for (auto & drv : toDerivations()) + res.insert(drv.drvPath); + return res; +} + struct InstallableAttrPath : InstallableValue { SourceExprCommand & cmd; @@ -412,7 +441,7 @@ struct InstallableAttrPath : InstallableValue : InstallableValue(state), cmd(cmd), v(allocRootValue(v)), attrPath(attrPath) { } - std::string what() override { return attrPath; } + std::string what() const override { return attrPath; } std::pair toValue(EvalState & state) override { @@ -836,11 +865,7 @@ StorePathSet toDerivations( [&](const DerivedPath::Opaque & bo) { if (!useDeriver) throw Error("argument '%s' did not evaluate to a derivation", i->what()); - auto derivers = store->queryValidDerivers(bo.path); - if (derivers.empty()) - throw Error("'%s' does not have a known deriver", i->what()); - // FIXME: use all derivers? - drvPaths.insert(*derivers.begin()); + drvPaths.insert(getDeriver(store, *i, bo.path)); }, [&](const DerivedPath::Built & bfd) { drvPaths.insert(bfd.drvPath); diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh index 79931ad3e..ced6b3f10 100644 --- a/src/libcmd/installables.hh +++ b/src/libcmd/installables.hh @@ -33,10 +33,15 @@ struct Installable { virtual ~Installable() { } - virtual std::string what() = 0; + virtual std::string what() const = 0; virtual DerivedPaths toDerivedPaths() = 0; + virtual StorePathSet toDrvPaths(ref store) + { + throw Error("'%s' cannot be converted to a derivation path", what()); + } + DerivedPath toDerivedPath(); UnresolvedApp toApp(EvalState & state); @@ -81,6 +86,8 @@ struct InstallableValue : Installable virtual std::vector toDerivations() = 0; DerivedPaths toDerivedPaths() override; + + StorePathSet toDrvPaths(ref store) override; }; struct InstallableFlake : InstallableValue @@ -99,7 +106,7 @@ struct InstallableFlake : InstallableValue Strings && prefixes, const flake::LockFlags & lockFlags); - std::string what() override { return flakeRef.to_string() + "#" + *attrPaths.begin(); } + std::string what() const override { return flakeRef.to_string() + "#" + *attrPaths.begin(); } std::vector getActualAttrPaths(); diff --git a/src/nix/app.cc b/src/nix/app.cc index 2fcf4752c..e104cc9c1 100644 --- a/src/nix/app.cc +++ b/src/nix/app.cc @@ -19,7 +19,7 @@ struct InstallableDerivedPath : Installable } - std::string what() override { return derivedPath.to_string(*store); } + std::string what() const override { return derivedPath.to_string(*store); } DerivedPaths toDerivedPaths() override { diff --git a/src/nix/store-copy-log.cc b/src/nix/store-copy-log.cc index fa6436cd0..079cd6b3e 100644 --- a/src/nix/store-copy-log.cc +++ b/src/nix/store-copy-log.cc @@ -28,11 +28,17 @@ struct CmdCopyLog : virtual CopyCommand, virtual InstallablesCommand { auto dstStore = getDstStore(); - for (auto & path : toDerivations(srcStore, installables, true)) { - if (auto log = srcStore->getBuildLog(path)) - dstStore->addBuildLog(path, *log); + StorePathSet drvPaths; + + for (auto & i : installables) + for (auto & drvPath : i->toDrvPaths(getEvalStore())) + drvPaths.insert(drvPath); + + for (auto & drvPath : drvPaths) { + if (auto log = srcStore->getBuildLog(drvPath)) + dstStore->addBuildLog(drvPath, *log); else - throw Error("build log for '%s' is not available", srcStore->printStorePath(path)); + throw Error("build log for '%s' is not available", srcStore->printStorePath(drvPath)); } } };