Package: debian-goodies
Version: 0.79
Tags: patch

which-pkg-broke is awfully slow, especially for packages with exuberant dependency chains:

   $ time which-pkg-broke mpv >/dev/null
real 4m43.203s
   user 4m32.232s
   sys  0m9.287s

This is because w-p-b spawns "apt-cache depends" for every dependency. The attached patch makes it call "apt-cache depends" for multiple packages at once. This is slightly faster:

   $ time which-pkg-broke mpv >/dev/null
real 0m8.526s
   user 0m8.222s
   sys  0m0.290s

One side effect of this new implementation that the output order of packages that have the time timestamp is no longer deterministic. I don't think this is a big deal, but I'd be happy to fix it if you think it is.


-- System Information:
Architecture: i386

Versions of packages debian-goodies recommends:
ii  apt                        1.6~alpha5
ii  curl                       7.57.0-1
ii  dctrl-tools                2.24-2+b1
ii  elfutils                   0.170-0.1
ii  libipc-system-simple-perl  1.25-3
ii  man-db                     2.7.6.1-4
ii  perl                       5.26.1-3
un  popularity-contest         <none>
ii  procps                     2:3.3.12-3
ii  python3                    3.6.3-2
ii  sensible-utils             0.0.11
ii  whiptail                   0.52.20-1+b1
ii  dialog                     1.3-20160828-2
un  zenity                     <none>

--
Jakub Wilk
diff --git a/which-pkg-broke b/which-pkg-broke
index 4f53139..59601fb 100755
--- a/which-pkg-broke
+++ b/which-pkg-broke
@@ -9,9 +9,9 @@ import time
 from string import *
 from stat import *
 
-def pkgdeps(pkg):
+def pkgdeps(pkgs):
     apt_cache = subprocess.Popen(
-        ['apt-cache', 'depends', pkg],
+        ['apt-cache', 'depends', *pkgs],
         stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
         universal_newlines=True,
         env={} # force POSIX locale
@@ -27,21 +27,14 @@ def pkgdeps(pkg):
     apt_cache.wait()
     return deps
 
-def alldeps(pkg, ignore):
-    deps = {}
-    imm_deps = pkgdeps(pkg)
-    for i in imm_deps:
-        if ignore.get(i) is None:
-            deps[i] = 1
-            ignore[i] = 1
-            childeps = alldeps(i, ignore)
-            for c in childeps:
-                deps[c] = 1
-                ignore[i] = 1
-
-    dlist = list(deps.keys())
-    return dlist
-
+def alldeps(pkg):
+    seen = set()
+    todo = set([pkg])
+    while todo:
+        new = pkgdeps(todo)
+        seen |= todo
+        todo = set(new) - seen
+    return seen
 
 def localarchitectures():
     architectures = []
@@ -88,8 +81,7 @@ def pkginstalltime(pkg, architectures):
     return times
 
 def what_broke(pname):
-    pkgs = [ pname ]
-    pkgs.extend(alldeps(sys.argv[1], {}))
+    pkgs = alldeps(pname)
 
     architectures = localarchitectures()
 

Reply via email to