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.
This commit is contained in:
Eelco Dolstra 2022-01-18 17:28:18 +01:00
parent 5b243a2b4b
commit 3876238546
4 changed files with 52 additions and 14 deletions

View file

@ -345,6 +345,18 @@ Installable::getCursor(EvalState & state)
return cursors[0]; return cursors[0];
} }
static StorePath getDeriver(
ref<Store> 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 struct InstallableStorePath : Installable
{ {
ref<Store> store; ref<Store> store;
@ -353,7 +365,7 @@ struct InstallableStorePath : Installable
InstallableStorePath(ref<Store> store, StorePath && storePath) InstallableStorePath(ref<Store> store, StorePath && storePath)
: store(store), storePath(std::move(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 DerivedPaths toDerivedPaths() override
{ {
@ -374,6 +386,15 @@ struct InstallableStorePath : Installable
} }
} }
StorePathSet toDrvPaths(ref<Store> store) override
{
if (storePath.isDerivation()) {
return {storePath};
} else {
return {getDeriver(store, *this, storePath)};
}
}
std::optional<StorePath> getStorePath() override std::optional<StorePath> getStorePath() override
{ {
return storePath; return storePath;
@ -402,6 +423,14 @@ DerivedPaths InstallableValue::toDerivedPaths()
return res; return res;
} }
StorePathSet InstallableValue::toDrvPaths(ref<Store> store)
{
StorePathSet res;
for (auto & drv : toDerivations())
res.insert(drv.drvPath);
return res;
}
struct InstallableAttrPath : InstallableValue struct InstallableAttrPath : InstallableValue
{ {
SourceExprCommand & cmd; SourceExprCommand & cmd;
@ -412,7 +441,7 @@ struct InstallableAttrPath : InstallableValue
: InstallableValue(state), cmd(cmd), v(allocRootValue(v)), attrPath(attrPath) : InstallableValue(state), cmd(cmd), v(allocRootValue(v)), attrPath(attrPath)
{ } { }
std::string what() override { return attrPath; } std::string what() const override { return attrPath; }
std::pair<Value *, Pos> toValue(EvalState & state) override std::pair<Value *, Pos> toValue(EvalState & state) override
{ {
@ -836,11 +865,7 @@ StorePathSet toDerivations(
[&](const DerivedPath::Opaque & bo) { [&](const DerivedPath::Opaque & bo) {
if (!useDeriver) if (!useDeriver)
throw Error("argument '%s' did not evaluate to a derivation", i->what()); throw Error("argument '%s' did not evaluate to a derivation", i->what());
auto derivers = store->queryValidDerivers(bo.path); drvPaths.insert(getDeriver(store, *i, bo.path));
if (derivers.empty())
throw Error("'%s' does not have a known deriver", i->what());
// FIXME: use all derivers?
drvPaths.insert(*derivers.begin());
}, },
[&](const DerivedPath::Built & bfd) { [&](const DerivedPath::Built & bfd) {
drvPaths.insert(bfd.drvPath); drvPaths.insert(bfd.drvPath);

View file

@ -33,10 +33,15 @@ struct Installable
{ {
virtual ~Installable() { } virtual ~Installable() { }
virtual std::string what() = 0; virtual std::string what() const = 0;
virtual DerivedPaths toDerivedPaths() = 0; virtual DerivedPaths toDerivedPaths() = 0;
virtual StorePathSet toDrvPaths(ref<Store> store)
{
throw Error("'%s' cannot be converted to a derivation path", what());
}
DerivedPath toDerivedPath(); DerivedPath toDerivedPath();
UnresolvedApp toApp(EvalState & state); UnresolvedApp toApp(EvalState & state);
@ -81,6 +86,8 @@ struct InstallableValue : Installable
virtual std::vector<DerivationInfo> toDerivations() = 0; virtual std::vector<DerivationInfo> toDerivations() = 0;
DerivedPaths toDerivedPaths() override; DerivedPaths toDerivedPaths() override;
StorePathSet toDrvPaths(ref<Store> store) override;
}; };
struct InstallableFlake : InstallableValue struct InstallableFlake : InstallableValue
@ -99,7 +106,7 @@ struct InstallableFlake : InstallableValue
Strings && prefixes, Strings && prefixes,
const flake::LockFlags & lockFlags); 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<std::string> getActualAttrPaths(); std::vector<std::string> getActualAttrPaths();

View file

@ -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 DerivedPaths toDerivedPaths() override
{ {

View file

@ -28,11 +28,17 @@ struct CmdCopyLog : virtual CopyCommand, virtual InstallablesCommand
{ {
auto dstStore = getDstStore(); auto dstStore = getDstStore();
for (auto & path : toDerivations(srcStore, installables, true)) { StorePathSet drvPaths;
if (auto log = srcStore->getBuildLog(path))
dstStore->addBuildLog(path, *log); 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 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));
} }
} }
}; };