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

from __future__ import print_function

import os
import platform
import signal
import sys

# This block ensures that ^C interrupts are handled quietly. We handle
# KeyboardInterrupt instead of installing a SIGINT handler, since
# exiting from signal handlers intermittently causes python to ignore
# the SystemExit exception with a message like this:
# Exception SystemExit: 130 in <function remove at 0x7fd2146c1320> ignored
global_event_loop = None
token = None
try:

	def exithandler(signum, _frame):
		signal.signal(signal.SIGTERM, signal.SIG_IGN)
		sys.exit(128 + signum)

	signal.signal(signal.SIGTERM, exithandler)
	# Prevent "[Errno 32] Broken pipe" exceptions when
	# writing to a pipe.
	signal.signal(signal.SIGPIPE, signal.SIG_DFL)

	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)

	from portage import telemetry
	telemetry.USE_TELEMETRY = True

	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__))), "lib"))
	import portage
	portage._internal_caller = True
	portage._disable_legacy_globals()
	from portage.util._eventloop.global_event_loop import global_event_loop
	from _emerge.main import emerge_main

	tracer = telemetry.get_tracer(__name__)

	if __name__ == "__main__":
		try:
			telemetry.init()
		except Exception:
			pass

		from portage.exception import IsADirectory, ParseError, \
				PermissionDenied
		portage.process.sanitize_fds()

		span = tracer.start_span(__name__)
		token = telemetry.attach_span(span)

		try:
			retval = emerge_main()
		except PermissionDenied as e:
			span.record_exception(e)
			span.set_status(telemetry.StatusCode.ERROR)
			sys.stderr.write("Permission denied: '%s'\n" % str(e))
			sys.exit(e.errno)
		except IsADirectory as e:
			span.record_exception(e)
			span.set_status(telemetry.StatusCode.ERROR)
			sys.stderr.write("'%s' is a directory, but should be a file!\n"
					"See portage man page for information on "
					"which files may be directories.\n" %
					str(e))
			sys.exit(e.errno)
		except ParseError as e:
			span.record_exception(e)
			span.set_status(telemetry.StatusCode.ERROR)
			sys.stderr.write("%s\n" % str(e))
			sys.exit(1)
		except (KeyboardInterrupt, SystemExit) as e:
			span.record_exception(e)
			raise
		except Exception as e:
			# If an unexpected exception occurs then we don't want the
			# mod_echo output to obscure the traceback, so dump the
			# mod_echo output before showing the traceback.
			span.record_exception(e)
			span.set_status(telemetry.StatusCode.ERROR)
			import traceback
			tb_str = traceback.format_exc()
			try:
				from portage.elog import mod_echo
			except ImportError:
				pass
			else:
				mod_echo.finalize()
			sys.stderr.write(tb_str)
			sys.exit(1)

		span.set_status(telemetry.StatusCode.OK if retval == os.EX_OK else telemetry.StatusCode.ERROR)
		sys.exit(retval)

except KeyboardInterrupt:
	sys.stderr.write("\n\nExiting on signal %(signal)s\n" %
		{"signal": signal.SIGINT})
	sys.stderr.flush()
	sys.exit(128 + signal.SIGINT)
finally:
	if token is not None:
		span = telemetry.get_current_span()
		if span and span.is_recording():
			span.end()

		telemetry.detach_span(token)
	if global_event_loop is not None:
		global_event_loop().close()
