+
+
+class MaintainerEmailMatcher(object):
+ def __init__(self, maintainer_emails):
+ self._re = re.compile("^(%s)$" % "|".join(maintainer_emails))
+
+ def __call__(self, metadata_xml):
+ match = False
+ matcher = self._re.match
+ for x in metadata_xml.maintainers():
+ if x.email is not None and matcher(x.email) is not None:
+ match = True
+ break
+ return match
+
+class HerdMatcher(object):
+ def __init__(self, herds):
+ self._herds = frozenset(herds)
+
+ def __call__(self, metadata_xml):
+ herds = self._herds
+ return any(x in herds for x in metadata_xml.herds())
+
+
+def pquery(parser, opts, args):
+ """[options] [atom]+
+ Emulates a subset of Pkgcore's pquery tool.
+ """
+
+ portdb = portage.db[portage.root]['porttree'].dbapi
+ root_config = RootConfig(portdb.settings,
+ portage.db[portage.root], None)
+
+ def _pkg(cpv, repo_name):
+ try:
+ metadata = dict(zip(
+ Package.metadata_keys,
+ portdb.aux_get(cpv,
+ Package.metadata_keys,
+ myrepo=repo_name)))
+ except KeyError:
+ raise portage.exception.PackageNotFound(cpv)
+ return Package(built=False, cpv=cpv,
+ installed=False, metadata=metadata,
+ root_config=root_config,
+ type_name="ebuild")
+
+ need_metadata = False
+ atoms = []
+ for arg in args:
+ if "/" not in arg.split(":")[0]:
+ atom = insert_category_into_atom(arg, '*')
+ if atom is None:
+ writemsg("ERROR: Invalid atom: '%s'\n" % arg,
+ noiselevel=-1)
+ return 2
+ else:
+ atom = arg
+
+ try:
+ atom = portage.dep.Atom(atom, allow_wildcard=True, allow_repo=True)
+ except portage.exception.InvalidAtom:
+ writemsg("ERROR: Invalid atom: '%s'\n" % arg,
+ noiselevel=-1)
+ return 2
+
+ if atom.slot is not None:
+ need_metadata = True
+
+ atoms.append(atom)
+
+ if "*/*" in atoms:
+ del atoms[:]
+ need_metadata = False
+
+ if not opts.no_filters:
+ need_metadata = True
+
+ xml_matchers = []
+ if opts.maintainer_email:
+ maintainer_emails = []
+ for x in opts.maintainer_email:
+ maintainer_emails.extend(x.split(","))
+ xml_matchers.append(MaintainerEmailMatcher(maintainer_emails))
+ if opts.herd is not None:
+ herds = []
+ for x in opts.herd:
+ herds.extend(x.split(","))
+ xml_matchers.append(HerdMatcher(herds))
+
+ repos = []
+ if opts.all_repos:
+ repos.extend(portdb.repositories.get_repo_for_location(location)
+ for location in portdb.porttrees)
+ elif opts.repo is not None:
+ repos.append(portdb.repositories[opts.repo])
+ else:
+ repos.append(portdb.repositories.mainRepo())
+
+ if not atoms:
+ names = None
+ categories = list(portdb.categories)
+ else:
+ category_wildcard = False
+ name_wildcard = False
+ categories = []
+ names = []
+ for atom in atoms:
+ category, name = portage.catsplit(atom.cp)
+ categories.append(category)
+ names.append(name)
+ if "*" in category:
+ category_wildcard = True
+ if "*" in name:
+ name_wildcard = True
+
+ if category_wildcard:
+ categories = list(portdb.categories)
+ else:
+ categories = list(set(categories))
+
+ if name_wildcard:
+ names = None
+ else:
+ names = sorted(set(names))
+
+ no_version = opts.no_version
+ categories.sort()
+
+ for category in categories:
+ if names is None:
+ cp_list = portdb.cp_all(categories=(category,))
+ else:
+ cp_list = [category + "/" + name for name in names]
+ for cp in cp_list:
+ matches = []
+ for repo in repos:
+ match = True
+ if xml_matchers:
+ metadata_xml_path = os.path.join(
+ repo.location, cp, 'metadata.xml')
+ try:
+ metadata_xml = MetaDataXML(metadata_xml_path, None)
+ except (EnvironmentError, SyntaxError):
+ match = False
+ else:
+ for matcher in xml_matchers:
+ if not matcher(metadata_xml):
+ match = False
+ break
+ if not match:
+ continue
+ cpv_list = portdb.cp_list(cp, mytree=[repo.location])
+ if atoms:
+ for cpv in cpv_list:
+ pkg = None
+ for atom in atoms:
+ if atom.repo is not None and \
+ atom.repo != repo.name:
+ continue
+ if not portage.match_from_list(atom, [cpv]):
+ continue
+ if need_metadata:
+ if pkg is None:
+ try:
+ pkg = _pkg(cpv, repo.name)
+ except portage.exception.PackageNotFound:
+ continue
+
+ if not (opts.no_filters or pkg.visible):
+ continue
+ if not portage.match_from_list(atom, [pkg]):
+ continue
+ matches.append(cpv)
+ break
+ if no_version and matches:
+ break
+ elif opts.no_filters:
+ matches.extend(cpv_list)
+ else:
+ for cpv in cpv_list:
+ try:
+ pkg = _pkg(cpv, repo.name)
+ except portage.exception.PackageNotFound:
+ continue
+ else:
+ if pkg.visible:
+ matches.append(cpv)
+ if no_version:
+ break
+
+ if no_version and matches:
+ break
+
+ if not matches:
+ continue
+
+ if no_version:
+ writemsg_stdout("%s\n" % (cp,), noiselevel=-1)
+ else:
+ matches = list(set(matches))
+ portdb._cpv_sort_ascending(matches)
+ for cpv in matches:
+ writemsg_stdout("%s\n" % (cpv,), noiselevel=-1)
+
+ return os.EX_OK
+