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

from __future__ import print_function

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

# Avoid sandbox violations after python upgrade.
pym_path = os.path.join(os.path.dirname(
	os.path.dirname(os.path.realpath(__file__))), "pym")
if os.environ.get("SANDBOX_ON") == "1":
	sandbox_write = os.environ.get("SANDBOX_WRITE", "").split(":")
	if pym_path not in sandbox_write:
		sandbox_write.append(pym_path)
		os.environ["SANDBOX_WRITE"] = \
			":".join(filter(None, sandbox_write))
	del sandbox_write

sys.path.insert(0, pym_path)
import portage
from portage import os
from portage.eapi import eapi_has_repo_deps
from portage.util import writemsg, writemsg_stdout
from portage.output import colormap
portage.proxy.lazyimport.lazyimport(globals(),
	'subprocess',
	'_emerge.Package:Package',
	'_emerge.RootConfig:RootConfig',
	'portage.dbapi._expand_new_virt:expand_new_virt',
	'portage._sets.base:InternalPackageSet',
)

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

#-----------------------------------------------------------------------------
#
# To add functionality to this tool, add a function below.
#
# The format for functions is:
#
#   def function(argv):
#       """<list of options for this function>
#       <description of the function>
#       """
#       <code>
#
# "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!
#

def has_version(argv):
	"""<eroot> <category/package>
	Return code 0 if it's available, 1 otherwise.
	"""
	if (len(argv) < 2):
		print("ERROR: insufficient parameters!")
		return 2

	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(
					portage._unicode_decode("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
has_version.uses_eroot = True


def best_version(argv):
	"""<eroot> <category/package>
	Returns category/package-version (without .ebuild).
	"""
	if (len(argv) < 2):
		print("ERROR: insufficient parameters!")
		return 2

	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(
					portage._unicode_decode("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
best_version.uses_eroot = True


def mass_best_version(argv):
	"""<eroot> [<category/package>]+
	Returns category/package-version (without .ebuild).
	"""
	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(pack+":"+portage.best(mylist))
	except KeyError:
		return 1
mass_best_version.uses_eroot = True

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

metadata.__doc__ = """
<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.uses_eroot = True

def contents(argv):
	"""<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>.
	"""
	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)
contents.uses_eroot = True

def owners(argv):
	"""<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.
	"""
	if len(argv) < 2:
		sys.stderr.write("ERROR: insufficient parameters!\n")
		sys.stderr.flush()
		return 2

	from portage import catsplit, dblink
	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

owners.uses_eroot = True

def is_protected(argv):
	"""<eroot> <filename>
	Given a single filename, return code 0 if it's protected, 1 otherwise.
	The filename must begin with <eroot>.
	"""
	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)

	if protect_obj.isprotected(f):
		return 0
	return 1

is_protected.uses_eroot = True

def filter_protected(argv):
	"""<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>.
	"""
	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)

	protected = 0
	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):
			protected += 1
			out.write("%s\n" % filename)
	out.flush()

	if errors:
		return 2

	return 0

filter_protected.uses_eroot = True

def best_visible(argv):
	"""<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.
	"""
	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
best_visible.uses_eroot = True


def mass_best_visible(argv):
	"""<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.
	"""
	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
mass_best_visible.uses_eroot = True


def all_best_visible(argv):
	"""<eroot>
	Returns all best_visible packages (without .ebuild).
	"""
	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)
all_best_visible.uses_eroot = True


def match(argv):
	"""<eroot> <atom>
	Returns a \\n separated list of category/package-version.
	When given an empty string, all installed packages will
	be listed.
	"""
	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)
match.uses_eroot = True

def expand_virtual(argv):
	"""<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.
	"""
	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

expand_virtual.uses_eroot = True

def vdb_path(argv):
	"""
	Returns the path used for the var(installed) package database for the
	set environment/configuration options.
	"""
	out = sys.stdout
	out.write(os.path.join(portage.settings["EROOT"], portage.VDB_PATH) + "\n")
	out.flush()
	return os.EX_OK

def gentoo_mirrors(argv):
	"""
	Returns the mirrors set to use in the portage configuration.
	"""
	print(portage.settings["GENTOO_MIRRORS"])


def portdir(argv):
	"""
	Returns the PORTDIR path.
	"""
	print(portage.settings["PORTDIR"])


def config_protect(argv):
	"""
	Returns the CONFIG_PROTECT paths.
	"""
	print(portage.settings["CONFIG_PROTECT"])


def config_protect_mask(argv):
	"""
	Returns the CONFIG_PROTECT_MASK paths.
	"""
	print(portage.settings["CONFIG_PROTECT_MASK"])


def portdir_overlay(argv):
	"""
	Returns the PORTDIR_OVERLAY path.
	"""
	print(portage.settings["PORTDIR_OVERLAY"])


def pkgdir(argv):
	"""
	Returns the PKGDIR path.
	"""
	print(portage.settings["PKGDIR"])


def distdir(argv):
	"""
	Returns the DISTDIR path.
	"""
	print(portage.settings["DISTDIR"])


def colormap(argv):
	"""
	Display the color.map as environment variables.
	"""
	print(portage.output.colormap())


def envvar(argv):
	"""<variable>+
	Returns a specific environment variable as exists prior to ebuild.sh.
	Similar to: emerge --verbose --info | egrep '^<variable>='
	"""
	verbose = "-v" in argv
	if verbose:
		argv.pop(argv.index("-v"))

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

	for arg in argv:
		if verbose:
			print(arg +"='"+ portage.settings[arg] +"'")
		else:
			print(portage.settings[arg])

def get_repos(argv):
	"""<eroot>
	Returns all repos with names (repo_name file) argv[0] = $EROOT
	"""
	if len(argv) < 1:
		print("ERROR: insufficient parameters!")
		return 2
	print(" ".join(portage.db[argv[0]]["porttree"].dbapi.getRepositories()))

get_repos.uses_eroot = True

def get_repo_path(argv):
	"""<eroot> <repo_id>+
	Returns the path to the repo named argv[1], argv[0] = $EROOT
	"""
	if len(argv) < 2:
		print("ERROR: insufficient parameters!")
		return 2
	for arg in argv[1:]:
		path = portage.db[argv[0]]["porttree"].dbapi.getRepositoryPath(arg)
		if path is None:
			path = ""
		print(path)

get_repo_path.uses_eroot = True

def list_preserved_libs(argv):
	"""<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.
	"""

	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
list_preserved_libs.uses_eroot = True

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

if not portage.const._ENABLE_PRESERVE_LIBS:
	del list_preserved_libs

non_commands = frozenset(['elog', 'eval_atom_use',
	'exithandler', 'expand_new_virt', 'main',
	'usage', 'writemsg', 'writemsg_stdout'])
commands = sorted(k for k, v in globals().items() \
	if k not in non_commands and isinstance(v, types.FunctionType))

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 sys.argv
	for name in commands:
		# Drop non-functions
		obj = globals()[name]

		doc = obj.__doc__
		if (doc == None):
			print("   " + name)
			print("      MISSING DOCUMENTATION!")
			print("")
			continue

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

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

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

	for x in sys.argv:
		if x in ("-h", "--help"):
			usage(sys.argv)
			sys.exit(os.EX_OK)
		elif x == "--version":
			print("Portage", portage.VERSION)
			sys.exit(os.EX_OK)

	cmd = sys.argv[1]
	function = globals().get(cmd)
	if function is None or cmd not in commands:
		usage(sys.argv)
		sys.exit(os.EX_USAGE)
	function = globals()[cmd]
	uses_eroot = getattr(function, "uses_eroot", False) and len(sys.argv) > 2
	if uses_eroot:
		if not os.path.isdir(sys.argv[2]):
			sys.stderr.write("Not a directory: '%s'\n" % sys.argv[2])
			sys.stderr.write("Run portageq with --help for info\n")
			sys.stderr.flush()
			sys.exit(os.EX_USAGE)
		eprefix = portage.const.EPREFIX
		eroot = portage.util.normalize_path(sys.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

	args = sys.argv[2:]
	if args and isinstance(args[0], bytes):
		for i in range(len(args)):
			args[i] = portage._unicode_decode(args[i])

	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)

main()

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