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

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

	def exithandler(signum, frame):
		signal.signal(signal.SIGINT, signal.SIG_IGN)
		signal.signal(signal.SIGTERM, signal.SIG_IGN)
		sys.exit(1)

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

except KeyboardInterrupt:
	sys.exit(1)

import os

import types

#-----------------------------------------------------------------------------
#
# 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)
	if atom_validate_strict and not portage.isvalidatom(argv[1]):
		portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
			noiselevel=-1)
		return 2
	try:
		mylist=portage.db[argv[0]]["vartree"].dbapi.match(argv[1])
		if mylist:
			sys.exit(0)
		else:
			sys.exit(1)
	except KeyError:
		sys.exit(1)
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)
	if atom_validate_strict and not portage.isvalidatom(argv[1]):
		portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
			noiselevel=-1)
		return 2
	try:
		mylist=portage.db[argv[0]]["vartree"].dbapi.match(argv[1])
		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):
	"""<root> <pkgtype> <category/package> [<key>]+
	Returns metadata values for the specified package.
	"""
	if (len(argv) < 4):
		print >> sys.stderr, "ERROR: insufficient parameters!"
		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 >> sys.stderr, "Unrecognized package type: '%s'" % pkgtype
		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)
			for value in values:
				print value
	except KeyError:
		print >> sys.stderr, "Package not found: '%s'" % pkgspec
		sys.exit(1)

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)
	file_list = db.getcontents().keys()
	file_list.sort()
	for f in file_list:
		sys.stdout.write("%s\n" % f)
	sys.stdout.flush()
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 = []
	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)
		else:
			files.append(f[len(root)-1:])

	owners = vardb._owners.get_owners(files)

	for pkg, owned_files in owners.iteritems():
		cpv = pkg.mycpv
		sys.stdout.write("%s\n" % cpv)
		for f in sorted(owned_files):
			sys.stdout.write("\t%s\n" % \
				os.path.join(root, f.lstrip(os.path.sep)))
	if owners:
		sys.stdout.flush()
		return 0

	sys.stderr.write("None of the installed packages claim the file(s).\n")
	sys.stderr.flush()
	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

	import shlex
	from portage.util import ConfigProtect

	settings = portage.settings
	protect = shlex.split(settings.get("CONFIG_PROTECT", ""))
	protect_mask = 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

	import shlex
	from portage.util import ConfigProtect

	settings = portage.settings
	protect = shlex.split(settings.get("CONFIG_PROTECT", ""))
	protect_mask = 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> [<category/package>]+
	Returns category/package-version (without .ebuild).
	"""
	if (len(argv) < 2):
		print "ERROR: insufficient parameters!"
		sys.exit(2)
	try:
		mylist=portage.db[argv[0]]["porttree"].dbapi.match(argv[1])
		visible=portage.best(mylist)
		if visible:
			print visible
			sys.exit(0)
		else:
			sys.exit(1)
	except KeyError:
		sys.exit(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):
		print "ERROR: insufficient parameters!"
	
	#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 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["ROOT"], 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:]:
		print portage.db[argv[0]]["porttree"].dbapi.getRepositoryPath(arg)

def list_preserved_libs(argv):
	"""<root>
	Print a list of libraries preserved during a package update in the form
	package: path. Returns 0 if no preserved libraries could be found, 
	1 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 = 0
	for cpv in mylibs:
		print cpv,
		for path in mylibs[cpv]:
			print path,
			rValue = 1
		print
	return rValue
list_preserved_libs.uses_root = True

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

def usage(argv):
	print ">>> Portage information query tool"
	print ">>> $Id$"
	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.
	#
	commands = [x for x in globals() if x not in \
				("usage", "__doc__", "__name__", "main", "os", "portage", \
				"sys", "__builtins__", "types", "string","exithandler")]
	commands.sort()

	for name in commands:
		# Drop non-functions
		obj = globals()[name]
		if  (type(obj) != types.FunctionType):
			continue

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

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

def main():
	if "-h" in sys.argv or "--help" in sys.argv:
		usage(sys.argv)
		sys.exit(os.EX_OK)
	elif len(sys.argv) < 2:
		usage(sys.argv)
		sys.exit(os.EX_USAGE)

	cmd = sys.argv[1]
	function = globals().get(cmd)
	if function is None:
		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]

	# Avoid sandbox violations after python upgrade.
	from os import path as osp
	pym_path = osp.join(osp.dirname(
		osp.dirname(osp.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))

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

	try:
		if uses_root:
			sys.argv[2] = portage.settings["ROOT"]
		retval = function(sys.argv[2:])
		if retval:
			sys.exit(retval)
	except portage.exception.PermissionDenied, e:
		sys.stderr.write("Permission denied: '%s'\n" % str(e))
		sys.exit(e.errno)
	except portage.exception.ParseError, e:
		sys.stderr.write("%s\n" % str(e))
		sys.exit(1)
	except ValueError, e:
		if not e.args or \
			not hasattr(e.args[0], "__len__") or \
			len(e.args[0]) < 2:
			raise
		# 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()

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