root/releases/pkgcore-checks/0.3/pkgcore_checks/visibility.py @ ferringb%2540gmail.com-20070207174621-yb3eqrqc6jtmdgse

Revision ferringb%2540gmail.com-20070207174621-yb3eqrqc6jtmdgse, 7.3 KB (checked in by Brian Harring <ferringb@…>, 2 years ago)

kill off to_str, no longer used; use short_desc and long_desc properties instead

Line 
1# Copyright: 2006 Brian Harring <ferringb@gmail.com>
2# License: GPL2
3
4from pkgcore.util.compatibility import any
5from pkgcore_checks import base, addons
6from pkgcore.util.iterables import caching_iter
7from pkgcore.util.lists import stable_unique, iflatten_instance
8from pkgcore.ebuild.atom import atom
9from pkgcore.util.demandload import demandload
10demandload(globals(), "pkgcore.util.xml:escape ")
11
12
13class VisibleVcsPkg(base.Result):
14    """pkg is vcs based, but visible"""
15
16    __slots__ = ("category", "package", "version", "profile", "arch")
17
18    threshold = base.versioned_feed
19
20    def __init__(self, pkg, arch, profile):
21        base.Result.__init__(self)
22        self._store_cpv(pkg)
23        self.arch = arch.lstrip("~")
24        self.profile = profile
25   
26    @property
27    def short_desc(self):
28        return "VCS version visible for arch %s, profile %s" % (
29            self.arch, self.profile)
30
31
32class NonExistantDeps(base.Result):
33    """No matches exist for a depset element"""
34
35    __slots__ = ("category", "package", "version", "attr", "atoms")
36
37    threshold = base.versioned_feed
38   
39    def __init__(self, pkg, attr, nonexistant_atoms):
40        base.Result.__init__(self)
41        self._store_cpv(pkg)
42        self.attr = attr
43        self.atoms = tuple(str(x) for x in nonexistant_atoms)
44   
45    @property
46    def short_desc(self):
47        return "depset %s: nonexistant atoms [ %s ]" % (
48            self.attr, ', '.join(self.atoms))
49   
50
51class NonsolvableDeps(base.Result):
52    """No potential solution for a depset attribute"""
53
54    __slots__ = ("category", "package", "version", "attr", "profile",
55        "keyword", "potentials")
56
57    threshold = base.versioned_feed
58   
59    def __init__(self, pkg, attr, keyword, profile, horked):
60        base.Result.__init__(self)
61        self._store_cpv(pkg)
62        self.attr = attr
63        self.profile = profile
64        self.keyword = keyword
65        self.potentials = tuple(str(x) for x in stable_unique(horked))
66       
67    @property
68    def short_desc(self):
69        return "nonsolvable depset(%s) keyword(%s) profile (%s): " \
70            "solutions: [ %s ]" % (self.attr, self.keyword, self.profile,
71            ', '.join(self.potentials))
72
73
74class VisibilityReport(base.Template):
75
76    """Visibility dependency scans.
77    Check that at least one solution is possible for a pkg, checking all
78    profiles (defined by arch.list) visibility modifiers per stable/unstable
79    keyword
80    """
81
82    feed_type = base.versioned_feed
83    required_addons = (
84        addons.ArchesAddon, addons.QueryCacheAddon, addons.ProfileAddon,
85        addons.EvaluateDepSetAddon)
86    known_results = (VisibleVcsPkg, NonExistantDeps, NonsolvableDeps)
87
88    vcs_eclasses = frozenset(["subversion", "git", "cvs", "darcs"])
89
90    def __init__(self, options, arches, query_cache, profiles, depset_cache):
91        base.Template.__init__(self, options)
92        self.query_cache = query_cache.query_cache
93        self.depset_cache = depset_cache
94        self.profiles = profiles
95        self.arches = frozenset(x.lstrip("~") for x in options.arches)
96
97    def feed(self, pkg, reporter):
98        # query_cache gets caching_iter partial repo searches shoved into it-
99        # reason is simple, it's likely that versions of this pkg probably
100        # use similar deps- so we're forcing those packages that were
101        # accessed for atom matching to remain in memory.
102        # end result is less going to disk
103
104        fvcs = self.vcs_eclasses
105        for eclass in pkg.data["_eclasses_"]:
106            if eclass in fvcs:
107                # vcs ebuild that better not be visible
108                self.check_visibility_vcs(pkg, reporter)
109                break
110
111        for attr, depset in (("depends", pkg.depends),
112            ("rdepends", pkg.rdepends), ("post_rdepends", pkg.post_rdepends)):
113            nonexistant = set()
114            for node in iflatten_instance(depset, atom):
115
116                h = str(node)
117                if h not in self.query_cache:
118                    if h in self.profiles.global_insoluable:
119                        nonexistant.add(node)
120                        # insert an empty tuple, so that tight loops further
121                        # on don't have to use the slower get method
122                        self.query_cache[h] = ()
123
124                    else:
125                        matches = caching_iter(
126                            self.options.search_repo.itermatch(node))
127                        if matches:
128                            self.query_cache[h] = matches
129                        elif not node.blocks and not node.category == "virtual":
130                            nonexistant.add(node)
131                            self.query_cache[h] = ()
132                            self.profiles.global_insoluable.add(h)
133
134            if nonexistant:
135                reporter.add_report(NonExistantDeps(pkg, attr, nonexistant))
136
137        del nonexistant
138
139        for attr, depset in (("depends", pkg.depends),
140            ("rdepends", pkg.rdepends), ("post_rdepends", pkg.post_rdepends)):
141
142            for edepset, profiles in self.depset_cache.collapse_evaluate_depset(
143                pkg, attr, depset):
144
145                self.process_depset(pkg, attr, edepset, profiles, reporter)
146
147    def check_visibility_vcs(self, pkg, reporter):
148        for key, profiles in self.profiles.profile_filters.iteritems():
149            if key.startswith("~") or key.startswith("-"):
150                continue
151            for profile in profiles:
152                if profile.visible(pkg):
153                    reporter.add_report(VisibleVcsPkg(pkg,
154                        profile.key, profile.name))
155
156    def process_depset(self, pkg, attr, depset, profiles, reporter):
157        csolutions = depset.cnf_solutions()
158
159        for profile in profiles:
160            failures = set()
161            # is it visible?  ie, is it masked?
162            # if so, skip it.
163            # long term, probably should do testing in the same respect we do
164            # for other visibility tiers
165            cache = profile.cache
166            provided = profile.provides_repo.match
167            is_virtual = profile.virtuals.match
168            insoluable = profile.insoluable
169            visible = profile.visible
170            for required in csolutions:
171                if any(True for a in required if a.blocks):
172                    continue
173                for a in required:
174                    h = str(a)
175                    if h in insoluable:
176                        pass
177                    elif h in cache:
178                        break
179                    elif provided(a):
180                        break
181                    elif is_virtual(a):
182                        cache.add(h)
183                        break
184                    elif a.category == "virtual" and h not in self.query_cache:
185                        insoluable.add(h)
186                    else:
187                        if any(True for pkg in self.query_cache[h] if
188                            visible(pkg)):
189                            cache.add(h)
190                            break
191                        else:
192                            insoluable.add(h)
193                else:
194                    # no matches.  not great, should collect them all
195                    failures.update(required)
196            if failures:
197                reporter.add_report(NonsolvableDeps(pkg, attr, profile.key,
198                    profile.name, list(failures)))
Note: See TracBrowser for help on using the browser.