From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <gentoo-commits+bounces-571220-garchives=archives.gentoo.org@lists.gentoo.org>
Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80])
	by finch.gentoo.org (Postfix) with ESMTP id 3D52F198005
	for <garchives@archives.gentoo.org>; Sun, 17 Mar 2013 23:45:13 +0000 (UTC)
Received: from pigeon.gentoo.org (localhost [127.0.0.1])
	by pigeon.gentoo.org (Postfix) with SMTP id BF0CBE055C;
	Sun, 17 Mar 2013 23:45:12 +0000 (UTC)
Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183])
	(using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by pigeon.gentoo.org (Postfix) with ESMTPS id 3835EE055C
	for <gentoo-commits@lists.gentoo.org>; Sun, 17 Mar 2013 23:45:12 +0000 (UTC)
Received: from hornbill.gentoo.org (hornbill.gentoo.org [94.100.119.163])
	(using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by smtp.gentoo.org (Postfix) with ESMTPS id BE6D233BE2C
	for <gentoo-commits@lists.gentoo.org>; Sun, 17 Mar 2013 23:45:10 +0000 (UTC)
Received: from localhost.localdomain (localhost [127.0.0.1])
	by hornbill.gentoo.org (Postfix) with ESMTP id 5EA3CE4073
	for <gentoo-commits@lists.gentoo.org>; Sun, 17 Mar 2013 23:45:09 +0000 (UTC)
From: "Zac Medico" <zmedico@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Content-Transfer-Encoding: 8bit
Content-type: text/plain; charset=UTF-8
Reply-To: gentoo-dev@lists.gentoo.org, "Zac Medico" <zmedico@gentoo.org>
Message-ID: <1363563899.7aab4998882319e668bf48be2279dcbbec4022b9.zmedico@gentoo>
Subject: [gentoo-commits] proj/portage:master commit in: bin/
X-VCS-Repository: proj/portage
X-VCS-Files: bin/portageq
X-VCS-Directories: bin/
X-VCS-Committer: zmedico
X-VCS-Committer-Name: Zac Medico
X-VCS-Revision: 7aab4998882319e668bf48be2279dcbbec4022b9
X-VCS-Branch: master
Date: Sun, 17 Mar 2013 23:45:09 +0000 (UTC)
Precedence: bulk
List-Post: <mailto:gentoo-commits@lists.gentoo.org>
List-Help: <mailto:gentoo-commits+help@lists.gentoo.org>
List-Unsubscribe: <mailto:gentoo-commits+unsubscribe@lists.gentoo.org>
List-Subscribe: <mailto:gentoo-commits+subscribe@lists.gentoo.org>
List-Id: Gentoo Linux mail <gentoo-commits.gentoo.org>
X-BeenThere: gentoo-commits@lists.gentoo.org
X-Archives-Salt: 8dec0afe-1fe7-4295-a2d6-cc0b267e5ab2
X-Archives-Hash: c81c38e1579b544beeb78f2e12a99f64

commit:     7aab4998882319e668bf48be2279dcbbec4022b9
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Sun Mar 17 22:36:54 2013 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Sun Mar 17 23:44:59 2013 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=7aab4998

portageq: emulate subset of Pkgcore's pquery

Pkgcore pquery compatible options:

Repository matching options:
  --repo=REPO           repo to use (default is PORTDIR if omitted)
  --all-repos           search all repos

Package matching options:
  --herd=HERD           exact match on a herd
  --maintainer-email=MAINTAINER_EMAIL
                        comma-separated list of maintainer email regexes to
                        search for

Output formatting:
  -n, --no-version      collapse multiple matching versions together

---
 bin/portageq |  156 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 145 insertions(+), 11 deletions(-)

diff --git a/bin/portageq b/bin/portageq
index 48e7651..d482772 100755
--- a/bin/portageq
+++ b/bin/portageq
@@ -20,6 +20,7 @@ try:
 except KeyboardInterrupt:
 	sys.exit(128 + signal.SIGINT)
 
+import optparse
 import os
 import types
 
@@ -41,11 +42,13 @@ from portage import os
 from portage.eapi import eapi_has_repo_deps
 from portage.util import writemsg, writemsg_stdout
 portage.proxy.lazyimport.lazyimport(globals(),
+	're',
 	'subprocess',
 	'_emerge.Package:Package',
 	'_emerge.RootConfig:RootConfig',
 	'portage.dbapi._expand_new_virt:expand_new_virt',
 	'portage._sets.base:InternalPackageSet',
+	'portage.xml.metadata:MetaDataXML'
 )
 
 def eval_atom_use(atom):
@@ -874,11 +877,11 @@ list_preserved_libs.uses_eroot = True
 # DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED!
 #
 
-non_commands = frozenset(['elog', 'eval_atom_use', 'exithandler', 'main', 'usage'])
+non_commands = frozenset(['elog', 'eval_atom_use', 'exithandler', 'main', 'pquery', 'usage'])
 commands = sorted(k for k, v in globals().items() \
 	if k not in non_commands and isinstance(v, types.FunctionType) and v.__module__ == "__main__")
 
-def usage(argv):
+def usage(argv, parser=None, pquery_option_groups=None):
 	print(">>> Portage information query tool")
 	print(">>> %s" % portage.VERSION)
 	print(">>> Usage: portageq <command> [<option> ...]")
@@ -908,6 +911,15 @@ def usage(argv):
 				lines = lines[:-1]
 			for line in lines[1:]:
 				print("      " + line.strip())
+
+	if pquery_option_groups is not None:
+		parser.formatter.store_option_strings(parser)
+		print()
+		print('Pkgcore pquery compatible options:')
+		print()
+		for optgroup in pquery_option_groups:
+			print(optgroup.format_help(parser.formatter))
+
 	if len(argv) == 1:
 		print("\nRun portageq with --help for info")
 
@@ -927,6 +939,87 @@ else:
 	def elog(elog_funcname, lines):
 		pass
 
+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, pquery_option_groups, opts, args):
+
+	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))
+
+	portdb = portage.db[portage.root]['porttree'].dbapi
+
+	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())
+
+	for category in sorted(portdb.categories):
+		for cp in portdb.cp_all(categories=(category,)):
+			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])
+				matches.extend(cpv_list)
+
+			if not matches:
+				continue
+
+			if opts.no_version:
+				writemsg_stdout("%s\n" % (cp,), noiselevel=-1)
+			else:
+				matches = sorted(set(matches),
+					key=portage.versions.cpv_sort_key())
+				for cpv in matches:
+					writemsg_stdout("%s\n" % (cpv,), noiselevel=-1)
+
+	return os.EX_OK
+
 def main(argv):
 
 	if argv and isinstance(argv[0], bytes):
@@ -936,18 +1029,58 @@ def main(argv):
 	if nocolor in ('yes', 'true'):
 		portage.output.nocolor()
 
+	parser = optparse.OptionParser(add_help_option=False)
+	actions = optparse.OptionGroup(parser, 'Actions')
+	actions.add_option("-h", "--help", action="store_true")
+	actions.add_option("--version", action="store_true")
+	parser.add_option_group(actions)
+
+	pquery_option_groups = []
+
+	repo_optgroup = optparse.OptionGroup(parser,
+		'Repository matching options')
+	repo_optgroup.add_option("--repo", action="store",
+		help="repo to use (default is PORTDIR if omitted)")
+	repo_optgroup.add_option("--all-repos", action="store_true",
+		help="search all repos")
+	parser.add_option_group(repo_optgroup)
+	pquery_option_groups.append(repo_optgroup)
+
+	matching_optgroup = optparse.OptionGroup(parser,
+		'Package matching options')
+	matching_optgroup.add_option("--herd", action="append",
+		help="exact match on a herd")
+	matching_optgroup.add_option("--maintainer-email", action="append",
+		help="comma-separated list of maintainer email regexes to search for")
+	parser.add_option_group(matching_optgroup)
+	pquery_option_groups.append(matching_optgroup)
+
+	formatting_optgroup = optparse.OptionGroup(parser,
+		'Output formatting')
+	formatting_optgroup.add_option("-n", "--no-version", action="store_true",
+		help="collapse multiple matching versions together")
+	parser.add_option_group(formatting_optgroup)
+	pquery_option_groups.append(formatting_optgroup)
+
+	opts, args = parser.parse_args(argv[1:])
+
+	if opts.help:
+		usage(argv, parser=parser, pquery_option_groups=pquery_option_groups)
+		return os.EX_OK
+	elif opts.version:
+		print("Portage", portage.VERSION)
+		return os.EX_OK
+
+	if (opts.herd is not None or
+		opts.maintainer_email is not None):
+		return pquery(parser, pquery_option_groups, opts, args)
+
+	argv = argv[:1] + args
+
 	if len(argv) < 2:
 		usage(argv)
 		sys.exit(os.EX_USAGE)
 
-	for x in argv:
-		if x in ("-h", "--help"):
-			usage(argv)
-			sys.exit(os.EX_OK)
-		elif x == "--version":
-			print("Portage", portage.VERSION)
-			sys.exit(os.EX_OK)
-
 	cmd = argv[1]
 	function = globals().get(cmd)
 	if function is None or cmd not in commands:
@@ -1002,6 +1135,7 @@ def main(argv):
 		portage.writemsg("\nPlease use a more specific atom.\n", noiselevel=-1)
 		sys.exit(1)
 
-main(sys.argv)
+if __name__ == '__main__':
+	sys.exit(main(sys.argv))
 
 #-----------------------------------------------------------------------------