nix-env: refactor uninstallDerivations

Reduces the number of store queries it performs. Also prints a warning
if any of the selectors did not match any installed derivations.

UX Caveats:
- Will print a warning that nothing matched if a previous selector
  already removed the path
- Will not do anything if no selectors were provided (no change from
  before).

Fixes #3531
This commit is contained in:
Linus Heckemann 2020-04-25 13:18:39 +02:00
parent c9d0cf7e02
commit f59404e1a6

View file

@ -718,28 +718,39 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
while (true) { while (true) {
string lockToken = optimisticLockProfile(profile); string lockToken = optimisticLockProfile(profile);
DrvInfos installedElems = queryInstalled(*globals.state, profile); DrvInfos workingElems = queryInstalled(*globals.state, profile);
DrvInfos newElems;
for (auto & i : installedElems) { for (auto & selector : selectors) {
DrvName drvName(i.queryName()); DrvInfos::iterator split = workingElems.begin();
bool found = false; if (isPath(selector)) {
for (auto & j : selectors) StorePath selectorStorePath = globals.state->store->followLinksToStorePath(selector);
/* !!! the repeated calls to followLinksToStorePath() split = std::partition(
are expensive, should pre-compute them. */ workingElems.begin(), workingElems.end(),
if ((isPath(j) && globals.state->store->parseStorePath(i.queryOutPath()) == globals.state->store->followLinksToStorePath(j)) [&selectorStorePath, globals](auto &elem) {
|| DrvName(j).matches(drvName)) return selectorStorePath != globals.state->store->parseStorePath(elem.queryOutPath());
{ }
printInfo("uninstalling '%s'", i.queryName()); );
found = true; } else {
break; DrvName selectorName(selector);
} split = std::partition(
if (!found) newElems.push_back(i); workingElems.begin(), workingElems.end(),
[&selectorName](auto &elem){
DrvName elemName(elem.queryName());
return !selectorName.matches(elemName);
}
);
}
if (split == workingElems.end())
warn("Selector '%s' matched no installed paths", selector);
for (auto removedElem = split; removedElem != workingElems.end(); removedElem++) {
printInfo("uninstalling '%s'", removedElem->queryName());
}
workingElems.erase(split, workingElems.end());
} }
if (globals.dryRun) return; if (globals.dryRun) return;
if (createUserEnv(*globals.state, newElems, if (createUserEnv(*globals.state, workingElems,
profile, settings.envKeepDerivations, lockToken)) break; profile, settings.envKeepDerivations, lockToken)) break;
} }
} }