def cpv_all_diff_use( cpvs=None, system_flags=None, # override-able for testing _get_flags=get_flags, _get_used=get_installed_use, ): """Data gathering and analysis function determines the difference between the current default USE flag settings and the currently installed pkgs recorded USE flag settings @type cpvs: list @param cpvs: optional list of [cat/pkg-ver,...] to analyze or defaults to entire installed pkg db @type: system_flags: list @param system_flags: the current default USE flags as defined by portage.settings["USE"].split() @type _get_flags: function @param _get_flags: ovride-able for testing, defaults to gentoolkit.enalyze.lib.get_flags @param _get_used: ovride-able for testing, defaults to gentoolkit.enalyze.lib.get_installed_use @rtype dict. {cpv:['flag1', '-flag2',...]} """ if cpvs is None: cpvs = portage.db[portage.root]["vartree"].dbapi.cpv_all() cpvs.sort() data = {} cp_counts = {} # pass them in to override for tests flags = FlagAnalyzer( system_flags, filter_defaults=True, target="USE", _get_flags=_get_flags, _get_used=get_installed_use, ) for cpv in cpvs: plus, minus, unset = flags.analyse_cpv(cpv) atom = Atom("=" + cpv) atom.slot = portage.db[portage.root]["vartree"].dbapi.aux_get( atom.cpv, ["SLOT"] )[0] for flag in minus: plus.add("-" + flag) if len(plus): if atom.cp not in data: data[atom.cp] = [] if atom.cp not in cp_counts: cp_counts[atom.cp] = 0 atom.use = list(plus) data[atom.cp].append(atom) cp_counts[atom.cp] += 1 return data, cp_counts
def cpv_all_diff_keywords( cpvs=None, system_keywords=None, use_portage=False, # override-able for testing keywords=portage.settings["ACCEPT_KEYWORDS"], analyser = None ): """Analyze the installed pkgs 'keywords' for difference from ACCEPT_KEYWORDS @param cpvs: optional list of [cat/pkg-ver,...] to analyze or defaults to entire installed pkg db @param system_keywords: list of the system keywords @param keywords: user defined list of keywords to check and report on or reports on all relevant keywords found to have been used. @param _get_kwds: overridable function for testing @param _get_used: overridable function for testing @rtype dict. {keyword:{"stable":[cat/pkg-ver,...], "testing":[cat/pkg-ver,...]} """ if cpvs is None: cpvs = portage.db[portage.root]["vartree"].dbapi.cpv_all() keyword_users = {} cp_counts = {} for cpv in cpvs: if cpv.startswith("virtual"): continue if use_portage: keyword = analyser.get_inst_keyword_cpv(cpv) else: pkg = Package(cpv) keyword = analyser.get_inst_keyword_pkg(pkg) #print "returned keyword =", cpv, keyword, keyword[0] key = keyword[0] if key in ["~", "-"] and keyword not in system_keywords: atom = Atom("="+cpv) if atom.cp not in keyword_users: keyword_users[atom.cp] = [] if atom.cp not in cp_counts: cp_counts[atom.cp] = 0 if key in ["~"]: atom.keyword = keyword atom.slot = portage.db[portage.root]["vartree"].dbapi.aux_get(atom.cpv, ["SLOT"])[0] keyword_users[atom.cp].append(atom) cp_counts[atom.cp] += 1 elif key in ["-"]: #print "adding cpv to missing:", cpv atom.keyword = "**" atom.slot = portage.db[portage.root]["vartree"].dbapi.aux_get(atom.cpv, ["SLOT"])[0] keyword_users[atom.cp].append(atom) cp_counts[atom.cp] += 1 return keyword_users, cp_counts
def cpv_all_diff_use( cpvs=None, system_flags=None, # override-able for testing _get_flags=get_flags, _get_used=get_installed_use ): """Data gathering and analysis function determines the difference between the current default USE flag settings and the currently installed pkgs recorded USE flag settings @type cpvs: list @param cpvs: optional list of [cat/pkg-ver,...] to analyze or defaults to entire installed pkg db @type: system_flags: list @param system_flags: the current default USE flags as defined by portage.settings["USE"].split() @type _get_flags: function @param _get_flags: ovride-able for testing, defaults to gentoolkit.enalyze.lib.get_flags @param _get_used: ovride-able for testing, defaults to gentoolkit.enalyze.lib.get_installed_use @rtype dict. {cpv:['flag1', '-flag2',...]} """ if cpvs is None: cpvs = portage.db[portage.root]["vartree"].dbapi.cpv_all() cpvs.sort() data = {} cp_counts = {} # pass them in to override for tests flags = FlagAnalyzer(system_flags, filter_defaults=True, target="USE", _get_flags=_get_flags, _get_used=get_installed_use ) for cpv in cpvs: plus, minus, unset = flags.analyse_cpv(cpv) atom = Atom("="+cpv) atom.slot = portage.db[portage.root]["vartree"].dbapi.aux_get(atom.cpv, ["SLOT"])[0] for flag in minus: plus.add("-"+flag) if len(plus): if atom.cp not in data: data[atom.cp] = [] if atom.cp not in cp_counts: cp_counts[atom.cp] = 0 atom.use = list(plus) data[atom.cp].append(atom) cp_counts[atom.cp] += 1 return data, cp_counts
def __init__(self, query, is_regex=False): """Create query object. @type is_regex: bool @param is_regex: query is a regular expression """ # We need at least one of these chars for a valid query needed_chars = ascii_letters + '*' if not set(query).intersection(needed_chars): raise errors.GentoolkitInvalidPackage(query) # Separate repository repository = None if query.count(':') == 2: query, repository = query.rsplit(':', 1) self.query = query.rstrip(':') # Don't leave dangling colon self.repo_filter = repository self.is_regex = is_regex self.query_type = self._get_query_type() # Name the rest of the chunks, if possible if self.query_type != "set": try: atom = Atom(self.query) self.__dict__.update(atom.__dict__) except errors.GentoolkitInvalidAtom: CPV.__init__(self, self.query) self.operator = '' self.atom = self.cpv
def _parser(self, deps, use_conditional=None, depth=0): """?DEPEND file parser. @rtype: list @return: L{gentoolkit.atom.Atom} objects """ result = [] if depth == 0: deps = paren_reduce(deps) for tok in deps: if tok == '||': continue if tok[-1] == '?': use_conditional = tok[:-1] continue if isinstance(tok, list): sub_r = self._parser(tok, use_conditional, depth=depth + 1) result.extend(sub_r) use_conditional = None continue # FIXME: This is a quick fix for bug #299260. # A better fix is to not discard blockers in the parser, # but to check for atom.blocker in whatever equery/depends # (in this case) and ignore them there. # TODO: Test to see how much a performance impact ignoring # blockers here rather than checking for atom.blocker has. if tok[0] == '!': # We're not interested in blockers continue # skip it if it's empty if tok and tok != '': atom = Atom(tok) if use_conditional is not None: atom.use_conditional = use_conditional result.append(atom) else: message = "dependencies.py: _parser() found an empty " +\ "dep string token for: %s, deps= %s" raise errors.GentoolkitInvalidAtom(message % (self.cpv, deps)) return result
def _parser(self, deps, use_conditional=None, depth=0): """?DEPEND file parser. @rtype: list @return: L{gentoolkit.atom.Atom} objects """ result = [] if depth == 0: deps = paren_reduce(deps) for tok in deps: if tok == '||': continue if tok[-1] == '?': use_conditional = tok[:-1] continue if isinstance(tok, list): sub_r = self._parser(tok, use_conditional, depth=depth+1) result.extend(sub_r) use_conditional = None continue # FIXME: This is a quick fix for bug #299260. # A better fix is to not discard blockers in the parser, # but to check for atom.blocker in whatever equery/depends # (in this case) and ignore them there. # TODO: Test to see how much a performance impact ignoring # blockers here rather than checking for atom.blocker has. if tok[0] == '!': # We're not interested in blockers continue # skip it if it's empty if tok and tok != '': atom = Atom(tok) if use_conditional is not None: atom.use_conditional = use_conditional result.append(atom) else: message = "dependencies.py: _parser() found an empty " +\ "dep string token for: %s, deps= %s" raise errors.GentoolkitInvalidAtom(message %(self.cpv, deps)) return result
def entries_matching_atom(self, atom): """Return entries whose header versions match atom's version. @type atom: L{gentoolkit.atom.Atom} or str @param atom: a atom to find matching entries against @rtype: list @return: entries matching atom @raise errors.GentoolkitInvalidAtom: if atom is a string and malformed """ result = [] if not isinstance(atom, Atom): atom = Atom(atom) for entry_set in self.indexed_entries: i, entry = entry_set # VersionMatch doesn't store .cp, so we'll force it to match here: i.cp = atom.cp if atom.intersects(i): result.append(entry) return result
def cpv_all_diff_keywords( cpvs=None, system_keywords=None, use_portage=False, # override-able for testing keywords=portage.settings["ACCEPT_KEYWORDS"], analyser=None, ): """Analyze the installed pkgs 'keywords' for difference from ACCEPT_KEYWORDS @param cpvs: optional list of [cat/pkg-ver,...] to analyze or defaults to entire installed pkg db @param system_keywords: list of the system keywords @param keywords: user defined list of keywords to check and report on or reports on all relevant keywords found to have been used. @param _get_kwds: overridable function for testing @param _get_used: overridable function for testing @rtype dict. {keyword:{"stable":[cat/pkg-ver,...], "testing":[cat/pkg-ver,...]} """ if cpvs is None: cpvs = portage.db[portage.root]["vartree"].dbapi.cpv_all() keyword_users = {} cp_counts = {} for cpv in cpvs: if cpv.startswith("virtual"): continue if use_portage: keyword = analyser.get_inst_keyword_cpv(cpv) else: pkg = Package(cpv) keyword = analyser.get_inst_keyword_pkg(pkg) # print "returned keyword =", cpv, keyword, keyword[0] key = keyword[0] if key in ["~", "-"] and keyword not in system_keywords: atom = Atom("=" + cpv) if atom.cp not in keyword_users: keyword_users[atom.cp] = [] if atom.cp not in cp_counts: cp_counts[atom.cp] = 0 if key in ["~"]: atom.keyword = keyword atom.slot = portage.db[portage.root]["vartree"].dbapi.aux_get( atom.cpv, ["SLOT"] )[0] keyword_users[atom.cp].append(atom) cp_counts[atom.cp] += 1 elif key in ["-"]: # print "adding cpv to missing:", cpv atom.keyword = "**" atom.slot = portage.db[portage.root]["vartree"].dbapi.aux_get( atom.cpv, ["SLOT"] )[0] keyword_users[atom.cp].append(atom) cp_counts[atom.cp] += 1 return keyword_users, cp_counts
def get_set_atoms(setname): """Return atoms belonging to the given set @type setname: string @param setname: Name of the set @rtype list @return: List of atoms in the given set """ if _sets_available: _init_set_config() try: return set( [Atom(str(x)) for x in _set_config.getSetAtoms(setname)]) except portage.sets.PackageSetNotFound: raise errors.GentoolkitSetNotFound(setname) raise errors.GentoolkitSetNotFound(setname)
def test_intersects(self): for this, that, result in [ ("cat/pkg", "pkg/cat", False), ("cat/pkg", "cat/pkg", True), ("cat/pkg:1", "cat/pkg:1", True), ("cat/pkg:1", "cat/pkg:2", False), ("cat/pkg:1", "cat/pkg[foo]", True), ("cat/pkg[foo]", "cat/pkg[-bar]", True), ("cat/pkg[foo]", "cat/pkg[-foo]", False), (">cat/pkg-3", ">cat/pkg-1", True), (">cat/pkg-3", "<cat/pkg-3", False), (">=cat/pkg-3", "<cat/pkg-3", False), (">cat/pkg-2", "=cat/pkg-2*", True), # Portage vercmp disagrees with this one: # ('<cat/pkg-2_alpha1', '=cat/pkg-2*', True), ("=cat/pkg-2", "=cat/pkg-2", True), ("=cat/pkg-3", "=cat/pkg-2", False), ("=cat/pkg-2", ">cat/pkg-2", False), ("=cat/pkg-2", ">=cat/pkg-2", True), ("~cat/pkg-2", "~cat/pkg-2", True), ("~cat/pkg-2", "~cat/pkg-2.1", False), ("=cat/pkg-2*", "=cat/pkg-2.3*", True), (">cat/pkg-2.4", "=cat/pkg-2*", True), ("<cat/pkg-2.4", "=cat/pkg-2*", True), ("<cat/pkg-1", "=cat/pkg-2*", False), ("~cat/pkg-2", ">cat/pkg-2-r1", True), ("~cat/pkg-2", "<=cat/pkg-2", True), ("=cat/pkg-2-r2*", "<=cat/pkg-2-r20", True), ("=cat/pkg-2-r2*", "<cat/pkg-2-r20", True), ("=cat/pkg-2-r2*", "<=cat/pkg-2-r2", True), ("~cat/pkg-2", "<cat/pkg-2", False), ("=cat/pkg-1-r10*", "~cat/pkg-1", True), ("=cat/pkg-1-r1*", "<cat/pkg-1-r1", False), ("=cat/pkg-1*", ">cat/pkg-2", False), (">=cat/pkg-8.4", "=cat/pkg-8.3.4*", False), ("cat/pkg::gentoo", "cat/pkg", True), ("cat/pkg::gentoo", "cat/pkg::foo", False), ("=sys-devel/gcc-4.1.1-r3", "=sys-devel/gcc-3.3*", False), ("=sys-libs/db-4*", "~sys-libs/db-4.3.29", True), ]: this_atom = Atom(this) that_atom = Atom(that) self.assertEqual( result, this_atom.intersects(that_atom), "%s intersecting %s should be %s" % (this, that, result), ) self.assertEqual( result, that_atom.intersects(this_atom), "%s intersecting %s should be %s" % (that, this, result), )
def test_intersects(self): for this, that, result in [ ('cat/pkg', 'pkg/cat', False), ('cat/pkg', 'cat/pkg', True), ('cat/pkg:1', 'cat/pkg:1', True), ('cat/pkg:1', 'cat/pkg:2', False), ('cat/pkg:1', 'cat/pkg[foo]', True), ('cat/pkg[foo]', 'cat/pkg[-bar]', True), ('cat/pkg[foo]', 'cat/pkg[-foo]', False), ('>cat/pkg-3', '>cat/pkg-1', True), ('>cat/pkg-3', '<cat/pkg-3', False), ('>=cat/pkg-3', '<cat/pkg-3', False), ('>cat/pkg-2', '=cat/pkg-2*', True), # Portage vercmp disagrees with this one: #('<cat/pkg-2_alpha1', '=cat/pkg-2*', True), ('=cat/pkg-2', '=cat/pkg-2', True), ('=cat/pkg-3', '=cat/pkg-2', False), ('=cat/pkg-2', '>cat/pkg-2', False), ('=cat/pkg-2', '>=cat/pkg-2', True), ('~cat/pkg-2', '~cat/pkg-2', True), ('~cat/pkg-2', '~cat/pkg-2.1', False), ('=cat/pkg-2*', '=cat/pkg-2.3*', True), ('>cat/pkg-2.4', '=cat/pkg-2*', True), ('<cat/pkg-2.4', '=cat/pkg-2*', True), ('<cat/pkg-1', '=cat/pkg-2*', False), ('~cat/pkg-2', '>cat/pkg-2-r1', True), ('~cat/pkg-2', '<=cat/pkg-2', True), ('=cat/pkg-2-r2*', '<=cat/pkg-2-r20', True), ('=cat/pkg-2-r2*', '<cat/pkg-2-r20', True), ('=cat/pkg-2-r2*', '<=cat/pkg-2-r2', True), ('~cat/pkg-2', '<cat/pkg-2', False), ('=cat/pkg-1-r10*', '~cat/pkg-1', True), ('=cat/pkg-1-r1*', '<cat/pkg-1-r1', False), ('=cat/pkg-1*', '>cat/pkg-2', False), ('>=cat/pkg-8.4', '=cat/pkg-8.3.4*', False), # Repos not yet supported by Portage #('cat/pkg::gentoo', 'cat/pkg', True), #('cat/pkg::gentoo', 'cat/pkg::foo', False), ('=sys-devel/gcc-4.1.1-r3', '=sys-devel/gcc-3.3*', False), ('=sys-libs/db-4*', '~sys-libs/db-4.3.29', True), ]: this_atom = Atom(this) that_atom = Atom(that) self.assertEqual( result, this_atom.intersects(that_atom), '%s intersecting %s should be %s' % (this, that, result)) self.assertEqual( result, that_atom.intersects(this_atom), '%s intersecting %s should be %s' % (that, this, result))
def parse_atom(tok, indent=0): """Parse dependency atom""" assert (not isinstance(tok, list)) if CONFIG['verbose']: print(' ' * indent, 'atom', tok) atom = Atom(tok) # Try to find matches for this atom query = Query(atom) matches = query.find(include_masked=True) # We didn't find any so raise an error if not matches: raise errors.GentoolkitNoMatches(query) # Loop through the matching packages combining their best arch keywords into a single dictionary matches.sort() kwdict = {} for pkg in matches: if CONFIG['verbose']: print(' ' * (indent + 2), pkg) keywords_str = pkg.environment(('KEYWORDS'), prefer_vdb=False) if keywords_str: if CONFIG['verbose']: print(' ' * (indent + 4), keywords_str) for keyword in keywords_str.split(): skw = make_stable(keyword) if skw not in kwdict: kwdict[skw] = keyword else: kwdict[skw] = best_keyword(kwdict[skw], keyword) if CONFIG['verbose']: print(' ' * indent, 'return', kwdict) return kwdict
def main(input_args): """Parse input and run the program""" short_opts = "hlf" long_opts = ('help', 'full', 'from=', 'latest', 'limit=', 'to=') try: module_opts, queries = gnu_getopt(input_args, short_opts, long_opts) except GetoptError as err: sys.stderr.write(pp.error("Module %s" % err)) print() print_help(with_description=False) sys.exit(2) parse_module_options(module_opts) if not queries: print_help() sys.exit(2) first_run = True got_match = False for query in (Query(x) for x in queries): if not first_run: print() match = query.find_best() if match is None: continue got_match = True changelog_path = os.path.join(match.package_path(), 'ChangeLog') changelog = ChangeLog(changelog_path) # # Output # if (QUERY_OPTS['only_latest'] or (changelog.entries and not changelog.indexed_entries)): pp.uprint(changelog.latest.strip()) else: end = QUERY_OPTS['limit'] or len(changelog.indexed_entries) if QUERY_OPTS['to'] or QUERY_OPTS['from']: print_entries( changelog.entries_matching_range( from_ver=QUERY_OPTS['from'], to_ver=QUERY_OPTS['to'])[:end]) elif QUERY_OPTS['show_full_log']: print_entries(changelog.full[:end]) else: # Raises GentoolkitInvalidAtom here if invalid if query.is_ranged(): atom = Atom(str(query)) else: atom = '=' + str(match.cpv) print_entries(changelog.entries_matching_atom(atom)[:end]) first_run = False if not got_match: sys.exit(1)
def test_comparison(self): self.assertEqual2(Atom("cat/pkg"), Atom("cat/pkg")) self.assertNotEqual2(Atom("cat/pkg"), Atom("cat/pkgb")) self.assertNotEqual2(Atom("cata/pkg"), Atom("cat/pkg")) self.assertNotEqual2(Atom("cat/pkg"), Atom("!cat/pkg")) self.assertEqual2(Atom("!cat/pkg"), Atom("!cat/pkg")) self.assertNotEqual2(Atom("=cat/pkg-0.1:0"), Atom("=cat/pkg-0.1")) self.assertNotEqual2(Atom("=cat/pkg-1[foon]"), Atom("=cat/pkg-1")) self.assertEqual2(Atom("=cat/pkg-0"), Atom("=cat/pkg-0")) self.assertNotEqual2(Atom("<cat/pkg-2"), Atom(">cat/pkg-2")) self.assertNotEqual2(Atom("=cat/pkg-2*"), Atom("=cat/pkg-2")) # Portage Atom doesn't have 'negate_version' capability # self.assertNotEqual2(Atom('=cat/pkg-2', True), Atom('=cat/pkg-2')) # use... self.assertNotEqual2(Atom("cat/pkg[foo]"), Atom("cat/pkg")) self.assertNotEqual2(Atom("cat/pkg[foo]"), Atom("cat/pkg[-foo]")) self.assertEqual2(Atom("cat/pkg[foo,-bar]"), Atom("cat/pkg[-bar,foo]")) # repoid not supported by Portage Atom yet # repoid # self.assertEqual2(Atom('cat/pkg::a'), Atom('cat/pkg::a')) # self.assertNotEqual2(Atom('cat/pkg::a'), Atom('cat/pkg::b')) # self.assertNotEqual2(Atom('cat/pkg::a'), Atom('cat/pkg')) # slots. self.assertNotEqual2(Atom("cat/pkg:1"), Atom("cat/pkg")) self.assertEqual2(Atom("cat/pkg:2"), Atom("cat/pkg:2")) # http://dev.gentoo.org/~tanderson/pms/eapi-2-approved/pms.html#x1-190002.1.2 self.assertEqual2(Atom("cat/pkg:AZaz09+_.-"), Atom("cat/pkg:AZaz09+_.-")) for lesser, greater in (("0.1", "1"), ("1", "1-r1"), ("1.1", "1.2")): self.assertTrue( Atom("=d/b-%s" % lesser) < Atom("=d/b-%s" % greater), msg="d/b-%s < d/b-%s" % (lesser, greater), ) self.assertFalse( Atom("=d/b-%s" % lesser) > Atom("=d/b-%s" % greater), msg="!: d/b-%s < d/b-%s" % (lesser, greater), ) self.assertTrue( Atom("=d/b-%s" % greater) > Atom("=d/b-%s" % lesser), msg="d/b-%s > d/b-%s" % (greater, lesser), ) self.assertFalse( Atom("=d/b-%s" % greater) < Atom("=d/b-%s" % lesser), msg="!: d/b-%s > d/b-%s" % (greater, lesser), ) # self.assertTrue(Atom("!!=d/b-1", eapi=2) > Atom("!=d/b-1")) self.assertTrue(Atom("!=d/b-1") < Atom("!!=d/b-1")) self.assertEqual(Atom("!=d/b-1"), Atom("!=d/b-1"))
def test_intersects_nameonly(self): atom = Atom("cat/pkg") self.assertTrue(atom.intersects(CPV("pkg"))) self.assertFalse(atom.intersects(CPV("other"))) self.assertFalse(atom.intersects(CPV("dkg")))
def test_intersects_nameonly(self): atom = Atom('cat/pkg') self.assertTrue(atom.intersects(CPV('pkg'))) self.assertFalse(atom.intersects(CPV('other'))) self.assertFalse(atom.intersects(CPV('dkg')))