diff options
author | Linus Heckemann <git@sphalerite.org> | 2020-04-25 13:18:39 +0200 |
---|---|---|
committer | Linus Heckemann <git@sphalerite.org> | 2020-04-25 16:30:42 +0200 |
commit | f59404e1a619934b9430b3a5bf352dbfffef2c31 (patch) | |
tree | 9c51337adc6cd6c72f492a601dcddfecdada801e /src/nix-env | |
parent | c9d0cf7e02d4b3af3c027d7d74d5caa3c8963d26 (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
Diffstat (limited to 'src/nix-env')
-rw-r--r-- | src/nix-env/nix-env.cc | 47 |
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; } } |