#!/usr/bin/python -O
# Copyright 1999-2011 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

try:
	import portage
except ImportError:
	sys.path.insert(0, pym_path)
	import portage
del pym_path

from portage import os
from portage.util import writemsg, writemsg_stdout
portage.proxy.lazyimport.lazyimport(globals(),
	'subprocess',
	'_emerge.Package:Package',
	'_emerge.RootConfig:RootConfig',
	'portage.dbapi._expand_new_virt:expand_new_virt',
)

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):
	"""<root> <category/package>
	Return code 0 if it's available, 1 otherwise.
	"""
	if (len(argv) < 2):
		print("ERROR: insufficient parameters!")
		sys.exit(2)

	warnings = []

	try:
		atom = portage.dep.Atom(argv[1])
	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], 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:
			sys.exit(0)
		else:
			sys.exit(1)
	except KeyError:
		sys.exit(1)
	except portage.exception.InvalidAtom:
		portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
			noiselevel=-1)
		return 2
has_version.uses_root = True


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

	warnings = []

	try:
		atom = portage.dep.Atom(argv[1])
	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], 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:
		sys.exit(1)
best_version.uses_root = True


def mass_best_version(argv):
	"""<root> [<category/package>]+
	Returns category/package-version (without .ebuild).
	"""
	if (len(argv) < 2):
		print("ERROR: insufficient parameters!")
		sys.exit(2)
	try:
		for pack in argv[1:]:
			mylist=portage.db[argv[0]]["vartree"].dbapi.match(pack)
			print(pack+":"+portage.best(mylist))
	except KeyError:
		sys.exit(1)
mass_best_version.uses_root = True

def metadata(argv):
	if (len(argv) < 4):
		print("ERROR: insufficient parameters!", file=sys.stderr)
		sys.exit(2)

	root, 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)
		sys.exit(1)
	trees = portage.db
	if os.path.realpath(root) == os.path.realpath(portage.settings["ROOT"]):
		root = portage.settings["ROOT"] # contains the normalized $ROOT
	try:
			values = trees[root][type_map[pkgtype]].dbapi.aux_get(
				pkgspec, metakeys)
			writemsg_stdout(''.join('%s\n' % x for x in values), noiselevel=-1)
	except KeyError:
		print("Package not found: '%s'" % pkgspec, file=sys.stderr)
		sys.exit(1)

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

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

def owners(argv):
	"""<root> [<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 <root> 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
	settings = portage.settings
	root = settings["ROOT"]
	vardb = portage.db[root]["vartree"].dbapi

	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(root):
			sys.stderr.write("ERROR: file paths must begin with <root>!\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_root = True

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

def filter_protected(argv):
	"""<root>
	Read filenames from stdin and write them to stdout if they are protected.
	All filenames are delimited by \\n and must begin with <root>.
	"""
	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 <root>!\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_root = True

def best_visible(argv):
	"""<root> [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

	db = portage.db[portage.settings["ROOT"]][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[portage.settings["ROOT"]], None)

	try:
		# reversed, for descending order
		for cpv in reversed(db.match(atom)):
			metadata = dict(zip(Package.metadata_keys,
				db.aux_get(cpv, Package.metadata_keys, myrepo=atom.repo)))
			pkg = Package(built=(pkgtype != "ebuild"), cpv=cpv,
				installed=(pkgtype=="installed"), metadata=metadata,
				root_config=root_config, type_name=pkgtype)
			if pkg.visible:
				writemsg_stdout("%s\n" % (pkg.cpv,), noiselevel=-1)
				return os.EX_OK
	except KeyError:
		pass
	return 1
best_visible.uses_root = True


def mass_best_visible(argv):
	"""<root> [<category/package>]+
	Returns category/package-version (without .ebuild).
	"""
	if (len(argv) < 2):
		print("ERROR: insufficient parameters!")
		sys.exit(2)
	try:
		for pack in argv[1:]:
			mylist=portage.db[argv[0]]["porttree"].dbapi.match(pack)
			print(pack+":"+portage.best(mylist))
	except KeyError:
		sys.exit(1)
mass_best_visible.uses_root = True


def all_best_visible(argv):
	"""<root>
	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_root = True


def match(argv):
	"""<root> <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))
		sys.exit(2)
	root, atom = argv
	if atom:
		if atom_validate_strict and not portage.isvalidatom(atom):
			portage.writemsg("ERROR: Invalid atom: '%s'\n" % atom,
				noiselevel=-1)
			return 2
		results = portage.db[root]["vartree"].dbapi.match(atom)
	else:
		results = portage.db[root]["vartree"].dbapi.cpv_all()
		results.sort()
	for cpv in results:
		print(cpv)
match.uses_root = True

def expand_virtual(argv):
	"""<root> <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_root = 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 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!")
		sys.exit(2)

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

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

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

def list_preserved_libs(argv):
	"""<root>
	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")
		sys.exit(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_root = 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_root = getattr(function, "uses_root", False) and len(sys.argv) > 2
	if uses_root:
		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)
		os.environ["ROOT"] = sys.argv[2]

	args = sys.argv[2:]
	if args and sys.hexversion < 0x3000000 and not isinstance(args[0], unicode):
		for i in range(len(args)):
			args[i] = portage._unicode_decode(args[i])

	try:
		if uses_root:
			args[0] = portage.settings["ROOT"]
		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()

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