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) {};
auto [path, outputNames] = parsePathWithOutputs(absolute);
if (evalStore->isStorePath(path) && path.ends_with(".drv"))
drvs.push_back(DrvInfo(*state, evalStore, absolute));
drvs.push_back(DrvInfo(evalStore, absolute));
else
/* If we're in a #! script, interpret filenames
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");
auto & drvInfo = drvs.front();
auto drv = evalStore->derivationFromPath(drvInfo.requireDrvPath());
auto drv = evalStore->derivationFromPath(drvInfo.requireDrvPath(*state));
std::vector<DerivedPath> pathsToBuild;
RealisedPath::Set pathsToCopy;
@ -347,7 +347,7 @@ static void main_nix_build(std::string programName, Strings argv)
if (!drv)
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 {
.drvPath = makeConstantStorePathRef(bashDrv),
.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)
accumInputClosure(inputDrv, inputNode);
ParsedDerivation parsedDrv(drvInfo.requireDrvPath(), drv);
ParsedDerivation parsedDrv(drvInfo.requireDrvPath(*state), drv);
if (auto structAttrs = parsedDrv.prepareStructuredAttrs(*store, inputs)) {
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;
for (auto & drvInfo : drvs) {
auto drvPath = drvInfo.requireDrvPath();
auto drvPath = drvInfo.requireDrvPath(*state);
auto outputName = drvInfo.queryOutputName();
auto outputName = drvInfo.queryOutputName(*state);
if (outputName == "")
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. */
for (DrvInfos::iterator i = elems.begin(), j; i != elems.end(); i = j) {
j = i; j++;
if (systemFilter != "*" && i->querySystem() != systemFilter)
if (systemFilter != "*" && i->querySystem(state) != systemFilter)
elems.erase(i);
}
}
@ -208,7 +208,7 @@ static void loadDerivations(EvalState & state, const SourcePath & nixExprPath,
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.
static bool isPrebuilt(EvalState & state, DrvInfo & elem)
{
auto path = elem.queryOutPath();
auto path = elem.queryOutPath(state);
if (state.store->isValidPath(path)) return true;
return state.store->querySubstitutablePaths({path}).count(path);
}
@ -239,11 +239,11 @@ static void checkSelectorUse(DrvNames & selectors)
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;
std::set<std::string> result;
for (auto & drvInfo : allElems) {
const auto drvName = DrvName { drvInfo.queryName() };
const auto drvName = DrvName { drvInfo.queryName(state) };
if (drvName.name.starts_with(prefix)) {
result.emplace(drvName.name);
@ -281,7 +281,7 @@ std::vector<Match> pickNewestOnly(EvalState & state, std::vector<Match> matches)
for (auto & match : matches) {
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;
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;
comparison =
oneDrv.querySystem() == newestDrv.querySystem() ? std::strong_ordering::equal :
oneDrv.querySystem() == settings.thisSystem ? std::strong_ordering::greater :
newestDrv.querySystem() == settings.thisSystem ? std::strong_ordering::less : std::strong_ordering::equal;
oneDrv.querySystem(state) == newestDrv.querySystem(state) ? std::strong_ordering::equal :
oneDrv.querySystem(state) == settings.thisSystem ? std::strong_ordering::greater :
newestDrv.querySystem(state) == settings.thisSystem ? std::strong_ordering::less : std::strong_ordering::equal;
if (comparison == 0)
comparison = comparePriorities(state, oneDrv, newestDrv);
if (comparison == 0)
comparison = compareVersions(drvName.version, DrvName { newestDrv.queryName() }.version);
comparison = compareVersions(drvName.version, DrvName{newestDrv.queryName(state)}.version);
}
if (comparison > 0) {
@ -335,7 +335,7 @@ static DrvInfos filterBySelector(EvalState & state, DrvInfos & allElems,
for (auto & selector : selectors) {
std::vector<Match> matches;
for (auto && [index, drvInfo] : enumerate(allElems)) {
const auto drvName = DrvName { drvInfo.queryName() };
const auto drvName = DrvName { drvInfo.queryName(state) };
if (selector.matches(drvName)) {
++selector.hits;
matches.emplace_back(drvInfo, index);
@ -353,7 +353,7 @@ static DrvInfos filterBySelector(EvalState & state, DrvInfos & allElems,
elems.push_back(match.drvInfo);
if (selector.hits == 0 && selector.fullName != "*") {
const auto prefixHits = searchByPrefix(allElems, selector.name);
const auto prefixHits = searchByPrefix(state, allElems, selector.name);
if (prefixHits.empty()) {
throw Error("selector '%1%' matches no derivations", selector.fullName);
@ -436,7 +436,7 @@ static void queryInstSources(EvalState & state,
std::string name(path.name());
DrvInfo elem(state, "", nullptr);
DrvInfo elem("", nullptr);
elem.setName(name);
if (path.isDerivation()) {
@ -486,23 +486,23 @@ static void printMissing(EvalState & state, DrvInfos & elems)
{
std::vector<DerivedPath> targets;
for (auto & i : elems)
if (auto drvPath = i.queryDrvPath())
if (auto drvPath = i.queryDrvPath(state))
targets.emplace_back(DerivedPath::Built{
.drvPath = makeConstantStorePathRef(*drvPath),
.outputs = OutputsSpec::All { },
});
else
targets.emplace_back(DerivedPath::Opaque{
.path = i.queryOutPath(),
.path = i.queryOutPath(state),
});
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'). */
if (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);
for (auto & i : installedElems) {
DrvName drvName(i.queryName());
DrvName drvName(i.queryName(*globals.state));
if (!globals.preserveInstalled &&
newNames.find(drvName.name) != newNames.end() &&
!keep(i))
printInfo("replacing old '%s'", i.queryName());
!keep(*globals.state, i))
printInfo("replacing old '%s'", i.queryName(*globals.state));
else
allElems.push_back(i);
}
for (auto & i : newElems)
printInfo("installing '%s'", i.queryName());
printInfo("installing '%s'", i.queryName(*globals.state));
}
printMissing(*globals.state, newElems);
@ -607,11 +607,11 @@ static void upgradeDerivations(Globals & globals,
/* Go through all installed derivations. */
DrvInfos newElems;
for (auto & i : installedElems) {
DrvName drvName(i.queryName());
DrvName drvName(i.queryName(*globals.state));
try {
if (keep(i)) {
if (keep(*globals.state, i)) {
newElems.push_back(i);
continue;
}
@ -628,7 +628,7 @@ static void upgradeDerivations(Globals & globals,
for (auto j = availElems.begin(); j != availElems.end(); ++j) {
if (comparePriorities(*globals.state, i, *j) > 0)
continue;
DrvName newName(j->queryName());
DrvName newName(j->queryName(*globals.state));
if (newName.name == drvName.name) {
std::strong_ordering d = compareVersions(drvName.version, newName.version);
if ((upgradeType == utLt && d < 0) ||
@ -650,18 +650,18 @@ static void upgradeDerivations(Globals & globals,
}
if (bestElem != availElems.end() &&
i.queryOutPath() !=
bestElem->queryOutPath())
i.queryOutPath(*globals.state) !=
bestElem->queryOutPath(*globals.state))
{
const char * action = compareVersions(drvName.version, bestVersion) <= 0
? "upgrading" : "downgrading";
printInfo("%1% '%2%' to '%3%'",
action, i.queryName(), bestElem->queryName());
action, i.queryName(*globals.state), bestElem->queryName(*globals.state));
newElems.push_back(*bestElem);
} else newElems.push_back(i);
} 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;
}
}
@ -698,7 +698,7 @@ static void setMetaFlag(EvalState & state, DrvInfo & drv,
{
auto v = state.mem.allocValue();
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. */
for (auto & i : installedElems) {
DrvName drvName(i.queryName());
DrvName drvName(i.queryName(*globals.state));
for (auto & j : selectors)
if (j.matches(drvName)) {
printInfo("setting flag on '%1%'", i.queryName());
printInfo("setting flag on '%1%'", i.queryName(*globals.state));
j.hits++;
setMetaFlag(*globals.state, i, flagName, flagValue);
break;
@ -762,7 +762,7 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
if (globals.forceName != "")
drv.setName(globals.forceName);
auto drvPath = drv.queryDrvPath();
auto drvPath = drv.queryDrvPath(*globals.state);
std::vector<DerivedPath> paths {
drvPath
? (DerivedPath) (DerivedPath::Built {
@ -770,7 +770,7 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
.outputs = OutputsSpec::All { },
})
: (DerivedPath) (DerivedPath::Opaque {
.path = drv.queryOutPath(),
.path = drv.queryOutPath(*globals.state),
}),
};
printMissing(globals.state->store, paths);
@ -781,7 +781,7 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
Path generation = createGeneration(
*store2,
globals.profile,
drv.queryOutPath());
drv.queryOutPath(*globals.state));
switchLink(globals.profile, generation);
}
@ -801,15 +801,15 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
split = std::partition(
workingElems.begin(), workingElems.end(),
[&selectorStorePath, globals](auto &elem) {
return selectorStorePath != elem.queryOutPath();
return selectorStorePath != elem.queryOutPath(*globals.state);
}
);
} else {
DrvName selectorName(selector);
split = std::partition(
workingElems.begin(), workingElems.end(),
[&selectorName](auto &elem){
DrvName elemName(elem.queryName());
[&selectorName, &globals](auto &elem){
DrvName elemName(elem.queryName(*globals.state));
return !selectorName.matches(elemName);
}
);
@ -817,7 +817,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
if (split == workingElems.end())
warn("selector '%s' matched no installed derivations", selector);
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());
}
@ -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 b_name = b.queryName();
auto a_name = a.queryName(state);
auto b_name = b.queryName(state);
return lexicographical_compare(
a_name.begin(), a_name.end(),
b_name.begin(), b_name.end(), cmpChars);
@ -897,15 +897,15 @@ void printTable(Table & table)
typedef enum { cvLess, cvEqual, cvGreater, cvUnavail } VersionDiff;
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;
version = "?";
for (auto & i : elems) {
DrvName name2(i.queryName());
DrvName name2(i.queryName(state));
if (name.name == name2.name) {
std::strong_ordering d = compareVersions(name.version, name2.version);
if (d < 0) {
@ -937,18 +937,18 @@ static void queryJSON(Globals & globals, std::vector<DrvInfo> & elems, bool prin
if (i.hasFailed()) continue;
auto drvName = DrvName(i.queryName());
auto drvName = DrvName(i.queryName(*globals.state));
json &pkgObj = topObj[i.attrPath];
pkgObj = {
{"name", drvName.fullName},
{"pname", drvName.name},
{"version", drvName.version},
{"system", i.querySystem()},
{"outputName", i.queryOutputName()},
{"system", i.querySystem(*globals.state)},
{"outputName", i.queryOutputName(*globals.state)},
};
{
DrvInfo::Outputs outputs = i.queryOutputs(printOutPath);
DrvInfo::Outputs outputs = i.queryOutputs(*globals.state, printOutPath);
json &outputObj = pkgObj["outputs"];
outputObj = json::object();
for (auto & j : outputs) {
@ -960,18 +960,22 @@ static void queryJSON(Globals & globals, std::vector<DrvInfo> & elems, bool prin
}
if (printDrvPath) {
auto drvPath = i.queryDrvPath();
auto drvPath = i.queryDrvPath(*globals.state);
if (drvPath) pkgObj["drvPath"] = globals.state->store->printStorePath(*drvPath);
}
if (printMeta) {
json &metaObj = pkgObj["meta"];
metaObj = json::object();
StringSet metaNames = i.queryMetaNames();
StringSet metaNames = i.queryMetaNames(*globals.state);
for (auto & j : metaNames) {
Value * v = i.queryMeta(j);
Value * v = i.queryMeta(*globals.state, j);
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;
} else {
NixStringContext context;
@ -980,9 +984,13 @@ static void queryJSON(Globals & globals, std::vector<DrvInfo> & elems, bool prin
}
}
} 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) {
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;
}
}
@ -1059,8 +1067,9 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
/* !!! */
std::vector<DrvInfo> elems;
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
the status of the derivation. */
@ -1068,7 +1077,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
if (printStatus)
for (auto & i : installedElems)
installed.insert(i.queryOutPath());
installed.insert(i.queryOutPath(*globals.state));
/* Query which paths have substitutes. */
@ -1078,9 +1087,13 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
StorePathSet paths;
for (auto & i : elems)
try {
paths.insert(i.queryOutPath());
paths.insert(i.queryOutPath(*globals.state));
} 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();
}
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);
if (globals.prebuiltOnly &&
!validPaths.count(i.queryOutPath()) &&
!substitutablePaths.count(i.queryOutPath()))
!validPaths.count(i.queryOutPath(*globals.state)) &&
!substitutablePaths.count(i.queryOutPath(*globals.state)))
continue;
/* For table output. */
@ -1120,7 +1133,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
XMLAttrs attrs;
if (printStatus) {
auto outPath = i.queryOutPath();
auto outPath = i.queryOutPath(*globals.state);
bool hasSubs = substitutablePaths.count(outPath);
bool isInstalled = installed.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);
if (xmlOutput) {
auto drvName = DrvName(i.queryName());
auto drvName = DrvName(i.queryName(*globals.state));
attrs["name"] = drvName.fullName;
attrs["pname"] = drvName.name;
attrs["version"] = drvName.version;
} else if (printName) {
columns.push_back(i.queryName());
columns.push_back(i.queryName(*globals.state));
}
if (compareVersions) {
@ -1155,7 +1168,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
elements, or the set of installed elements. !!!
This is O(N * M), should be O(N * lg M). */
std::string version;
VersionDiff diff = compareVersionAgainstSet(i, otherElems, version);
VersionDiff diff = compareVersionAgainstSet(*globals.state, i, otherElems, version);
char ch;
switch (diff) {
@ -1180,13 +1193,13 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
}
if (xmlOutput) {
if (i.querySystem() != "") attrs["system"] = i.querySystem();
if (i.querySystem(*globals.state) != "") attrs["system"] = i.querySystem(*globals.state);
}
else if (printSystem)
columns.push_back(i.querySystem());
columns.push_back(i.querySystem(*globals.state));
if (printDrvPath) {
auto drvPath = i.queryDrvPath();
auto drvPath = i.queryDrvPath(*globals.state);
if (xmlOutput) {
if (drvPath) attrs["drvPath"] = store.printStorePath(*drvPath);
} else
@ -1194,10 +1207,10 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
}
if (xmlOutput)
attrs["outputName"] = i.queryOutputName();
attrs["outputName"] = i.queryOutputName(*globals.state);
if (printOutPath && !xmlOutput) {
DrvInfo::Outputs outputs = i.queryOutputs();
DrvInfo::Outputs outputs = i.queryOutputs(*globals.state);
std::string s;
for (auto & j : outputs) {
if (!s.empty()) s += ';';
@ -1208,7 +1221,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
}
if (printDescription) {
auto descr = i.queryMetaString("description");
auto descr = i.queryMetaString(*globals.state, "description");
if (xmlOutput) {
if (descr != "") attrs["description"] = descr;
} else
@ -1217,7 +1230,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
if (xmlOutput) {
XMLOpenElement item(xml, "item", attrs);
DrvInfo::Outputs outputs = i.queryOutputs(printOutPath);
DrvInfo::Outputs outputs = i.queryOutputs(*globals.state, printOutPath);
for (auto & j : outputs) {
XMLAttrs attrs2;
attrs2["name"] = j.first;
@ -1226,15 +1239,15 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
xml.writeEmptyElement("output", attrs2);
}
if (printMeta) {
StringSet metaNames = i.queryMetaNames();
StringSet metaNames = i.queryMetaNames(*globals.state);
for (auto & j : metaNames) {
XMLAttrs attrs2;
attrs2["name"] = j;
Value * v = i.queryMeta(j);
Value * v = i.queryMeta(*globals.state, j);
if (!v)
printError(
"derivation '%s' has invalid meta attribute '%s'",
i.queryName(), j);
i.queryName(*globals.state), j);
else {
if (v->type() == nString) {
attrs2["type"] = "string";
@ -1283,9 +1296,13 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
cout.flush();
} 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) {
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;
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -470,7 +470,7 @@ StorePath NixRepl::getDerivationPath(Value & v) {
auto drvInfo = getDerivation(state, v, false);
if (!drvInfo)
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)
throw Error("expression did not evaluate to a valid derivation (no 'drvPath' attribute)");
if (!state.store->isValidPath(*drvPath))

View file

@ -12,14 +12,14 @@
namespace nix {
DrvInfo::DrvInfo(EvalState & state, std::string attrPath, Bindings * attrs)
: state(&state), attrs(attrs), attrPath(std::move(attrPath))
DrvInfo::DrvInfo(std::string attrPath, Bindings * attrs)
: attrs(attrs), attrPath(std::move(attrPath))
{
}
DrvInfo::DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPathWithOutputs)
: state(&state), attrs(nullptr), attrPath("")
DrvInfo::DrvInfo(ref<Store> store, const std::string & drvPathWithOutputs)
: attrs(nullptr), attrPath("")
{
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) {
auto i = attrs->find(state->s.name);
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");
auto i = attrs->find(state.s.name);
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");
}
return name;
}
std::string DrvInfo::querySystem()
std::string DrvInfo::querySystem(EvalState & state)
{
if (system == "" && attrs) {
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");
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");
}
return system;
}
std::optional<StorePath> DrvInfo::queryDrvPath()
std::optional<StorePath> DrvInfo::queryDrvPath(EvalState & state)
{
if (!drvPath && attrs) {
Bindings::iterator i = attrs->find(state->s.drvPath);
Bindings::iterator i = attrs->find(state.s.drvPath);
NixStringContext context;
if (i == attrs->end())
drvPath = {std::nullopt};
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);
}
StorePath DrvInfo::requireDrvPath()
StorePath DrvInfo::requireDrvPath(EvalState & state)
{
if (auto drvPath = queryDrvPath())
if (auto drvPath = queryDrvPath(state))
return *drvPath;
throw Error("derivation does not contain a 'drvPath' attribute");
}
StorePath DrvInfo::queryOutPath()
StorePath DrvInfo::queryOutPath(EvalState & state)
{
if (!outPath && attrs) {
Bindings::iterator i = attrs->find(state->s.outPath);
Bindings::iterator i = attrs->find(state.s.outPath);
NixStringContext context;
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)
throw UnimplementedError("CA derivations are not yet supported");
return *outPath;
}
void DrvInfo::fillOutputs(bool withPaths)
void DrvInfo::fillOutputs(EvalState & state, bool withPaths)
{
auto fillDefault = [&]() {
std::optional<StorePath> outPath = std::nullopt;
if (withPaths) {
outPath.emplace(this->queryOutPath());
outPath.emplace(this->queryOutPath(state));
}
this->outputs.emplace("out", outPath);
};
@ -118,14 +118,14 @@ void DrvInfo::fillOutputs(bool withPaths)
return;
}
Attr * outputs = this->attrs->get(this->state->s.outputs);
Attr * outputs = this->attrs->get(state.s.outputs);
if (outputs == nullptr) {
fillDefault();
return;
}
// NOTE(Qyriad): I don't think there is any codepath that can cause this to error.
this->state->forceList(
state.forceList(
*outputs->value,
outputs->pos,
"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
// one of those with `//` to introduce the failing `outputs` entry.
auto errMsg = fmt("while evaluating output %d of a derivation", idx);
std::string_view outputName = state->forceStringNoCtx(
std::string_view outputName = state.forceStringNoCtx(
*elem,
outputs->pos,
errMsg
@ -146,7 +146,7 @@ void DrvInfo::fillOutputs(bool withPaths)
if (withPaths) {
// 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) {
// FIXME: throw error?
continue;
@ -154,10 +154,10 @@ void DrvInfo::fillOutputs(bool withPaths)
// Meanwhile we couldn't figure out any circumstances
// that cause this to error.
state->forceAttrs(*out->value, outputs->pos, errMsg);
state.forceAttrs(*out->value, outputs->pos, errMsg);
// ...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) {
continue;
// FIXME: throw error?
@ -166,7 +166,7 @@ void DrvInfo::fillOutputs(bool withPaths)
NixStringContext context;
// And idk what could possibly cause this one to error
// that wouldn't error before here.
auto storePath = state->coerceToStorePath(
auto storePath = state.coerceToStorePath(
outPath->pos,
*outPath->value,
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 (outputs.empty()) {
// FIXME: this behavior seems kind of busted, since whether or not this
// DrvInfo will have paths is forever determined by the *first* call to
// this function??
fillOutputs(withPaths);
fillOutputs(state, withPaths);
}
// 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
// attribute `outputSpecified = true`, and changes the `outputName` attr to the
// explicitly selected-into output.
if (Attr * outSpecAttr = attrs->get(state->s.outputSpecified)) {
bool outputSpecified = this->state->forceBool(
if (Attr * outSpecAttr = attrs->get(state.s.outputSpecified)) {
bool outputSpecified = state.forceBool(
*outSpecAttr->value,
outSpecAttr->pos,
"while evaluating the 'outputSpecified' attribute of a derivation"
);
if (outputSpecified) {
auto maybeOut = outputs.find(queryOutputName());
auto maybeOut = outputs.find(queryOutputName(state));
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};
}
}
/* 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;
auto errMsg = Error("this derivation has bad 'meta.outputsToInstall'");
/* ^ 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) {
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") : "";
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") : "";
}
return outputName;
}
Bindings * DrvInfo::getMeta()
Bindings * DrvInfo::getMeta(EvalState & state)
{
if (meta) return meta;
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;
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;
return meta;
}
StringSet DrvInfo::queryMetaNames()
StringSet DrvInfo::queryMetaNames(EvalState & state)
{
StringSet res;
if (!getMeta()) return res;
if (!getMeta(state)) return res;
for (auto & i : *meta)
res.emplace(state->symbols[i.name]);
res.emplace(state.symbols[i.name]);
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) {
for (auto elem : v.listItems())
if (!checkMeta(*elem)) return false;
if (!checkMeta(state, *elem)) return false;
return true;
}
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;
for (auto & i : *v.attrs)
if (!checkMeta(*i.value)) return false;
if (!checkMeta(state, *i.value)) return false;
return true;
}
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;
Bindings::iterator a = meta->find(state->symbols.create(name));
if (a == meta->end() || !checkMeta(*a->value)) return 0;
if (!getMeta(state)) return 0;
Bindings::iterator a = meta->find(state.symbols.create(name));
if (a == meta->end() || !checkMeta(state, *a->value)) return 0;
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 "";
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->type() == nInt) return v->integer;
if (v->type() == nString) {
@ -316,9 +316,9 @@ NixInt DrvInfo::queryMetaInt(const std::string & name, NixInt 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->type() == nBool) return v->boolean;
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();
auto attrs = state->buildBindings(1 + (meta ? meta->size() : 0));
auto sym = state->symbols.create(name);
getMeta(state);
auto attrs = state.buildBindings(1 + (meta ? meta->size() : 0));
auto sym = state.symbols.create(name);
if (meta)
for (auto i : *meta)
if (i.name != sym)
@ -359,9 +359,9 @@ static bool getDerivation(EvalState & state, Value & v,
state.forceValue(v, v.determinePos(noPos));
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);

View file

@ -17,8 +17,6 @@ public:
typedef std::map<std::string, std::optional<StorePath>> Outputs;
private:
EvalState * state;
std::string name;
std::string system;
std::optional<std::optional<StorePath>> drvPath;
@ -33,11 +31,11 @@ private:
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:
/**
@ -45,27 +43,27 @@ public:
*/
std::string attrPath;
DrvInfo(EvalState & state, std::string attrPath, Bindings * attrs);
DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPathWithOutputs);
DrvInfo(std::string attrPath, Bindings * attrs);
DrvInfo(ref<Store> store, const std::string & drvPathWithOutputs);
std::string queryName();
std::string querySystem();
std::optional<StorePath> queryDrvPath();
StorePath requireDrvPath();
StorePath queryOutPath();
std::string queryOutputName();
std::string queryName(EvalState & state);
std::string querySystem(EvalState & state);
std::optional<StorePath> queryDrvPath(EvalState & state);
StorePath requireDrvPath(EvalState & state);
StorePath queryOutPath(EvalState & state);
std::string queryOutputName(EvalState & state);
/**
* Return the unordered map of output names to (optional) output paths.
* 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();
Value * queryMeta(const std::string & name);
std::string queryMetaString(const std::string & name);
NixInt queryMetaInt(const std::string & name, NixInt def);
bool queryMetaBool(const std::string & name, bool def);
void setMeta(const std::string & name, Value * v);
StringSet queryMetaNames(EvalState & state);
Value * queryMeta(EvalState & state, const std::string & name);
std::string queryMetaString(EvalState & state, const std::string & name);
NixInt queryMetaInt(EvalState & state, const std::string & name, NixInt def);
bool queryMetaBool(EvalState & state, const std::string & name, bool def);
void setMeta(EvalState & state, const std::string & name, Value * v);
/*
MetaInfo queryMetaInfo(EvalState & state) const;

View file

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