libcmd: DrvInfo should not have an EvalState*

in the future eval states will be asyncio root contexts. proving that
they are used correctly is impossible if the are referenced by things
with weakly scoped lifetimes, or entirely unscoped lifetimes, as we'd
have to deal with in the case of `DrvInfos` passed as out parameters.

Change-Id: I9ca5c46a714c6c914a77c7c7500cb4939ac9aff5
This commit is contained in:
eldritch horrors 2024-12-03 20:38:41 +01:00
parent f47cd0fc88
commit 8468dc65c7
10 changed files with 199 additions and 184 deletions

View file

@ -248,7 +248,7 @@ static void main_nix_build(std::string programName, Strings argv)
} catch (Error & e) {}; } catch (Error & e) {};
auto [path, outputNames] = parsePathWithOutputs(absolute); auto [path, outputNames] = parsePathWithOutputs(absolute);
if (evalStore->isStorePath(path) && path.ends_with(".drv")) if (evalStore->isStorePath(path) && path.ends_with(".drv"))
drvs.push_back(DrvInfo(*state, evalStore, absolute)); drvs.push_back(DrvInfo(evalStore, absolute));
else else
/* If we're in a #! script, interpret filenames /* If we're in a #! script, interpret filenames
relative to the script. */ relative to the script. */
@ -322,7 +322,7 @@ static void main_nix_build(std::string programName, Strings argv)
throw UsageError("nix-shell requires a single derivation"); throw UsageError("nix-shell requires a single derivation");
auto & drvInfo = drvs.front(); auto & drvInfo = drvs.front();
auto drv = evalStore->derivationFromPath(drvInfo.requireDrvPath()); auto drv = evalStore->derivationFromPath(drvInfo.requireDrvPath(*state));
std::vector<DerivedPath> pathsToBuild; std::vector<DerivedPath> pathsToBuild;
RealisedPath::Set pathsToCopy; RealisedPath::Set pathsToCopy;
@ -347,7 +347,7 @@ static void main_nix_build(std::string programName, Strings argv)
if (!drv) if (!drv)
throw Error("the 'bashInteractive' attribute in <nixpkgs> did not evaluate to a derivation"); throw Error("the 'bashInteractive' attribute in <nixpkgs> did not evaluate to a derivation");
auto bashDrv = drv->requireDrvPath(); auto bashDrv = drv->requireDrvPath(*state);
pathsToBuild.push_back(DerivedPath::Built { pathsToBuild.push_back(DerivedPath::Built {
.drvPath = makeConstantStorePathRef(bashDrv), .drvPath = makeConstantStorePathRef(bashDrv),
.outputs = OutputsSpec::Names {"out"}, .outputs = OutputsSpec::Names {"out"},
@ -463,7 +463,7 @@ static void main_nix_build(std::string programName, Strings argv)
for (const auto & [inputDrv, inputNode] : drv.inputDrvs.map) for (const auto & [inputDrv, inputNode] : drv.inputDrvs.map)
accumInputClosure(inputDrv, inputNode); accumInputClosure(inputDrv, inputNode);
ParsedDerivation parsedDrv(drvInfo.requireDrvPath(), drv); ParsedDerivation parsedDrv(drvInfo.requireDrvPath(*state), drv);
if (auto structAttrs = parsedDrv.prepareStructuredAttrs(*store, inputs)) { if (auto structAttrs = parsedDrv.prepareStructuredAttrs(*store, inputs)) {
auto json = structAttrs.value(); auto json = structAttrs.value();
@ -566,9 +566,9 @@ static void main_nix_build(std::string programName, Strings argv)
std::map<StorePath, std::pair<size_t, StringSet>> drvMap; std::map<StorePath, std::pair<size_t, StringSet>> drvMap;
for (auto & drvInfo : drvs) { for (auto & drvInfo : drvs) {
auto drvPath = drvInfo.requireDrvPath(); auto drvPath = drvInfo.requireDrvPath(*state);
auto outputName = drvInfo.queryOutputName(); auto outputName = drvInfo.queryOutputName(*state);
if (outputName == "") if (outputName == "")
throw Error("derivation '%s' lacks an 'outputName' attribute", store->printStorePath(drvPath)); throw Error("derivation '%s' lacks an 'outputName' attribute", store->printStorePath(drvPath));

View file

@ -200,7 +200,7 @@ static void loadDerivations(EvalState & state, const SourcePath & nixExprPath,
system. */ system. */
for (DrvInfos::iterator i = elems.begin(), j; i != elems.end(); i = j) { for (DrvInfos::iterator i = elems.begin(), j; i != elems.end(); i = j) {
j = i; j++; j = i; j++;
if (systemFilter != "*" && i->querySystem() != systemFilter) if (systemFilter != "*" && i->querySystem(state) != systemFilter)
elems.erase(i); elems.erase(i);
} }
} }
@ -208,7 +208,7 @@ static void loadDerivations(EvalState & state, const SourcePath & nixExprPath,
static NixInt getPriority(EvalState & state, DrvInfo & drv) static NixInt getPriority(EvalState & state, DrvInfo & drv)
{ {
return drv.queryMetaInt("priority", NixInt(0)); return drv.queryMetaInt(state, "priority", NixInt(0));
} }
@ -222,7 +222,7 @@ static std::strong_ordering comparePriorities(EvalState & state, DrvInfo & drv1,
// at a time. // at a time.
static bool isPrebuilt(EvalState & state, DrvInfo & elem) static bool isPrebuilt(EvalState & state, DrvInfo & elem)
{ {
auto path = elem.queryOutPath(); auto path = elem.queryOutPath(state);
if (state.store->isValidPath(path)) return true; if (state.store->isValidPath(path)) return true;
return state.store->querySubstitutablePaths({path}).count(path); return state.store->querySubstitutablePaths({path}).count(path);
} }
@ -239,11 +239,11 @@ static void checkSelectorUse(DrvNames & selectors)
namespace { namespace {
std::set<std::string> searchByPrefix(DrvInfos & allElems, std::string_view prefix) { std::set<std::string> searchByPrefix(EvalState & state, DrvInfos & allElems, std::string_view prefix) {
constexpr std::size_t maxResults = 3; constexpr std::size_t maxResults = 3;
std::set<std::string> result; std::set<std::string> result;
for (auto & drvInfo : allElems) { for (auto & drvInfo : allElems) {
const auto drvName = DrvName { drvInfo.queryName() }; const auto drvName = DrvName { drvInfo.queryName(state) };
if (drvName.name.starts_with(prefix)) { if (drvName.name.starts_with(prefix)) {
result.emplace(drvName.name); result.emplace(drvName.name);
@ -281,7 +281,7 @@ std::vector<Match> pickNewestOnly(EvalState & state, std::vector<Match> matches)
for (auto & match : matches) { for (auto & match : matches) {
auto & oneDrv = match.drvInfo; auto & oneDrv = match.drvInfo;
const auto drvName = DrvName { oneDrv.queryName() }; const auto drvName = DrvName { oneDrv.queryName(state) };
std::strong_ordering comparison = std::strong_ordering::greater; std::strong_ordering comparison = std::strong_ordering::greater;
const auto itOther = newest.find(drvName.name); const auto itOther = newest.find(drvName.name);
@ -290,13 +290,13 @@ std::vector<Match> pickNewestOnly(EvalState & state, std::vector<Match> matches)
auto & newestDrv = itOther->second.drvInfo; auto & newestDrv = itOther->second.drvInfo;
comparison = comparison =
oneDrv.querySystem() == newestDrv.querySystem() ? std::strong_ordering::equal : oneDrv.querySystem(state) == newestDrv.querySystem(state) ? std::strong_ordering::equal :
oneDrv.querySystem() == settings.thisSystem ? std::strong_ordering::greater : oneDrv.querySystem(state) == settings.thisSystem ? std::strong_ordering::greater :
newestDrv.querySystem() == settings.thisSystem ? std::strong_ordering::less : std::strong_ordering::equal; newestDrv.querySystem(state) == settings.thisSystem ? std::strong_ordering::less : std::strong_ordering::equal;
if (comparison == 0) if (comparison == 0)
comparison = comparePriorities(state, oneDrv, newestDrv); comparison = comparePriorities(state, oneDrv, newestDrv);
if (comparison == 0) if (comparison == 0)
comparison = compareVersions(drvName.version, DrvName { newestDrv.queryName() }.version); comparison = compareVersions(drvName.version, DrvName{newestDrv.queryName(state)}.version);
} }
if (comparison > 0) { if (comparison > 0) {
@ -335,7 +335,7 @@ static DrvInfos filterBySelector(EvalState & state, DrvInfos & allElems,
for (auto & selector : selectors) { for (auto & selector : selectors) {
std::vector<Match> matches; std::vector<Match> matches;
for (auto && [index, drvInfo] : enumerate(allElems)) { for (auto && [index, drvInfo] : enumerate(allElems)) {
const auto drvName = DrvName { drvInfo.queryName() }; const auto drvName = DrvName { drvInfo.queryName(state) };
if (selector.matches(drvName)) { if (selector.matches(drvName)) {
++selector.hits; ++selector.hits;
matches.emplace_back(drvInfo, index); matches.emplace_back(drvInfo, index);
@ -353,7 +353,7 @@ static DrvInfos filterBySelector(EvalState & state, DrvInfos & allElems,
elems.push_back(match.drvInfo); elems.push_back(match.drvInfo);
if (selector.hits == 0 && selector.fullName != "*") { if (selector.hits == 0 && selector.fullName != "*") {
const auto prefixHits = searchByPrefix(allElems, selector.name); const auto prefixHits = searchByPrefix(state, allElems, selector.name);
if (prefixHits.empty()) { if (prefixHits.empty()) {
throw Error("selector '%1%' matches no derivations", selector.fullName); throw Error("selector '%1%' matches no derivations", selector.fullName);
@ -436,7 +436,7 @@ static void queryInstSources(EvalState & state,
std::string name(path.name()); std::string name(path.name());
DrvInfo elem(state, "", nullptr); DrvInfo elem("", nullptr);
elem.setName(name); elem.setName(name);
if (path.isDerivation()) { if (path.isDerivation()) {
@ -486,23 +486,23 @@ static void printMissing(EvalState & state, DrvInfos & elems)
{ {
std::vector<DerivedPath> targets; std::vector<DerivedPath> targets;
for (auto & i : elems) for (auto & i : elems)
if (auto drvPath = i.queryDrvPath()) if (auto drvPath = i.queryDrvPath(state))
targets.emplace_back(DerivedPath::Built{ targets.emplace_back(DerivedPath::Built{
.drvPath = makeConstantStorePathRef(*drvPath), .drvPath = makeConstantStorePathRef(*drvPath),
.outputs = OutputsSpec::All { }, .outputs = OutputsSpec::All { },
}); });
else else
targets.emplace_back(DerivedPath::Opaque{ targets.emplace_back(DerivedPath::Opaque{
.path = i.queryOutPath(), .path = i.queryOutPath(state),
}); });
printMissing(state.store, targets); printMissing(state.store, targets);
} }
static bool keep(DrvInfo & drv) static bool keep(EvalState & state, DrvInfo & drv)
{ {
return drv.queryMetaBool("keep", false); return drv.queryMetaBool(state, "keep", false);
} }
@ -528,7 +528,7 @@ static void installDerivations(Globals & globals,
`java-front-0.9pre15899'). */ `java-front-0.9pre15899'). */
if (globals.forceName != "") if (globals.forceName != "")
i.setName(globals.forceName); i.setName(globals.forceName);
newNames.insert(DrvName(i.queryName()).name); newNames.insert(DrvName(i.queryName(*globals.state)).name);
} }
@ -543,17 +543,17 @@ static void installDerivations(Globals & globals,
DrvInfos installedElems = queryInstalled(*globals.state, profile); DrvInfos installedElems = queryInstalled(*globals.state, profile);
for (auto & i : installedElems) { for (auto & i : installedElems) {
DrvName drvName(i.queryName()); DrvName drvName(i.queryName(*globals.state));
if (!globals.preserveInstalled && if (!globals.preserveInstalled &&
newNames.find(drvName.name) != newNames.end() && newNames.find(drvName.name) != newNames.end() &&
!keep(i)) !keep(*globals.state, i))
printInfo("replacing old '%s'", i.queryName()); printInfo("replacing old '%s'", i.queryName(*globals.state));
else else
allElems.push_back(i); allElems.push_back(i);
} }
for (auto & i : newElems) for (auto & i : newElems)
printInfo("installing '%s'", i.queryName()); printInfo("installing '%s'", i.queryName(*globals.state));
} }
printMissing(*globals.state, newElems); printMissing(*globals.state, newElems);
@ -607,11 +607,11 @@ static void upgradeDerivations(Globals & globals,
/* Go through all installed derivations. */ /* Go through all installed derivations. */
DrvInfos newElems; DrvInfos newElems;
for (auto & i : installedElems) { for (auto & i : installedElems) {
DrvName drvName(i.queryName()); DrvName drvName(i.queryName(*globals.state));
try { try {
if (keep(i)) { if (keep(*globals.state, i)) {
newElems.push_back(i); newElems.push_back(i);
continue; continue;
} }
@ -628,7 +628,7 @@ static void upgradeDerivations(Globals & globals,
for (auto j = availElems.begin(); j != availElems.end(); ++j) { for (auto j = availElems.begin(); j != availElems.end(); ++j) {
if (comparePriorities(*globals.state, i, *j) > 0) if (comparePriorities(*globals.state, i, *j) > 0)
continue; continue;
DrvName newName(j->queryName()); DrvName newName(j->queryName(*globals.state));
if (newName.name == drvName.name) { if (newName.name == drvName.name) {
std::strong_ordering d = compareVersions(drvName.version, newName.version); std::strong_ordering d = compareVersions(drvName.version, newName.version);
if ((upgradeType == utLt && d < 0) || if ((upgradeType == utLt && d < 0) ||
@ -650,18 +650,18 @@ static void upgradeDerivations(Globals & globals,
} }
if (bestElem != availElems.end() && if (bestElem != availElems.end() &&
i.queryOutPath() != i.queryOutPath(*globals.state) !=
bestElem->queryOutPath()) bestElem->queryOutPath(*globals.state))
{ {
const char * action = compareVersions(drvName.version, bestVersion) <= 0 const char * action = compareVersions(drvName.version, bestVersion) <= 0
? "upgrading" : "downgrading"; ? "upgrading" : "downgrading";
printInfo("%1% '%2%' to '%3%'", printInfo("%1% '%2%' to '%3%'",
action, i.queryName(), bestElem->queryName()); action, i.queryName(*globals.state), bestElem->queryName(*globals.state));
newElems.push_back(*bestElem); newElems.push_back(*bestElem);
} else newElems.push_back(i); } else newElems.push_back(i);
} catch (Error & e) { } catch (Error & e) {
e.addTrace(nullptr, "while trying to find an upgrade for '%s'", i.queryName()); e.addTrace(nullptr, "while trying to find an upgrade for '%s'", i.queryName(*globals.state));
throw; throw;
} }
} }
@ -698,7 +698,7 @@ static void setMetaFlag(EvalState & state, DrvInfo & drv,
{ {
auto v = state.mem.allocValue(); auto v = state.mem.allocValue();
v->mkString(value); v->mkString(value);
drv.setMeta(name, v); drv.setMeta(state, name, v);
} }
@ -721,10 +721,10 @@ static void opSetFlag(Globals & globals, Strings opFlags, Strings opArgs)
/* Update all matching derivations. */ /* Update all matching derivations. */
for (auto & i : installedElems) { for (auto & i : installedElems) {
DrvName drvName(i.queryName()); DrvName drvName(i.queryName(*globals.state));
for (auto & j : selectors) for (auto & j : selectors)
if (j.matches(drvName)) { if (j.matches(drvName)) {
printInfo("setting flag on '%1%'", i.queryName()); printInfo("setting flag on '%1%'", i.queryName(*globals.state));
j.hits++; j.hits++;
setMetaFlag(*globals.state, i, flagName, flagValue); setMetaFlag(*globals.state, i, flagName, flagValue);
break; break;
@ -762,7 +762,7 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
if (globals.forceName != "") if (globals.forceName != "")
drv.setName(globals.forceName); drv.setName(globals.forceName);
auto drvPath = drv.queryDrvPath(); auto drvPath = drv.queryDrvPath(*globals.state);
std::vector<DerivedPath> paths { std::vector<DerivedPath> paths {
drvPath drvPath
? (DerivedPath) (DerivedPath::Built { ? (DerivedPath) (DerivedPath::Built {
@ -770,7 +770,7 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
.outputs = OutputsSpec::All { }, .outputs = OutputsSpec::All { },
}) })
: (DerivedPath) (DerivedPath::Opaque { : (DerivedPath) (DerivedPath::Opaque {
.path = drv.queryOutPath(), .path = drv.queryOutPath(*globals.state),
}), }),
}; };
printMissing(globals.state->store, paths); printMissing(globals.state->store, paths);
@ -781,7 +781,7 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
Path generation = createGeneration( Path generation = createGeneration(
*store2, *store2,
globals.profile, globals.profile,
drv.queryOutPath()); drv.queryOutPath(*globals.state));
switchLink(globals.profile, generation); switchLink(globals.profile, generation);
} }
@ -801,15 +801,15 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
split = std::partition( split = std::partition(
workingElems.begin(), workingElems.end(), workingElems.begin(), workingElems.end(),
[&selectorStorePath, globals](auto &elem) { [&selectorStorePath, globals](auto &elem) {
return selectorStorePath != elem.queryOutPath(); return selectorStorePath != elem.queryOutPath(*globals.state);
} }
); );
} else { } else {
DrvName selectorName(selector); DrvName selectorName(selector);
split = std::partition( split = std::partition(
workingElems.begin(), workingElems.end(), workingElems.begin(), workingElems.end(),
[&selectorName](auto &elem){ [&selectorName, &globals](auto &elem){
DrvName elemName(elem.queryName()); DrvName elemName(elem.queryName(*globals.state));
return !selectorName.matches(elemName); return !selectorName.matches(elemName);
} }
); );
@ -817,7 +817,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
if (split == workingElems.end()) if (split == workingElems.end())
warn("selector '%s' matched no installed derivations", selector); warn("selector '%s' matched no installed derivations", selector);
for (auto removedElem = split; removedElem != workingElems.end(); removedElem++) { for (auto removedElem = split; removedElem != workingElems.end(); removedElem++) {
printInfo("uninstalling '%s'", removedElem->queryName()); printInfo("uninstalling '%s'", removedElem->queryName(*globals.state));
} }
workingElems.erase(split, workingElems.end()); workingElems.erase(split, workingElems.end());
} }
@ -844,10 +844,10 @@ static bool cmpChars(char a, char b)
} }
static bool cmpElemByName(DrvInfo & a, DrvInfo & b) static bool cmpElemByName(EvalState & state, DrvInfo & a, DrvInfo & b)
{ {
auto a_name = a.queryName(); auto a_name = a.queryName(state);
auto b_name = b.queryName(); auto b_name = b.queryName(state);
return lexicographical_compare( return lexicographical_compare(
a_name.begin(), a_name.end(), a_name.begin(), a_name.end(),
b_name.begin(), b_name.end(), cmpChars); b_name.begin(), b_name.end(), cmpChars);
@ -897,15 +897,15 @@ void printTable(Table & table)
typedef enum { cvLess, cvEqual, cvGreater, cvUnavail } VersionDiff; typedef enum { cvLess, cvEqual, cvGreater, cvUnavail } VersionDiff;
static VersionDiff compareVersionAgainstSet( static VersionDiff compareVersionAgainstSet(
DrvInfo & elem, DrvInfos & elems, std::string & version) EvalState & state, DrvInfo & elem, DrvInfos & elems, std::string & version)
{ {
DrvName name(elem.queryName()); DrvName name(elem.queryName(state));
VersionDiff diff = cvUnavail; VersionDiff diff = cvUnavail;
version = "?"; version = "?";
for (auto & i : elems) { for (auto & i : elems) {
DrvName name2(i.queryName()); DrvName name2(i.queryName(state));
if (name.name == name2.name) { if (name.name == name2.name) {
std::strong_ordering d = compareVersions(name.version, name2.version); std::strong_ordering d = compareVersions(name.version, name2.version);
if (d < 0) { if (d < 0) {
@ -937,18 +937,18 @@ static void queryJSON(Globals & globals, std::vector<DrvInfo> & elems, bool prin
if (i.hasFailed()) continue; if (i.hasFailed()) continue;
auto drvName = DrvName(i.queryName()); auto drvName = DrvName(i.queryName(*globals.state));
json &pkgObj = topObj[i.attrPath]; json &pkgObj = topObj[i.attrPath];
pkgObj = { pkgObj = {
{"name", drvName.fullName}, {"name", drvName.fullName},
{"pname", drvName.name}, {"pname", drvName.name},
{"version", drvName.version}, {"version", drvName.version},
{"system", i.querySystem()}, {"system", i.querySystem(*globals.state)},
{"outputName", i.queryOutputName()}, {"outputName", i.queryOutputName(*globals.state)},
}; };
{ {
DrvInfo::Outputs outputs = i.queryOutputs(printOutPath); DrvInfo::Outputs outputs = i.queryOutputs(*globals.state, printOutPath);
json &outputObj = pkgObj["outputs"]; json &outputObj = pkgObj["outputs"];
outputObj = json::object(); outputObj = json::object();
for (auto & j : outputs) { for (auto & j : outputs) {
@ -960,18 +960,22 @@ static void queryJSON(Globals & globals, std::vector<DrvInfo> & elems, bool prin
} }
if (printDrvPath) { if (printDrvPath) {
auto drvPath = i.queryDrvPath(); auto drvPath = i.queryDrvPath(*globals.state);
if (drvPath) pkgObj["drvPath"] = globals.state->store->printStorePath(*drvPath); if (drvPath) pkgObj["drvPath"] = globals.state->store->printStorePath(*drvPath);
} }
if (printMeta) { if (printMeta) {
json &metaObj = pkgObj["meta"]; json &metaObj = pkgObj["meta"];
metaObj = json::object(); metaObj = json::object();
StringSet metaNames = i.queryMetaNames(); StringSet metaNames = i.queryMetaNames(*globals.state);
for (auto & j : metaNames) { for (auto & j : metaNames) {
Value * v = i.queryMeta(j); Value * v = i.queryMeta(*globals.state, j);
if (!v) { if (!v) {
printError("derivation '%s' has invalid meta attribute '%s'", i.queryName(), j); printError(
"derivation '%s' has invalid meta attribute '%s'",
i.queryName(*globals.state),
j
);
metaObj[j] = nullptr; metaObj[j] = nullptr;
} else { } else {
NixStringContext context; NixStringContext context;
@ -980,9 +984,13 @@ static void queryJSON(Globals & globals, std::vector<DrvInfo> & elems, bool prin
} }
} }
} catch (AssertionError & e) { } catch (AssertionError & e) {
printMsg(lvlTalkative, "skipping derivation named '%1%' which gives an assertion failure", i.queryName()); printMsg(
lvlTalkative,
"skipping derivation named '%1%' which gives an assertion failure",
i.queryName(*globals.state)
);
} catch (Error & e) { } catch (Error & e) {
e.addTrace(nullptr, "while querying the derivation named '%1%'", i.queryName()); e.addTrace(nullptr, "while querying the derivation named '%1%'", i.queryName(*globals.state));
throw; throw;
} }
} }
@ -1059,8 +1067,9 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
/* !!! */ /* !!! */
std::vector<DrvInfo> elems; std::vector<DrvInfo> elems;
for (auto & i : elems_) elems.push_back(i); for (auto & i : elems_) elems.push_back(i);
sort(elems.begin(), elems.end(), cmpElemByName); sort(elems.begin(), elems.end(), [&](auto & a, auto & b) {
return cmpElemByName(*globals.state, a, b);
});
/* We only need to know the installed paths when we are querying /* We only need to know the installed paths when we are querying
the status of the derivation. */ the status of the derivation. */
@ -1068,7 +1077,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
if (printStatus) if (printStatus)
for (auto & i : installedElems) for (auto & i : installedElems)
installed.insert(i.queryOutPath()); installed.insert(i.queryOutPath(*globals.state));
/* Query which paths have substitutes. */ /* Query which paths have substitutes. */
@ -1078,9 +1087,13 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
StorePathSet paths; StorePathSet paths;
for (auto & i : elems) for (auto & i : elems)
try { try {
paths.insert(i.queryOutPath()); paths.insert(i.queryOutPath(*globals.state));
} catch (AssertionError & e) { } catch (AssertionError & e) {
printMsg(lvlTalkative, "skipping derivation named '%s' which gives an assertion failure", i.queryName()); printMsg(
lvlTalkative,
"skipping derivation named '%s' which gives an assertion failure",
i.queryName(*globals.state)
);
i.setFailed(); i.setFailed();
} }
validPaths = store.queryValidPaths(paths); validPaths = store.queryValidPaths(paths);
@ -1109,8 +1122,8 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
//Activity act(*logger, lvlDebug, "outputting query result '%1%'", i.attrPath); //Activity act(*logger, lvlDebug, "outputting query result '%1%'", i.attrPath);
if (globals.prebuiltOnly && if (globals.prebuiltOnly &&
!validPaths.count(i.queryOutPath()) && !validPaths.count(i.queryOutPath(*globals.state)) &&
!substitutablePaths.count(i.queryOutPath())) !substitutablePaths.count(i.queryOutPath(*globals.state)))
continue; continue;
/* For table output. */ /* For table output. */
@ -1120,7 +1133,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
XMLAttrs attrs; XMLAttrs attrs;
if (printStatus) { if (printStatus) {
auto outPath = i.queryOutPath(); auto outPath = i.queryOutPath(*globals.state);
bool hasSubs = substitutablePaths.count(outPath); bool hasSubs = substitutablePaths.count(outPath);
bool isInstalled = installed.count(outPath); bool isInstalled = installed.count(outPath);
bool isValid = validPaths.count(outPath); bool isValid = validPaths.count(outPath);
@ -1141,12 +1154,12 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
columns.push_back(i.attrPath); columns.push_back(i.attrPath);
if (xmlOutput) { if (xmlOutput) {
auto drvName = DrvName(i.queryName()); auto drvName = DrvName(i.queryName(*globals.state));
attrs["name"] = drvName.fullName; attrs["name"] = drvName.fullName;
attrs["pname"] = drvName.name; attrs["pname"] = drvName.name;
attrs["version"] = drvName.version; attrs["version"] = drvName.version;
} else if (printName) { } else if (printName) {
columns.push_back(i.queryName()); columns.push_back(i.queryName(*globals.state));
} }
if (compareVersions) { if (compareVersions) {
@ -1155,7 +1168,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
elements, or the set of installed elements. !!! elements, or the set of installed elements. !!!
This is O(N * M), should be O(N * lg M). */ This is O(N * M), should be O(N * lg M). */
std::string version; std::string version;
VersionDiff diff = compareVersionAgainstSet(i, otherElems, version); VersionDiff diff = compareVersionAgainstSet(*globals.state, i, otherElems, version);
char ch; char ch;
switch (diff) { switch (diff) {
@ -1180,13 +1193,13 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
} }
if (xmlOutput) { if (xmlOutput) {
if (i.querySystem() != "") attrs["system"] = i.querySystem(); if (i.querySystem(*globals.state) != "") attrs["system"] = i.querySystem(*globals.state);
} }
else if (printSystem) else if (printSystem)
columns.push_back(i.querySystem()); columns.push_back(i.querySystem(*globals.state));
if (printDrvPath) { if (printDrvPath) {
auto drvPath = i.queryDrvPath(); auto drvPath = i.queryDrvPath(*globals.state);
if (xmlOutput) { if (xmlOutput) {
if (drvPath) attrs["drvPath"] = store.printStorePath(*drvPath); if (drvPath) attrs["drvPath"] = store.printStorePath(*drvPath);
} else } else
@ -1194,10 +1207,10 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
} }
if (xmlOutput) if (xmlOutput)
attrs["outputName"] = i.queryOutputName(); attrs["outputName"] = i.queryOutputName(*globals.state);
if (printOutPath && !xmlOutput) { if (printOutPath && !xmlOutput) {
DrvInfo::Outputs outputs = i.queryOutputs(); DrvInfo::Outputs outputs = i.queryOutputs(*globals.state);
std::string s; std::string s;
for (auto & j : outputs) { for (auto & j : outputs) {
if (!s.empty()) s += ';'; if (!s.empty()) s += ';';
@ -1208,7 +1221,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
} }
if (printDescription) { if (printDescription) {
auto descr = i.queryMetaString("description"); auto descr = i.queryMetaString(*globals.state, "description");
if (xmlOutput) { if (xmlOutput) {
if (descr != "") attrs["description"] = descr; if (descr != "") attrs["description"] = descr;
} else } else
@ -1217,7 +1230,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
if (xmlOutput) { if (xmlOutput) {
XMLOpenElement item(xml, "item", attrs); XMLOpenElement item(xml, "item", attrs);
DrvInfo::Outputs outputs = i.queryOutputs(printOutPath); DrvInfo::Outputs outputs = i.queryOutputs(*globals.state, printOutPath);
for (auto & j : outputs) { for (auto & j : outputs) {
XMLAttrs attrs2; XMLAttrs attrs2;
attrs2["name"] = j.first; attrs2["name"] = j.first;
@ -1226,15 +1239,15 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
xml.writeEmptyElement("output", attrs2); xml.writeEmptyElement("output", attrs2);
} }
if (printMeta) { if (printMeta) {
StringSet metaNames = i.queryMetaNames(); StringSet metaNames = i.queryMetaNames(*globals.state);
for (auto & j : metaNames) { for (auto & j : metaNames) {
XMLAttrs attrs2; XMLAttrs attrs2;
attrs2["name"] = j; attrs2["name"] = j;
Value * v = i.queryMeta(j); Value * v = i.queryMeta(*globals.state, j);
if (!v) if (!v)
printError( printError(
"derivation '%s' has invalid meta attribute '%s'", "derivation '%s' has invalid meta attribute '%s'",
i.queryName(), j); i.queryName(*globals.state), j);
else { else {
if (v->type() == nString) { if (v->type() == nString) {
attrs2["type"] = "string"; attrs2["type"] = "string";
@ -1283,9 +1296,13 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
cout.flush(); cout.flush();
} catch (AssertionError & e) { } catch (AssertionError & e) {
printMsg(lvlTalkative, "skipping derivation named '%1%' which gives an assertion failure", i.queryName()); printMsg(
lvlTalkative,
"skipping derivation named '%1%' which gives an assertion failure",
i.queryName(*globals.state)
);
} catch (Error & e) { } catch (Error & e) {
e.addTrace(nullptr, "while querying the derivation named '%1%'", i.queryName()); e.addTrace(nullptr, "while querying the derivation named '%1%'", i.queryName(*globals.state));
throw; throw;
} }
} }

View file

@ -65,11 +65,11 @@ void processExpr(EvalState & state, const Strings & attrPaths,
DrvInfos drvs; DrvInfos drvs;
getDerivations(state, v, "", autoArgs, drvs, false); getDerivations(state, v, "", autoArgs, drvs, false);
for (auto & i : drvs) { for (auto & i : drvs) {
auto drvPath = i.requireDrvPath(); auto drvPath = i.requireDrvPath(state);
auto drvPathS = state.store->printStorePath(drvPath); auto drvPathS = state.store->printStorePath(drvPath);
/* What output do we want? */ /* What output do we want? */
std::string outputName = i.queryOutputName(); std::string outputName = i.queryOutputName(state);
if (outputName == "") if (outputName == "")
throw Error("derivation '%1%' lacks an 'outputName' attribute", drvPathS); throw Error("derivation '%1%' lacks an 'outputName' attribute", drvPathS);

View file

@ -24,7 +24,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
exist already. */ exist already. */
std::vector<StorePathWithOutputs> drvsToBuild; std::vector<StorePathWithOutputs> drvsToBuild;
for (auto & i : elems) for (auto & i : elems)
if (auto drvPath = i.queryDrvPath()) if (auto drvPath = i.queryDrvPath(state))
drvsToBuild.push_back({*drvPath}); drvsToBuild.push_back({*drvPath});
debug("building user environment dependencies"); debug("building user environment dependencies");
@ -40,18 +40,18 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
/* Create a pseudo-derivation containing the name, system, /* Create a pseudo-derivation containing the name, system,
output paths, and optionally the derivation path, as well output paths, and optionally the derivation path, as well
as the meta attributes. */ as the meta attributes. */
std::optional<StorePath> drvPath = keepDerivations ? i.queryDrvPath() : std::nullopt; std::optional<StorePath> drvPath = keepDerivations ? i.queryDrvPath(state) : std::nullopt;
DrvInfo::Outputs outputs = i.queryOutputs(true, true); DrvInfo::Outputs outputs = i.queryOutputs(state, true, true);
StringSet metaNames = i.queryMetaNames(); StringSet metaNames = i.queryMetaNames(state);
auto attrs = state.buildBindings(7 + outputs.size()); auto attrs = state.buildBindings(7 + outputs.size());
attrs.alloc(state.s.type).mkString("derivation"); attrs.alloc(state.s.type).mkString("derivation");
attrs.alloc(state.s.name).mkString(i.queryName()); attrs.alloc(state.s.name).mkString(i.queryName(state));
auto system = i.querySystem(); auto system = i.querySystem(state);
if (!system.empty()) if (!system.empty())
attrs.alloc(state.s.system).mkString(system); attrs.alloc(state.s.system).mkString(system);
attrs.alloc(state.s.outPath).mkString(state.store->printStorePath(i.queryOutPath())); attrs.alloc(state.s.outPath).mkString(state.store->printStorePath(i.queryOutPath(state)));
if (drvPath) if (drvPath)
attrs.alloc(state.s.drvPath).mkString(state.store->printStorePath(*drvPath)); attrs.alloc(state.s.drvPath).mkString(state.store->printStorePath(*drvPath));
@ -75,7 +75,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
// Copy the meta attributes. // Copy the meta attributes.
auto meta = state.buildBindings(metaNames.size()); auto meta = state.buildBindings(metaNames.size());
for (auto & j : metaNames) { for (auto & j : metaNames) {
Value * v = i.queryMeta(j); Value * v = i.queryMeta(state, j);
if (!v) continue; if (!v) continue;
meta.insert(state.symbols.create(j), v); meta.insert(state.symbols.create(j), v);
} }

View file

@ -169,7 +169,7 @@ ProfileManifest::ProfileManifest(EvalState & state, const Path & profile)
for (auto & drvInfo : drvInfos) { for (auto & drvInfo : drvInfos) {
ProfileElement element; ProfileElement element;
element.storePaths = {drvInfo.queryOutPath()}; element.storePaths = {drvInfo.queryOutPath(state)};
addElement(std::move(element)); addElement(std::move(element));
} }
} }

View file

@ -53,14 +53,14 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths()
std::map<StorePath, OutputsSpec> byDrvPath; std::map<StorePath, OutputsSpec> byDrvPath;
for (auto & drvInfo : drvInfos) { for (auto & drvInfo : drvInfos) {
auto drvPath = drvInfo.queryDrvPath(); auto drvPath = drvInfo.queryDrvPath(*state);
if (!drvPath) if (!drvPath)
throw Error("'%s' is not a derivation", what()); throw Error("'%s' is not a derivation", what());
auto newOutputs = std::visit(overloaded { auto newOutputs = std::visit(overloaded {
[&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec { [&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec {
std::set<std::string> outputsToInstall; std::set<std::string> outputsToInstall;
for (auto & output : drvInfo.queryOutputs(false, true)) for (auto & output : drvInfo.queryOutputs(*state, false, true))
outputsToInstall.insert(output.first); outputsToInstall.insert(output.first);
return OutputsSpec::Names { std::move(outputsToInstall) }; return OutputsSpec::Names { std::move(outputsToInstall) };
}, },

View file

@ -470,7 +470,7 @@ StorePath NixRepl::getDerivationPath(Value & v) {
auto drvInfo = getDerivation(state, v, false); auto drvInfo = getDerivation(state, v, false);
if (!drvInfo) if (!drvInfo)
throw Error("expression does not evaluate to a derivation, so I can't build it"); throw Error("expression does not evaluate to a derivation, so I can't build it");
auto drvPath = drvInfo->queryDrvPath(); auto drvPath = drvInfo->queryDrvPath(state);
if (!drvPath) if (!drvPath)
throw Error("expression did not evaluate to a valid derivation (no 'drvPath' attribute)"); throw Error("expression did not evaluate to a valid derivation (no 'drvPath' attribute)");
if (!state.store->isValidPath(*drvPath)) if (!state.store->isValidPath(*drvPath))

View file

@ -12,14 +12,14 @@
namespace nix { namespace nix {
DrvInfo::DrvInfo(EvalState & state, std::string attrPath, Bindings * attrs) DrvInfo::DrvInfo(std::string attrPath, Bindings * attrs)
: state(&state), attrs(attrs), attrPath(std::move(attrPath)) : attrs(attrs), attrPath(std::move(attrPath))
{ {
} }
DrvInfo::DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPathWithOutputs) DrvInfo::DrvInfo(ref<Store> store, const std::string & drvPathWithOutputs)
: state(&state), attrs(nullptr), attrPath("") : attrs(nullptr), attrPath("")
{ {
auto [drvPath, selectedOutputs] = parsePathWithOutputs(*store, drvPathWithOutputs); auto [drvPath, selectedOutputs] = parsePathWithOutputs(*store, drvPathWithOutputs);
@ -46,68 +46,68 @@ DrvInfo::DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPat
} }
std::string DrvInfo::queryName() std::string DrvInfo::queryName(EvalState & state)
{ {
if (name == "" && attrs) { if (name == "" && attrs) {
auto i = attrs->find(state->s.name); auto i = attrs->find(state.s.name);
if (i == attrs->end()) state->errors.make<TypeError>("derivation name missing").debugThrow(); if (i == attrs->end()) state.errors.make<TypeError>("derivation name missing").debugThrow();
name = state->forceStringNoCtx(*i->value, noPos, "while evaluating the 'name' attribute of a derivation"); name = state.forceStringNoCtx(*i->value, noPos, "while evaluating the 'name' attribute of a derivation");
} }
return name; return name;
} }
std::string DrvInfo::querySystem() std::string DrvInfo::querySystem(EvalState & state)
{ {
if (system == "" && attrs) { if (system == "" && attrs) {
auto i = attrs->find(state->s.system); auto i = attrs->find(state.s.system);
system = i == attrs->end() ? "unknown" : state->forceStringNoCtx(*i->value, i->pos, "while evaluating the 'system' attribute of a derivation"); system = i == attrs->end() ? "unknown" : state.forceStringNoCtx(*i->value, i->pos, "while evaluating the 'system' attribute of a derivation");
} }
return system; return system;
} }
std::optional<StorePath> DrvInfo::queryDrvPath() std::optional<StorePath> DrvInfo::queryDrvPath(EvalState & state)
{ {
if (!drvPath && attrs) { if (!drvPath && attrs) {
Bindings::iterator i = attrs->find(state->s.drvPath); Bindings::iterator i = attrs->find(state.s.drvPath);
NixStringContext context; NixStringContext context;
if (i == attrs->end()) if (i == attrs->end())
drvPath = {std::nullopt}; drvPath = {std::nullopt};
else else
drvPath = {state->coerceToStorePath(i->pos, *i->value, context, "while evaluating the 'drvPath' attribute of a derivation")}; drvPath = {state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the 'drvPath' attribute of a derivation")};
} }
return drvPath.value_or(std::nullopt); return drvPath.value_or(std::nullopt);
} }
StorePath DrvInfo::requireDrvPath() StorePath DrvInfo::requireDrvPath(EvalState & state)
{ {
if (auto drvPath = queryDrvPath()) if (auto drvPath = queryDrvPath(state))
return *drvPath; return *drvPath;
throw Error("derivation does not contain a 'drvPath' attribute"); throw Error("derivation does not contain a 'drvPath' attribute");
} }
StorePath DrvInfo::queryOutPath() StorePath DrvInfo::queryOutPath(EvalState & state)
{ {
if (!outPath && attrs) { if (!outPath && attrs) {
Bindings::iterator i = attrs->find(state->s.outPath); Bindings::iterator i = attrs->find(state.s.outPath);
NixStringContext context; NixStringContext context;
if (i != attrs->end()) if (i != attrs->end())
outPath = state->coerceToStorePath(i->pos, *i->value, context, "while evaluating the output path of a derivation"); outPath = state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the output path of a derivation");
} }
if (!outPath) if (!outPath)
throw UnimplementedError("CA derivations are not yet supported"); throw UnimplementedError("CA derivations are not yet supported");
return *outPath; return *outPath;
} }
void DrvInfo::fillOutputs(bool withPaths) void DrvInfo::fillOutputs(EvalState & state, bool withPaths)
{ {
auto fillDefault = [&]() { auto fillDefault = [&]() {
std::optional<StorePath> outPath = std::nullopt; std::optional<StorePath> outPath = std::nullopt;
if (withPaths) { if (withPaths) {
outPath.emplace(this->queryOutPath()); outPath.emplace(this->queryOutPath(state));
} }
this->outputs.emplace("out", outPath); this->outputs.emplace("out", outPath);
}; };
@ -118,14 +118,14 @@ void DrvInfo::fillOutputs(bool withPaths)
return; return;
} }
Attr * outputs = this->attrs->get(this->state->s.outputs); Attr * outputs = this->attrs->get(state.s.outputs);
if (outputs == nullptr) { if (outputs == nullptr) {
fillDefault(); fillDefault();
return; return;
} }
// NOTE(Qyriad): I don't think there is any codepath that can cause this to error. // NOTE(Qyriad): I don't think there is any codepath that can cause this to error.
this->state->forceList( state.forceList(
*outputs->value, *outputs->value,
outputs->pos, outputs->pos,
"while evaluating the 'outputs' attribute of a derivation" "while evaluating the 'outputs' attribute of a derivation"
@ -138,7 +138,7 @@ void DrvInfo::fillOutputs(bool withPaths)
// it is only possible by overriding a derivation attrset already created by // it is only possible by overriding a derivation attrset already created by
// one of those with `//` to introduce the failing `outputs` entry. // one of those with `//` to introduce the failing `outputs` entry.
auto errMsg = fmt("while evaluating output %d of a derivation", idx); auto errMsg = fmt("while evaluating output %d of a derivation", idx);
std::string_view outputName = state->forceStringNoCtx( std::string_view outputName = state.forceStringNoCtx(
*elem, *elem,
outputs->pos, outputs->pos,
errMsg errMsg
@ -146,7 +146,7 @@ void DrvInfo::fillOutputs(bool withPaths)
if (withPaths) { if (withPaths) {
// Find the attr with this output's name... // Find the attr with this output's name...
Attr * out = this->attrs->get(this->state->symbols.create(outputName)); Attr * out = this->attrs->get(state.symbols.create(outputName));
if (out == nullptr) { if (out == nullptr) {
// FIXME: throw error? // FIXME: throw error?
continue; continue;
@ -154,10 +154,10 @@ void DrvInfo::fillOutputs(bool withPaths)
// Meanwhile we couldn't figure out any circumstances // Meanwhile we couldn't figure out any circumstances
// that cause this to error. // that cause this to error.
state->forceAttrs(*out->value, outputs->pos, errMsg); state.forceAttrs(*out->value, outputs->pos, errMsg);
// ...and evaluate its `outPath` attribute. // ...and evaluate its `outPath` attribute.
Attr * outPath = out->value->attrs->get(this->state->s.outPath); Attr * outPath = out->value->attrs->get(state.s.outPath);
if (outPath == nullptr) { if (outPath == nullptr) {
continue; continue;
// FIXME: throw error? // FIXME: throw error?
@ -166,7 +166,7 @@ void DrvInfo::fillOutputs(bool withPaths)
NixStringContext context; NixStringContext context;
// And idk what could possibly cause this one to error // And idk what could possibly cause this one to error
// that wouldn't error before here. // that wouldn't error before here.
auto storePath = state->coerceToStorePath( auto storePath = state.coerceToStorePath(
outPath->pos, outPath->pos,
*outPath->value, *outPath->value,
context, context,
@ -179,14 +179,14 @@ void DrvInfo::fillOutputs(bool withPaths)
} }
} }
DrvInfo::Outputs DrvInfo::queryOutputs(bool withPaths, bool onlyOutputsToInstall) DrvInfo::Outputs DrvInfo::queryOutputs(EvalState & state, bool withPaths, bool onlyOutputsToInstall)
{ {
// If we haven't already cached the outputs set, then do so now. // If we haven't already cached the outputs set, then do so now.
if (outputs.empty()) { if (outputs.empty()) {
// FIXME: this behavior seems kind of busted, since whether or not this // FIXME: this behavior seems kind of busted, since whether or not this
// DrvInfo will have paths is forever determined by the *first* call to // DrvInfo will have paths is forever determined by the *first* call to
// this function?? // this function??
fillOutputs(withPaths); fillOutputs(state, withPaths);
} }
// Things that operate on derivations like packages, like `nix-env` and `nix build`, // Things that operate on derivations like packages, like `nix-env` and `nix build`,
@ -201,23 +201,23 @@ DrvInfo::Outputs DrvInfo::queryOutputs(bool withPaths, bool onlyOutputsToInstall
// output by its attribute, e.g. `pkgs.lix.dev`, which (lol?) sets the magic // output by its attribute, e.g. `pkgs.lix.dev`, which (lol?) sets the magic
// attribute `outputSpecified = true`, and changes the `outputName` attr to the // attribute `outputSpecified = true`, and changes the `outputName` attr to the
// explicitly selected-into output. // explicitly selected-into output.
if (Attr * outSpecAttr = attrs->get(state->s.outputSpecified)) { if (Attr * outSpecAttr = attrs->get(state.s.outputSpecified)) {
bool outputSpecified = this->state->forceBool( bool outputSpecified = state.forceBool(
*outSpecAttr->value, *outSpecAttr->value,
outSpecAttr->pos, outSpecAttr->pos,
"while evaluating the 'outputSpecified' attribute of a derivation" "while evaluating the 'outputSpecified' attribute of a derivation"
); );
if (outputSpecified) { if (outputSpecified) {
auto maybeOut = outputs.find(queryOutputName()); auto maybeOut = outputs.find(queryOutputName(state));
if (maybeOut == outputs.end()) { if (maybeOut == outputs.end()) {
throw Error("derivation does not have output '%s'", queryOutputName()); throw Error("derivation does not have output '%s'", queryOutputName(state));
} }
return Outputs{*maybeOut}; return Outputs{*maybeOut};
} }
} }
/* Check for `meta.outputsToInstall` and return `outputs` reduced to that. */ /* Check for `meta.outputsToInstall` and return `outputs` reduced to that. */
const Value * outTI = queryMeta("outputsToInstall"); const Value * outTI = queryMeta(state, "outputsToInstall");
if (!outTI) return outputs; if (!outTI) return outputs;
auto errMsg = Error("this derivation has bad 'meta.outputsToInstall'"); auto errMsg = Error("this derivation has bad 'meta.outputsToInstall'");
/* ^ this shows during `nix-env -i` right under the bad derivation */ /* ^ this shows during `nix-env -i` right under the bad derivation */
@ -233,51 +233,51 @@ DrvInfo::Outputs DrvInfo::queryOutputs(bool withPaths, bool onlyOutputsToInstall
} }
std::string DrvInfo::queryOutputName() std::string DrvInfo::queryOutputName(EvalState & state)
{ {
if (outputName == "" && attrs) { if (outputName == "" && attrs) {
Bindings::iterator i = attrs->find(state->s.outputName); Bindings::iterator i = attrs->find(state.s.outputName);
outputName = i != attrs->end() ? state->forceStringNoCtx(*i->value, noPos, "while evaluating the output name of a derivation") : ""; outputName = i != attrs->end() ? state.forceStringNoCtx(*i->value, noPos, "while evaluating the output name of a derivation") : "";
} }
return outputName; return outputName;
} }
Bindings * DrvInfo::getMeta() Bindings * DrvInfo::getMeta(EvalState & state)
{ {
if (meta) return meta; if (meta) return meta;
if (!attrs) return 0; if (!attrs) return 0;
Bindings::iterator a = attrs->find(state->s.meta); Bindings::iterator a = attrs->find(state.s.meta);
if (a == attrs->end()) return 0; if (a == attrs->end()) return 0;
state->forceAttrs(*a->value, a->pos, "while evaluating the 'meta' attribute of a derivation"); state.forceAttrs(*a->value, a->pos, "while evaluating the 'meta' attribute of a derivation");
meta = a->value->attrs; meta = a->value->attrs;
return meta; return meta;
} }
StringSet DrvInfo::queryMetaNames() StringSet DrvInfo::queryMetaNames(EvalState & state)
{ {
StringSet res; StringSet res;
if (!getMeta()) return res; if (!getMeta(state)) return res;
for (auto & i : *meta) for (auto & i : *meta)
res.emplace(state->symbols[i.name]); res.emplace(state.symbols[i.name]);
return res; return res;
} }
bool DrvInfo::checkMeta(Value & v) bool DrvInfo::checkMeta(EvalState & state, Value & v)
{ {
state->forceValue(v, v.determinePos(noPos)); state.forceValue(v, v.determinePos(noPos));
if (v.type() == nList) { if (v.type() == nList) {
for (auto elem : v.listItems()) for (auto elem : v.listItems())
if (!checkMeta(*elem)) return false; if (!checkMeta(state, *elem)) return false;
return true; return true;
} }
else if (v.type() == nAttrs) { else if (v.type() == nAttrs) {
Bindings::iterator i = v.attrs->find(state->s.outPath); Bindings::iterator i = v.attrs->find(state.s.outPath);
if (i != v.attrs->end()) return false; if (i != v.attrs->end()) return false;
for (auto & i : *v.attrs) for (auto & i : *v.attrs)
if (!checkMeta(*i.value)) return false; if (!checkMeta(state, *i.value)) return false;
return true; return true;
} }
else return v.type() == nInt || v.type() == nBool || v.type() == nString || else return v.type() == nInt || v.type() == nBool || v.type() == nString ||
@ -285,26 +285,26 @@ bool DrvInfo::checkMeta(Value & v)
} }
Value * DrvInfo::queryMeta(const std::string & name) Value * DrvInfo::queryMeta(EvalState & state, const std::string & name)
{ {
if (!getMeta()) return 0; if (!getMeta(state)) return 0;
Bindings::iterator a = meta->find(state->symbols.create(name)); Bindings::iterator a = meta->find(state.symbols.create(name));
if (a == meta->end() || !checkMeta(*a->value)) return 0; if (a == meta->end() || !checkMeta(state, *a->value)) return 0;
return a->value; return a->value;
} }
std::string DrvInfo::queryMetaString(const std::string & name) std::string DrvInfo::queryMetaString(EvalState & state, const std::string & name)
{ {
Value * v = queryMeta(name); Value * v = queryMeta(state, name);
if (!v || v->type() != nString) return ""; if (!v || v->type() != nString) return "";
return v->string.s; return v->string.s;
} }
NixInt DrvInfo::queryMetaInt(const std::string & name, NixInt def) NixInt DrvInfo::queryMetaInt(EvalState & state, const std::string & name, NixInt def)
{ {
Value * v = queryMeta(name); Value * v = queryMeta(state, name);
if (!v) return def; if (!v) return def;
if (v->type() == nInt) return v->integer; if (v->type() == nInt) return v->integer;
if (v->type() == nString) { if (v->type() == nString) {
@ -316,9 +316,9 @@ NixInt DrvInfo::queryMetaInt(const std::string & name, NixInt def)
return def; return def;
} }
bool DrvInfo::queryMetaBool(const std::string & name, bool def) bool DrvInfo::queryMetaBool(EvalState & state, const std::string & name, bool def)
{ {
Value * v = queryMeta(name); Value * v = queryMeta(state, name);
if (!v) return def; if (!v) return def;
if (v->type() == nBool) return v->boolean; if (v->type() == nBool) return v->boolean;
if (v->type() == nString) { if (v->type() == nString) {
@ -331,11 +331,11 @@ bool DrvInfo::queryMetaBool(const std::string & name, bool def)
} }
void DrvInfo::setMeta(const std::string & name, Value * v) void DrvInfo::setMeta(EvalState & state, const std::string & name, Value * v)
{ {
getMeta(); getMeta(state);
auto attrs = state->buildBindings(1 + (meta ? meta->size() : 0)); auto attrs = state.buildBindings(1 + (meta ? meta->size() : 0));
auto sym = state->symbols.create(name); auto sym = state.symbols.create(name);
if (meta) if (meta)
for (auto i : *meta) for (auto i : *meta)
if (i.name != sym) if (i.name != sym)
@ -359,9 +359,9 @@ static bool getDerivation(EvalState & state, Value & v,
state.forceValue(v, v.determinePos(noPos)); state.forceValue(v, v.determinePos(noPos));
if (!state.isDerivation(v)) return true; if (!state.isDerivation(v)) return true;
DrvInfo drv(state, attrPath, v.attrs); DrvInfo drv(attrPath, v.attrs);
drv.queryName(); drv.queryName(state);
drvs.push_back(drv); drvs.push_back(drv);

View file

@ -17,8 +17,6 @@ public:
typedef std::map<std::string, std::optional<StorePath>> Outputs; typedef std::map<std::string, std::optional<StorePath>> Outputs;
private: private:
EvalState * state;
std::string name; std::string name;
std::string system; std::string system;
std::optional<std::optional<StorePath>> drvPath; std::optional<std::optional<StorePath>> drvPath;
@ -33,11 +31,11 @@ private:
Bindings * attrs = nullptr, * meta = nullptr; Bindings * attrs = nullptr, * meta = nullptr;
Bindings * getMeta(); Bindings * getMeta(EvalState & state);
bool checkMeta(Value & v); bool checkMeta(EvalState & state, Value & v);
void fillOutputs(bool withPaths = true); void fillOutputs(EvalState & state, bool withPaths = true);
public: public:
/** /**
@ -45,27 +43,27 @@ public:
*/ */
std::string attrPath; std::string attrPath;
DrvInfo(EvalState & state, std::string attrPath, Bindings * attrs); DrvInfo(std::string attrPath, Bindings * attrs);
DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPathWithOutputs); DrvInfo(ref<Store> store, const std::string & drvPathWithOutputs);
std::string queryName(); std::string queryName(EvalState & state);
std::string querySystem(); std::string querySystem(EvalState & state);
std::optional<StorePath> queryDrvPath(); std::optional<StorePath> queryDrvPath(EvalState & state);
StorePath requireDrvPath(); StorePath requireDrvPath(EvalState & state);
StorePath queryOutPath(); StorePath queryOutPath(EvalState & state);
std::string queryOutputName(); std::string queryOutputName(EvalState & state);
/** /**
* Return the unordered map of output names to (optional) output paths. * Return the unordered map of output names to (optional) output paths.
* The "outputs to install" are determined by `meta.outputsToInstall`. * The "outputs to install" are determined by `meta.outputsToInstall`.
*/ */
Outputs queryOutputs(bool withPaths = true, bool onlyOutputsToInstall = false); Outputs queryOutputs(EvalState & state, bool withPaths = true, bool onlyOutputsToInstall = false);
StringSet queryMetaNames(); StringSet queryMetaNames(EvalState & state);
Value * queryMeta(const std::string & name); Value * queryMeta(EvalState & state, const std::string & name);
std::string queryMetaString(const std::string & name); std::string queryMetaString(EvalState & state, const std::string & name);
NixInt queryMetaInt(const std::string & name, NixInt def); NixInt queryMetaInt(EvalState & state, const std::string & name, NixInt def);
bool queryMetaBool(const std::string & name, bool def); bool queryMetaBool(EvalState & state, const std::string & name, bool def);
void setMeta(const std::string & name, Value * v); void setMeta(EvalState & state, const std::string & name, Value * v);
/* /*
MetaInfo queryMetaInfo(EvalState & state) const; MetaInfo queryMetaInfo(EvalState & state) const;

View file

@ -420,7 +420,7 @@ struct CmdFlakeCheck : FlakeCommand
throw Error("flake attribute '%s' is not a derivation", attrPath); throw Error("flake attribute '%s' is not a derivation", attrPath);
else { else {
// FIXME: check meta attributes // FIXME: check meta attributes
auto storePath = drvInfo->queryDrvPath(); auto storePath = drvInfo->queryDrvPath(*state);
if (storePath) { if (storePath) {
logger->log(lvlInfo, logger->log(lvlInfo,
fmt("derivation evaluated to %s", fmt("derivation evaluated to %s",