aboutsummaryrefslogtreecommitdiff
path: root/src/nix-env
diff options
context:
space:
mode:
Diffstat (limited to 'src/nix-env')
-rw-r--r--src/nix-env/nix-env.cc359
-rw-r--r--src/nix-env/user-env.cc61
-rw-r--r--src/nix-env/user-env.hh2
3 files changed, 246 insertions, 176 deletions
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index a86f55f84..12e08bbe1 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -46,7 +46,7 @@ struct InstallSourceInfo
InstallSourceType type;
Path nixExprPath; /* for srcNixExprDrvs, srcNixExprs */
Path profile; /* for srcProfile */
- string systemFilter; /* for srcNixExprDrvs */
+ std::string systemFilter; /* for srcNixExprDrvs */
Bindings * autoArgs;
};
@@ -59,7 +59,7 @@ struct Globals
bool dryRun;
bool preserveInstalled;
bool removeAll;
- string forceName;
+ std::string forceName;
bool prebuiltOnly;
};
@@ -68,8 +68,8 @@ typedef void (* Operation) (Globals & globals,
Strings opFlags, Strings opArgs);
-static string needArg(Strings::iterator & i,
- Strings & args, const string & arg)
+static std::string needArg(Strings::iterator & i,
+ Strings & args, const std::string & arg)
{
if (i == args.end()) throw UsageError("'%1%' requires an argument", arg);
return *i++;
@@ -77,7 +77,7 @@ static string needArg(Strings::iterator & i,
static bool parseInstallSourceOptions(Globals & globals,
- Strings::iterator & i, Strings & args, const string & arg)
+ Strings::iterator & i, Strings & args, const std::string & arg)
{
if (arg == "--from-expression" || arg == "-E")
globals.instSource.type = srcNixExprs;
@@ -98,8 +98,11 @@ static bool isNixExpr(const Path & path, struct stat & st)
}
+static constexpr size_t maxAttrs = 1024;
+
+
static void getAllExprs(EvalState & state,
- const Path & path, StringSet & attrs, Value & v)
+ const Path & path, StringSet & seen, BindingsBuilder & attrs)
{
StringSet namesSorted;
for (auto & i : readDirectory(path)) namesSorted.insert(i.name);
@@ -121,25 +124,24 @@ static void getAllExprs(EvalState & state,
otherwise the attribute cannot be selected with the
`-A' option. Useful if you want to stick a Nix
expression directly in ~/.nix-defexpr. */
- string attrName = i;
+ std::string attrName = i;
if (hasSuffix(attrName, ".nix"))
- attrName = string(attrName, 0, attrName.size() - 4);
- if (!attrs.insert(attrName).second) {
+ attrName = std::string(attrName, 0, attrName.size() - 4);
+ if (!seen.insert(attrName).second) {
printError("warning: name collision in input Nix expressions, skipping '%1%'", path2);
continue;
}
/* Load the expression on demand. */
- Value & vFun = state.getBuiltin("import");
- Value & vArg(*state.allocValue());
- mkString(vArg, path2);
- if (v.attrs->size() == v.attrs->capacity())
+ auto vArg = state.allocValue();
+ vArg->mkString(path2);
+ if (seen.size() == maxAttrs)
throw Error("too many Nix expressions in directory '%1%'", path);
- mkApp(*state.allocAttr(v, state.symbols.create(attrName)), vFun, vArg);
+ attrs.alloc(attrName).mkApp(&state.getBuiltin("import"), vArg);
}
else if (S_ISDIR(st.st_mode))
/* `path2' is a directory (with no default.nix in it);
recurse into it. */
- getAllExprs(state, path2, attrs, v);
+ getAllExprs(state, path2, seen, attrs);
}
}
@@ -161,11 +163,11 @@ static void loadSourceExpr(EvalState & state, const Path & path, Value & v)
~/.nix-defexpr directory that includes some system-wide
directory). */
else if (S_ISDIR(st.st_mode)) {
- state.mkAttrs(v, 1024);
- state.mkList(*state.allocAttr(v, state.symbols.create("_combineChannels")), 0);
- StringSet attrs;
- getAllExprs(state, path, attrs, v);
- v.attrs->sort();
+ auto attrs = state.buildBindings(maxAttrs);
+ attrs.alloc("_combineChannels").mkList(0);
+ StringSet seen;
+ getAllExprs(state, path, seen, attrs);
+ v.mkAttrs(attrs);
}
else throw Error("path '%s' is not a directory or a Nix expression", path);
@@ -173,8 +175,8 @@ static void loadSourceExpr(EvalState & state, const Path & path, Value & v)
static void loadDerivations(EvalState & state, Path nixExprPath,
- string systemFilter, Bindings & autoArgs,
- const string & pathPrefix, DrvInfos & elems)
+ std::string systemFilter, Bindings & autoArgs,
+ const std::string & pathPrefix, DrvInfos & elems)
{
Value vRoot;
loadSourceExpr(state, nixExprPath, vRoot);
@@ -224,6 +226,91 @@ static void checkSelectorUse(DrvNames & selectors)
}
+namespace {
+
+std::set<std::string> searchByPrefix(const DrvInfos & allElems, std::string_view prefix) {
+ constexpr std::size_t maxResults = 3;
+ std::set<std::string> result;
+ for (const auto & drvInfo : allElems) {
+ const auto drvName = DrvName { drvInfo.queryName() };
+ if (hasPrefix(drvName.name, prefix)) {
+ result.emplace(drvName.name);
+
+ if (result.size() >= maxResults) {
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+struct Match
+{
+ DrvInfo drvInfo;
+ std::size_t index;
+
+ Match(DrvInfo drvInfo_, std::size_t index_)
+ : drvInfo{std::move(drvInfo_)}
+ , index{index_}
+ {}
+};
+
+/* If a selector matches multiple derivations
+ with the same name, pick the one matching the current
+ system. If there are still multiple derivations, pick the
+ one with the highest priority. If there are still multiple
+ derivations, pick the one with the highest version.
+ Finally, if there are still multiple derivations,
+ arbitrarily pick the first one. */
+std::vector<Match> pickNewestOnly(EvalState & state, std::vector<Match> matches) {
+ /* Map from package names to derivations. */
+ std::map<std::string, Match> newest;
+ StringSet multiple;
+
+ for (auto & match : matches) {
+ auto & oneDrv = match.drvInfo;
+
+ const auto drvName = DrvName { oneDrv.queryName() };
+ long comparison = 1;
+
+ const auto itOther = newest.find(drvName.name);
+
+ if (itOther != newest.end()) {
+ auto & newestDrv = itOther->second.drvInfo;
+
+ comparison =
+ oneDrv.querySystem() == newestDrv.querySystem() ? 0 :
+ oneDrv.querySystem() == settings.thisSystem ? 1 :
+ newestDrv.querySystem() == settings.thisSystem ? -1 : 0;
+ if (comparison == 0)
+ comparison = comparePriorities(state, oneDrv, newestDrv);
+ if (comparison == 0)
+ comparison = compareVersions(drvName.version, DrvName { newestDrv.queryName() }.version);
+ }
+
+ if (comparison > 0) {
+ newest.erase(drvName.name);
+ newest.emplace(drvName.name, match);
+ multiple.erase(drvName.fullName);
+ } else if (comparison == 0) {
+ multiple.insert(drvName.fullName);
+ }
+ }
+
+ matches.clear();
+ for (auto & [name, match] : newest) {
+ if (multiple.find(name) != multiple.end())
+ warn(
+ "there are multiple derivations named '%1%'; using the first one",
+ name);
+ matches.push_back(match);
+ }
+
+ return matches;
+}
+
+} // end namespace
+
static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
const Strings & args, bool newestOnly)
{
@@ -232,87 +319,50 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
selectors.emplace_back("*");
DrvInfos elems;
- set<unsigned int> done;
-
- for (auto & i : selectors) {
- typedef list<std::pair<DrvInfo, unsigned int> > Matches;
- Matches matches;
- unsigned int n = 0;
- for (DrvInfos::const_iterator j = allElems.begin();
- j != allElems.end(); ++j, ++n)
- {
- DrvName drvName(j->queryName());
- if (i.matches(drvName)) {
- i.hits++;
- matches.push_back(std::pair<DrvInfo, unsigned int>(*j, n));
+ std::set<std::size_t> done;
+
+ for (auto & selector : selectors) {
+ std::vector<Match> matches;
+ for (const auto & [index, drvInfo] : enumerate(allElems)) {
+ const auto drvName = DrvName { drvInfo.queryName() };
+ if (selector.matches(drvName)) {
+ ++selector.hits;
+ matches.emplace_back(drvInfo, index);
}
}
- /* If `newestOnly', if a selector matches multiple derivations
- with the same name, pick the one matching the current
- system. If there are still multiple derivations, pick the
- one with the highest priority. If there are still multiple
- derivations, pick the one with the highest version.
- Finally, if there are still multiple derivations,
- arbitrarily pick the first one. */
if (newestOnly) {
+ matches = pickNewestOnly(state, std::move(matches));
+ }
- /* Map from package names to derivations. */
- typedef map<string, std::pair<DrvInfo, unsigned int> > Newest;
- Newest newest;
- StringSet multiple;
-
- for (auto & j : matches) {
- DrvName drvName(j.first.queryName());
- long d = 1;
-
- Newest::iterator k = newest.find(drvName.name);
-
- if (k != newest.end()) {
- d = j.first.querySystem() == k->second.first.querySystem() ? 0 :
- j.first.querySystem() == settings.thisSystem ? 1 :
- k->second.first.querySystem() == settings.thisSystem ? -1 : 0;
- if (d == 0)
- d = comparePriorities(state, j.first, k->second.first);
- if (d == 0)
- d = compareVersions(drvName.version, DrvName(k->second.first.queryName()).version);
- }
+ /* Insert only those elements in the final list that we
+ haven't inserted before. */
+ for (auto & match : matches)
+ if (done.insert(match.index).second)
+ elems.push_back(match.drvInfo);
- if (d > 0) {
- newest.erase(drvName.name);
- newest.insert(Newest::value_type(drvName.name, j));
- multiple.erase(j.first.queryName());
- } else if (d == 0) {
- multiple.insert(j.first.queryName());
- }
- }
+ if (selector.hits == 0 && selector.fullName != "*") {
+ const auto prefixHits = searchByPrefix(allElems, selector.name);
- matches.clear();
- for (auto & j : newest) {
- if (multiple.find(j.second.first.queryName()) != multiple.end())
- printInfo(
- "warning: there are multiple derivations named '%1%'; using the first one",
- j.second.first.queryName());
- matches.push_back(j.second);
+ if (prefixHits.empty()) {
+ throw Error("selector '%1%' matches no derivations", selector.fullName);
+ } else {
+ std::string suggestionMessage = ", maybe you meant:";
+ for (const auto & drvName : prefixHits) {
+ suggestionMessage += fmt("\n%s", drvName);
+ }
+ throw Error("selector '%1%' matches no derivations" + suggestionMessage, selector.fullName);
}
}
-
- /* Insert only those elements in the final list that we
- haven't inserted before. */
- for (auto & j : matches)
- if (done.insert(j.second).second)
- elems.push_back(j.first);
}
- checkSelectorUse(selectors);
-
return elems;
}
-static bool isPath(const string & s)
+static bool isPath(std::string_view s)
{
- return s.find('/') != string::npos;
+ return s.find('/') != std::string_view::npos;
}
@@ -358,7 +408,7 @@ static void queryInstSources(EvalState & state,
Expr * eFun = state.parseExprFromString(i, absPath("."));
Value vFun, vTmp;
state.eval(eFun, vFun);
- mkApp(vTmp, vFun, vArg);
+ vTmp.mkApp(&vFun, &vArg);
getDerivations(state, vTmp, "", *instSource.autoArgs, elems, true);
}
@@ -383,8 +433,8 @@ static void queryInstSources(EvalState & state,
auto outputs = state.store->queryDerivationOutputMap(path);
elem.setOutPath(state.store->printStorePath(outputs.at("out")));
if (name.size() >= drvExtension.size() &&
- string(name, name.size() - drvExtension.size()) == drvExtension)
- name = string(name, 0, name.size() - drvExtension.size());
+ std::string(name, name.size() - drvExtension.size()) == drvExtension)
+ name = name.substr(0, name.size() - drvExtension.size());
}
else elem.setOutPath(state.store->printStorePath(path));
@@ -465,7 +515,7 @@ static void installDerivations(Globals & globals,
while (true) {
- string lockToken = optimisticLockProfile(profile);
+ auto lockToken = optimisticLockProfile(profile);
DrvInfos allElems(newElems);
@@ -501,7 +551,7 @@ static void installDerivations(Globals & globals,
static void opInstall(Globals & globals, Strings opFlags, Strings opArgs)
{
for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) {
- string arg = *i++;
+ auto arg = *i++;
if (parseInstallSourceOptions(globals, i, opFlags, arg)) ;
else if (arg == "--preserve-installed" || arg == "-P")
globals.preserveInstalled = true;
@@ -528,7 +578,7 @@ static void upgradeDerivations(Globals & globals,
name and a higher version number. */
while (true) {
- string lockToken = optimisticLockProfile(globals.profile);
+ auto lockToken = optimisticLockProfile(globals.profile);
DrvInfos installedElems = queryInstalled(*globals.state, globals.profile);
@@ -556,7 +606,7 @@ static void upgradeDerivations(Globals & globals,
take the one with the highest version.
Do not upgrade if it would decrease the priority. */
DrvInfos::iterator bestElem = availElems.end();
- string bestVersion;
+ std::string bestVersion;
for (auto j = availElems.begin(); j != availElems.end(); ++j) {
if (comparePriorities(*globals.state, i, *j) > 0)
continue;
@@ -612,7 +662,7 @@ static void opUpgrade(Globals & globals, Strings opFlags, Strings opArgs)
{
UpgradeType upgradeType = utLt;
for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) {
- string arg = *i++;
+ std::string arg = *i++;
if (parseInstallSourceOptions(globals, i, opFlags, arg)) ;
else if (arg == "--lt") upgradeType = utLt;
else if (arg == "--leq") upgradeType = utLeq;
@@ -626,10 +676,10 @@ static void opUpgrade(Globals & globals, Strings opFlags, Strings opArgs)
static void setMetaFlag(EvalState & state, DrvInfo & drv,
- const string & name, const string & value)
+ const std::string & name, const std::string & value)
{
- Value * v = state.allocValue();
- mkString(*v, value.c_str());
+ auto v = state.allocValue();
+ v->mkString(value);
drv.setMeta(name, v);
}
@@ -642,12 +692,12 @@ static void opSetFlag(Globals & globals, Strings opFlags, Strings opArgs)
throw UsageError("not enough arguments to '--set-flag'");
Strings::iterator arg = opArgs.begin();
- string flagName = *arg++;
- string flagValue = *arg++;
+ std::string flagName = *arg++;
+ std::string flagValue = *arg++;
DrvNames selectors = drvNamesFromArgs(Strings(arg, opArgs.end()));
while (true) {
- string lockToken = optimisticLockProfile(globals.profile);
+ std::string lockToken = optimisticLockProfile(globals.profile);
DrvInfos installedElems = queryInstalled(*globals.state, globals.profile);
@@ -678,7 +728,7 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
if (!store2) throw Error("--set is not supported for this Nix store");
for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) {
- string arg = *i++;
+ std::string arg = *i++;
if (parseInstallSourceOptions(globals, i, opFlags, arg)) ;
else throw UsageError("unknown flag '%1%'", arg);
}
@@ -719,7 +769,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
Path & profile)
{
while (true) {
- string lockToken = optimisticLockProfile(profile);
+ auto lockToken = optimisticLockProfile(profile);
DrvInfos workingElems = queryInstalled(*globals.state, profile);
@@ -783,14 +833,14 @@ static bool cmpElemByName(const DrvInfo & a, const DrvInfo & b)
}
-typedef list<Strings> Table;
+typedef std::list<Strings> Table;
void printTable(Table & table)
{
auto nrColumns = table.size() > 0 ? table.front().size() : 0;
- vector<size_t> widths;
+ std::vector<size_t> widths;
widths.resize(nrColumns);
for (auto & i : table) {
@@ -805,11 +855,11 @@ void printTable(Table & table)
Strings::iterator j;
size_t column;
for (j = i.begin(), column = 0; j != i.end(); ++j, ++column) {
- string s = *j;
+ std::string s = *j;
replace(s.begin(), s.end(), '\n', ' ');
cout << s;
if (column < nrColumns - 1)
- cout << string(widths[column] - s.size() + 2, ' ');
+ cout << std::string(widths[column] - s.size() + 2, ' ');
}
cout << std::endl;
}
@@ -826,7 +876,7 @@ void printTable(Table & table)
typedef enum { cvLess, cvEqual, cvGreater, cvUnavail } VersionDiff;
static VersionDiff compareVersionAgainstSet(
- const DrvInfo & elem, const DrvInfos & elems, string & version)
+ const DrvInfo & elem, const DrvInfos & elems, std::string & version)
{
DrvName name(elem.queryName());
@@ -857,30 +907,49 @@ static VersionDiff compareVersionAgainstSet(
}
-static void queryJSON(Globals & globals, vector<DrvInfo> & elems)
+static void queryJSON(Globals & globals, std::vector<DrvInfo> & elems, bool printOutPath, bool printMeta)
{
JSONObject topObj(cout, true);
for (auto & i : elems) {
- JSONObject pkgObj = topObj.object(i.attrPath);
-
- auto drvName = DrvName(i.queryName());
- pkgObj.attr("name", drvName.fullName);
- pkgObj.attr("pname", drvName.name);
- pkgObj.attr("version", drvName.version);
- pkgObj.attr("system", i.querySystem());
-
- JSONObject metaObj = pkgObj.object("meta");
- StringSet metaNames = i.queryMetaNames();
- for (auto & j : metaNames) {
- auto placeholder = metaObj.placeholder(j);
- Value * v = i.queryMeta(j);
- if (!v) {
- printError("derivation '%s' has invalid meta attribute '%s'", i.queryName(), j);
- placeholder.write(nullptr);
- } else {
- PathSet context;
- printValueAsJSON(*globals.state, true, *v, placeholder, context);
+ try {
+ if (i.hasFailed()) continue;
+
+ JSONObject pkgObj = topObj.object(i.attrPath);
+
+ auto drvName = DrvName(i.queryName());
+ pkgObj.attr("name", drvName.fullName);
+ pkgObj.attr("pname", drvName.name);
+ pkgObj.attr("version", drvName.version);
+ pkgObj.attr("system", i.querySystem());
+
+ if (printOutPath) {
+ DrvInfo::Outputs outputs = i.queryOutputs();
+ JSONObject outputObj = pkgObj.object("outputs");
+ for (auto & j : outputs) {
+ outputObj.attr(j.first, j.second);
+ }
}
+
+ if (printMeta) {
+ JSONObject metaObj = pkgObj.object("meta");
+ StringSet metaNames = i.queryMetaNames();
+ for (auto & j : metaNames) {
+ auto placeholder = metaObj.placeholder(j);
+ Value * v = i.queryMeta(j);
+ if (!v) {
+ printError("derivation '%s' has invalid meta attribute '%s'", i.queryName(), j);
+ placeholder.write(nullptr);
+ } else {
+ PathSet context;
+ printValueAsJSON(*globals.state, true, *v, noPos, placeholder, context);
+ }
+ }
+ }
+ } catch (AssertionError & e) {
+ printMsg(lvlTalkative, "skipping derivation named '%1%' which gives an assertion failure", i.queryName());
+ } catch (Error & e) {
+ e.addTrace(std::nullopt, "while querying the derivation named '%1%'", i.queryName());
+ throw;
}
}
}
@@ -889,7 +958,7 @@ static void queryJSON(Globals & globals, vector<DrvInfo> & elems)
static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
{
Strings remaining;
- string attrPath;
+ std::string attrPath;
bool printStatus = false;
bool printName = true;
@@ -908,7 +977,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
settings.readOnlyMode = true; /* makes evaluation a bit faster */
for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) {
- string arg = *i++;
+ auto arg = *i++;
if (arg == "--status" || arg == "-s") printStatus = true;
else if (arg == "--no-name") printName = false;
else if (arg == "--system") printSystem = true;
@@ -951,7 +1020,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
/* Sort them by name. */
/* !!! */
- vector<DrvInfo> elems;
+ std::vector<DrvInfo> elems;
for (auto & i : elems_) elems.push_back(i);
sort(elems.begin(), elems.end(), cmpElemByName);
@@ -985,7 +1054,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
/* Print the desired columns, or XML output. */
if (jsonOutput) {
- queryJSON(globals, elems);
+ queryJSON(globals, elems, printOutPath, printMeta);
return;
}
@@ -1025,7 +1094,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
attrs["substitutable"] = hasSubs ? "1" : "0";
} else
columns.push_back(
- (string) (isInstalled ? "I" : "-")
+ (std::string) (isInstalled ? "I" : "-")
+ (isValid ? "P" : "-")
+ (hasSubs ? "S" : "-"));
}
@@ -1049,7 +1118,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
same named packages in either the set of available
elements, or the set of installed elements. !!!
This is O(N * M), should be O(N * lg M). */
- string version;
+ std::string version;
VersionDiff diff = compareVersionAgainstSet(i, otherElems, version);
char ch;
@@ -1067,7 +1136,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
attrs["maxComparedVersion"] = version;
}
} else {
- string column = (string) "" + ch + " " + version;
+ auto column = (std::string) "" + ch + " " + version;
if (diff == cvGreater && tty)
column = ANSI_RED + column + ANSI_NORMAL;
columns.push_back(column);
@@ -1081,7 +1150,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
columns.push_back(i.querySystem());
if (printDrvPath) {
- string drvPath = i.queryDrvPath();
+ auto drvPath = i.queryDrvPath();
if (xmlOutput) {
if (drvPath != "") attrs["drvPath"] = drvPath;
} else
@@ -1090,7 +1159,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
if (printOutPath && !xmlOutput) {
DrvInfo::Outputs outputs = i.queryOutputs();
- string s;
+ std::string s;
for (auto & j : outputs) {
if (!s.empty()) s += ';';
if (j.first != "out") { s += j.first; s += "="; }
@@ -1100,7 +1169,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
}
if (printDescription) {
- string descr = i.queryMetaString("description");
+ auto descr = i.queryMetaString("description");
if (xmlOutput) {
if (descr != "") attrs["description"] = descr;
} else
@@ -1149,10 +1218,10 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
} else if (v->type() == nList) {
attrs2["type"] = "strings";
XMLOpenElement m(xml, "meta", attrs2);
- for (unsigned int j = 0; j < v->listSize(); ++j) {
- if (v->listElems()[j]->type() != nString) continue;
+ for (auto elem : v->listItems()) {
+ if (elem->type() != nString) continue;
XMLAttrs attrs3;
- attrs3["value"] = v->listElems()[j]->string.s;
+ attrs3["value"] = elem->string.s;
xml.writeEmptyElement("string", attrs3);
}
} else if (v->type() == nAttrs) {
@@ -1262,12 +1331,12 @@ static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opAr
if (opArgs.size() == 1 && opArgs.front() == "old") {
deleteOldGenerations(globals.profile, globals.dryRun);
- } else if (opArgs.size() == 1 && opArgs.front().find('d') != string::npos) {
+ } else if (opArgs.size() == 1 && opArgs.front().find('d') != std::string::npos) {
deleteGenerationsOlderThan(globals.profile, opArgs.front(), globals.dryRun);
- } else if (opArgs.size() == 1 && opArgs.front().find('+') != string::npos) {
+ } else if (opArgs.size() == 1 && opArgs.front().find('+') != std::string::npos) {
if (opArgs.front().size() < 2)
throw Error("invalid number of generations '%1%'", opArgs.front());
- string str_max = string(opArgs.front(), 1, opArgs.front().size());
+ auto str_max = opArgs.front().substr(1);
auto max = string2Int<GenerationNumber>(str_max);
if (!max || *max == 0)
throw Error("invalid number of generations to keep '%1%'", opArgs.front());
@@ -1297,7 +1366,7 @@ static int main_nix_env(int argc, char * * argv)
Strings opFlags, opArgs;
Operation op = 0;
RepairFlag repair = NoRepair;
- string file;
+ std::string file;
Globals globals;
diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc
index 1fd4bcbd3..37e4086cb 100644
--- a/src/nix-env/user-env.cc
+++ b/src/nix-env/user-env.cc
@@ -32,7 +32,7 @@ DrvInfos queryInstalled(EvalState & state, const Path & userEnv)
bool createUserEnv(EvalState & state, DrvInfos & elems,
const Path & profile, bool keepDerivations,
- const string & lockToken)
+ const std::string & lockToken)
{
/* Build the components in the user environment, if they don't
exist already. */
@@ -50,7 +50,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
StorePathSet references;
Value manifest;
state.mkList(manifest, elems.size());
- unsigned int n = 0;
+ size_t n = 0;
for (auto & i : elems) {
/* Create a pseudo-derivation containing the name, system,
output paths, and optionally the derivation path, as well
@@ -59,28 +59,25 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
DrvInfo::Outputs outputs = i.queryOutputs(true);
StringSet metaNames = i.queryMetaNames();
- Value & v(*state.allocValue());
- manifest.listElems()[n++] = &v;
- state.mkAttrs(v, 7 + outputs.size());
+ auto attrs = state.buildBindings(7 + outputs.size());
- mkString(*state.allocAttr(v, state.sType), "derivation");
- mkString(*state.allocAttr(v, state.sName), i.queryName());
+ attrs.alloc(state.sType).mkString("derivation");
+ attrs.alloc(state.sName).mkString(i.queryName());
auto system = i.querySystem();
if (!system.empty())
- mkString(*state.allocAttr(v, state.sSystem), system);
- mkString(*state.allocAttr(v, state.sOutPath), i.queryOutPath());
+ attrs.alloc(state.sSystem).mkString(system);
+ attrs.alloc(state.sOutPath).mkString(i.queryOutPath());
if (drvPath != "")
- mkString(*state.allocAttr(v, state.sDrvPath), i.queryDrvPath());
+ attrs.alloc(state.sDrvPath).mkString(i.queryDrvPath());
// Copy each output meant for installation.
- Value & vOutputs = *state.allocAttr(v, state.sOutputs);
+ auto & vOutputs = attrs.alloc(state.sOutputs);
state.mkList(vOutputs, outputs.size());
- unsigned int m = 0;
- for (auto & j : outputs) {
- mkString(*(vOutputs.listElems()[m++] = state.allocValue()), j.first);
- Value & vOutputs = *state.allocAttr(v, state.symbols.create(j.first));
- state.mkAttrs(vOutputs, 2);
- mkString(*state.allocAttr(vOutputs, state.sOutPath), j.second);
+ for (const auto & [m, j] : enumerate(outputs)) {
+ (vOutputs.listElems()[m] = state.allocValue())->mkString(j.first);
+ auto outputAttrs = state.buildBindings(2);
+ outputAttrs.alloc(state.sOutPath).mkString(j.second);
+ attrs.alloc(j.first).mkAttrs(outputAttrs);
/* This is only necessary when installing store paths, e.g.,
`nix-env -i /nix/store/abcd...-foo'. */
@@ -91,15 +88,16 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
}
// Copy the meta attributes.
- Value & vMeta = *state.allocAttr(v, state.sMeta);
- state.mkAttrs(vMeta, metaNames.size());
+ auto meta = state.buildBindings(metaNames.size());
for (auto & j : metaNames) {
Value * v = i.queryMeta(j);
if (!v) continue;
- vMeta.attrs->push_back(Attr(state.symbols.create(j), v));
+ meta.insert(state.symbols.create(j), v);
}
- vMeta.attrs->sort();
- v.attrs->sort();
+
+ attrs.alloc(state.sMeta).mkAttrs(meta);
+
+ (manifest.listElems()[n++] = state.allocValue())->mkAttrs(attrs);
if (drvPath != "") references.insert(state.store->parseStorePath(drvPath));
}
@@ -118,17 +116,20 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
/* Construct a Nix expression that calls the user environment
builder with the manifest as argument. */
- Value args, topLevel;
- state.mkAttrs(args, 3);
- mkString(*state.allocAttr(args, state.symbols.create("manifest")),
- state.store->printStorePath(manifestFile), {state.store->printStorePath(manifestFile)});
- args.attrs->push_back(Attr(state.symbols.create("derivations"), &manifest));
- args.attrs->sort();
- mkApp(topLevel, envBuilder, args);
+ auto attrs = state.buildBindings(3);
+ attrs.alloc("manifest").mkString(
+ state.store->printStorePath(manifestFile),
+ {state.store->printStorePath(manifestFile)});
+ attrs.insert(state.symbols.create("derivations"), &manifest);
+ Value args;
+ args.mkAttrs(attrs);
+
+ Value topLevel;
+ topLevel.mkApp(&envBuilder, &args);
/* Evaluate it. */
debug("evaluating user environment builder");
- state.forceValue(topLevel);
+ state.forceValue(topLevel, [&]() { return topLevel.determinePos(noPos); });
PathSet context;
Attr & aDrvPath(*topLevel.attrs->find(state.sDrvPath));
auto topLevelDrv = state.store->parseStorePath(state.coerceToPath(*aDrvPath.pos, *aDrvPath.value, context));
diff --git a/src/nix-env/user-env.hh b/src/nix-env/user-env.hh
index f188efe9b..10646f713 100644
--- a/src/nix-env/user-env.hh
+++ b/src/nix-env/user-env.hh
@@ -8,6 +8,6 @@ DrvInfos queryInstalled(EvalState & state, const Path & userEnv);
bool createUserEnv(EvalState & state, DrvInfos & elems,
const Path & profile, bool keepDerivations,
- const string & lockToken);
+ const std::string & lockToken);
}