aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Heckemann <git@sphalerite.org>2020-04-25 13:18:39 +0200
committerLinus Heckemann <git@sphalerite.org>2020-04-25 16:30:42 +0200
commitf59404e1a619934b9430b3a5bf352dbfffef2c31 (patch)
tree9c51337adc6cd6c72f492a601dcddfecdada801e
parentc9d0cf7e02d4b3af3c027d7d74d5caa3c8963d26 (diff)
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
-rw-r--r--src/nix-env/nix-env.cc47
1 files changed, 29 insertions, 18 deletions
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index 1a2bb42a3..6c9cd9548 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -718,28 +718,39 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
while (true) {
string lockToken = optimisticLockProfile(profile);
- DrvInfos installedElems = queryInstalled(*globals.state, profile);
- DrvInfos newElems;
-
- for (auto & i : installedElems) {
- DrvName drvName(i.queryName());
- bool found = false;
- for (auto & j : selectors)
- /* !!! the repeated calls to followLinksToStorePath()
- are expensive, should pre-compute them. */
- if ((isPath(j) && globals.state->store->parseStorePath(i.queryOutPath()) == globals.state->store->followLinksToStorePath(j))
- || DrvName(j).matches(drvName))
- {
- printInfo("uninstalling '%s'", i.queryName());
- found = true;
- break;
- }
- if (!found) newElems.push_back(i);
+ DrvInfos workingElems = queryInstalled(*globals.state, profile);
+
+ for (auto & selector : selectors) {
+ DrvInfos::iterator split = workingElems.begin();
+ if (isPath(selector)) {
+ StorePath selectorStorePath = globals.state->store->followLinksToStorePath(selector);
+ split = std::partition(
+ workingElems.begin(), workingElems.end(),
+ [&selectorStorePath, globals](auto &elem) {
+ return selectorStorePath != globals.state->store->parseStorePath(elem.queryOutPath());
+ }
+ );
+ } else {
+ DrvName selectorName(selector);
+ split = std::partition(
+ 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 (createUserEnv(*globals.state, newElems,
+ if (createUserEnv(*globals.state, workingElems,
profile, settings.envKeepDerivations, lockToken)) break;
}
}