Fix why-depends for CA derivations

why-depends assumed that we knew the output path of the second argument.
For CA derivations, we might not know until it's built. One way to solve
this would be to build the second installable to get the output path.

In this case we don't need to, though. If the first installable (A)
depends on the second (B), then getting the store path of A will
necessitate having the store path B. The contrapositive is, if the store
path of B is not known (i.e. it's a CA derivation which hasn't been
built), then A does not depend on B.
This commit is contained in:
Taeer Bar-Yam 2022-11-23 11:39:50 -05:00
parent 62960f3291
commit b13fd4c58e

View File

@ -84,19 +84,35 @@ struct CmdWhyDepends : SourceExprCommand
auto package = parseInstallable(store, _package);
auto packagePath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, package);
auto dependency = parseInstallable(store, _dependency);
auto dependencyPath = Installable::toStorePath(getEvalStore(), store, Realise::Derivation, operateOn, dependency);
auto dependencyPathHash = dependencyPath.hashPart();
auto derivedDependency = dependency->toDerivedPath();
auto optDependencyPath = std::visit(overloaded {
[](const DerivedPath::Opaque & nodrv) -> std::optional<StorePath> {
return { nodrv.path };
},
[&](const DerivedPath::Built & hasdrv) -> std::optional<StorePath> {
if (hasdrv.outputs.size() != 1) {
throw Error("argument '%s' should evaluate to one store path", dependency->what());
}
auto outputMap = store->queryPartialDerivationOutputMap(hasdrv.drvPath);
auto maybePath = outputMap.find(*hasdrv.outputs.begin());
if (maybePath == outputMap.end()) {
throw Error("unexpected end of iterator");
}
return maybePath->second;
},
}, derivedDependency.raw());
StorePathSet closure;
store->computeFSClosure({packagePath}, closure, false, false);
if (!closure.count(dependencyPath)) {
printError("'%s' does not depend on '%s'",
store->printStorePath(packagePath),
store->printStorePath(dependencyPath));
if (!optDependencyPath.has_value() || !closure.count(*optDependencyPath)) {
printError("'%s' does not depend on '%s'", package->what(), dependency->what());
return;
}
auto dependencyPath = *optDependencyPath;
auto dependencyPathHash = dependencyPath.hashPart();
stopProgressBar(); // FIXME
auto accessor = store->getFSAccessor();