def smart_find(self, in_installed=True, in_porttree=True, in_overlay=True, include_masked=True, show_progress=True, no_matches_fatal=True, **kwargs): """A high-level wrapper around gentoolkit package-finder functions. @type in_installed: bool @param in_installed: search for query in VARDB @type in_porttree: bool @param in_porttree: search for query in PORTDB @type in_overlay: bool @param in_overlay: search for query in overlays @type show_progress: bool @param show_progress: output search progress @type no_matches_fatal: bool @param no_matches_fatal: raise errors.GentoolkitNoMatches @rtype: list @return: Package objects matching query """ if in_installed: if in_porttree or in_overlay: simple_package_finder = partial(self.find, include_masked=include_masked) complex_package_finder = helpers.get_cpvs else: simple_package_finder = self.find_installed complex_package_finder = helpers.get_installed_cpvs elif in_porttree or in_overlay: simple_package_finder = partial(self.find, include_masked=include_masked, in_installed=False) complex_package_finder = helpers.get_uninstalled_cpvs else: raise errors.GentoolkitFatalError( "Not searching in installed, Portage tree, or overlay. " "Nothing to do.") if self.query_type == "set": self.package_finder = simple_package_finder matches = self._do_set_lookup(show_progress=show_progress) elif self.query_type == "simple": self.package_finder = simple_package_finder matches = self._do_simple_lookup(in_installed=in_installed, show_progress=show_progress) else: self.package_finder = complex_package_finder matches = self._do_complex_lookup(show_progress=show_progress) if self.repo_filter is not None: matches = self._filter_by_repository(matches) if no_matches_fatal and not matches: ii = in_installed and not (in_porttree or in_overlay) raise errors.GentoolkitNoMatches(self.query, in_installed=ii) return matches
def __init__(self, changelog_path, invalid_entry_is_fatal=False): if not (os.path.isfile(changelog_path) and os.access(changelog_path, os.R_OK)): raise errors.GentoolkitFatalError( "%s does not exist or is unreadable" % pp.path(changelog_path)) self.changelog_path = changelog_path self.invalid_entry_is_fatal = invalid_entry_is_fatal # Process the ChangeLog: self.entries = self._split_changelog() self.indexed_entries = self._index_changelog() self.full = self.entries self.latest = self.entries[0]
def entries_matching_range(self, from_ver=None, to_ver=None): """Return entries whose header versions are within a range of versions. @type from_ver: str @param from_ver: valid Gentoo version @type to_ver: str @param to_ver: valid Gentoo version @rtype: list @return: entries between from_ver and to_ver @raise errors.GentoolkitFatalError: if neither vers are set @raise errors.GentoolkitInvalidVersion: if either ver is invalid """ result = [] # Make sure we have at least one version set if not (from_ver or to_ver): raise errors.GentoolkitFatalError( "Need to specifiy 'from_ver' or 'to_ver'" ) # Create a VersionMatch instance out of from_ver from_restriction = None if from_ver: try: from_ver_rev = CPV("null-%s" % from_ver) except errors.GentoolkitInvalidCPV: raise errors.GentoolkitInvalidVersion(from_ver) from_restriction = VersionMatch(from_ver_rev, op='>=') # Create a VersionMatch instance out of to_ver to_restriction = None if to_ver: try: to_ver_rev = CPV("null-%s" % to_ver) except errors.GentoolkitInvalidCPV: raise errors.GentoolkitInvalidVersion(to_ver) to_restriction = VersionMatch(to_ver_rev, op='<=') # Add entry to result if version ranges intersect it for entry_set in self.indexed_entries: i, entry = entry_set if from_restriction and not from_restriction.match(i): continue if to_restriction and not to_restriction.match(i): # TODO: is it safe to break here? continue result.append(entry) return result
def graph_reverse_depends( self, pkgset=None, max_depth=-1, only_direct=True, printer_fn=None, # The rest of these are only used internally: depth=0, depcache=None, seen=None, result=None): """Graph direct reverse dependencies for self. Example usage: >>> from gentoolkit.dependencies import Dependencies >>> ffmpeg = Dependencies('media-video/ffmpeg-9999') >>> # I only care about installed packages that depend on me: ... from gentoolkit.helpers import get_installed_cpvs >>> # I want to pass in a sorted list. We can pass strings or ... # Package or Atom types, so I'll use Package to sort: ... from gentoolkit.package import Package >>> installed = sorted(get_installed_cpvs()) >>> deptree = ffmpeg.graph_reverse_depends( ... only_direct=False, # Include indirect revdeps ... pkgset=installed) # from installed pkgset >>> len(deptree) 24 @type pkgset: iterable @keyword pkgset: sorted pkg cpv strings or anything sublassing L{gentoolkit.cpv.CPV} to use for calculate our revdep graph. @type max_depth: int @keyword max_depth: Maximum depth to recurse if only_direct=False. -1 means no maximum depth; 0 is the same as only_direct=True; >0 means recurse only this many times; @type only_direct: bool @keyword only_direct: to recurse or not to recurse @type printer_fn: callable @keyword printer_fn: If None, no effect. If set, it will be applied to each L{gentoolkit.atom.Atom} object as it is added to the results. @rtype: list @return: L{gentoolkit.dependencies.Dependencies} objects """ if not pkgset: err = ("%s kwarg 'pkgset' must be set. " "Can be list of cpv strings or any 'intersectable' object.") raise errors.GentoolkitFatalError(err % (self.__class__.__name__, )) if depcache is None: depcache = dict() if seen is None: seen = set() if result is None: result = list() if depth == 0: pkgset = tuple(Dependencies(x) for x in pkgset) pkgdep = None for pkgdep in pkgset: try: all_depends = depcache[pkgdep] except KeyError: all_depends = uniqify(pkgdep.get_all_depends()) depcache[pkgdep] = all_depends dep_is_displayed = False for dep in all_depends: # TODO: Add ability to determine if dep is enabled by USE flag. # Check portage.dep.use_reduce if dep.intersects(self): pkgdep.depth = depth pkgdep.matching_dep = dep if printer_fn is not None: printer_fn(pkgdep, dep_is_displayed=dep_is_displayed) result.append(pkgdep) dep_is_displayed = True # if --indirect specified, call ourselves again with the dep # Do not call if we have already called ourselves. if (dep_is_displayed and not only_direct and pkgdep.cpv not in seen and (depth < max_depth or max_depth == -1)): seen.add(pkgdep.cpv) result.append( pkgdep.graph_reverse_depends(pkgset=pkgset, max_depth=max_depth, only_direct=only_direct, printer_fn=printer_fn, depth=depth + 1, depcache=depcache, seen=seen, result=result)) if depth == 0: return result return pkgdep
def environment(self, envvars, prefer_vdb=True, fallback=True): """Returns one or more of the predefined environment variables. Some available envvars are: ---------------------- BINPKGMD5 COUNTER FEATURES LICENSE SRC_URI CATEGORY CXXFLAGS HOMEPAGE PDEPEND USE CBUILD DEFINED_PHASES INHERITED PF CFLAGS DEPEND IUSE PROVIDE CHOST DESCRIPTION KEYWORDS RDEPEND CONTENTS EAPI LDFLAGS SLOT Example usage: >>> pkg = Package('sys-apps/portage-9999') >>> pkg.environment('USE') '' >>> pkg.environment(('USE', 'IUSE')) ... # doctest: +NORMALIZE_WHITESPACE ['', 'build doc epydoc +ipc pypy1_9 python2 python3 selinux xattr'] @type envvars: str or array @param envvars: one or more of (DEPEND, SRC_URI, etc.) @type prefer_vdb: bool @keyword prefer_vdb: if True, look in the vardb before portdb, else reverse order. Specifically KEYWORDS will get more recent information by preferring portdb. @type fallback: bool @keyword fallback: query only the preferred db if False @rtype: str or list @return: str if envvars is str, list if envvars is array @raise KeyError: if key is not found in requested db(s) """ got_string = False if isinstance(envvars, str): got_string = True envvars = (envvars, ) if prefer_vdb: try: result = portage.db[portage.root]['vartree'].dbapi.aux_get( self.cpv, envvars) except KeyError: try: if not fallback: raise KeyError result = portage.db[ portage.root]['porttree'].dbapi.aux_get( self.cpv, envvars) except KeyError: raise errors.GentoolkitFatalError( 'aux_get returned unexpected ' 'results') else: try: result = portage.db[portage.root]['porttree'].dbapi.aux_get( self.cpv, envvars) except KeyError: try: if not fallback: raise KeyError result = portage.db[portage.root]['vartree'].dbapi.aux_get( self.cpv, envvars) except KeyError: raise errors.GentoolkitFatalError( 'aux_get returned unexpected ' 'results') if got_string: return result[0] return result
def main(input_args): """Parse input and run the program""" short_opts = "hiIpoF:" # -i was option for default action # --installed is no longer needed, kept for compatibility (djanderson '09) long_opts = ('help', 'installed', 'exclude-installed', 'portage-tree', 'overlay-tree', 'format=', 'package=') 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) query_scope = QUERY_OPTS['package_filter'] or '*' matches = Query(query_scope).smart_find(**QUERY_OPTS) matches.sort() # split out the first query since it is suppose to be the env_var QUERY_OPTS['env_var'] = queries.pop(0) env_var = QUERY_OPTS['env_var'] # # Output # if not queries: if not QUERY_OPTS['package_filter']: err = "Used ENV_VAR without match_expression or --package" raise errors.GentoolkitFatalError(err, is_serious=False) else: if len(matches) > 1: raise errors.AmbiguousPackageName(matches) for match in matches: env = QUERY_OPTS['env_var'] print(match.environment(env)) first_run = True got_match = False for query in queries: if not first_run: print() if CONFIG['verbose']: status = " * Searching for {0} {1} ... " pp.uprint(status.format(env_var, pp.emph(query))) for pkg in matches: if query_in_env(query, env_var, pkg): display_pkg(query, env_var, pkg) got_match = True first_run = False if not got_match: sys.exit(1)