incoming: dependency warnings
Bill Nottingham
notting at redhat.com
Thu Jul 14 16:28:22 UTC 2005
Jeff Spaleta (jspaleta at gmail.com) said:
> Is the script that generates that report open for review and patching?
> 'someone' might be able to patch the script to produce a common block
> of dep problems to bloat if this approach is worth attempting.
I'd suspect the initial problem with coalescing them is that the
deps can be different per-arch (64bit or not).
Bill
-------------- next part --------------
#!/usr/bin/python
import os
from stat import *
import sys
import tempfile
import pwd
import re
import string
import glob
import yum
from yum.constants import *
sys.path.append("/usr/bin/")
import repoclosure
arches = []
owners = {}
deps = {}
dbh = None
cspec = None
tmpdir = '/var/tmp'
def generateConfig(theDir):
for entry in os.listdir(theDir):
try:
if 'repodata' in os.listdir("%s/%s" % (theDir,entry)):
arches.append(entry)
except:
pass
try:
(fd, conffile) = tempfile.mkstemp()
except:
conffile = tempfile.mktemp()
fd = os.open(conffile,os.O_RDWR|os.O_CREAT)
confheader = """
[main]
cachedir=/var/cache/yum
debuglevel=2
logfile=/var/log/yum.log
pkgpolicy=newest
distroverpkg=fedora-release
reposdir=/dev/null
"""
os.write(fd,confheader)
for arch in arches:
repo = """
[development-%s]
name=Fedora Core Development Tree - %s
baseurl=file://%s/%s
enabled=1
""" % (arch, arch, theDir, arch)
os.write(fd,repo)
os.close(fd)
return conffile
def libmunge(match):
if match.groups()[1].isdigit():
return "%s%d" % (match.groups()[0],int(match.groups()[1])+1)
else:
return "%s%s" % (match.groups()[0],match.groups()[1])
def getCacheDir():
uid = os.geteuid()
try:
usertup = pwd.getpwuid(uid)
username = usertup[0]
except KeyError:
return None # if it returns None then, well, it's bollocksed
prefix = 'yum-%s-' % username
dirpath = '%s/%s*' % (tmpdir, prefix)
cachedirs = glob.glob(dirpath)
for thisdir in cachedirs:
# if one exists take the first one
# check if it is:
# 0. is a dir
if not os.path.isdir(thisdir):
continue
stats = os.stat(thisdir)
# 1. owned by the user
if stats[4] != uid:
continue
# 2. 0700
if S_IMODE(stats[0]) != 448:
continue
# it made it through the gauntlet!
return thisdir
if 'mkdtemp' in dir(tempfile):
cachedir = tempfile.mkdtemp(prefix=prefix, dir=tmpdir)
else:
tempfile.tempdir = tmpdir
tempfile.template = prefix
cachedir = tempfile.mktemp()
try:
os.mkdir(cachedir,0700)
except:
cachedir = None
return cachedir
def addOwner(list, pkg):
if list.has_key(pkg):
return True
f = getOwner(pkg)
if f:
list[pkg] = f
return True
return False
def getSrcPkg(pkg):
srpm = pkg.returnSimple('sourcerpm')
if not srpm:
return None
srcpkg = string.join(srpm.split('-')[:-2],'-')
return srcpkg
def printableReq(pkg, dep):
(n, f, v) = dep
req = '%s' % n
if f:
flag = LETTERFLAGS[f]
req = '%s %s' % (req, flag)
if v:
req = '%s %s' % (req, v)
return "%s requires %s" % (pkg, req,)
def assignBlame(resolver, dep, guilty):
# Given a dep, find potential responsible parties
list = []
# The dep itself
if addOwner(guilty, dep):
list.append(dep)
# Something that provides the dep
try:
sack = resolver.whatProvides(dep, None, None)
for package in sack.returnPackages():
p = getSrcPkg(package)
if addOwner(guilty, p):
list.append(p)
except yum.Errors.RepoError, e:
pass
# Libraries: check for variant in soname
if re.match("lib*\.so\.[0-9]+",dep):
new = re.sub("(lib.*\.so\.)([0-9])+",libmunge,1)
try:
sack = resolver.whatProvides(new, None, None)
for package in sack.returnPackages():
p = getSrcPkg(package)
if addOwner(guilty, p):
list.append(p)
except yum.Errors.RepoError, e:
pass
return list
def generateSpam(pkgname, sendmail = True):
package = deps[pkgname]
guilty = owners[pkgname]
conspirators = []
for s in package.keys():
subpackage = package[s]
for arch in subpackage.keys():
brokendeps = subpackage[arch]
for dep in brokendeps:
for blame in dep[2]:
party = owners[blame]
if party != guilty and party not in conspirators:
conspirators.append(party)
foo = """
%s has broken dependencies in the development tree:
""" % (pkgname,)
for s in package.keys():
subpackage = package[s]
for arch in subpackage.keys():
foo = foo + "On %s:\n" % (arch)
brokendeps = subpackage[arch]
for dep in brokendeps:
foo = foo + "\t%s\n" % printableReq(dep[0],dep[1])
foo = foo + "Please resolve this as soon as possible.\n\n"
command = '/bin/mail -s "Broken dependencies: %s" %s' % (pkgname, guilty)
if conspirators:
command = command + " -c %s" % (string.join(conspirators,","),)
if sendmail:
mailer = os.popen(command, 'w')
mailer.write(foo)
mailer.close()
else:
print """
To: %s
Cc: %s
Subject: Broken dependencies: %s
""" % (guilty, string.join(conspirators,','), pkgname)
print foo
def doit(args):
conffile = generateConfig(args[0])
mail = True
if len(args) > 1:
mail = False
cachedir = getCacheDir()
for arch in arches:
if arch == 'i386':
carch = 'i686'
else:
carch = arch
repoid = 'development-%s' % (arch,)
my = repoclosure.RepoClosure(config = conffile, arch = carch)
for repo in my.repos.repos.values():
repo.cachedir = '%s/%s' % (cachedir,repo.id)
repo.hdrdir = '%s/%s/headers' % (cachedir, repo.id)
repo.pkgdir = '%s/%s/packages' % (cachedir, repo.id)
if repo.id != repoid:
repo.disable()
else:
repo.enable()
my.readMetadata()
baddeps = my.getBrokenDeps()
pkgs = baddeps.keys()
pkgs.sort()
if len(pkgs) > 0:
print "Broken deps for %s" % (arch,)
print "----------------------------------------------------------"
for pkg in pkgs:
srcpkg = getSrcPkg(pkg)
addOwner(owners, srcpkg)
if not deps.has_key(srcpkg):
deps[srcpkg] = {}
pkgid = pkg.returnNevraPrintable()
if not deps[srcpkg].has_key(pkgid):
deps[srcpkg][pkgid] = {}
broken = []
for (n, f, v) in baddeps[pkg]:
print "\t%s" % printableReq(pkg, (n, f, v))
blamelist = assignBlame(my, n, owners)
broken.append( (pkg, (n, f, v), blamelist) )
deps[srcpkg][pkgid][arch] = broken
print "\n\n"
pkglist = deps.keys()
for pkg in pkglist:
generateSpam(pkg, mail)
os.unlink(conffile)
if __name__ == '__main__':
if len(sys.argv) > 1:
doit(sys.argv[1:])
else:
print "usage: spam-o-matic <directory>"
More information about the Fedora-maintainers
mailing list