예제 #1
0
파일: queue_report.py 프로젝트: Debian/dak
def process_queue(queue, log, rrd_dir):
    msg = ""
    type = queue.queue_name
    session = DBConn().session()

    # Divide the .changes into per-source groups
    per_source = {}
    total_pending = 0
    for upload in queue.uploads:
        source = upload.changes.source
        if source not in per_source:
            per_source[source] = {}
            per_source[source]["list"] = []
            per_source[source]["processed"] = ""
            handler = PolicyQueueUploadHandler(upload, session)
            if handler.get_action():
                per_source[source]["processed"] = "PENDING %s" % handler.get_action()
                total_pending += 1
        per_source[source]["list"].append(upload)
        per_source[source]["list"].sort(key=lambda x: x.changes.created, reverse=True)
    # Determine oldest time and have note status for each source group
    for source in per_source.keys():
        source_list = per_source[source]["list"]
        first = source_list[0]
        oldest = time.mktime(first.changes.created.timetuple())
        have_note = 0
        for d in per_source[source]["list"]:
            mtime = time.mktime(d.changes.created.timetuple())
            if "Queue-Report::Options::New" in Cnf:
                if mtime > oldest:
                    oldest = mtime
            else:
                if mtime < oldest:
                    oldest = mtime
            have_note += has_new_comment(d.policy_queue, d.changes.source, d.changes.version)
        per_source[source]["oldest"] = oldest
        if not have_note:
            per_source[source]["note_state"] = 0 # none
        elif have_note < len(source_list):
            per_source[source]["note_state"] = 1 # some
        else:
            per_source[source]["note_state"] = 2 # all
    per_source_items = per_source.items()
    per_source_items.sort(key=functools.cmp_to_key(sg_compare))

    update_graph_database(rrd_dir, type, len(per_source_items), len(queue.uploads))

    entries = []
    max_source_len = 0
    max_version_len = 0
    max_arch_len = 0
    try:
        logins = get_logins_from_ldap()
    except:
        logins = dict()
    for i in per_source_items:
        maintainer = {}
        maint = ""
        distribution = ""
        closes = ""
        fingerprint = ""
        changeby = {}
        changedby = ""
        sponsor = ""
        filename = i[1]["list"][0].changes.changesname
        last_modified = time.time() - i[1]["oldest"]
        source = i[1]["list"][0].changes.source
        if len(source) > max_source_len:
            max_source_len = len(source)
        binary_list = i[1]["list"][0].binaries
        binary = ', '.join([b.package for b in binary_list])
        arches = set()
        versions = set()
        for j in i[1]["list"]:
            dbc = j.changes
            changesbase = dbc.changesname

            if "Queue-Report::Options::New" in Cnf or "Queue-Report::Options::822" in Cnf:
                try:
                    (maintainer["maintainer822"], maintainer["maintainer2047"],
                    maintainer["maintainername"], maintainer["maintaineremail"]) = \
                    fix_maintainer(dbc.maintainer)
                except ParseMaintError as msg:
                    print("Problems while parsing maintainer address\n")
                    maintainer["maintainername"] = "Unknown"
                    maintainer["maintaineremail"] = "Unknown"
                maint = "%s:%s" % (maintainer["maintainername"], maintainer["maintaineremail"])
                # ...likewise for the Changed-By: field if it exists.
                try:
                    (changeby["changedby822"], changeby["changedby2047"],
                     changeby["changedbyname"], changeby["changedbyemail"]) = \
                        fix_maintainer(dbc.changedby)
                except ParseMaintError as msg:
                    (changeby["changedby822"], changeby["changedby2047"],
                     changeby["changedbyname"], changeby["changedbyemail"]) = \
                        ("", "", "", "")
                changedby = "%s:%s" % (changeby["changedbyname"], changeby["changedbyemail"])

                distribution = dbc.distribution.split()
                closes = dbc.closes

                fingerprint = dbc.fingerprint
                sponsor_name = get_uid_from_fingerprint(fingerprint).name
                sponsor_login = get_uid_from_fingerprint(fingerprint).uid
                if '@' in sponsor_login:
                    if fingerprint in logins:
                        sponsor_login = logins[fingerprint]
                if (sponsor_name != maintainer["maintainername"]
                  and sponsor_name != changeby["changedbyname"]
                  and sponsor_login + '@debian.org' != maintainer["maintaineremail"]
                  and sponsor_name != changeby["changedbyemail"]):
                    sponsor = sponsor_login

            for arch in dbc.architecture.split():
                arches.add(arch)
            versions.add(dbc.version)
        arches_list = list(arches)
        arches_list.sort(key=utils.ArchKey)
        arch_list = " ".join(arches_list)
        version_list = " ".join(sorted(versions, reverse=True))
        if len(version_list) > max_version_len:
            max_version_len = len(version_list)
        if len(arch_list) > max_arch_len:
            max_arch_len = len(arch_list)
        if i[1]["note_state"]:
            note = " | [N]"
        else:
            note = ""
        entries.append([source, binary, version_list, arch_list, per_source[source]["processed"], note, last_modified, maint, distribution, closes, fingerprint, sponsor, changedby, filename])

    # direction entry consists of "Which field, which direction, time-consider" where
    # time-consider says how we should treat last_modified. Thats all.

    # Look for the options for sort and then do the sort.
    age = "h"
    if "Queue-Report::Options::Age" in Cnf:
        age = Cnf["Queue-Report::Options::Age"]
    if "Queue-Report::Options::New" in Cnf:
        # If we produce html we always have oldest first.
        direction.append([6, -1, "ao"])
    else:
        if "Queue-Report::Options::Sort" in Cnf:
            for i in Cnf["Queue-Report::Options::Sort"].split(","):
                if i == "ao":
                    # Age, oldest first.
                    direction.append([6, -1, age])
                elif i == "an":
                    # Age, newest first.
                    direction.append([6, 1, age])
                elif i == "na":
                    # Name, Ascending.
                    direction.append([0, 1, 0])
                elif i == "nd":
                    # Name, Descending.
                    direction.append([0, -1, 0])
                elif i == "nl":
                    # Notes last.
                    direction.append([5, 1, 0])
                elif i == "nf":
                    # Notes first.
                    direction.append([5, -1, 0])
    entries.sort(key=functools.cmp_to_key(sortfunc))
    # Yes, in theory you can add several sort options at the commandline with. But my mind is to small
    # at the moment to come up with a real good sorting function that considers all the sidesteps you
    # have with it. (If you combine options it will simply take the last one at the moment).
    # Will be enhanced in the future.

    if "Queue-Report::Options::822" in Cnf:
        # print stuff out in 822 format
        for entry in entries:
            (source, binary, version_list, arch_list, processed, note, last_modified, maint, distribution, closes, fingerprint, sponsor, changedby, changes_file) = entry

            # We'll always have Source, Version, Arch, Mantainer, and Dist
            # For the rest, check to see if we have them, then print them out
            log.write("Source: " + source + "\n")
            log.write("Binary: " + binary + "\n")
            log.write("Version: " + version_list + "\n")
            log.write("Architectures: ")
            log.write((", ".join(arch_list.split(" "))) + "\n")
            log.write("Age: " + time_pp(last_modified) + "\n")
            log.write("Last-Modified: " + str(int(time.time()) - int(last_modified)) + "\n")
            log.write("Queue: " + type + "\n")

            (name, mail) = maint.split(":", 1)
            log.write("Maintainer: " + name + " <" + mail + ">" + "\n")
            if changedby:
                (name, mail) = changedby.split(":", 1)
                log.write("Changed-By: " + name + " <" + mail + ">" + "\n")
            if sponsor:
                log.write("Sponsored-By: %[email protected]\n" % sponsor)
            log.write("Distribution:")
            for dist in distribution:
                log.write(" " + dist)
            log.write("\n")
            log.write("Fingerprint: " + fingerprint + "\n")
            if closes:
                bug_string = ""
                for bugs in closes:
                    bug_string += "#" + bugs + ", "
                log.write("Closes: " + bug_string[:-2] + "\n")
            log.write("Changes-File: " + os.path.basename(changes_file) + "\n")
            log.write("\n")

    total_count = len(queue.uploads)
    source_count = len(per_source_items)

    if "Queue-Report::Options::New" in Cnf:
        direction.append([6, 1, "ao"])
        entries.sort(key=functools.cmp_to_key(sortfunc))
        # Output for a html file. First table header. then table_footer.
        # Any line between them is then a <tr> printed from subroutine table_row.
        if len(entries) > 0:
            table_header(type.upper(), source_count, total_count)
            for entry in entries:
                (source, binary, version_list, arch_list, processed, note, last_modified, maint, distribution, closes, fingerprint, sponsor, changedby, _) = entry
                table_row(source, version_list, arch_list, last_modified, maint, distribution, closes, fingerprint, sponsor, changedby)
            table_footer(type.upper())
    elif "Queue-Report::Options::822" not in Cnf:
        # The "normal" output without any formatting.
        msg = ""
        for entry in entries:
            (source, binary, version_list, arch_list, processed, note, last_modified, _, _, _, _, _, _, _) = entry
            if processed:
                format = "%%-%ds | %%-%ds | %%-%ds | %%s\n" % (max_source_len, max_version_len, max_arch_len)
                msg += format % (source, version_list, arch_list, processed)
            else:
                format = "%%-%ds | %%-%ds | %%-%ds%%s | %%s old\n" % (max_source_len, max_version_len, max_arch_len)
                msg += format % (source, version_list, arch_list, note, time_pp(last_modified))

        if msg:
            print(type.upper())
            print("-" * len(type))
            print()
            print(msg)
            print(("%s %s source package%s / %s %s package%s in total / %s %s package%s to be processed." %
                   (source_count, type, plural(source_count),
                    total_count, type, plural(total_count),
                    total_pending, type, plural(total_pending))))
            print()
예제 #2
0
def process_queue(queue, log, rrd_dir):
    msg = ""
    type = queue.queue_name
    session = DBConn().session()

    # Divide the .changes into per-source groups
    per_source = {}
    total_pending = 0
    for upload in queue.uploads:
        source = upload.changes.source
        if source not in per_source:
            per_source[source] = {}
            per_source[source]["list"] = []
            per_source[source]["processed"] = ""
            handler = PolicyQueueUploadHandler(upload, session)
            if handler.get_action():
                per_source[source][
                    "processed"] = "PENDING %s" % handler.get_action()
                total_pending += 1
        per_source[source]["list"].append(upload)
        per_source[source]["list"].sort(key=lambda x: x.changes.created,
                                        reverse=True)
    # Determine oldest time and have note status for each source group
    for source in per_source.keys():
        source_list = per_source[source]["list"]
        first = source_list[0]
        oldest = time.mktime(first.changes.created.timetuple())
        have_note = 0
        for d in per_source[source]["list"]:
            mtime = time.mktime(d.changes.created.timetuple())
            if "Queue-Report::Options::New" in Cnf:
                if mtime > oldest:
                    oldest = mtime
            else:
                if mtime < oldest:
                    oldest = mtime
            have_note += has_new_comment(d.policy_queue, d.changes.source,
                                         d.changes.version)
        per_source[source]["oldest"] = oldest
        if not have_note:
            per_source[source]["note_state"] = 0  # none
        elif have_note < len(source_list):
            per_source[source]["note_state"] = 1  # some
        else:
            per_source[source]["note_state"] = 2  # all
    per_source_items = per_source.items()
    per_source_items.sort(key=functools.cmp_to_key(sg_compare))

    update_graph_database(rrd_dir, type, len(per_source_items),
                          len(queue.uploads))

    entries = []
    max_source_len = 0
    max_version_len = 0
    max_arch_len = 0
    try:
        logins = get_logins_from_ldap()
    except:
        logins = dict()
    for i in per_source_items:
        maintainer = {}
        maint = ""
        distribution = ""
        closes = ""
        fingerprint = ""
        changeby = {}
        changedby = ""
        sponsor = ""
        filename = i[1]["list"][0].changes.changesname
        last_modified = time.time() - i[1]["oldest"]
        source = i[1]["list"][0].changes.source
        if len(source) > max_source_len:
            max_source_len = len(source)
        binary_list = i[1]["list"][0].binaries
        binary = ', '.join([b.package for b in binary_list])
        arches = set()
        versions = set()
        for j in i[1]["list"]:
            dbc = j.changes
            changesbase = dbc.changesname

            if "Queue-Report::Options::New" in Cnf or "Queue-Report::Options::822" in Cnf:
                try:
                    (maintainer["maintainer822"], maintainer["maintainer2047"],
                    maintainer["maintainername"], maintainer["maintaineremail"]) = \
                    fix_maintainer(dbc.maintainer)
                except ParseMaintError as msg:
                    print("Problems while parsing maintainer address\n")
                    maintainer["maintainername"] = "Unknown"
                    maintainer["maintaineremail"] = "Unknown"
                maint = "%s:%s" % (maintainer["maintainername"],
                                   maintainer["maintaineremail"])
                # ...likewise for the Changed-By: field if it exists.
                try:
                    (changeby["changedby822"], changeby["changedby2047"],
                     changeby["changedbyname"], changeby["changedbyemail"]) = \
                        fix_maintainer(dbc.changedby)
                except ParseMaintError as msg:
                    (changeby["changedby822"], changeby["changedby2047"],
                     changeby["changedbyname"], changeby["changedbyemail"]) = \
                        ("", "", "", "")
                changedby = "%s:%s" % (changeby["changedbyname"],
                                       changeby["changedbyemail"])

                distribution = dbc.distribution.split()
                closes = dbc.closes

                fingerprint = dbc.fingerprint
                sponsor_name = get_uid_from_fingerprint(fingerprint).name
                sponsor_login = get_uid_from_fingerprint(fingerprint).uid
                if '@' in sponsor_login:
                    if fingerprint in logins:
                        sponsor_login = logins[fingerprint]
                if (sponsor_name != maintainer["maintainername"]
                        and sponsor_name != changeby["changedbyname"]
                        and sponsor_login + '@debian.org' !=
                        maintainer["maintaineremail"]
                        and sponsor_name != changeby["changedbyemail"]):
                    sponsor = sponsor_login

            for arch in dbc.architecture.split():
                arches.add(arch)
            versions.add(dbc.version)
        arches_list = sorted(arches, key=utils.ArchKey)
        arch_list = " ".join(arches_list)
        version_list = " ".join(sorted(versions, reverse=True))
        if len(version_list) > max_version_len:
            max_version_len = len(version_list)
        if len(arch_list) > max_arch_len:
            max_arch_len = len(arch_list)
        if i[1]["note_state"]:
            note = " | [N]"
        else:
            note = ""
        entries.append([
            source, binary, version_list, arch_list,
            per_source[source]["processed"], note, last_modified, maint,
            distribution, closes, fingerprint, sponsor, changedby, filename
        ])

    # direction entry consists of "Which field, which direction, time-consider" where
    # time-consider says how we should treat last_modified. Thats all.

    # Look for the options for sort and then do the sort.
    age = "h"
    if "Queue-Report::Options::Age" in Cnf:
        age = Cnf["Queue-Report::Options::Age"]
    if "Queue-Report::Options::New" in Cnf:
        # If we produce html we always have oldest first.
        direction.append([6, -1, "ao"])
    else:
        if "Queue-Report::Options::Sort" in Cnf:
            for i in Cnf["Queue-Report::Options::Sort"].split(","):
                if i == "ao":
                    # Age, oldest first.
                    direction.append([6, -1, age])
                elif i == "an":
                    # Age, newest first.
                    direction.append([6, 1, age])
                elif i == "na":
                    # Name, Ascending.
                    direction.append([0, 1, 0])
                elif i == "nd":
                    # Name, Descending.
                    direction.append([0, -1, 0])
                elif i == "nl":
                    # Notes last.
                    direction.append([5, 1, 0])
                elif i == "nf":
                    # Notes first.
                    direction.append([5, -1, 0])
    entries.sort(key=functools.cmp_to_key(sortfunc))
    # Yes, in theory you can add several sort options at the commandline with. But my mind is to small
    # at the moment to come up with a real good sorting function that considers all the sidesteps you
    # have with it. (If you combine options it will simply take the last one at the moment).
    # Will be enhanced in the future.

    if "Queue-Report::Options::822" in Cnf:
        # print stuff out in 822 format
        for entry in entries:
            (source, binary, version_list, arch_list, processed, note,
             last_modified, maint, distribution, closes, fingerprint, sponsor,
             changedby, changes_file) = entry

            # We'll always have Source, Version, Arch, Mantainer, and Dist
            # For the rest, check to see if we have them, then print them out
            log.write("Source: " + source + "\n")
            log.write("Binary: " + binary + "\n")
            log.write("Version: " + version_list + "\n")
            log.write("Architectures: ")
            log.write((", ".join(arch_list.split(" "))) + "\n")
            log.write("Age: " + time_pp(last_modified) + "\n")
            log.write("Last-Modified: " +
                      str(int(time.time()) - int(last_modified)) + "\n")
            log.write("Queue: " + type + "\n")

            (name, mail) = maint.split(":", 1)
            log.write("Maintainer: " + name + " <" + mail + ">" + "\n")
            if changedby:
                (name, mail) = changedby.split(":", 1)
                log.write("Changed-By: " + name + " <" + mail + ">" + "\n")
            if sponsor:
                log.write("Sponsored-By: %[email protected]\n" % sponsor)
            log.write("Distribution:")
            for dist in distribution:
                log.write(" " + dist)
            log.write("\n")
            log.write("Fingerprint: " + fingerprint + "\n")
            if closes:
                bug_string = ""
                for bugs in closes:
                    bug_string += "#" + bugs + ", "
                log.write("Closes: " + bug_string[:-2] + "\n")
            log.write("Changes-File: " + os.path.basename(changes_file) + "\n")
            log.write("\n")

    total_count = len(queue.uploads)
    source_count = len(per_source_items)

    if "Queue-Report::Options::New" in Cnf:
        direction.append([6, 1, "ao"])
        entries.sort(key=functools.cmp_to_key(sortfunc))
        # Output for a html file. First table header. then table_footer.
        # Any line between them is then a <tr> printed from subroutine table_row.
        if len(entries) > 0:
            table_header(type.upper(), source_count, total_count)
            for entry in entries:
                (source, binary, version_list, arch_list, processed, note,
                 last_modified, maint, distribution, closes, fingerprint,
                 sponsor, changedby, _) = entry
                table_row(source, version_list, arch_list, last_modified,
                          maint, distribution, closes, fingerprint, sponsor,
                          changedby)
            table_footer(type.upper())
    elif "Queue-Report::Options::822" not in Cnf:
        # The "normal" output without any formatting.
        msg = ""
        for entry in entries:
            (source, binary, version_list, arch_list, processed, note,
             last_modified, _, _, _, _, _, _, _) = entry
            if processed:
                format = "%%-%ds | %%-%ds | %%-%ds | %%s\n" % (
                    max_source_len, max_version_len, max_arch_len)
                msg += format % (source, version_list, arch_list, processed)
            else:
                format = "%%-%ds | %%-%ds | %%-%ds%%s | %%s old\n" % (
                    max_source_len, max_version_len, max_arch_len)
                msg += format % (source, version_list, arch_list, note,
                                 time_pp(last_modified))

        if msg:
            print(type.upper())
            print("-" * len(type))
            print()
            print(msg)
            print((
                "%s %s source package%s / %s %s package%s in total / %s %s package%s to be processed."
                % (source_count, type, plural(source_count), total_count, type,
                   plural(total_count), total_pending, type,
                   plural(total_pending))))
            print()
예제 #3
0
def process_changes_files(changes_files, type, log, rrd_dir):
    msg = ""
    cache = {}
    unprocessed = []
    # Read in all the .changes files
    for filename in changes_files:
        try:
            u = Upload()
            u.load_changes(filename)
            cache[filename] = copy(u.pkg.changes)
            cache[filename]["filename"] = filename
        except Exception as e:
            print "WARNING: Exception %s" % e
            continue
    # Divide the .changes into per-source groups
    per_source = {}
    for filename in cache.keys():
	if not cache[filename].has_key("source"):
            unprocessed.append(filename)
            continue
        source = cache[filename]["source"]
        if not per_source.has_key(source):
            per_source[source] = {}
            per_source[source]["list"] = []
        per_source[source]["list"].append(cache[filename])
    # Determine oldest time and have note status for each source group
    for source in per_source.keys():
        source_list = per_source[source]["list"]
        first = source_list[0]
        oldest = os.stat(first["filename"])[stat.ST_MTIME]
        have_note = 0
        for d in per_source[source]["list"]:
            mtime = os.stat(d["filename"])[stat.ST_MTIME]
            if Cnf.has_key("Queue-Report::Options::New"):
                if mtime > oldest:
                    oldest = mtime
            else:
                if mtime < oldest:
                    oldest = mtime
            have_note += has_new_comment(d["source"], d["version"])
        per_source[source]["oldest"] = oldest
        if not have_note:
            per_source[source]["note_state"] = 0; # none
        elif have_note < len(source_list):
            per_source[source]["note_state"] = 1; # some
        else:
            per_source[source]["note_state"] = 2; # all
    per_source_items = per_source.items()
    per_source_items.sort(sg_compare)

    update_graph_database(rrd_dir, type, len(per_source_items), len(changes_files))

    entries = []
    max_source_len = 0
    max_version_len = 0
    max_arch_len = 0
    for i in per_source_items:
        maintainer = {}
        maint=""
        distribution=""
        closes=""
        fingerprint=""
        changeby = {}
        changedby=""
        sponsor=""
        filename=i[1]["list"][0]["filename"]
        last_modified = time.time()-i[1]["oldest"]
        source = i[1]["list"][0]["source"]
        if len(source) > max_source_len:
            max_source_len = len(source)
        binary_list = i[1]["list"][0]["binary"].keys()
        binary = ', '.join(binary_list)
        arches = {}
        versions = {}
        for j in i[1]["list"]:
            changesbase = os.path.basename(j["filename"])
            try:
                session = DBConn().session()
                dbc = session.query(DBChange).filter_by(changesname=changesbase).one()
                session.close()
            except Exception as e:
                print "Can't find changes file in NEW for %s (%s)" % (changesbase, e)
                dbc = None

            if Cnf.has_key("Queue-Report::Options::New") or Cnf.has_key("Queue-Report::Options::822"):
                try:
                    (maintainer["maintainer822"], maintainer["maintainer2047"],
                    maintainer["maintainername"], maintainer["maintaineremail"]) = \
                    fix_maintainer (j["maintainer"])
                except ParseMaintError as msg:
                    print "Problems while parsing maintainer address\n"
                    maintainer["maintainername"] = "Unknown"
                    maintainer["maintaineremail"] = "Unknown"
                maint="%s:%s" % (maintainer["maintainername"], maintainer["maintaineremail"])
                # ...likewise for the Changed-By: field if it exists.
                try:
                    (changeby["changedby822"], changeby["changedby2047"],
                     changeby["changedbyname"], changeby["changedbyemail"]) = \
                     fix_maintainer (j["changed-by"])
                except ParseMaintError as msg:
                    (changeby["changedby822"], changeby["changedby2047"],
                     changeby["changedbyname"], changeby["changedbyemail"]) = \
                     ("", "", "", "")
                changedby="%s:%s" % (changeby["changedbyname"], changeby["changedbyemail"])

                distribution=j["distribution"].keys()
                closes=j["closes"].keys()
                if dbc:
                    fingerprint = dbc.fingerprint
                    sponsor_name = get_uid_from_fingerprint(fingerprint).name
                    sponsor_email = get_uid_from_fingerprint(fingerprint).uid + "@debian.org"
                    if sponsor_name != maintainer["maintainername"] and sponsor_name != changeby["changedbyname"] and \
                    sponsor_email != maintainer["maintaineremail"] and sponsor_name != changeby["changedbyemail"]:
                        sponsor = sponsor_email

            for arch in j["architecture"].keys():
                arches[arch] = ""
            version = j["version"]
            versions[version] = ""
        arches_list = arches.keys()
        arches_list.sort(utils.arch_compare_sw)
        arch_list = " ".join(arches_list)
        version_list = " ".join(versions.keys())
        if len(version_list) > max_version_len:
            max_version_len = len(version_list)
        if len(arch_list) > max_arch_len:
            max_arch_len = len(arch_list)
        if i[1]["note_state"]:
            note = " | [N]"
        else:
            note = ""
        entries.append([source, binary, version_list, arch_list, note, last_modified, maint, distribution, closes, fingerprint, sponsor, changedby, filename])

    # direction entry consists of "Which field, which direction, time-consider" where
    # time-consider says how we should treat last_modified. Thats all.

    # Look for the options for sort and then do the sort.
    age = "h"
    if Cnf.has_key("Queue-Report::Options::Age"):
        age =  Cnf["Queue-Report::Options::Age"]
    if Cnf.has_key("Queue-Report::Options::New"):
    # If we produce html we always have oldest first.
        direction.append([5,-1,"ao"])
    else:
        if Cnf.has_key("Queue-Report::Options::Sort"):
            for i in Cnf["Queue-Report::Options::Sort"].split(","):
                if i == "ao":
                    # Age, oldest first.
                    direction.append([5,-1,age])
                elif i == "an":
                    # Age, newest first.
                    direction.append([5,1,age])
                elif i == "na":
                    # Name, Ascending.
                    direction.append([0,1,0])
                elif i == "nd":
                    # Name, Descending.
                    direction.append([0,-1,0])
                elif i == "nl":
                    # Notes last.
                    direction.append([4,1,0])
                elif i == "nf":
                    # Notes first.
                    direction.append([4,-1,0])
    entries.sort(lambda x, y: sortfunc(x, y))
    # Yes, in theory you can add several sort options at the commandline with. But my mind is to small
    # at the moment to come up with a real good sorting function that considers all the sidesteps you
    # have with it. (If you combine options it will simply take the last one at the moment).
    # Will be enhanced in the future.

    if Cnf.has_key("Queue-Report::Options::822"):
        # print stuff out in 822 format
        for entry in entries:
            (source, binary, version_list, arch_list, note, last_modified, maint, distribution, closes, fingerprint, sponsor, changedby, changes_file) = entry

            # We'll always have Source, Version, Arch, Mantainer, and Dist
            # For the rest, check to see if we have them, then print them out
            log.write("Source: " + source + "\n")
            log.write("Binary: " + binary + "\n")
            log.write("Version: " + version_list + "\n")
            log.write("Architectures: ")
            log.write( (", ".join(arch_list.split(" "))) + "\n")
            log.write("Age: " + time_pp(last_modified) + "\n")
            log.write("Last-Modified: " + str(int(time.time()) - int(last_modified)) + "\n")
            log.write("Queue: " + type + "\n")

            (name, mail) = maint.split(":", 1)
            log.write("Maintainer: " + name + " <"+mail+">" + "\n")
            if changedby:
               (name, mail) = changedby.split(":", 1)
               log.write("Changed-By: " + name + " <"+mail+">" + "\n")
            if sponsor:
               log.write("Sponsored-By: " + "@".join(sponsor.split("@")[:2]) + "\n")
            log.write("Distribution:")
            for dist in distribution:
               log.write(" " + dist)
            log.write("\n")
            log.write("Fingerprint: " + fingerprint + "\n")
            if closes:
                bug_string = ""
                for bugs in closes:
                    bug_string += "#"+bugs+", "
                log.write("Closes: " + bug_string[:-2] + "\n")
            log.write("Changes-File: " + os.path.basename(changes_file) + "\n")
            log.write("\n")

    if Cnf.has_key("Queue-Report::Options::New"):
        direction.append([5,1,"ao"])
        entries.sort(lambda x, y: sortfunc(x, y))
    # Output for a html file. First table header. then table_footer.
    # Any line between them is then a <tr> printed from subroutine table_row.
        if len(entries) > 0:
            total_count = len(changes_files)
            source_count = len(per_source_items)
            table_header(type.upper(), source_count, total_count)
            for entry in entries:
                (source, binary, version_list, arch_list, note, last_modified, maint, distribution, closes, fingerprint, sponsor, changedby, undef) = entry
                table_row(source, version_list, arch_list, time_pp(last_modified), maint, distribution, closes, fingerprint, sponsor, changedby)
            table_footer(type.upper())
    elif not Cnf.has_key("Queue-Report::Options::822"):
    # The "normal" output without any formatting.
        format="%%-%ds | %%-%ds | %%-%ds%%s | %%s old\n" % (max_source_len, max_version_len, max_arch_len)

        msg = ""
        for entry in entries:
            (source, binary, version_list, arch_list, note, last_modified, undef, undef, undef, undef, undef, undef, undef) = entry
            msg += format % (source, version_list, arch_list, note, time_pp(last_modified))

        if msg:
            total_count = len(changes_files)
            source_count = len(per_source_items)
            print type.upper()
            print "-"*len(type)
            print
            print msg
            print "%s %s source package%s / %s %s package%s in total." % (source_count, type, plural(source_count), total_count, type, plural(total_count))
            print

        if len(unprocessed):
            print "UNPROCESSED"
            print "-----------"
            for u in unprocessed:
                print u
            print