#!/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 start with <root>. 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)
		if not f.startswith(os.path.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 f.startswith(root):
			sys.stderr.write("ERROR: file paths must begin with <root>!\n")
			sys.stderr.flush()
			return 2
		files.append(f[len(root):])

	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 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()

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