# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

from __future__ import unicode_literals

import functools
import io

import _emerge.emergelog
from _emerge.AsynchronousTask import AsynchronousTask
from _emerge.EbuildExecuter import EbuildExecuter
from _emerge.EbuildPhase import EbuildPhase
from _emerge.EbuildBinpkg import EbuildBinpkg
from _emerge.EbuildFetcher import EbuildFetcher
from _emerge.CompositeTask import CompositeTask
from _emerge.EbuildMerge import EbuildMerge
from _emerge.EbuildFetchonly import EbuildFetchonly
from _emerge.EbuildBuildDir import EbuildBuildDir
from _emerge.MiscFunctionsProcess import MiscFunctionsProcess
from _emerge.TaskSequence import TaskSequence

import portage
from portage import _encodings, _unicode_decode, _unicode_encode, os
from portage.package.ebuild.digestcheck import digestcheck
from portage.package.ebuild.doebuild import _check_temp_dir
from portage.package.ebuild._spawn_nofetch import SpawnNofetchWithoutBuilddir
from portage.util._async.AsyncTaskFuture import AsyncTaskFuture


class EbuildBuild(CompositeTask):

	__slots__ = ("args_set", "config_pool", "find_blockers",
		"ldpath_mtimes", "logger", "opts", "pkg", "pkg_count",
		"prefetcher", "settings", "world_atom") + \
		("_build_dir", "_buildpkg", "_ebuild_path", "_issyspkg", "_tree")

	def _start(self):
		if not self.opts.fetchonly:
			rval = _check_temp_dir(self.settings)
			if rval != os.EX_OK:
				self.returncode = rval
				self._current_task = None
				self._async_wait()
				return

		# First get the SRC_URI metadata (it's not cached in self.pkg.metadata
		# because some packages have an extremely large SRC_URI value).
		self._start_task(
			AsyncTaskFuture(
				future=self.pkg.root_config.trees["porttree"].dbapi.\
				async_aux_get(self.pkg.cpv, ["SRC_URI"], myrepo=self.pkg.repo,
				loop=self.scheduler)),
			self._start_with_metadata)

	def _start_with_metadata(self, aux_get_task):
		self._assert_current(aux_get_task)
		pkg = self.pkg
		settings = self.settings
		root_config = pkg.root_config
		tree = "porttree"
		self._tree = tree
		portdb = root_config.trees[tree].dbapi
		settings.setcpv(pkg)
		settings.configdict["pkg"]["SRC_URI"], = aux_get_task.future.result()
		settings.configdict["pkg"]["EMERGE_FROM"] = "ebuild"
		if self.opts.buildpkgonly:
			settings.configdict["pkg"]["MERGE_TYPE"] = "buildonly"
		else:
			settings.configdict["pkg"]["MERGE_TYPE"] = "source"
		ebuild_path = portdb.findname(pkg.cpv, myrepo=pkg.repo)
		if ebuild_path is None:
			raise AssertionError("ebuild not found for '%s'" % pkg.cpv)
		self._ebuild_path = ebuild_path
		portage.doebuild_environment(ebuild_path, 'setup',
			settings=self.settings, db=portdb)

		# Check the manifest here since with --keep-going mode it's
		# currently possible to get this far with a broken manifest.
		if not self._check_manifest():
			self.returncode = 1
			self._current_task = None
			self._async_wait()
			return

		prefetcher = self.prefetcher
		if prefetcher is None:
			pass
		elif prefetcher.isAlive() and \
			prefetcher.poll() is None:

			if not self.background:
				fetch_log = os.path.join(
					_emerge.emergelog._emerge_log_dir, 'emerge-fetch.log')
				msg = (
					'Fetching files in the background.',
					'To view fetch progress, run in another terminal:',
					'tail -f %s' % fetch_log,
				)
				out = portage.output.EOutput()
				for l in msg:
					out.einfo(l)

			self._current_task = prefetcher
			prefetcher.addExitListener(self._prefetch_exit)
			return

		self._prefetch_exit(prefetcher)

	def _check_manifest(self):
		success = True

		settings = self.settings
		if 'strict' in settings.features and \
			'digest' not in settings.features:
			settings['O'] = os.path.dirname(self._ebuild_path)
			quiet_setting = settings.get('PORTAGE_QUIET')
			settings['PORTAGE_QUIET'] = '1'
			try:
				success = digestcheck([], settings, strict=True)
			finally:
				if quiet_setting:
					settings['PORTAGE_QUIET'] = quiet_setting
				else:
					del settings['PORTAGE_QUIET']

		return success

	def _prefetch_exit(self, prefetcher):

		if self._was_cancelled():
			self.wait()
			return

		opts = self.opts
		pkg = self.pkg
		settings = self.settings

		if opts.fetchonly:
			if opts.pretend:
				fetcher = EbuildFetchonly(
					fetch_all=opts.fetch_all_uri,
					pkg=pkg, pretend=opts.pretend,
					settings=settings)
				retval = fetcher.execute()
				self.returncode = retval
				self.wait()
				return
			else:
				fetcher = EbuildFetcher(
					config_pool=self.config_pool,
					ebuild_path=self._ebuild_path,
					fetchall=self.opts.fetch_all_uri,
					fetchonly=self.opts.fetchonly,
					background=False,
					logfile=None,
					pkg=self.pkg,
					scheduler=self.scheduler)
				self._start_task(fetcher, self._fetchonly_exit)
				return

		self._build_dir = EbuildBuildDir(
			scheduler=self.scheduler, settings=settings)
		self._start_task(
			AsyncTaskFuture(future=self._build_dir.async_lock()),
			self._start_pre_clean)

	def _start_pre_clean(self, lock_task):
		self._assert_current(lock_task)
		lock_task.future.result()
		# Cleaning needs to happen before fetch, since the build dir
		# is used for log handling.
		msg = " === (%s of %s) Cleaning (%s::%s)" % \
			(self.pkg_count.curval, self.pkg_count.maxval,
			self.pkg.cpv, self._ebuild_path)
		short_msg = "emerge: (%s of %s) %s Clean" % \
			(self.pkg_count.curval, self.pkg_count.maxval, self.pkg.cpv)
		self.logger.log(msg, short_msg=short_msg)

		pre_clean_phase = EbuildPhase(background=self.background,
			phase='clean', scheduler=self.scheduler, settings=self.settings)
		self._start_task(pre_clean_phase, self._pre_clean_exit)

	def _fetchonly_exit(self, fetcher):
		self._final_exit(fetcher)
		if self.returncode != os.EX_OK:
			self.returncode = None
			portdb = self.pkg.root_config.trees[self._tree].dbapi
			self._start_task(SpawnNofetchWithoutBuilddir(
				background=self.background,
				portdb=portdb,
				ebuild_path=self._ebuild_path,
				scheduler=self.scheduler,
				settings=self.settings),
				self._nofetch_without_builddir_exit)
			return

		self.wait()

	def _nofetch_without_builddir_exit(self, nofetch):
		self._final_exit(nofetch)
		self.returncode = 1
		self.wait()

	def _pre_clean_exit(self, pre_clean_phase):
		if self._default_exit(pre_clean_phase) != os.EX_OK:
			self._async_unlock_builddir(returncode=self.returncode)
			return

		# for log handling
		portage.prepare_build_dirs(self.pkg.root, self.settings, 1)

		fetcher = EbuildFetcher(config_pool=self.config_pool,
			ebuild_path=self._ebuild_path,
			fetchall=self.opts.fetch_all_uri,
			fetchonly=self.opts.fetchonly,
			background=self.background,
			logfile=self.settings.get('PORTAGE_LOG_FILE'),
			pkg=self.pkg, scheduler=self.scheduler)

		self._start_task(AsyncTaskFuture(
			future=fetcher.async_already_fetched(self.settings)),
			functools.partial(self._start_fetch, fetcher))

	def _start_fetch(self, fetcher, already_fetched_task):
		self._assert_current(already_fetched_task)
		try:
			already_fetched = already_fetched_task.future.result()
		except portage.exception.InvalidDependString as e:
			msg_lines = []
			msg = "Fetch failed for '%s' due to invalid SRC_URI: %s" % \
				(self.pkg.cpv, e)
			msg_lines.append(msg)
			fetcher._eerror(msg_lines)
			portage.elog.elog_process(self.pkg.cpv, self.settings)
			self._async_unlock_builddir(returncode=1)
			return

		if already_fetched:
			# This case is optimized to skip the fetch queue.
			fetcher = None
			self._fetch_exit(fetcher)
			return

		# Allow the Scheduler's fetch queue to control the
		# number of concurrent fetchers.
		fetcher.addExitListener(self._fetch_exit)
		self._task_queued(fetcher)
		self.scheduler.fetch.schedule(fetcher)

	def _fetch_exit(self, fetcher):

		if fetcher is not None and \
			self._default_exit(fetcher) != os.EX_OK:
			self._fetch_failed()
			return

		# discard successful fetch log
		self._build_dir.clean_log()
		pkg = self.pkg
		logger = self.logger
		opts = self.opts
		pkg_count = self.pkg_count
		scheduler = self.scheduler
		settings = self.settings
		features = settings.features
		ebuild_path = self._ebuild_path
		system_set = pkg.root_config.sets["system"]

		#buildsyspkg: Check if we need to _force_ binary package creation
		self._issyspkg = "buildsyspkg" in features and \
				system_set.findAtomForPackage(pkg) and \
				"buildpkg" not in features and \
				opts.buildpkg != 'n'

		if ("buildpkg" in features or self._issyspkg) \
			and not self.opts.buildpkg_exclude.findAtomForPackage(pkg):

			self._buildpkg = True

			msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
				(pkg_count.curval, pkg_count.maxval, pkg.cpv, ebuild_path)
			short_msg = "emerge: (%s of %s) %s Compile" % \
				(pkg_count.curval, pkg_count.maxval, pkg.cpv)
			logger.log(msg, short_msg=short_msg)

		else:
			msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
				(pkg_count.curval, pkg_count.maxval, pkg.cpv, ebuild_path)
			short_msg = "emerge: (%s of %s) %s Compile" % \
				(pkg_count.curval, pkg_count.maxval, pkg.cpv)
			logger.log(msg, short_msg=short_msg)

		build = EbuildExecuter(background=self.background, pkg=pkg,
			scheduler=scheduler, settings=settings)
		self._start_task(build, self._build_exit)

	def _fetch_failed(self):
		# We only call the pkg_nofetch phase if either RESTRICT=fetch
		# is set or the package has explicitly overridden the default
		# pkg_nofetch implementation. This allows specialized messages
		# to be displayed for problematic packages even though they do
		# not set RESTRICT=fetch (bug #336499).

		if 'fetch' not in self.pkg.restrict and \
			'nofetch' not in self.pkg.defined_phases:
			self._async_unlock_builddir(returncode=self.returncode)
			return

		self.returncode = None
		nofetch_phase = EbuildPhase(background=self.background,
			phase='nofetch', scheduler=self.scheduler, settings=self.settings)
		self._start_task(nofetch_phase, self._nofetch_exit)

	def _nofetch_exit(self, nofetch_phase):
		self._final_exit(nofetch_phase)
		self._async_unlock_builddir(returncode=1)

	def _async_unlock_builddir(self, returncode=None):
		"""
		Release the lock asynchronously, and if a returncode parameter
		is given then set self.returncode and notify exit listeners.
		"""
		if returncode is not None:
			# The returncode will be set after unlock is complete.
			self.returncode = None
		portage.elog.elog_process(self.pkg.cpv, self.settings)
		self._start_task(
			AsyncTaskFuture(future=self._build_dir.async_unlock()),
			functools.partial(self._unlock_builddir_exit, returncode=returncode))

	def _unlock_builddir_exit(self, unlock_task, returncode=None):
		self._assert_current(unlock_task)
		# Normally, async_unlock should not raise an exception here.
		unlock_task.future.result()
		if returncode is not None:
			self.returncode = returncode
			self._async_wait()

	def _build_exit(self, build):
		if self._default_exit(build) != os.EX_OK:
			self._async_unlock_builddir(returncode=self.returncode)
			return

		buildpkg = self._buildpkg

		if not buildpkg:
			self._final_exit(build)
			self.wait()
			return

		if self._issyspkg:
			msg = ">>> This is a system package, " + \
				"let's pack a rescue tarball.\n"
			self.scheduler.output(msg,
				log_path=self.settings.get("PORTAGE_LOG_FILE"))

		binpkg_tasks = TaskSequence()
		requested_binpkg_formats = self.settings.get("PORTAGE_BINPKG_FORMAT", "tar").split()
		for pkg_fmt in portage.const.SUPPORTED_BINPKG_FORMATS:
			if pkg_fmt in requested_binpkg_formats:
				if pkg_fmt == "rpm":
					binpkg_tasks.add(EbuildPhase(background=self.background,
						phase="rpm", scheduler=self.scheduler,
						settings=self.settings))
				else:
					task = EbuildBinpkg(
						background=self.background,
						pkg=self.pkg, scheduler=self.scheduler,
						settings=self.settings)
					binpkg_tasks.add(task)
					# Guarantee that _record_binpkg_info is called
					# immediately after EbuildBinpkg. Note that
					# task.addExitListener does not provide the
					# necessary guarantee (see bug 578204).
					binpkg_tasks.add(self._RecordBinpkgInfo(
						ebuild_binpkg=task, ebuild_build=self))

		if binpkg_tasks:
			self._start_task(binpkg_tasks, self._buildpkg_exit)
			return

		self._final_exit(build)
		self.wait()

	class _RecordBinpkgInfo(AsynchronousTask):
		"""
		This class wraps the EbuildBuild _record_binpkg_info method
		with an AsynchronousTask interface, so that it can be
		scheduled as a member of a TaskSequence.
		"""

		__slots__ = ('ebuild_binpkg', 'ebuild_build',)

		def _start(self):
			self.ebuild_build._record_binpkg_info(self.ebuild_binpkg)
			AsynchronousTask._start(self)

	def _buildpkg_exit(self, packager):
		"""
		Released build dir lock when there is a failure or
		when in buildpkgonly mode. Otherwise, the lock will
		be released when merge() is called.
		"""

		if self._default_exit(packager) != os.EX_OK:
			self._async_unlock_builddir(returncode=self.returncode)
			return

		if self.opts.buildpkgonly:
			phase = 'success_hooks'
			success_hooks = MiscFunctionsProcess(
				background=self.background,
				commands=[phase], phase=phase,
				scheduler=self.scheduler, settings=self.settings)
			self._start_task(success_hooks,
				self._buildpkgonly_success_hook_exit)
			return

		# Continue holding the builddir lock until
		# after the package has been installed.
		self._current_task = None
		self.returncode = packager.returncode
		self.wait()

	def _record_binpkg_info(self, task):
		if task.returncode != os.EX_OK:
			return

		# Save info about the created binary package, so that
		# identifying information can be passed to the install
		# task, to be recorded in the installed package database.
		pkg = task.get_binpkg_info()
		infoloc = os.path.join(self.settings["PORTAGE_BUILDDIR"],
			"build-info")
		info = {
			"BINPKGMD5": "%s\n" % pkg._metadata["MD5"],
		}
		if pkg.build_id is not None:
			info["BUILD_ID"] = "%s\n" % pkg.build_id
		for k, v in info.items():
			with io.open(_unicode_encode(os.path.join(infoloc, k),
				encoding=_encodings['fs'], errors='strict'),
				mode='w', encoding=_encodings['repo.content'],
				errors='strict') as f:
				f.write(v)

	def _buildpkgonly_success_hook_exit(self, success_hooks):
		self._default_exit(success_hooks)
		self.returncode = None
		# Need to call "clean" phase for buildpkgonly mode
		portage.elog.elog_process(self.pkg.cpv, self.settings)
		phase = 'clean'
		clean_phase = EbuildPhase(background=self.background,
			phase=phase, scheduler=self.scheduler, settings=self.settings)
		self._start_task(clean_phase, self._clean_exit)

	def _clean_exit(self, clean_phase):
		if self._final_exit(clean_phase) != os.EX_OK or \
			self.opts.buildpkgonly:
			self._async_unlock_builddir(returncode=self.returncode)
		else:
			self.wait()

	def create_install_task(self):
		"""
		Install the package and then clean up and release locks.
		Only call this after the build has completed successfully
		and neither fetchonly nor buildpkgonly mode are enabled.
		"""

		ldpath_mtimes = self.ldpath_mtimes
		logger = self.logger
		pkg = self.pkg
		pkg_count = self.pkg_count
		settings = self.settings
		world_atom = self.world_atom
		ebuild_path = self._ebuild_path
		tree = self._tree

		task = EbuildMerge(exit_hook=self._install_exit,
			find_blockers=self.find_blockers,
			ldpath_mtimes=ldpath_mtimes, logger=logger, pkg=pkg,
			pkg_count=pkg_count, pkg_path=ebuild_path,
			scheduler=self.scheduler,
			settings=settings, tree=tree, world_atom=world_atom)

		msg = " === (%s of %s) Merging (%s::%s)" % \
			(pkg_count.curval, pkg_count.maxval,
			pkg.cpv, ebuild_path)
		short_msg = "emerge: (%s of %s) %s Merge" % \
			(pkg_count.curval, pkg_count.maxval, pkg.cpv)
		logger.log(msg, short_msg=short_msg)

		return task

	def _install_exit(self, task):
		self._async_unlock_builddir()
