X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=dak%2Fauto_decruft.py;h=66479a47fd863f155257a37c9d3bfdf61c9d7bdd;hb=98d086ddda3772fb58c1bfa97478e8044596b569;hp=e16850d61457e527e9d9846cb4923bbf8a97468d;hpb=18e076c10a1d176af81a717373e05a1cb0c511f8;p=dak.git diff --git a/dak/auto_decruft.py b/dak/auto_decruft.py index e16850d6..66479a47 100644 --- a/dak/auto_decruft.py +++ b/dak/auto_decruft.py @@ -54,9 +54,11 @@ Automatic removal of common kinds of cruft -h, --help show this help and exit. -n, --dry-run don't do anything, just show what would have been done -s, --suite=SUITE check suite SUITE. - --if-NVI OSUITE remove all packages in SUITE with a lower version than - in OSUITE (e.g. -s experimental --if-NVI unstable) - --if-NVI-rm-tag RMTAG use RMTAG in the removal message (e.g. "NVIU") + --if-newer-version-in OS remove all packages in SUITE with a lower version than + in OS (e.g. -s experimental --if-newer-version-in + unstable) + --if-newer-version-in-rm-msg RMMSG + use RMMSG in the removal message (e.g. "NVIU") """ sys.exit(exit_code) @@ -74,7 +76,8 @@ def compute_sourceless_groups(suite_id, session): """"" rows = query_without_source(suite_id, session) message = '[auto-cruft] no longer built from source, no reverse dependencies' - arch_all_id_tuple = tuple([get_architecture('all', session=session)]) + arch = get_architecture('all', session=session) + arch_all_id_tuple = tuple([arch.arch_id]) arch_all_list = ["all"] for row in rows: package = row[0] @@ -141,6 +144,52 @@ def remove_groups(groups, suite_id, suite_name, session): remove(session, message, [suite_name], list(q), partial=True, whoami="DAK's auto-decrufter") +def dedup(*args): + seen = set() + for iterable in args: + for value in iterable: + if value not in seen: + seen.add(value) + yield value + + +def merge_group(groupA, groupB): + """Merges two removal groups into one + + Note that some values are taken entirely from groupA (e.g. name and message) + + @type groupA: dict + @param groupA: A removal group + + @type groupB: dict + @param groupB: Another removal group + + @rtype: dict + @returns: A merged group + """ + pkg_list = sorted(dedup(groupA["packages"], groupB["packages"])) + arch_list = sorted(dedup(groupA["architectures"], groupB["architectures"]), cmp=utils.arch_compare_sw) + arch_list_id = dedup(groupA["architecture_ids"], groupB["architecture_ids"]) + removalA = groupA["removal_request"] + removalB = groupB["removal_request"] + new_removal = {} + for pkg in dedup(removalA, removalB): + listA = removalA[pkg] if pkg in removalA else [] + listB = removalB[pkg] if pkg in removalB else [] + new_removal[pkg] = sorted(dedup(listA, listB), cmp=utils.arch_compare_sw) + + merged_group = { + "name": groupA["name"], + "packages": tuple(pkg_list), + "architectures": arch_list, + "architecture_ids": tuple(arch_list_id), + "message": groupA["message"], + "removal_request": new_removal, + } + + return merged_group + + def auto_decruft_suite(suite_name, suite_id, session, dryrun, debug): """Run the auto-decrufter on a given suite @@ -172,22 +221,30 @@ def auto_decruft_suite(suite_name, suite_id, session, dryrun, debug): group_name = group["name"] pkgs = group["packages"] affected_archs = group["architectures"] - removal_request = group["removal_request"] # If we remove an arch:all package, then the breakage can occur on any # of the architectures. if "all" in affected_archs: affected_archs = all_architectures for pkg_arch in product(pkgs, affected_archs): pkg_arch2groups[pkg_arch].add(group_name) - groups[group_name] = group - group_order.append(group_name) + if group_name not in groups: + groups[group_name] = group + group_order.append(group_name) + else: + # This case usually happens when versions differ between architectures... + if debug: + print "N: Merging group %s" % (group_name) + groups[group_name] = merge_group(groups[group_name], group) + for group_name in group_order: + removal_request = groups[group_name]["removal_request"] full_removal_request.extend(removal_request.iteritems()) if not groups: if debug: print "N: Found no candidates" return + if debug: print "N: Considering to remove the following packages:" for group_name in sorted(groups): @@ -302,20 +359,17 @@ def sources2removals(source_list, suite_id, session): params = {"suite_id": suite_id, "sources": tuple(source_list)} q = session.execute(""" SELECT s.source, s.version, 'source', s.id - FROM source s, + FROM source s JOIN src_associations sa ON sa.source = s.id - JOIN suite su ON sa.suite = su.id - WHERE su.id = :suite_id AND s.source IN :sources""", params) + WHERE sa.suite = :suite_id AND s.source IN :sources""", params) to_remove.extend(q) q = session.execute(""" SELECT b.package, b.version, a.arch_string, b.id FROM binaries b JOIN bin_associations ba ON b.id = ba.bin JOIN architecture a ON b.architecture = a.id - JOIN suite su ON ba.suite = su.id JOIN source s ON b.source = s.id - JOIN src_associations sa ON s.id = sa.source AND sa.suite = su.id - WHERE su.id = :suite_id AND s.source IN :sources""", params) + WHERE ba.suite = :suite_id AND s.source IN :sources""", params) to_remove.extend(q) return to_remove @@ -360,8 +414,9 @@ def main (): ('n',"dry-run","Auto-Decruft::Options::Dry-Run"), ('d',"debug","Auto-Decruft::Options::Debug"), ('s',"suite","Auto-Decruft::Options::Suite","HasArg"), - ('z','if-NVI',"Auto-Decruft::Options::OtherSuite", "HasArg"), - ('Z','if-NVI-rm-msg',"Auto-Decruft::Options::OtherSuiteRMMsg", "HasArg")] + # The "\0" seems to be the only way to disable short options. + ("\0",'if-newer-version-in',"Auto-Decruft::Options::OtherSuite", "HasArg"), + ("\0",'if-newer-version-in-rm-msg',"Auto-Decruft::Options::OtherSuiteRMMsg", "HasArg")] for i in ["help", "Dry-Run", "Debug", "OtherSuite", "OtherSuiteRMMsg"]: if not cnf.has_key("Auto-Decruft::Options::%s" % (i)): cnf["Auto-Decruft::Options::%s" % (i)] = "" @@ -382,7 +437,7 @@ def main (): debug = True if Options["OtherSuite"] and not Options["OtherSuiteRMMsg"]: - utils.fubar("--if-NVI requires --if-NVI-rm-msg") + utils.fubar("--if-newer-version-in requires --if-newer-version-in-rm-msg") session = DBConn().session() @@ -399,6 +454,9 @@ def main (): osuite = get_suite(Options["OtherSuite"].lower(), session).suite_name decruft_newer_version_in(osuite, suite_name, suite_id, Options["OtherSuiteRMMsg"], session, dryrun) + if not dryrun: + session.commit() + ################################################################################ if __name__ == '__main__':