chore: update docs + rm obsolete collectUninstall

This commit is contained in:
relikd
2025-09-01 12:55:32 +02:00
parent 9ac2e4aac8
commit 9dd94b7b5e

70
brew.py
View File

@@ -892,55 +892,6 @@ class DependencyTree:
else: else:
return set(self.reverse).difference(self.forward) return set(self.reverse).difference(self.forward)
class UninstallRecipe(NamedTuple):
remove: set[str]
skip: set[str]
warnings: list[tuple[str, set[str]]] # [(pkg, {deps})]
def collectUninstall(
self, deletePkgs: list[str], hiddenPkgs: list[str],
*, ignoreDependencies: bool
) -> UninstallRecipe:
'''
Try to uninstall all `deletePkgs`. Act as if `hiddenPkgs` don't exist.
Any package that depends on another package (not in those two sets)
will be skipped and remains on the system.
'''
def warnings(hidden: set[str]) -> list[tuple]:
# uses after uninstall (dependencies with multiple parents)
return [(pkg, deps) for pkg in deletePkgs
if (deps := self.reverse.direct[pkg] - hidden)]
# user said "these aren't the packages you're looking for"
activelyIgnored = self.obsolete(hiddenPkgs)
if ignoreDependencies:
hidden = activelyIgnored.union(deletePkgs)
return self.UninstallRecipe(
set(deletePkgs), set(), warnings(hidden))
# ideally, we uninstall <deletePkgs> and all its dependencies
rawUninstall = self.forward.unionAll(deletePkgs)
# dont consider these, they will be gone (or are actively ignored)
hidden = activelyIgnored.union(rawUninstall)
# only secondary items can be skipped, primary are always removed
secondary = rawUninstall.difference(deletePkgs)
# skip a package if it has other, non-ignored, parents
skipped = self.reverse.filterDifference(secondary, hidden)
removed = rawUninstall.difference(skipped)
# recursively ignore dependencies that rely on already ignored
while deps := self.reverse.filterIntersection(removed, skipped):
skipped.update(deps)
removed.difference_update(deps)
# remove any not-installed packages
removed -= self.forward.missing(removed)
return self.UninstallRecipe(removed, skipped, warnings(hidden))
# ----------------------------------- # -----------------------------------
# Remote logic # Remote logic
@@ -1581,21 +1532,21 @@ class UninstallQueue:
Any package that depends on another package (not in those two sets) Any package that depends on another package (not in those two sets)
will be skipped and remains on the system. will be skipped and remains on the system.
''' '''
tree = Cellar.getDependencyTree() depTree = Cellar.getDependencyTree()
tree.forward.assertExist(deletePkgs + hiddenPkgs) depTree.forward.assertExist(deletePkgs + hiddenPkgs)
def getDeps(pkg: str) -> set[str]: def getDeps(pkg: str) -> set[str]:
if leaves: if leaves:
return tree.reverse.getLeaves(pkg) return depTree.reverse.getLeaves(pkg)
else: else:
return tree.reverse.direct[pkg] return depTree.reverse.direct[pkg]
def setWarnings(hidden: set[str]) -> None: def setWarnings(hidden: set[str]) -> None:
self.warnings = {pkg: deps for pkg in deletePkgs self.warnings = {pkg: deps for pkg in deletePkgs
if (deps := getDeps(pkg) - hidden)} if (deps := getDeps(pkg) - hidden)}
# user said "these aren't the packages you're looking for" # user said "these aren't the packages you're looking for"
activelyIgnored = tree.obsolete(hiddenPkgs) activelyIgnored = depTree.obsolete(hiddenPkgs)
if ignoreDependencies: if ignoreDependencies:
setWarnings(activelyIgnored.union(deletePkgs)) setWarnings(activelyIgnored.union(deletePkgs))
@@ -1604,7 +1555,7 @@ class UninstallQueue:
return return
# ideally, we uninstall <deletePkgs> and all its dependencies # ideally, we uninstall <deletePkgs> and all its dependencies
rawUninstall = tree.forward.unionAll(deletePkgs) rawUninstall = depTree.forward.unionAll(deletePkgs)
# dont consider these, they will be gone (or are actively ignored) # dont consider these, they will be gone (or are actively ignored)
hidden = activelyIgnored.union(rawUninstall) hidden = activelyIgnored.union(rawUninstall)
@@ -1612,16 +1563,16 @@ class UninstallQueue:
# only secondary items can be skipped, primary are always removed # only secondary items can be skipped, primary are always removed
secondary = rawUninstall.difference(deletePkgs) secondary = rawUninstall.difference(deletePkgs)
# skip a package if it has other, non-ignored, parents # skip a package if it has other, non-ignored, parents
skipped = tree.reverse.filterDifference(secondary, hidden) skipped = depTree.reverse.filterDifference(secondary, hidden)
removed = rawUninstall.difference(skipped) removed = rawUninstall.difference(skipped)
# recursively ignore dependencies that rely on already ignored # recursively ignore dependencies that rely on already ignored
while deps := tree.reverse.filterIntersection(removed, skipped): while deps := depTree.reverse.filterIntersection(removed, skipped):
skipped.update(deps) skipped.update(deps)
removed.difference_update(deps) removed.difference_update(deps)
# remove any not-installed packages # remove any not-installed packages
removed -= tree.forward.missing(removed) removed -= depTree.forward.missing(removed)
setWarnings(hidden) setWarnings(hidden)
self.uninstallQueue = sorted(removed) self.uninstallQueue = sorted(removed)
@@ -1637,14 +1588,17 @@ class UninstallQueue:
exit(1) exit(1)
def printUninstallQueue(self) -> None: def printUninstallQueue(self) -> None:
''' Print list of `==> will remove X.` '''
for pkg in self.uninstallQueue: for pkg in self.uninstallQueue:
Log.main(f'==> will remove {pkg}.') Log.main(f'==> will remove {pkg}.')
def printSkipped(self) -> None: def printSkipped(self) -> None:
''' Print list of `skip X. used by: {deps}` '''
for pkg, deps in sorted(self.skips.items()): for pkg, deps in sorted(self.skips.items()):
Log.warn(f'skip {pkg}. used by:', ', '.join(sorted(deps))) Log.warn(f'skip {pkg}. used by:', ', '.join(sorted(deps)))
def uninstall(self, *, dryRun: bool) -> None: def uninstall(self, *, dryRun: bool) -> None:
''' Remove symlinks and package directories (or pretend to do) '''
countPkgs = len(self.uninstallQueue) countPkgs = len(self.uninstallQueue)
# delete links # delete links