| 1 | # Copyright: 2006 Brian Harring <ferringb@gmail.com> |
|---|
| 2 | # License: GPL2 |
|---|
| 3 | |
|---|
| 4 | from pkgcore_checks.base import Template, package_feed, Result, versioned_feed |
|---|
| 5 | from pkgcore.util.compatibility import any |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | class RedundantVersionWarning(Result): |
|---|
| 9 | """ |
|---|
| 10 | Redundant version of a pkg in a slotting; keyword appears in a later |
|---|
| 11 | version |
|---|
| 12 | """ |
|---|
| 13 | |
|---|
| 14 | __slots__ = ("category", "package", "version", "slot", "later_versions") |
|---|
| 15 | threshold = versioned_feed |
|---|
| 16 | |
|---|
| 17 | def __init__(self, pkg, higher_pkgs): |
|---|
| 18 | Result.__init__(self) |
|---|
| 19 | self._store_cpv(pkg) |
|---|
| 20 | self.slot = pkg.slot |
|---|
| 21 | self.later_versions = tuple(x.fullver for x in higher_pkgs) |
|---|
| 22 | |
|---|
| 23 | @property |
|---|
| 24 | def short_desc(self): |
|---|
| 25 | return "slot(%s) keywords are overshadowed by version %r" % \ |
|---|
| 26 | (self.slot, ', '.join(self.later_versions)) |
|---|
| 27 | |
|---|
| 28 | |
|---|
| 29 | class RedundantVersionReport(Template): |
|---|
| 30 | """ |
|---|
| 31 | scan for versions that are likely shadowed by later versions from a |
|---|
| 32 | keywords standpoint (ignoring -9999 versioned packages) |
|---|
| 33 | |
|---|
| 34 | Example: pkga-1 is keyworded amd64, pkga-2 is amd64. |
|---|
| 35 | pkga-1 can potentially be removed. |
|---|
| 36 | """ |
|---|
| 37 | |
|---|
| 38 | feed_type = package_feed |
|---|
| 39 | known_results = (RedundantVersionWarning,) |
|---|
| 40 | |
|---|
| 41 | def feed(self, pkgset, reporter): |
|---|
| 42 | if len(pkgset) == 1: |
|---|
| 43 | return |
|---|
| 44 | |
|---|
| 45 | # algo is roughly thus; spot stable versions, hunt for subset |
|---|
| 46 | # keyworded pkgs that are less then the max version; |
|---|
| 47 | # repeats this for every overshadowing detected |
|---|
| 48 | # finally, does version comparison down slot lines |
|---|
| 49 | stack = [] |
|---|
| 50 | bad = [] |
|---|
| 51 | for pkg in reversed(pkgset): |
|---|
| 52 | # reduce false positives for idiot keywords/ebuilds |
|---|
| 53 | if pkg.version == '9999' or pkg.version.startswith("cvs."): |
|---|
| 54 | continue |
|---|
| 55 | curr_set = set(x for x in pkg.keywords if not x.startswith("-")) |
|---|
| 56 | if not curr_set: |
|---|
| 57 | continue |
|---|
| 58 | |
|---|
| 59 | matches = [ver for ver, keys in stack if ver.slot == pkg.slot |
|---|
| 60 | and not curr_set.difference(keys)] |
|---|
| 61 | |
|---|
| 62 | # we've done our checks; now we inject unstable for any stable |
|---|
| 63 | # via this, earlier versions that are unstable only get flagged |
|---|
| 64 | # as "not needed" since their unstable flag is a subset of the |
|---|
| 65 | # stable. |
|---|
| 66 | |
|---|
| 67 | # also, yes, have to use list comp here- we're adding as we go |
|---|
| 68 | curr_set.update(["~"+x for x in curr_set if not x.startswith("~")]) |
|---|
| 69 | |
|---|
| 70 | stack.append([pkg, curr_set]) |
|---|
| 71 | if matches: |
|---|
| 72 | bad.append((pkg, matches)) |
|---|
| 73 | |
|---|
| 74 | for pkg, matches in reversed(bad): |
|---|
| 75 | reporter.add_report(RedundantVersionWarning(pkg, matches)) |
|---|