Bug#231470: apt: Apt helper needed to debug package dependency breakage
Package: apt
Version: 0.6.18
Severity: wishlist
Tags: patch
I have frequently been in a situation where a program I use suddenly
breaks after an apt-get upgrade, but I'm not sure why. Was it a new
version of the package? Perhaps I don't recall what version I was
using before the breakage, or when I might have upgraded. Was it some
package that the program I'm using depends on? Maybe, but I'm not
really sure of EVERYTHING the package in question (recursively)
depends on or when I upgraded.
So I wrote a short python script to help with this problem. The
script prints out a list of the named package and all its dependencies
sorted by the time they were installed on the system (as determined
from /var/lib/dpkg/info/*.list mtime). This gives me information to
help correlate my apt-get runs with observed package breakage to try
to find the culprit.
For example, if aptitude stops working properly,
serrano> ~/what-broke aptitude
Package <libapt-pkg-libc6.3-5-3.3> has no install time info
libdb1-compat Fri Aug 8 03:02:11 2003
libsigc++-1.2-5c102 Fri Aug 8 05:15:58 2003
aptitude Sun Jan 11 17:38:06 2004
libncurses5 Sun Jan 18 08:11:05 2004
libc6 Thu Jan 22 07:55:10 2004
libgcc1 Tue Jan 27 07:37:22 2004
gcc-3.3-base Tue Jan 27 07:37:31 2004
libstdc++5 Tue Jan 27 07:37:32 2004
So depending on exactly when I started seeing the misbehavior, there
may be a reason to point the finger at a more-recently updated library
like libstdc++ or libncurses, which are more-recently installed than
aptitude itself.
I have put this script in the public domain and I am including it with
this bug report in case it might by useful in a future version of apt.
I guess it would have to be recoded in C/C++ to be part of apt so I
don't expect that it will be used as-is, but I thought it might be
nice as a concrete example of what I'm talking about.
Script pasted below. Enjoy!
#! /usr/bin/python
# what-broke: help find offending packages when something breaks
# Placed in the public domain by Bill Gribble <grib@billgribble.com>
import sys
import os
import popen2
import time
from string import *
from stat import *
def pkgdeps(pkg):
outstr, instr = popen2.popen4("apt-cache depends %s" % pkg)
deps = []
myline = outstr.readline()
while(myline != ''):
elts = map(strip, myline.split(':'))
if len(elts) == 2:
how, pkg = elts
if how == 'Depends':
deps.append(pkg)
myline = outstr.readline()
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 = deps.keys()
return dlist
def pkginstalltime(pkg):
listfile = '/var/lib/dpkg/info/' + pkg + '.list'
try:
return os.stat(listfile)[ST_MTIME]
except:
print "Package", pkg, "has no install time info"
return None
def what_broke(pname):
def sortfun(a, b):
return cmp(a[1], b[1])
pkgs = [ pname ]
pkgs.extend(alldeps(sys.argv[1], {}))
itimes = []
for p in pkgs:
itimes.append([p, pkginstalltime(p)])
itimes.sort(sortfun)
for i in itimes:
p, t = i
if t is not None:
print ljust(p, 54), time.asctime(time.localtime(float(t)))
if (len(sys.argv) != 2 or sys.argv[1][0] == '-'):
print "Usage: what-broke <pkg-name>"
sys.exit(-1)
else:
what_broke(sys.argv[1])
sys.exit(0)
-- Package-specific info:
-- (/etc/apt/preferences present, but not submitted) --
-- (/etc/apt/sources.list present, but not submitted) --
-- System Information:
Debian Release: testing/unstable
APT prefers experimental
APT policy: (900, 'experimental'), (500, 'unstable')
Architecture: i386 (i686)
Kernel: Linux 2.6.1
Locale: LANG=C, LC_CTYPE=C
Versions of packages apt depends on:
ii libc6 2.3.2.ds1-11 GNU C Library: Shared libraries an
ii libgcc1 1:3.3.3-0pre3 GCC support library
ii libstdc++5 1:3.3.3-0pre3 The GNU Standard C++ Library v3
-- no debconf information
Reply to: