diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 0349ce6e7..6a4afe8da 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -542,48 +542,59 @@ std::optional getSourceFilePathFromInStorePath(Store & store, const Path & return betterFilePath; } + +std::tuple toDerivationImpl(InstallableFlake & flake) { + auto lockedFlake = flake.getLockedFlake(); + + auto cache = openEvalCache(*flake.state, lockedFlake); + auto root = cache->getRoot(); + + for (auto & attrPath : flake.getActualAttrPaths()) { + auto attr = root->findAlongAttrPath( + parseAttrPath(*flake.state, attrPath), + true + ); + + if (!attr) continue; + + if (!attr->isDerivation()) + throw Error("flake output attribute '%s' is not a derivation", attrPath); + + auto drvPath = attr->forceDerivation(); + + auto drvInfo = InstallableValue::DerivationInfo{ + std::move(drvPath), + flake.state->store->maybeParseStorePath(attr->getAttr(flake.state->sOutPath)->getString()), + attr->getAttr(flake.state->sOutputName)->getString() + }; + + return {attrPath, lockedFlake->flake.lockedRef, std::move(drvInfo)}; + } + + throw Error("flake '%s' does not provide attribute %s", + flake.flakeRef, showAttrPaths(flake.getActualAttrPaths())); } -std::tuple InstallableFlake::toDerivation() -{ +template +auto patchErrorSourceFile(Store & store, const fetchers::Input & flakeInput, F && func) { try { - auto lockedFlake = getLockedFlake(); - - auto cache = openEvalCache(*state, lockedFlake); - auto root = cache->getRoot(); - - for (auto & attrPath : getActualAttrPaths()) { - auto attr = root->findAlongAttrPath( - parseAttrPath(*state, attrPath), - true - ); - - if (!attr) continue; - - if (!attr->isDerivation()) - throw Error("flake output attribute '%s' is not a derivation", attrPath); - - auto drvPath = attr->forceDerivation(); - - auto drvInfo = DerivationInfo{ - std::move(drvPath), - state->store->maybeParseStorePath(attr->getAttr(state->sOutPath)->getString()), - attr->getAttr(state->sOutputName)->getString() - }; - - return {attrPath, lockedFlake->flake.lockedRef, std::move(drvInfo)}; - } + return func(); } catch (BaseError & e) { if (auto pos = e.info().errPos) { - if (auto sourceFilePath = getSourceFilePathFromInStorePath(*state->store, pos->file, flakeRef.input)) { - e.setBetterErrPosFile(*sourceFilePath); + if (auto sourceFilePath = getSourceFilePathFromInStorePath(store, pos->file, flakeInput)) { + e.replacePosFile(*sourceFilePath); } } throw; } +} +} - throw Error("flake '%s' does not provide attribute %s", - flakeRef, showAttrPaths(getActualAttrPaths())); +std::tuple InstallableFlake::toDerivation() +{ + return patchErrorSourceFile(*state->store, flakeRef.input, [&] { + return toDerivationImpl(*this); + }); } std::vector InstallableFlake::toDerivations() diff --git a/src/libutil/error.hh b/src/libutil/error.hh index 4622fe4c6..6098d7732 100644 --- a/src/libutil/error.hh +++ b/src/libutil/error.hh @@ -165,7 +165,7 @@ public: const string & msg() const { return calcWhat(); } const ErrorInfo & info() const { calcWhat(); return err; } - void setBetterErrPosFile(std::string file) { + void replacePosFile(std::string file) { if (err.errPos) { err.errPos->file = std::move(file); }