X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=daklib%2Fqueue.py;h=35b85a7de7c61a3d044bf3c59303eddd19682c08;hb=ce324ffde27b192a8e713b6e98368a3b00edaf27;hp=b11534a0592ac4b7e7f1f8316dbc8a13b7bae9a6;hpb=85569c95d888b1ad94338f2326faabf6e22bcd8a;p=dak.git diff --git a/daklib/queue.py b/daklib/queue.py index b11534a0..35b85a7d 100755 --- a/daklib/queue.py +++ b/daklib/queue.py @@ -38,8 +38,12 @@ import apt_pkg import utils import commands import shutil +import textwrap +import tempfile from types import * +import yaml + from dak_exceptions import * from changes import * from regexes import * @@ -687,11 +691,12 @@ class Upload(object): # Check the version and for file overwrites self.check_binary_against_db(f, session) - b = Binary(f) - b.scan_package() - if len(b.rejects) > 0: - for j in b.rejects: - self.rejects.append(j) + # Temporarily disable contents generation until we change the table storage layout + #b = Binary(f) + #b.scan_package() + #if len(b.rejects) > 0: + # for j in b.rejects: + # self.rejects.append(j) def source_file_checks(self, f, session): entry = self.pkg.files[f] @@ -1202,6 +1207,81 @@ class Upload(object): self.ensure_hashes() + ########################################################################### + def check_lintian(self): + cnf = Config() + tagfile = cnf("Dinstall::LintianTags") + # Parse the yaml file + sourcefile = file(tagfile, 'r') + sourcecontent = sourcefile.read() + sourcefile.close() + try: + lintiantags = yaml.load(sourcecontent)['lintian'] + except yaml.YAMLError, msg: + utils.fubar("Can not read the lintian tags file %s, YAML error: %s." % (tagfile, msg)) + return + + # Now setup the input file for lintian. lintian wants "one tag per line" only, + # so put it together like it. We put all types of tags in one file and then sort + # through lintians output later to see if its a fatal tag we detected, or not. + # So we only run lintian once on all tags, even if we might reject on some, but not + # reject on others. + # Additionally build up a set of tags + tags = set() + (fd, temp_filename) = utils.temp_filename() + temptagfile = os.fdopen(fd, 'w') + for tagtype in lintiantags: + for tag in lintiantags[tagtype]: + temptagfile.write(tag) + tags.add(tag) + temptagfile.close() + + # So now we should look at running lintian at the .changes file, capturing output + # to then parse it. + command = "lintian --show-overrides --tags-from-file %s %s" % (temp_filename, self.pkg.changes_file) + (result, output) = commands.getstatusoutput(cmd) + # We are done with lintian, remove our tempfile + os.unlink(temp_filename) + if (result != 0): + self.rejects.append("lintian failed for %s [return code: %s]." % (self.pkg.changes_file, result)) + self.rejects.append(utils.prefix_multi_line_string(output, " [possible output:] "), "") + return + + if len(output) == 0: + return + + # We have output of lintian, this package isn't clean. Lets parse it and see if we + # are having a victim for a reject. + # W: tzdata: binary-without-manpage usr/sbin/tzconfig + for line in output.split('\n'): + m = re_parse_lintian.match(line) + if m is None: + continue + + etype = m.group(1) + epackage = m.group(2) + etag = m.group(3) + etext = m.group(4) + + # So lets check if we know the tag at all. + if etag not in tags: + continue + + if etype == 'O': + # We know it and it is overriden. Check that override is allowed. + if lintiantags['warning'][etag]: + # The tag is overriden, and it is allowed to be overriden. + # Don't add a reject message. + elif lintiantags['error'][etag]: + # The tag is overriden - but is not allowed to be + self.rejects.append("%s: Overriden tag %s found, but this tag may not be overwritten." % (epackage, etag)) + else: + # Tag is known, it is not overriden, direct reject. + self.rejects.append("%s: Found lintian output: '%s %s', automatically rejected package." % (epackage, etag, etext)) + # Now tell if they *might* override it. + if lintiantags['wayout'][etag]: + self.rejects.append("%s: If you have a good reason, you may override this lintian tag. Laziness to fix your crap is NOT A GOOD REASON, sod off" % (epackage)) + ########################################################################### def check_urgency(self): cnf = Config() @@ -1263,11 +1343,85 @@ class Upload(object): except: self.rejects.append("%s: deb contents timestamp check failed [%s: %s]" % (filename, sys.exc_type, sys.exc_value)) + ########################################################################### + def check_transition(self, session): + cnf = Config() + + sourcepkg = self.pkg.changes["source"] + + # No sourceful upload -> no need to do anything else, direct return + # We also work with unstable uploads, not experimental or those going to some + # proposed-updates queue + if "source" not in self.pkg.changes["architecture"] or \ + "unstable" not in self.pkg.changes["distribution"]: + return + + # Also only check if there is a file defined (and existant) with + # checks. + transpath = cnf.get("Dinstall::Reject::ReleaseTransitions", "") + if transpath == "" or not os.path.exists(transpath): + return + + # Parse the yaml file + sourcefile = file(transpath, 'r') + sourcecontent = sourcefile.read() + try: + transitions = yaml.load(sourcecontent) + except yaml.YAMLError, msg: + # This shouldn't happen, there is a wrapper to edit the file which + # checks it, but we prefer to be safe than ending up rejecting + # everything. + utils.warn("Not checking transitions, the transitions file is broken: %s." % (msg)) + return + + # Now look through all defined transitions + for trans in transitions: + t = transitions[trans] + source = t["source"] + expected = t["new"] + + # Will be None if nothing is in testing. + current = get_source_in_suite(source, "testing", session) + if current is not None: + compare = apt_pkg.VersionCompare(current.version, expected) + + if current is None or compare < 0: + # This is still valid, the current version in testing is older than + # the new version we wait for, or there is none in testing yet + + # Check if the source we look at is affected by this. + if sourcepkg in t['packages']: + # The source is affected, lets reject it. + + rejectmsg = "%s: part of the %s transition.\n\n" % ( + sourcepkg, trans) + + if current is not None: + currentlymsg = "at version %s" % (current.version) + else: + currentlymsg = "not present in testing" + + rejectmsg += "Transition description: %s\n\n" % (t["reason"]) + + rejectmsg += "\n".join(textwrap.wrap("""Your package +is part of a testing transition designed to get %s migrated (it is +currently %s, we need version %s). This transition is managed by the +Release Team, and %s is the Release-Team member responsible for it. +Please mail debian-release@lists.debian.org or contact %s directly if you +need further assistance. You might want to upload to experimental until this +transition is done.""" + % (source, currentlymsg, expected,t["rm"], t["rm"]))) + + self.rejects.append(rejectmsg) + return + ########################################################################### def check_signed_by_key(self): """Ensure the .changes is signed by an authorized uploader.""" session = DBConn().session() + self.check_transition(session) + (uid, uid_name, is_dm) = lookup_uid_from_fingerprint(self.pkg.changes["fingerprint"], session=session) # match claimed name with actual name: @@ -1397,6 +1551,7 @@ class Upload(object): for bug in bugs: summary += "%s " % (bug) if action: + self.update_subst() self.Subst["__BUG_NUMBER__"] = bug if self.pkg.changes["distribution"].has_key("stable"): self.Subst["__STABLE_WARNING__"] = """ @@ -1407,8 +1562,8 @@ The update will eventually make its way into the next released Debian distribution.""" else: self.Subst["__STABLE_WARNING__"] = "" - mail_message = utils.TemplateSubst(self.Subst, template) - utils.send_mail(mail_message) + mail_message = utils.TemplateSubst(self.Subst, template) + utils.send_mail(mail_message) # Clear up after ourselves del self.Subst["__BUG_NUMBER__"] @@ -1460,6 +1615,7 @@ distribution.""" summary += "Announcing to %s\n" % (announce_list) if action: + self.update_subst() self.Subst["__ANNOUNCE_LIST_ADDRESS__"] = announce_list if cnf.get("Dinstall::TrackingServer") and \ self.pkg.changes["architecture"].has_key("source"): @@ -1524,6 +1680,7 @@ distribution.""" # Send accept mail, announce to lists, close bugs and check for # override disparities if not cnf["Dinstall::Options::No-Mail"]: + self.update_subst() self.Subst["__SUITE__"] = "" self.Subst["__SUMMARY__"] = summary mail_message = utils.TemplateSubst(self.Subst, accepttemplate) @@ -1609,6 +1766,7 @@ distribution.""" overridetemplate = os.path.join(cnf["Dir::Templates"], 'process-unchecked.override-disparity') + self.update_subst() self.Subst["__SUMMARY__"] = summary mail_message = utils.TemplateSubst(self.Subst, overridetemplate) utils.send_mail(mail_message) @@ -1755,6 +1913,7 @@ distribution.""" rej_template = os.path.join(cnf["Dir::Templates"], "queue.rejected") + self.update_subst() if not manual: self.Subst["__REJECTOR_ADDRESS__"] = cnf["Dinstall::MyEmailAddress"] self.Subst["__MANUAL_REJECT_MESSAGE__"] = "" @@ -2166,6 +2325,7 @@ distribution.""" def do_unaccept(self): cnf = Config() + self.update_subst() self.Subst["__REJECTOR_ADDRESS__"] = cnf["Dinstall::MyEmailAddress"] self.Subst["__REJECT_MESSAGE__"] = self.package_info() self.Subst["__CC__"] = "Cc: " + cnf["Dinstall::MyEmailAddress"]