Codebase list debian-goodies / debian/0.69.1 which-pkg-broke
debian/0.69.1

Tree @debian/0.69.1 (Download .tar.gz)

which-pkg-broke @debian/0.69.1

f06492b
d4335bb
 
 
 
 
20cc60a
d4335bb
 
 
 
 
20cc60a
 
 
f06492b
20cc60a
 
d4335bb
f06492b
 
d4335bb
 
154a0c8
2f846bf
d4335bb
20cc60a
d4335bb
 
 
 
 
 
 
 
 
 
 
 
 
 
f06492b
d4335bb
 
c248760
 
 
 
 
98ec55c
f06492b
98ec55c
 
c248760
 
 
 
 
 
 
f06492b
c248760
 
 
 
 
 
 
98ec55c
c248760
 
 
98ec55c
c248760
98ec55c
 
 
217caba
98ec55c
 
 
 
 
 
217caba
f06492b
98ec55c
 
d4335bb
 
 
 
 
c248760
 
d4335bb
 
c248760
f06492b
d4335bb
 
 
f06492b
d4335bb
 
f06492b
d4335bb
 
 
 
#!/usr/bin/python3
#  which-pkg-broke: help find offending packages when something breaks
#  Placed in the public domain by Bill Gribble <grib@billgribble.com>

import sys
import os
import subprocess
import time
from string import *
from stat import *

def pkgdeps(pkg):
    apt_cache = subprocess.Popen(
        ['apt-cache', 'depends', pkg],
        stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
        universal_newlines=True,
        env={} # force POSIX locale
    )
    deps = []
    for myline in apt_cache.stdout:
        elts = list(s.strip() for s in myline.split(':'))
        if len(elts) == 2:
            how, pkg = elts
            how = how.replace('|', '')
            if how in ('Depends', 'PreDepends'):
                deps.append(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 localarchitectures():
    architectures = []
    dpkg_arch = subprocess.Popen(
        ['dpkg', '--print-architecture'],
        stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
        universal_newlines=True,
        env={} # force POSIX locale
    )
    for arch in dpkg_arch.stdout.readlines():
        architectures.append(arch.rstrip())

    try:
        dpkg_archs = subprocess.Popen(
            ['dpkg', '--print-foreign-architecture'],
            stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
            universal_newlines=True,
            env={} # force POSIX locale
            )
        for arch in dpkg_archs.stdout.readlines():
            architectures.append(arch.rstrip())

    except OSError:
        pass # non-multiarchy dpkg, which is ok

    return architectures

def pkginstalltime(pkg, architectures):
    times = []
    for arch in architectures:
        listfile = '/var/lib/dpkg/info/' + pkg + ':' + arch + '.list'
        try:
            times.append([pkg + ':' + arch, os.stat(listfile)[ST_MTIME]])
        except OSError:
            pass

    if not times:
        listfile = '/var/lib/dpkg/info/' + pkg + '.list'
        try:
            times.append([pkg, os.stat(listfile)[ST_MTIME]])
        except OSError:
            print("Package", pkg, "has no install time info")

    return times

def what_broke(pname):
    pkgs = [ pname ]
    pkgs.extend(alldeps(sys.argv[1], {}))

    architectures = localarchitectures()

    itimes = []
    for p in pkgs:
        itimes.extend(pkginstalltime(p, architectures))
    itimes.sort(key=lambda k: k[1])
    for i in itimes:
        p, t = i
        if t is not None:
            print(p.ljust(54), time.asctime(time.localtime(float(t))))

if (len(sys.argv) != 2 or sys.argv[1][0] == '-'):
    print("Usage: which-pkg-broke <pkg-name>")
    sys.exit(-1)
else:
    what_broke(sys.argv[1])
    sys.exit(0)