Implemented output stuff and half of the hints processing.

bzr-import-20160707
Fabio Tranchitella 19 years ago
parent 90768aa4e3
commit 04e735af4b

@ -1,3 +1,4 @@
# Unsatisfable dependencies are not valid candidates, please drop them from upgrade_me (waiting reply from aba) # Unsatisfable dependencies are not valid candidates, please drop them from upgrade_me (waiting reply from aba)
# Add support for old libraries (introducing a new operation: remove single binary) # Add support for old libraries (introducing a new operation: remove single binary)
# Add support for udeb # Add support for udeb
# Add support for writing out the Packages_* and Sources files.

@ -244,6 +244,7 @@ class Britney:
self.hints = self.read_hints(self.options.unstable) self.hints = self.read_hints(self.options.unstable)
self.excuses = [] self.excuses = []
self.dependencies = {} self.dependencies = {}
self.selected = []
def __parse_arguments(self): def __parse_arguments(self):
"""Parse the command line arguments """Parse the command line arguments
@ -377,7 +378,7 @@ class Britney:
'rdepends': [], 'rdepends': [],
'rconflicts': [], 'rconflicts': [],
} }
for k in ('Pre-Depends', 'Depends', 'Provides', 'Conflicts'): for k in ('Pre-Depends', 'Depends', 'Provides', 'Conflicts', 'Section'):
v = get_field(k) v = get_field(k)
if v: dpkg[k.lower()] = v if v: dpkg[k.lower()] = v
@ -483,6 +484,20 @@ class Britney:
self.__log("Bugs, unable to parse \"%s\"" % line, type="E") self.__log("Bugs, unable to parse \"%s\"" % line, type="E")
return bugs return bugs
def write_bugs(self, basedir, bugs):
"""Write the release critical bug summary to the specified directory
For a more detailed explanation of the format, please check the method
read_bugs.
"""
filename = os.path.join(basedir, "Bugs")
self.__log("Writing RC bugs count to %s" % filename)
f = open(filename, 'w')
for pkg in sorted(bugs.keys()):
if bugs[pkg] == 0: continue
f.write("%s %d\n" % (pkg, bugs[pkg]))
f.close()
def __maxver(self, pkg, dist): def __maxver(self, pkg, dist):
"""Return the maximum version for a given package name """Return the maximum version for a given package name
@ -562,6 +577,20 @@ class Britney:
self.__log("Dates, unable to parse \"%s\"" % line, type="E") self.__log("Dates, unable to parse \"%s\"" % line, type="E")
return dates return dates
def write_dates(self, basedir, dates):
"""Write the upload date for the packages to the specified directory
For a more detailed explanation of the format, please check the method
read_dates.
"""
filename = os.path.join(basedir, "Dates")
self.__log("Writing upload data to %s" % filename)
f = open(filename, 'w')
for pkg in sorted(dates.keys()):
f.write("%s %s %d\n" % ((pkg,) + dates[pkg]))
f.close()
def read_urgencies(self, basedir): def read_urgencies(self, basedir):
"""Read the upload urgency of the packages from the specified directory """Read the upload urgency of the packages from the specified directory
@ -680,6 +709,42 @@ class Britney:
return hints return hints
def write_heidi(self, basedir, filename):
"""Write the output HeidiResult
This method write the output for Heidi, which contains all the
binary packages and the source packages in the form:
<pkg-name> <pkg-version> <pkg-architecture> <pkg-section>
<src-name> <src-version> <src-section>
"""
filename = os.path.join(basedir, filename)
self.__log("Writing Heidi results to %s" % filename)
f = open(filename, 'w')
# local copies
sources = self.sources['testing']
# write binary packages
for arch in sorted(self.options.architectures):
binaries = self.binaries['testing'][arch][0]
for pkg_name in sorted(binaries):
pkg = binaries[pkg_name]
pkgv = pkg['version']
pkgarch = pkg['architecture']
pkgsec = pkg.get('section', 'unknown')
f.write('%s %s %s %s\n' % (pkg_name, pkgv, pkgarch, pkgsec))
# write sources
for src_name in sorted(sources):
src = sources[src_name]
srcv = src['version']
srcsec = 'fake' in src and 'faux' or src.get('section', 'unknown')
f.write('%s %s source %s\n' % (src_name, srcv, srcsec))
f.close()
# Utility methods for package analisys # Utility methods for package analisys
# ------------------------------------ # ------------------------------------
@ -1790,7 +1855,7 @@ class Britney:
n = l n = l
return packages return packages
def iter_packages(self, packages, output): def iter_packages(self, packages):
"""Iter on the list of actions and apply them one-by-one """Iter on the list of actions and apply them one-by-one
This method apply the changes from `packages` to testing, checking the uninstallability This method apply the changes from `packages` to testing, checking the uninstallability
@ -1817,7 +1882,7 @@ class Britney:
dependencies = self.dependencies dependencies = self.dependencies
compatible = self.options.compatible compatible = self.options.compatible
output.write("recur: [%s] %s %d/%d\n" % (",".join(self.selected), "", len(packages), len(extra))) self.output_write("recur: [%s] %s %d/%d\n" % (",".join(self.selected), "", len(packages), len(extra)))
# loop on the packages (or better, actions) # loop on the packages (or better, actions)
while packages: while packages:
@ -1842,7 +1907,7 @@ class Britney:
break break
if defer: continue if defer: continue
output.write("trying: %s\n" % (pkg)) self.output_write("trying: %s\n" % (pkg))
better = True better = True
nuninst = {} nuninst = {}
@ -1911,20 +1976,20 @@ class Britney:
self.selected.append(pkg) self.selected.append(pkg)
packages.extend(extra) packages.extend(extra)
extra = [] extra = []
output.write("accepted: %s\n" % (pkg)) self.output_write("accepted: %s\n" % (pkg))
output.write(" ori: %s\n" % (self.eval_nuninst(self.nuninst_orig))) self.output_write(" ori: %s\n" % (self.eval_nuninst(self.nuninst_orig)))
output.write(" pre: %s\n" % (self.eval_nuninst(nuninst_comp))) self.output_write(" pre: %s\n" % (self.eval_nuninst(nuninst_comp)))
output.write(" now: %s\n" % (self.eval_nuninst(nuninst))) self.output_write(" now: %s\n" % (self.eval_nuninst(nuninst)))
if len(self.selected) <= 20: if len(self.selected) <= 20:
output.write(" all: %s\n" % (" ".join(self.selected))) self.output_write(" all: %s\n" % (" ".join(self.selected)))
else: else:
output.write(" most: (%d) .. %s\n" % (len(self.selected), " ".join(self.selected[-20:]))) self.output_write(" most: (%d) .. %s\n" % (len(self.selected), " ".join(self.selected[-20:])))
for k in nuninst: for k in nuninst:
nuninst_comp[k] = nuninst[k] nuninst_comp[k] = nuninst[k]
else: else:
output.write("skipped: %s (%d <- %d)\n" % (pkg, len(extra), len(packages))) self.output_write("skipped: %s (%d <- %d)\n" % (pkg, len(extra), len(packages)))
output.write(" got: %s\n" % (self.eval_nuninst(nuninst, "/" in pkg and nuninst_comp or None))) self.output_write(" got: %s\n" % (self.eval_nuninst(nuninst, "/" in pkg and nuninst_comp or None)))
output.write(" * %s: %s\n" % (arch, ", ".join(sorted([b for b in broken if b not in nuninst_comp[arch]])))) self.output_write(" * %s: %s\n" % (arch, ", ".join(sorted([b for b in broken if b not in nuninst_comp[arch]]))))
extra.append(pkg) extra.append(pkg)
if not mark_passed: if not mark_passed:
@ -1959,16 +2024,16 @@ class Britney:
del binaries[arch][1][j[1:]] del binaries[arch][1][j[1:]]
else: binaries[arch][1][j] = undo['virtual'][p] else: binaries[arch][1][j] = undo['virtual'][p]
output.write(" finish: [%s]\n" % ",".join(self.selected)) self.output_write(" finish: [%s]\n" % ",".join(self.selected))
output.write("endloop: %s\n" % (self.eval_nuninst(self.nuninst_orig))) self.output_write("endloop: %s\n" % (self.eval_nuninst(self.nuninst_orig)))
output.write(" now: %s\n" % (self.eval_nuninst(nuninst_comp))) self.output_write(" now: %s\n" % (self.eval_nuninst(nuninst_comp)))
output.write(self.eval_uninst(self.newlyuninst(self.nuninst_orig, nuninst_comp))) self.output_write(self.eval_uninst(self.newlyuninst(self.nuninst_orig, nuninst_comp)))
output.write("\n") self.output_write("\n")
output.write("Apparently successful\n") self.output_write("Apparently successful\n")
return (nuninst_comp, extra) return (nuninst_comp, extra)
def do_all(self, output, maxdepth=0, init=None): def do_all(self, maxdepth=0, init=None):
"""Testing update runner """Testing update runner
This method tries to update testing checking the uninstallability This method tries to update testing checking the uninstallability
@ -1977,38 +2042,122 @@ class Britney:
""" """
self.__log("> Calculating current uninstallability counters", type="I") self.__log("> Calculating current uninstallability counters", type="I")
nuninst_start = self.get_nuninst() nuninst_start = self.get_nuninst()
output.write("start: %s\n" % self.eval_nuninst(nuninst_start))
output.write("orig: %s\n" % self.eval_nuninst(nuninst_start))
self.__log("> First loop on the packages with depth = 0", type="I") # these are special parameters for hints processing
self.selected = [] force = False
earlyabort = False
if maxdepth == "easy" or maxdepth == 0:
force = maxdepth < 0
earlyabort = True
maxdepth = 0
# if we have a list of initial packages, check them
if init:
self.output_write("leading: %s\n" % (",".join(init)))
for x in init:
if x not in self.upgrade_me:
self.output_write("failed: %s\n" % (x))
return None
self.doop_source(x)
self.selected.append(x)
self.nuninst_orig = nuninst_start self.nuninst_orig = nuninst_start
(nuninst_end, extra) = self.iter_packages(self.upgrade_me[:], output)
if earlyabort:
nuninst_end = self.get_nuninst()
self.output_write("easy: %s\n" % (self.eval_nuninst(nuninst_end)))
self.output_write(self.eval_uninst(self.newlyuninst(nuninst_start, nuninst_end)) + "\n")
extra = self.upgrade_me[:]
else:
self.__log("> First loop on the packages with depth = 0", type="I")
(nuninst_end, extra) = self.iter_packages(self.upgrade_me[:])
if nuninst_end: if nuninst_end:
output.write("final: %s\n" % ",".join(sorted(self.selected))) self.output_write("final: %s\n" % ",".join(sorted(self.selected)))
output.write("start: %s\n" % self.eval_nuninst(nuninst_start)) self.output_write("start: %s\n" % self.eval_nuninst(nuninst_start))
output.write(" orig: %s\n" % self.eval_nuninst(self.nuninst_orig)) self.output_write(" orig: %s\n" % self.eval_nuninst(self.nuninst_orig))
output.write(" end: %s\n" % self.eval_nuninst(nuninst_end)) self.output_write(" end: %s\n" % self.eval_nuninst(nuninst_end))
output.write("SUCCESS (%d/%d)\n" % (len(self.upgrade_me), len(extra))) self.output_write("SUCCESS (%d/%d)\n" % (len(self.upgrade_me), len(extra)))
def upgrade_testing(self): def upgrade_testing(self):
"""Upgrade testing using the unstable packages """Upgrade testing using the unstable packages
This method tries to upgrade testing using the packages from unstable. This method tries to upgrade testing using the packages from unstable.
Before running the do_all method, it tries the easy and force-hint
commands.
""" """
self.__log("Starting the upgrade test", type="I") self.__log("Starting the upgrade test", type="I")
output = open(self.options.upgrade_output, 'w') self.__output = open(self.options.upgrade_output, 'w')
output.write("Generated on: %s\n" % (time.strftime("%Y.%m.%d %H:%M:%S %z", time.gmtime(time.time())))) self.output_write("Generated on: %s\n" % (time.strftime("%Y.%m.%d %H:%M:%S %z", time.gmtime(time.time()))))
output.write("Arch order is: %s\n" % ", ".join(self.options.architectures)) self.output_write("Arch order is: %s\n" % ", ".join(self.options.architectures))
# process `easy' hints
self.hints['easy'].append(('kobold', [('a2ps', '1:4.13b-5'), ('adeos', '20050809-1')]))
for x in self.hints['easy']:
self.do_hint("easy", x[0], x[1])
# process `easy' hints
for x in self.hints["force-hint"]:
self.do_hint("force-hint", x[0], x[1])
# TODO: process hints! # run the first round of the upgrade
self.do_all(output) # FIXME: self.do_all()
output.close() # write bugs and dates
# FIXME: self.write_bugs(self.options.testing, self.bugs['testing'])
# FIXME: self.write_dates(self.options.testing, self.dates)
# write HeidiResult
# FIXME: self.write_heidi(self.options.testing, 'HeidiResult')
self.__output.close()
self.__log("Test completed!", type="I") self.__log("Test completed!", type="I")
def do_hint(self, type, who, pkgvers):
"""Process hints
This method process `easy`, `hint` and `force-hint` hints. If the
requested version is not in unstable, than the hint is skipped.
"""
hintinfo = {"easy": "easy",
"hint": 0,
"force-hint": -1,}
self.output_write("Trying %s from %s: %s\n" % (type, who, " ".join( ["%s/%s" % (p,v) for (p,v) in pkgvers])))
ok = True
# loop on the requested packages and versions
for pkg, v in pkgvers:
# remove architecture
if "/" in pkg:
pkg = pkg[:pkg.find("/")]
# skip removal requests
if pkg[0] == "-":
continue
# handle testing-proposed-updates
elif pkg.endswith("_tpu"):
pkg = pkg[:-4]
if pkg not in self.sources['tpu']: continue
if apt_pkg.VersionCompare(self.sources['tpu'][pkg]['version'], v) != 0:
self.output_write(" Version mismatch, %s %s != %s\n" % (pkg, v, self.sources['tpu'][pkg]['version']))
ok = False
# does the package exist in unstable?
elif pkg not in self.sources['unstable']:
self.output_write(" Source %s has no version in unstable\n" % pkg)
ok = False
elif apt_pkg.VersionCompare(self.sources['unstable'][pkg]['version'], v) != 0:
self.output_write(" Version mismatch, %s %s != %s\n" % (pkg, v, self.sources['unstable'][pkg]['version']))
ok = False
if not ok:
self.output_write("Not using hint\n")
return False
self.do_all(hintinfo[type], map(operator.itemgetter(0), pkgvers))
return True
def sort_actions(self): def sort_actions(self):
"""Sort actions in a smart way """Sort actions in a smart way
@ -2037,9 +2186,14 @@ class Britney:
upgrade_me.remove(e.name) upgrade_me.remove(e.name)
upgrade_me.insert(max(pos)+1, e.name) upgrade_me.insert(max(pos)+1, e.name)
self.dependencies[e.name] = e.deps self.dependencies[e.name] = e.deps
# replace the list of actions with the new one # replace the list of actions with the new one
self.upgrade_me = upgrade_me self.upgrade_me = upgrade_me
def output_write(self, msg):
"""Simple wrapper for output writing"""
self.__output.write(msg)
def main(self): def main(self):
"""Main method """Main method

Loading…
Cancel
Save