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

from __future__ import print_function

import platform
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)
	# Prevent "[Errno 32] Broken pipe" exceptions when
	# writing to a pipe.
	signal.signal(signal.SIGPIPE, signal.SIG_DFL)

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

def debug_signal(_signum, _frame):
	import pdb
	pdb.set_trace()

if platform.python_implementation() == 'Jython':
	debug_signum = signal.SIGUSR2 # bug #424259
else:
	debug_signum = signal.SIGUSR1

signal.signal(debug_signum, debug_signal)

import io
import os
from os import path as osp
if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")):
	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
import portage
portage._internal_caller = True
from portage import os
from portage import _encodings
from portage import _shell_quote
from portage import _unicode_decode
from portage import _unicode_encode
from portage.const import VDB_PATH
from portage.util._argparse import ArgumentParser
from _emerge.Package import Package
from _emerge.RootConfig import RootConfig

description = "See the ebuild(1) man page for more info"
usage = "Usage: ebuild <ebuild file> <command> [command] ..."
parser = ArgumentParser(description=description, usage=usage)

force_help = "When used together with the digest or manifest " + \
	"command, this option forces regeneration of digests for all " + \
	"distfiles associated with the current ebuild. Any distfiles " + \
	"that do not already exist in ${DISTDIR} will be automatically fetched."

parser.add_argument("--force", help=force_help, action="store_true")
parser.add_argument("--color", help="enable or disable color output",
	choices=("y", "n"))
parser.add_argument("--debug", help="show debug output",
	action="store_true")
parser.add_argument("--version", help="show version and exit",
	action="store_true")
parser.add_argument("--ignore-default-opts",
	action="store_true",
	help="do not use the EBUILD_DEFAULT_OPTS environment variable")
parser.add_argument("--skip-manifest", help="skip all manifest checks",
	action="store_true")

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

def err(txt):
	portage.writemsg('ebuild: %s\n' % (txt,), noiselevel=-1)
	sys.exit(1)

if opts.version:
	print("Portage", portage.VERSION)
	sys.exit(os.EX_OK)

if len(pargs) < 2:
	parser.error("missing required args")

if not opts.ignore_default_opts:
	default_opts = portage.util.shlex_split(
		portage.settings.get("EBUILD_DEFAULT_OPTS", ""))
	opts, pargs = parser.parse_known_args(default_opts + sys.argv[1:])

debug = opts.debug
force = opts.force

import portage.util, portage.const

# do this _after_ 'import portage' to prevent unnecessary tracing
if debug and "python-trace" in portage.features:
	import portage.debug
	portage.debug.set_trace(True)

if not opts.color == 'y' and \
	(opts.color == 'n' or \
	portage.settings.get('NOCOLOR') in ('yes', 'true') or \
	portage.settings.get('TERM') == 'dumb' or \
	not sys.stdout.isatty()):
	portage.output.nocolor()
	portage.settings.unlock()
	portage.settings['NOCOLOR'] = 'true'
	portage.settings.backup_changes('NOCOLOR')
	portage.settings.lock()

ebuild = pargs.pop(0)

pf = None
if ebuild.endswith(".ebuild"):
	pf = os.path.basename(ebuild)[:-7]

if pf is None:
	err("%s: does not end with '.ebuild'" % (ebuild,))

if not os.path.isabs(ebuild):
	mycwd = os.getcwd()
	# Try to get the non-canonical path from the PWD evironment variable, since
	# the canonical path returned from os.getcwd() may may be unusable in
	# cases where the directory stucture is built from symlinks.
	pwd = os.environ.get('PWD', '')
	if sys.hexversion < 0x3000000:
		pwd = _unicode_decode(pwd, encoding=_encodings['content'],
			errors='strict')
	if pwd and pwd != mycwd and \
		os.path.realpath(pwd) == mycwd:
		mycwd = portage.normalize_path(pwd)
	ebuild = os.path.join(mycwd, ebuild)
ebuild = portage.normalize_path(ebuild)
# portdbapi uses the canonical path for the base of the portage tree, but
# subdirectories of the base can be built from symlinks (like crossdev does).
ebuild_portdir = os.path.realpath(
	os.path.dirname(os.path.dirname(os.path.dirname(ebuild))))
ebuild = os.path.join(ebuild_portdir, *ebuild.split(os.path.sep)[-3:])
vdb_path = os.path.realpath(os.path.join(portage.settings['EROOT'], VDB_PATH))

# Make sure that portdb.findname() returns the correct ebuild.
if ebuild_portdir != vdb_path and \
	ebuild_portdir not in portage.portdb.porttrees:
	portdir_overlay = portage.settings.get("PORTDIR_OVERLAY", "")
	if sys.hexversion >= 0x3000000:
		os.environ["PORTDIR_OVERLAY"] = \
			portdir_overlay + \
			" " + _shell_quote(ebuild_portdir)
	else:
		os.environ["PORTDIR_OVERLAY"] = \
			_unicode_encode(portdir_overlay,
			encoding=_encodings['content'], errors='strict') + \
			" " + _unicode_encode(_shell_quote(ebuild_portdir),
			encoding=_encodings['content'], errors='strict')

	print("Appending %s to PORTDIR_OVERLAY..." % ebuild_portdir)
	portage._reset_legacy_globals()

myrepo = None
if ebuild_portdir != vdb_path:
	myrepo = portage.portdb.getRepositoryName(ebuild_portdir)

if not os.path.exists(ebuild):
	err('%s: does not exist' % (ebuild,))

ebuild_split = ebuild.split("/")
cpv = "%s/%s" % (ebuild_split[-3], pf)

with io.open(_unicode_encode(ebuild, encoding=_encodings['fs'], errors='strict'),
	mode='r', encoding=_encodings['repo.content'], errors='replace') as f:
	eapi = portage._parse_eapi_ebuild_head(f)[0]
if eapi is None:
	eapi = "0"
if not portage.catpkgsplit(cpv, eapi=eapi):
	err('%s: %s: does not follow correct package syntax' % (ebuild, cpv))

if ebuild.startswith(vdb_path):
	mytree = "vartree"
	pkg_type = "installed"

	portage_ebuild = portage.db[portage.root][mytree].dbapi.findname(cpv, myrepo=myrepo)

	if os.path.realpath(portage_ebuild) != ebuild:
		err('Portage seems to think that %s is at %s' % (cpv, portage_ebuild))

else:
	mytree = "porttree"
	pkg_type = "ebuild"

	portage_ebuild = portage.portdb.findname(cpv, myrepo=myrepo)

	if not portage_ebuild or portage_ebuild != ebuild:
		err('%s: does not seem to have a valid PORTDIR structure' % (ebuild,))

if len(pargs) > 1 and "config" in pargs:
	other_phases = set(pargs)
	other_phases.difference_update(
		("clean", "config", "digest", "manifest"))
	if other_phases:
		err('"config" must not be called with any other phase')

def discard_digests(myebuild, mysettings, mydbapi):
	"""Discard all distfiles digests for the given ebuild.  This is useful when
	upstream has changed the identity of the distfiles and the user would
	otherwise have to manually remove the Manifest and files/digest-* files in
	order to ensure correct results."""
	try:
		portage._doebuild_manifest_exempt_depend += 1
		pkgdir = os.path.dirname(myebuild)
		fetchlist_dict = portage.FetchlistDict(pkgdir, mysettings, mydbapi)
		mf = mysettings.repositories.get_repo_for_location(
			os.path.dirname(os.path.dirname(pkgdir)))
		mf = mf.load_manifest(pkgdir, mysettings["DISTDIR"],
			fetchlist_dict=fetchlist_dict)
		mf.create(requiredDistfiles=None,
			assumeDistHashesSometimes=True, assumeDistHashesAlways=True)
		distfiles = fetchlist_dict[cpv]
		for myfile in distfiles:
			try:
				del mf.fhashdict["DIST"][myfile]
			except KeyError:
				pass
		mf.write()
	finally:
		portage._doebuild_manifest_exempt_depend -= 1

portage.settings.validate() # generate warning messages if necessary

build_dir_phases = set(["setup", "unpack", "prepare", "configure", "compile",
	"test", "install", "package", "rpm", "merge", "qmerge"])

# If the current metadata is invalid then force the ebuild to be
# sourced again even if $T/environment already exists.
ebuild_changed = False
if mytree == "porttree" and build_dir_phases.intersection(pargs):
	ebuild_changed = \
		portage.portdb._pull_valid_cache(cpv, ebuild, ebuild_portdir)[0] is None

tmpsettings = portage.config(clone=portage.settings)
tmpsettings["PORTAGE_VERBOSE"] = "1"
tmpsettings.backup_changes("PORTAGE_VERBOSE")

if opts.skip_manifest:
	tmpsettings["EBUILD_SKIP_MANIFEST"] = "1"
	tmpsettings.backup_changes("EBUILD_SKIP_MANIFEST")

if opts.skip_manifest or \
	"digest" in tmpsettings.features or \
	"digest" in pargs or \
	"manifest" in pargs:
	portage._doebuild_manifest_exempt_depend += 1

if "test" in pargs:
	# This variable is a signal to config.regenerate() to
	# indicate that the test phase should be enabled regardless
	# of problems such as masked "test" USE flag.
	tmpsettings["EBUILD_FORCE_TEST"] = "1"
	tmpsettings.backup_changes("EBUILD_FORCE_TEST")
	tmpsettings.features.add("test")

tmpsettings.features.discard("fail-clean")

if "merge" in pargs and "noauto" in tmpsettings.features:
	print("Disabling noauto in features... merge disables it. (qmerge doesn't)")
	tmpsettings.features.discard("noauto")

try:
	metadata = dict(zip(Package.metadata_keys,
		portage.db[portage.settings['EROOT']][mytree].dbapi.aux_get(
		cpv, Package.metadata_keys, myrepo=myrepo)))
except KeyError:
	# aux_get failure, message should have been shown on stderr.
	sys.exit(1)

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

pkg = Package(built=(pkg_type != "ebuild"), cpv=cpv,
	installed=(pkg_type=="installed"),
	metadata=metadata, root_config=root_config,
	type_name=pkg_type)

# Apply package.env and repo-level settings. This allows per-package
# FEATURES and other variables (possibly PORTAGE_TMPDIR) to be
# available as soon as possible. Also, note that the only way to ensure
# that setcpv gets metadata from the correct repository is to pass in
# a Package instance, as we do here (previously we had to modify
# portdb.porttrees in order to accomplish this).
tmpsettings.setcpv(pkg)

def stale_env_warning():
	if "clean" not in pargs and \
		"noauto" not in tmpsettings.features and \
		build_dir_phases.intersection(pargs):
		portage.doebuild_environment(ebuild, "setup", portage.root,
			tmpsettings, debug, 1, portage.portdb)
		env_filename = os.path.join(tmpsettings["T"], "environment")
		if os.path.exists(env_filename):
			msg = ("Existing ${T}/environment for '%s' will be sourced. " + \
				"Run 'clean' to start with a fresh environment.") % \
				(tmpsettings["PF"], )
			from textwrap import wrap
			msg = wrap(msg, 70)
			for x in msg:
				portage.writemsg(">>> %s\n" % x)

			if ebuild_changed:
				open(os.path.join(tmpsettings['PORTAGE_BUILDDIR'],
					'.ebuild_changed'), 'w').close()

from portage.exception import PermissionDenied, \
	PortagePackageException, UnsupportedAPIException

if 'digest' in tmpsettings.features:
	if pargs and pargs[0] not in ("digest", "manifest"):
		pargs = ['digest'] + pargs
	# We only need to build digests on the first pass.
	tmpsettings.features.discard('digest')

checked_for_stale_env = False

for arg in pargs:
	try:
		if not checked_for_stale_env and arg not in ("digest","manifest"):
			# This has to go after manifest generation since otherwise
			# aux_get() might fail due to invalid ebuild digests.
			stale_env_warning()
			checked_for_stale_env = True

		if arg in ("digest", "manifest") and force:
			discard_digests(ebuild, tmpsettings, portage.portdb)
		a = portage.doebuild(ebuild, arg, settings=tmpsettings,
			debug=debug, tree=mytree,
			vartree=portage.db[portage.root]['vartree'])
	except KeyboardInterrupt:
		print("Interrupted.")
		a = 1
	except KeyError:
		# aux_get error
		a = 1
	except UnsupportedAPIException as e:
		from textwrap import wrap
		msg = wrap(str(e), 70)
		del e
		for x in msg:
			portage.writemsg("!!! %s\n" % x, noiselevel=-1)
		a = 1
	except PortagePackageException as e:
		portage.writemsg("!!! %s\n" % (e,), noiselevel=-1)
		a = 1
	except PermissionDenied as e:
		portage.writemsg("!!! Permission Denied: %s\n" % (e,), noiselevel=-1)
		a = 1
	if a == None:
		print("Could not run the required binary?")
		a = 127
	if a:
		sys.exit(a)
