#!/usr/bin/python -b
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

from __future__ import print_function, unicode_literals

import argparse
import signal
import sys
# This block ensures that ^C interrupts are handled quietly.
try:

	def exithandler(signum, _frame):
		signal.signal(signal.SIGINT, signal.SIG_IGN)
		signal.signal(signal.SIGTERM, signal.SIG_IGN)
		sys.exit(128 + signum)

	signal.signal(signal.SIGINT, exithandler)
	signal.signal(signal.SIGTERM, exithandler)

except KeyboardInterrupt:
	sys.exit(128 + signal.SIGINT)

import os
import types

if os.path.isfile(os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), ".portage_not_installed")):
	pym_paths = [os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "lib")]
	sys.path.insert(0, pym_paths[0])
else:
	import distutils.sysconfig
	pym_paths = [os.path.join(distutils.sysconfig.get_python_lib(), x) for x in ("_emerge", "portage")]
# Avoid sandbox violations after Python upgrade.
if os.environ.get("SANDBOX_ON") == "1":
	sandbox_write = os.environ.get("SANDBOX_WRITE", "").split(":")
	for pym_path in pym_paths:
		if pym_path not in sandbox_write:
			sandbox_write.append(pym_path)
			os.environ["SANDBOX_WRITE"] = ":".join(filter(None, sandbox_write))
	del pym_path, sandbox_write
del pym_paths

import portage
portage._internal_caller = True
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',
	'_emerge.is_valid_package_atom:insert_category_into_atom',
	'portage.dbapi._expand_new_virt:expand_new_virt',
	'portage._sets.base:InternalPackageSet',
	'portage.util._eventloop.global_event_loop:global_event_loop',
	'portage.xml.metadata:MetaDataXML'
)

def eval_atom_use(atom):
	if 'USE' in os.environ:
		use = frozenset(os.environ['USE'].split())
		atom = atom.evaluate_conditionals(use)
	return atom


def uses_configroot(function):
	function.uses_configroot = True
	return function


def uses_eroot(function):
	function.uses_eroot = True
	return function

# global to hold all function docstrings to be used for argparse help.
# Avoids python compilation level 2 optimization troubles.
docstrings = {}

#-----------------------------------------------------------------------------
#
# To add functionality to this tool, add a function below.
#
# The format for functions is:
#
#   def function(argv):
#       <code>
#
#   docstrings['function'] = """<list of options for this function>
#       <description of the function>
#       """
#   function.__doc__ = docstrings['function']
#
# "argv" is an array of the command line parameters provided after the command.
#
# Make sure you document the function in the right format.  The documentation
# is used to display help on the function.
#
# You do not need to add the function to any lists, this tool is introspective,
# and will automaticly add a command by the same name as the function!
#

@uses_eroot
def has_version(argv):
	if (len(argv) < 2):
		print("ERROR: insufficient parameters!")
		return 3

	warnings = []

	allow_repo = atom_validate_strict is False or eapi_has_repo_deps(eapi)
	try:
		atom = portage.dep.Atom(argv[1], allow_repo=allow_repo)
	except portage.exception.InvalidAtom:
		if atom_validate_strict:
			portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
				noiselevel=-1)
			return 2
		else:
			atom = argv[1]
	else:
		if atom_validate_strict:
			try:
				atom = portage.dep.Atom(argv[1], allow_repo=allow_repo, eapi=eapi)
			except portage.exception.InvalidAtom as e:
				warnings.append("QA Notice: %s: %s" % ('has_version', e))
		atom = eval_atom_use(atom)

	if warnings:
		elog('eqawarn', warnings)

	try:
		mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom)
		if mylist:
			return 0
		else:
			return 1
	except KeyError:
		return 1
	except portage.exception.InvalidAtom:
		portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
			noiselevel=-1)
		return 2

docstrings['has_version'] = """<eroot> <category/package>
	Return code 0 if it's available, 1 otherwise.
	"""
has_version.__doc__ = docstrings['has_version']


@uses_eroot
def best_version(argv):
	if (len(argv) < 2):
		print("ERROR: insufficient parameters!")
		return 3

	warnings = []

	allow_repo = atom_validate_strict is False or eapi_has_repo_deps(eapi)
	try:
		atom = portage.dep.Atom(argv[1], allow_repo=allow_repo)
	except portage.exception.InvalidAtom:
		if atom_validate_strict:
			portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
				noiselevel=-1)
			return 2
		else:
			atom = argv[1]
	else:
		if atom_validate_strict:
			try:
				atom = portage.dep.Atom(argv[1], allow_repo=allow_repo, eapi=eapi)
			except portage.exception.InvalidAtom as e:
				warnings.append("QA Notice: %s: %s" % ('best_version', e))
		atom = eval_atom_use(atom)

	if warnings:
		elog('eqawarn', warnings)

	try:
		mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom)
		print(portage.best(mylist))
	except KeyError:
		return 1

docstrings['best_version'] = """<eroot> <category/package>
	Returns highest installed matching category/package-version (without .ebuild).
	"""
best_version.__doc__ = docstrings['best_version']


@uses_eroot
def mass_best_version(argv):
	if (len(argv) < 2):
		print("ERROR: insufficient parameters!")
		return 2
	try:
		for pack in argv[1:]:
			mylist = portage.db[argv[0]]['vartree'].dbapi.match(pack)
			print('%s:%s' % (pack, portage.best(mylist)))
	except KeyError:
		return 1

docstrings['mass_best_version'] = """<eroot> [<category/package>]+
	Returns category/package-version (without .ebuild).
	"""
mass_best_version.__doc__ = docstrings['mass_best_version']


@uses_eroot
def metadata(argv):
	if (len(argv) < 4):
		print('ERROR: insufficient parameters!', file=sys.stderr)
		return 2

	eroot, pkgtype, pkgspec = argv[0:3]
	metakeys = argv[3:]
	type_map = {
		'ebuild': 'porttree',
		'binary': 'bintree',
		'installed': 'vartree'
	}
	if pkgtype not in type_map:
		print("Unrecognized package type: '%s'" % pkgtype, file=sys.stderr)
		return 1
	trees = portage.db
	repo = portage.dep.dep_getrepo(pkgspec)
	pkgspec = portage.dep.remove_slot(pkgspec)
	try:
		values = trees[eroot][type_map[pkgtype]].dbapi.aux_get(
			pkgspec, metakeys, myrepo=repo)
		writemsg_stdout(''.join('%s\n' % x for x in values), noiselevel=-1)
	except KeyError:
		print("Package not found: '%s'" % pkgspec, file=sys.stderr)
		return 1

docstrings['metadata'] = """
<eroot> <pkgtype> <category/package> [<key>]+
Returns metadata values for the specified package.
Available keys: %s
"""  % ','.join(sorted(x for x in portage.auxdbkeys \
if not x.startswith('UNUSED_')))
metadata.__doc__ = docstrings['metadata']


@uses_eroot
def contents(argv):
	if len(argv) != 2:
		print("ERROR: expected 2 parameters, got %d!" % len(argv))
		return 2

	root, cpv = argv
	vartree = portage.db[root]["vartree"]
	if not vartree.dbapi.cpv_exists(cpv):
		sys.stderr.write("Package not found: '%s'\n" % cpv)
		return 1
	cat, pkg = portage.catsplit(cpv)
	db = portage.dblink(cat, pkg, root, vartree.settings,
		treetype="vartree", vartree=vartree)
	writemsg_stdout(''.join('%s\n' % x for x in sorted(db.getcontents())),
		noiselevel=-1)

docstrings['contents'] = """<eroot> <category/package>
	List the files that are installed for a given package, with
	one file listed on each line. All file names will begin with
	<eroot>.
	"""
contents.__doc__ = docstrings['contents']


@uses_eroot
def owners(argv):
	if len(argv) < 2:
		sys.stderr.write("ERROR: insufficient parameters!\n")
		sys.stderr.flush()
		return 2

	eroot = argv[0]
	vardb = portage.db[eroot]["vartree"].dbapi
	root = portage.settings['ROOT']

	cwd = None
	try:
		cwd = os.getcwd()
	except OSError:
		pass

	files = []
	orphan_abs_paths = set()
	orphan_basenames = set()
	for f in argv[1:]:
		f = portage.normalize_path(f)
		is_basename = os.sep not in f
		if not is_basename and f[:1] != os.sep:
			if cwd is None:
				sys.stderr.write("ERROR: cwd does not exist!\n")
				sys.stderr.flush()
				return 2
			f = os.path.join(cwd, f)
			f = portage.normalize_path(f)
		if not is_basename and not f.startswith(eroot):
			sys.stderr.write("ERROR: file paths must begin with <eroot>!\n")
			sys.stderr.flush()
			return 2
		if is_basename:
			files.append(f)
			orphan_basenames.add(f)
		else:
			files.append(f[len(root)-1:])
			orphan_abs_paths.add(f)

	owners = vardb._owners.get_owners(files)

	msg = []
	for pkg, owned_files in owners.items():
		cpv = pkg.mycpv
		msg.append("%s\n" % cpv)
		for f in sorted(owned_files):
			f_abs = os.path.join(root, f.lstrip(os.path.sep))
			msg.append("\t%s\n" % (f_abs,))
			orphan_abs_paths.discard(f_abs)
			if orphan_basenames:
				orphan_basenames.discard(os.path.basename(f_abs))

	writemsg_stdout(''.join(msg), noiselevel=-1)

	if orphan_abs_paths or orphan_basenames:
		orphans = []
		orphans.extend(orphan_abs_paths)
		orphans.extend(orphan_basenames)
		orphans.sort()
		msg = []
		msg.append("None of the installed packages claim these files:\n")
		for f in orphans:
			msg.append("\t%s\n" % (f,))
		sys.stderr.write("".join(msg))
		sys.stderr.flush()

	if owners:
		return 0
	return 1

docstrings['owners'] = """<eroot> [<filename>]+
	Given a list of files, print the packages that own the files and which
	files belong to each package. Files owned by a package are listed on
	the lines below it, indented by a single tab character (\\t). All file
	paths must either start with <eroot> or be a basename alone.
	Returns 1 if no owners could be found, and 0 otherwise.
	"""
owners.__doc__ = docstrings['owners']


@uses_eroot
def is_protected(argv):
	if len(argv) != 2:
		sys.stderr.write("ERROR: expected 2 parameters, got %d!\n" % len(argv))
		sys.stderr.flush()
		return 2

	root, filename = argv

	err = sys.stderr
	cwd = None
	try:
		cwd = os.getcwd()
	except OSError:
		pass

	f = portage.normalize_path(filename)
	if not f.startswith(os.path.sep):
		if cwd is None:
			err.write("ERROR: cwd does not exist!\n")
			err.flush()
			return 2
		f = os.path.join(cwd, f)
		f = portage.normalize_path(f)

	if not f.startswith(root):
		err.write("ERROR: file paths must begin with <eroot>!\n")
		err.flush()
		return 2

	from portage.util import ConfigProtect

	settings = portage.settings
	protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", ""))
	protect_mask = portage.util.shlex_split(
		settings.get("CONFIG_PROTECT_MASK", ""))
	protect_obj = ConfigProtect(root, protect, protect_mask,
		case_insensitive=("case-insensitive-fs" in settings.features))
	if protect_obj.isprotected(f):
		return 0
	return 1

docstrings['is_protected'] = """<eroot> <filename>
	Given a single filename, return code 0 if it's protected, 1 otherwise.
	The filename must begin with <eroot>.
	"""
is_protected.__doc__ = docstrings['is_protected']


@uses_eroot
def filter_protected(argv):
	if len(argv) != 1:
		sys.stderr.write("ERROR: expected 1 parameter, got %d!\n" % len(argv))
		sys.stderr.flush()
		return 2

	root, = argv
	out = sys.stdout
	err = sys.stderr
	cwd = None
	try:
		cwd = os.getcwd()
	except OSError:
		pass

	from portage.util import ConfigProtect

	settings = portage.settings
	protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", ""))
	protect_mask = portage.util.shlex_split(
		settings.get("CONFIG_PROTECT_MASK", ""))
	protect_obj = ConfigProtect(root, protect, protect_mask,
		case_insensitive=("case-insensitive-fs" in settings.features))

	errors = 0

	for line in sys.stdin:
		filename = line.rstrip("\n")
		f = portage.normalize_path(filename)
		if not f.startswith(os.path.sep):
			if cwd is None:
				err.write("ERROR: cwd does not exist!\n")
				err.flush()
				errors += 1
				continue
			f = os.path.join(cwd, f)
			f = portage.normalize_path(f)

		if not f.startswith(root):
			err.write("ERROR: file paths must begin with <eroot>!\n")
			err.flush()
			errors += 1
			continue

		if protect_obj.isprotected(f):
			out.write("%s\n" % filename)
	out.flush()

	if errors:
		return 2

	return 0

docstrings['filter_protected'] = """<eroot>
	Read filenames from stdin and write them to stdout if they are protected.
	All filenames are delimited by \\n and must begin with <eroot>.
	"""
filter_protected.__doc__ = docstrings['filter_protected']


@uses_eroot
def best_visible(argv):
	if (len(argv) < 2):
		writemsg("ERROR: insufficient parameters!\n", noiselevel=-1)
		return 2

	pkgtype = "ebuild"
	if len(argv) > 2:
		pkgtype = argv[1]
		atom = argv[2]
	else:
		atom = argv[1]

	type_map = {
		"ebuild":"porttree",
		"binary":"bintree",
		"installed":"vartree"}

	if pkgtype not in type_map:
		writemsg("Unrecognized package type: '%s'\n" % pkgtype,
			noiselevel=-1)
		return 2

	eroot = argv[0]
	db = portage.db[eroot][type_map[pkgtype]].dbapi

	try:
		atom = portage.dep_expand(atom, mydb=db, settings=portage.settings)
	except portage.exception.InvalidAtom:
		writemsg("ERROR: Invalid atom: '%s'\n" % atom,
			noiselevel=-1)
		return 2

	root_config = RootConfig(portage.settings, portage.db[eroot], None)

	if hasattr(db, "xmatch"):
		cpv_list = db.xmatch("match-all-cpv-only", atom)
	else:
		cpv_list = db.match(atom)

	if cpv_list:
		# reversed, for descending order
		cpv_list.reverse()
		# verify match, since the atom may match the package
		# for a given cpv from one repo but not another, and
		# we can use match-all-cpv-only to avoid redundant
		# metadata access.
		atom_set = InternalPackageSet(initial_atoms=(atom,))

		if atom.repo is None and hasattr(db, "getRepositories"):
			repo_list = db.getRepositories()
		else:
			repo_list = [atom.repo]

		for cpv in cpv_list:
			for repo in repo_list:
				try:
					metadata = dict(zip(Package.metadata_keys,
						db.aux_get(cpv, Package.metadata_keys, myrepo=repo)))
				except KeyError:
					continue
				pkg = Package(built=(pkgtype != "ebuild"), cpv=cpv,
					installed=(pkgtype=="installed"), metadata=metadata,
					root_config=root_config, type_name=pkgtype)
				if not atom_set.findAtomForPackage(pkg):
					continue

				if pkg.visible:
					writemsg_stdout("%s\n" % (pkg.cpv,), noiselevel=-1)
					return os.EX_OK

	# No package found, write out an empty line.
	writemsg_stdout("\n", noiselevel=-1)

	return 1

docstrings['best_visible'] = """<eroot> [pkgtype] <atom>
	Returns category/package-version (without .ebuild).
	The pkgtype argument defaults to "ebuild" if unspecified,
	otherwise it must be one of ebuild, binary, or installed.
	"""
best_visible.__doc__ = docstrings['best_visible']


@uses_eroot
def mass_best_visible(argv):
	type_map = {
		"ebuild":"porttree",
		"binary":"bintree",
		"installed":"vartree"}

	if (len(argv) < 2):
		print("ERROR: insufficient parameters!")
		return 2
	try:
		root = argv.pop(0)
		pkgtype = "ebuild"
		if argv[0] in type_map:
			pkgtype = argv.pop(0)
		for pack in argv:
			writemsg_stdout("%s:" % pack, noiselevel=-1)
			best_visible([root, pkgtype, pack])
	except KeyError:
		return 1

docstrings['mass_best_visible'] = """<eroot> [<type>] [<category/package>]+
	Returns category/package-version (without .ebuild).
	The pkgtype argument defaults to "ebuild" if unspecified,
	otherwise it must be one of ebuild, binary, or installed.
	"""
mass_best_visible.__doc__ = docstrings['mass_best_visible']


@uses_eroot
def all_best_visible(argv):
	if len(argv) < 1:
		sys.stderr.write("ERROR: insufficient parameters!\n")
		sys.stderr.flush()
		return 2

	#print portage.db[argv[0]]["porttree"].dbapi.cp_all()
	for pkg in portage.db[argv[0]]["porttree"].dbapi.cp_all():
		mybest=portage.best(portage.db[argv[0]]["porttree"].dbapi.match(pkg))
		if mybest:
			print(mybest)

docstrings['all_best_visible'] = """<eroot>
	Returns all best_visible packages (without .ebuild).
	"""
all_best_visible.__doc__ = docstrings['all_best_visible']


@uses_eroot
def match(argv):
	if len(argv) != 2:
		print("ERROR: expected 2 parameters, got %d!" % len(argv))
		return 2
	root, atom = argv
	if not atom:
		atom = "*/*"

	vardb = portage.db[root]["vartree"].dbapi
	try:
		atom = portage.dep.Atom(atom, allow_wildcard=True, allow_repo=True)
	except portage.exception.InvalidAtom:
		# maybe it's valid but missing category
		atom = portage.dep_expand(atom, mydb=vardb, settings=vardb.settings)

	if atom.extended_syntax:
		if atom == "*/*":
			results = vardb.cpv_all()
		else:
			results = []
			require_metadata = atom.slot or atom.repo
			for cpv in vardb.cpv_all():

				if not portage.match_from_list(atom, [cpv]):
					continue

				if require_metadata:
					try:
						cpv = vardb._pkg_str(cpv, atom.repo)
					except (KeyError, portage.exception.InvalidData):
						continue
					if not portage.match_from_list(atom, [cpv]):
						continue

				results.append(cpv)

		results.sort()
	else:
		results = vardb.match(atom)
	for cpv in results:
		print(cpv)

docstrings['match'] = """<eroot> <atom>
	Returns a \\n separated list of category/package-version.
	When given an empty string, all installed packages will
	be listed.
	"""
match.__doc__ = docstrings['match']


@uses_eroot
def expand_virtual(argv):
	if len(argv) != 2:
		writemsg("ERROR: expected 2 parameters, got %d!\n" % len(argv),
			noiselevel=-1)
		return 2

	root, atom = argv

	try:
		results = list(expand_new_virt(
			portage.db[root]["vartree"].dbapi, atom))
	except portage.exception.InvalidAtom:
		writemsg("ERROR: Invalid atom: '%s'\n" % atom,
			noiselevel=-1)
		return 2

	results.sort()
	for x in results:
		if not x.blocker:
			writemsg_stdout("%s\n" % (x,))

	return os.EX_OK

docstrings['expand_virtual'] = """<eroot> <atom>
	Returns a \\n separated list of atoms expanded from a
	given virtual atom (GLEP 37 virtuals only),
	excluding blocker atoms. Satisfied
	virtual atoms are not included in the output, since
	they are expanded to real atoms which are displayed.
	Unsatisfied virtual atoms are displayed without
	any expansion. The "match" command can be used to
	resolve the returned atoms to specific installed
	packages.
	"""
expand_virtual.__doc__ = docstrings['expand_virtual']


def vdb_path(_argv):
	out = sys.stdout
	out.write(os.path.join(portage.settings["EROOT"], portage.VDB_PATH) + "\n")
	out.flush()
	return os.EX_OK

docstrings['vdb_path'] = """
	Returns the path used for the var(installed) package database for the
	set environment/configuration options.
	"""
vdb_path.__doc__ = docstrings['vdb_path']


def gentoo_mirrors(_argv):
	print(portage.settings["GENTOO_MIRRORS"])

docstrings['gentoo_mirrors'] = """
	Returns the mirrors set to use in the portage configuration.
	"""
gentoo_mirrors.__doc__ = docstrings['gentoo_mirrors']


@uses_configroot
@uses_eroot
def repositories_configuration(argv):
	if len(argv) < 1:
		print("ERROR: insufficient parameters!", file=sys.stderr)
		return 3
	sys.stdout.write(portage.db[argv[0]]["vartree"].settings.repositories.config_string())
	sys.stdout.flush()

docstrings['repositories_configuration'] = """<eroot>
	Returns the configuration of repositories.
	"""
repositories_configuration.__doc__ = docstrings['repositories_configuration']


@uses_configroot
@uses_eroot
def repos_config(argv):
	return repositories_configuration(argv)

docstrings['repos_config'] = """
	<eroot>
	This is an alias for the repositories_configuration command.
	"""
repos_config.__doc__ = docstrings['repos_config']


def portdir(_argv):
	print("WARNING: 'portageq portdir' is deprecated. Use the get_repo_path "
		"command instead. eg: "
		"'portageq get_repo_path / gentoo' instead.", file=sys.stderr)
	print(portage.settings["PORTDIR"])

docstrings['portdir'] = """
	Returns the PORTDIR path.
	Deprecated in favor of get_repo_path command.
	"""
portdir.__doc__ = docstrings['portdir']


def config_protect(_argv):
	print(portage.settings["CONFIG_PROTECT"])

docstrings['config_protect'] = """
	Returns the CONFIG_PROTECT paths.
	"""
config_protect.__doc__ = docstrings['config_protect']


def config_protect_mask(_argv):
	print(portage.settings["CONFIG_PROTECT_MASK"])

docstrings['config_protect_mask'] = """
	Returns the CONFIG_PROTECT_MASK paths.
	"""
config_protect_mask.__doc__ = docstrings['config_protect_mask']

def portdir_overlay(_argv):
	print("WARNING: 'portageq portdir_overlay' is deprecated. Use the get_repos"
		" and get_repo_path commands or the repos_config command instead. eg: "
		"'portageq repos_config /'", file=sys.stderr)
	print(portage.settings["PORTDIR_OVERLAY"])

docstrings['portdir_overlay'] = """
	Returns the PORTDIR_OVERLAY path.
	Deprecated in favor of get_repos & get_repo_path or repos_config commands.
	"""
portdir_overlay.__doc__ = docstrings['portdir_overlay']


def pkgdir(_argv):
	print(portage.settings["PKGDIR"])

docstrings['pkgdir'] = """
	Returns the PKGDIR path.
	"""
pkgdir.__doc__ = docstrings['pkgdir']


def distdir(_argv):
	print(portage.settings["DISTDIR"])

docstrings['distdir'] = """
	Returns the DISTDIR path.
	"""
distdir.__doc__ = docstrings['distdir']


def colormap(_argv):
	print(portage.output.colormap())

docstrings['colormap'] = """
	Display the color.map as environment variables.
	"""
colormap.__doc__ = docstrings['colormap']


def envvar(argv):
	verbose = "-v" in argv
	if verbose:
		argv.pop(argv.index("-v"))

	if len(argv) == 0:
		print("ERROR: insufficient parameters!")
		return 2

	exit_status = 0

	for arg in argv:
		if arg in ("PORTDIR", "PORTDIR_OVERLAY", "SYNC"):
			print("WARNING: 'portageq envvar %s' is deprecated. Use any of "
				"'get_repos, get_repo_path, repos_config' instead."
				% arg, file=sys.stderr)

		value = portage.settings.get(arg)
		if value is None:
			value = ""
			exit_status = 1

		if verbose:
			print(arg + "=" + portage._shell_quote(value))
		else:
			print(value)

	return exit_status

docstrings['envvar'] = """<variable>+
	Returns a specific environment variable as exists prior to ebuild.sh.
	Similar to: emerge --verbose --info | egrep '^<variable>='
	"""
envvar.__doc__ = docstrings['envvar']


@uses_eroot
def get_repos(argv):
	if len(argv) < 1:
		print("ERROR: insufficient parameters!")
		return 2
	print(" ".join(reversed(portage.db[argv[0]]["vartree"].settings.repositories.prepos_order)))

docstrings['get_repos'] = """<eroot>
	Returns all repos with names (repo_name file) argv[0] = $EROOT
	"""
get_repos.__doc__ = docstrings['get_repos']


@uses_eroot
def master_repositories(argv):
	if len(argv) < 2:
		print("ERROR: insufficient parameters!", file=sys.stderr)
		return 3
	for arg in argv[1:]:
		if portage.dep._repo_name_re.match(arg) is None:
			print("ERROR: invalid repository: %s" % arg, file=sys.stderr)
			return 2
		try:
			repo = portage.db[argv[0]]["vartree"].settings.repositories[arg]
		except KeyError:
			print("")
			return 1
		else:
			print(" ".join(x.name for x in repo.masters))

docstrings['master_repositories'] = """<eroot> <repo_id>+
	Returns space-separated list of master repositories for specified repository.
	"""
master_repositories.__doc__ = docstrings['master_repositories']


@uses_eroot
def master_repos(argv):
	return master_repositories(argv)

docstrings['master_repos'] = """<eroot> <repo_id>+
	This is an alias for the master_repositories command.
	"""
master_repos.__doc__ = docstrings['master_repos']


@uses_eroot
def get_repo_path(argv):

	if len(argv) < 2:
		print("ERROR: insufficient parameters!", file=sys.stderr)
		return 3
	for arg in argv[1:]:
		if portage.dep._repo_name_re.match(arg) is None:
			print("ERROR: invalid repository: %s" % arg, file=sys.stderr)
			return 2
		path = portage.db[argv[0]]["vartree"].settings.repositories.treemap.get(arg)
		if path is None:
			print("")
			return 1
		print(path)

docstrings['get_repo_path'] = """<eroot> <repo_id>+
	Returns the path to the repo named argv[1], argv[0] = $EROOT
	"""
get_repo_path.__doc__ = docstrings['get_repo_path']


@uses_eroot
def available_eclasses(argv):
	if len(argv) < 2:
		print("ERROR: insufficient parameters!", file=sys.stderr)
		return 3
	for arg in argv[1:]:
		if portage.dep._repo_name_re.match(arg) is None:
			print("ERROR: invalid repository: %s" % arg, file=sys.stderr)
			return 2
		try:
			repo = portage.db[argv[0]]["vartree"].settings.repositories[arg]
		except KeyError:
			print("")
			return 1
		else:
			print(" ".join(sorted(repo.eclass_db.eclasses)))

docstrings['available_eclasses'] = """<eroot> <repo_id>+
	Returns space-separated list of available eclasses for specified repository.
	"""
available_eclasses.__doc__ = docstrings['available_eclasses']


@uses_eroot
def eclass_path(argv):
	if len(argv) < 3:
		print("ERROR: insufficient parameters!", file=sys.stderr)
		return 3
	if portage.dep._repo_name_re.match(argv[1]) is None:
		print("ERROR: invalid repository: %s" % argv[1], file=sys.stderr)
		return 2
	try:
		repo = portage.db[argv[0]]["vartree"].settings.repositories[argv[1]]
	except KeyError:
		print("")
		return 1
	else:
		retval = 0
		for arg in argv[2:]:
			try:
				eclass = repo.eclass_db.eclasses[arg]
			except KeyError:
				print("")
				retval = 1
			else:
				print(eclass.location)
		return retval

docstrings['eclass_path'] = """<eroot> <repo_id> <eclass>+
	Returns the path to specified eclass for specified repository.
	"""
eclass_path.__doc__ = docstrings['eclass_path']


@uses_eroot
def license_path(argv):
	if len(argv) < 3:
		print("ERROR: insufficient parameters!", file=sys.stderr)
		return 3
	if portage.dep._repo_name_re.match(argv[1]) is None:
		print("ERROR: invalid repository: %s" % argv[1], file=sys.stderr)
		return 2
	try:
		repo = portage.db[argv[0]]["vartree"].settings.repositories[argv[1]]
	except KeyError:
		print("")
		return 1
	else:
		retval = 0
		for arg in argv[2:]:
			eclass_path = ""
			paths = reversed([os.path.join(x.location, 'licenses', arg) for x in list(repo.masters) + [repo]])
			for path in paths:
				if os.path.exists(path):
					eclass_path = path
					break
			if eclass_path == "":
				retval = 1
			print(eclass_path)
		return retval

docstrings['license_path'] = """<eroot> <repo_id> <license>+
	Returns the path to specified license for specified repository.
	"""
license_path.__doc__ = docstrings['license_path']


@uses_eroot
def list_preserved_libs(argv):
	if len(argv) != 1:
		print("ERROR: wrong number of arguments")
		return 2
	mylibs = portage.db[argv[0]]["vartree"].dbapi._plib_registry.getPreservedLibs()
	rValue = 1
	msg = []
	for cpv in sorted(mylibs):
		msg.append(cpv)
		for path in mylibs[cpv]:
			msg.append(' ' + path)
			rValue = 0
		msg.append('\n')
	writemsg_stdout(''.join(msg), noiselevel=-1)
	return rValue

docstrings['list_preserved_libs'] = """<eroot>
	Print a list of libraries preserved during a package update in the form
	package: path. Returns 1 if no preserved libraries could be found,
	0 otherwise.
	"""
list_preserved_libs.__doc__ = docstrings['list_preserved_libs']


class MaintainerEmailMatcher(object):
	def __init__(self, maintainer_emails):
		self._re = re.compile("^(%s)$" % "|".join(maintainer_emails), re.I)

	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

# Match if metadata.xml contains no maintainer (orphaned package)
def match_orphaned(metadata_xml):
	if not metadata_xml.maintainers():
		return True
	else:
		return False

def pquery(parser, opts, args):
	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(","))
		if opts.no_regex: # Escape regex-special characters for an exact match
			maintainer_emails = [re.escape(x) for x in maintainer_emails]
		xml_matchers.append(MaintainerEmailMatcher(maintainer_emails))
	if opts.orphaned:
		xml_matchers.append(match_orphaned)

	if opts.repo is not None:
		repos = [portdb.repositories[opts.repo]]
	else:
		repos = list(portdb.repositories)

	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

docstrings['pquery'] = """[options] [atom]+
	Emulates a subset of Pkgcore's pquery tool.
	"""
pquery.__doc__ = docstrings['pquery']


#-----------------------------------------------------------------------------
#
# DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED!
#

non_commands = frozenset(['elog', 'eval_atom_use', 'exithandler', 'match_orphaned', 'main', 'usage', 'uses_eroot'])
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 add_pquery_arguments(parser):
	pquery_option_groups = (
		(
			'Repository matching options',
			(
				{
					"longopt": "--no-filters",
					"action": "store_true",
					"help": "no visibility filters (ACCEPT_KEYWORDS, package masking, etc)"
				},
				{
					"longopt": "--repo",
					"help": "repository to use (all repositories are used by default)"
				},
			)
		),
		(
			'Package matching options',
			(
				{
					"longopt": "--maintainer-email",
					"action": "append",
					"help": "comma-separated list of maintainer email regexes to search for"
				},
				{
					"longopt": "--no-regex",
					"action": "store_true",
					"help": "Use exact matching instead of regex matching for --maintainer-email"
				},
				{
					"longopt": "--orphaned",
					"action": "store_true",
					"help": "match only orphaned (maintainer-needed) packages"
				}
			)
		),
		(
			'Output formatting',
			(
				{
					"shortopt": "-n",
					"longopt": "--no-version",
					"action": "store_true",
					"help": "collapse multiple matching versions together"
				},
			)
		),
	)

	for group_title, opt_data in pquery_option_groups:
		arg_group = parser.add_argument_group(group_title)
		for opt_info in opt_data:
			pargs = []
			try:
				pargs.append(opt_info["shortopt"])
			except KeyError:
				pass
			try:
				pargs.append(opt_info["longopt"])
			except KeyError:
				pass

			kwargs = {}
			try:
				kwargs["action"] = opt_info["action"]
			except KeyError:
				pass
			try:
				kwargs["help"] = opt_info["help"]
			except KeyError:
				pass
			arg_group.add_argument(*pargs, **kwargs)


def usage(argv):
	print(">>> Portage information query tool")
	print(">>> %s" % portage.VERSION)
	print(">>> Usage: portageq <command> [<option> ...]")
	print("")
	print("Available commands:")

	#
	# Show our commands -- we do this by scanning the functions in this
	# file, and formatting each functions documentation.
	#
	help_mode = '--help' in argv
	for name in commands:
		doc = docstrings.get(name)
		if (doc == None):
			print("   " + name)
			print("      MISSING DOCUMENTATION!")
			print("")
			continue

		lines = doc.lstrip("\n").split("\n")
		print("   " + name + " " + lines[0].strip())
		if len(argv) > 1:
			if (not help_mode):
				lines = lines[:-1]
			for line in lines[1:]:
				print("      " + line.strip())

	print()
	print('Pkgcore pquery compatible options:')
	print()
	parser = argparse.ArgumentParser(add_help=False,
		usage='portageq pquery [options] [atom ...]')
	add_pquery_arguments(parser)
	parser.print_help()

	if len(argv) == 1:
		print("\nRun portageq with --help for info")

atom_validate_strict = "EBUILD_PHASE" in os.environ
eapi = None
if atom_validate_strict:
	eapi = os.environ.get('EAPI')

	def elog(elog_funcname, lines):
		cmd = "source '%s/isolated-functions.sh' ; " % \
			os.environ["PORTAGE_BIN_PATH"]
		for line in lines:
			cmd += "%s %s ; " % (elog_funcname, portage._shell_quote(line))
		subprocess.call([portage.const.BASH_BINARY, "-c", cmd])

else:
	def elog(elog_funcname, lines):
		pass

def main(argv):

	argv = portage._decode_argv(argv)

	nocolor = os.environ.get('NOCOLOR')
	if nocolor in ('yes', 'true'):
		portage.output.nocolor()

	parser = argparse.ArgumentParser(add_help=False)

	# used by envvar
	parser.add_argument("-v", dest="verbose", action="store_true")

	actions = parser.add_argument_group('Actions')
	actions.add_argument("-h", "--help", action="store_true")
	actions.add_argument("--version", action="store_true")

	add_pquery_arguments(parser)

	opts, args = parser.parse_known_args(argv[1:])

	if opts.help:
		usage(argv)
		return os.EX_OK
	elif opts.version:
		print("Portage", portage.VERSION)
		return os.EX_OK

	cmd = None
	if args and args[0] in commands:
		cmd = args[0]

	if cmd == 'pquery':
		cmd = None
		args = args[1:]

	if cmd is None:
		return pquery(parser, opts, args)

	if opts.verbose:
		# used by envvar
		args.append("-v")

	argv = argv[:1] + args

	if len(argv) < 2:
		usage(argv)
		sys.exit(os.EX_USAGE)

	function = globals()[cmd]
	uses_eroot = getattr(function, "uses_eroot", False) and len(argv) > 2
	if uses_eroot:
		if not os.path.isdir(argv[2]):
			sys.stderr.write("Not a directory: '%s'\n" % argv[2])
			sys.stderr.write("Run portageq with --help for info\n")
			sys.stderr.flush()
			sys.exit(os.EX_USAGE)
		# Calculate EPREFIX and ROOT that will be used to construct
		# portage.settings later. It's tempting to use
		# portage.settings["EPREFIX"] here, but that would force
		# instantiation of portage.settings, which we don't want to do
		# until after we've calculated ROOT (see bug #529200).
		eprefix = portage.data._target_eprefix()
		eroot = portage.util.normalize_path(argv[2])

		if eprefix:
			if not eroot.endswith(eprefix):
				sys.stderr.write("ERROR: This version of portageq"
						 " only supports <eroot>s ending in"
						 " '%s'. The provided <eroot>, '%s',"
						 " doesn't.\n" % (eprefix, eroot))
				sys.stderr.flush()
				sys.exit(os.EX_USAGE)
			root = eroot[:1 - len(eprefix)]
		else:
			root = eroot

		os.environ["ROOT"] = root

		if getattr(function, "uses_configroot", False):
			os.environ["PORTAGE_CONFIGROOT"] = eroot
			# Disable RepoConfigLoader location validation, allowing raw
			# configuration to pass through, since repo locations are not
			# necessarily expected to exist if the configuration comes
			# from a chroot.
			portage._sync_mode = True

	args = argv[2:]

	try:
		if uses_eroot:
			args[0] = portage.settings['EROOT']
		retval = function(args)
		if retval:
			sys.exit(retval)
	except portage.exception.PermissionDenied as e:
		sys.stderr.write("Permission denied: '%s'\n" % str(e))
		sys.exit(e.errno)
	except portage.exception.ParseError as e:
		sys.stderr.write("%s\n" % str(e))
		sys.exit(1)
	except portage.exception.AmbiguousPackageName as e:
		# Multiple matches thrown from cpv_expand
		pkgs = e.args[0]
		# An error has occurred so we writemsg to stderr and exit nonzero.
		portage.writemsg("You specified an unqualified atom that matched multiple packages:\n", noiselevel=-1)
		for pkg in pkgs:
			portage.writemsg("* %s\n" % pkg, noiselevel=-1)
		portage.writemsg("\nPlease use a more specific atom.\n", noiselevel=-1)
		sys.exit(1)

if __name__ == '__main__':
	try:
		sys.exit(main(sys.argv))
	finally:
		global_event_loop().close()

#-----------------------------------------------------------------------------
