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

from __future__ import print_function


import sys
import logging
import grp
import pwd
import warnings

import portage
from portage import os
from portage.progress import ProgressBar
#from portage.emaint.defaults import DEFAULT_OPTIONS
from portage.util import writemsg, writemsg_level
from portage.output import create_color_func
good = create_color_func("GOOD")
bad = create_color_func("BAD")
warn = create_color_func("WARN")
from portage.package.ebuild.doebuild import _check_temp_dir
from portage.metadata import action_metadata
from portage.util._async.AsyncFunction import AsyncFunction
from portage import OrderedDict
from portage import _unicode_decode
from portage import util
from _emerge.CompositeTask import CompositeTask


class TaskHandler(object):
	"""Handles the running of the tasks it is given
	"""

	def __init__(self, show_progress_bar=True, verbose=True, callback=None):
		self.show_progress_bar = show_progress_bar
		self.verbose = verbose
		self.callback = callback
		self.isatty = os.environ.get('TERM') != 'dumb' and sys.stdout.isatty()
		self.progress_bar = ProgressBar(self.isatty, title="Portage-Sync", max_desc_length=27)


	def run_tasks(self, tasks, func, status=None, verbose=True, options=None):
		"""Runs the module tasks"""
		# Ensure we have a task and function
		assert(tasks)
		assert(func)
		for task in tasks:
			inst = task()
			show_progress = self.show_progress_bar and self.isatty
			# check if the function is capable of progressbar
			# and possibly override it off
			if show_progress and hasattr(inst, 'can_progressbar'):
				show_progress = inst.can_progressbar(func)
			if show_progress:
				self.progress_bar.reset()
				self.progress_bar.set_label(func + " " + inst.name())
				onProgress = self.progress_bar.start()
			else:
				onProgress = None
			kwargs = {
				'onProgress': onProgress,
				# pass in a copy of the options so a module can not pollute or change
				# them for other tasks if there is more to do.
				'options': options.copy()
				}
			result = getattr(inst, func)(**kwargs)
			if show_progress:
				# make sure the final progress is displayed
				self.progress_bar.display()
				print()
				self.progress_bar.stop()
			if self.callback:
				self.callback(result)


def print_results(results):
	if results:
		print()
		print("\n".join(results))
		print("\n")


class SyncManager(object):
	'''Main sync control module'''

	def __init__(self, settings, logger):
		self.settings = settings
		self.logger = logger
		# Similar to emerge, sync needs a default umask so that created
		# files have sane permissions.
		os.umask(0o22)

		self.module_controller = portage.sync.module_controller
		self.module_names = self.module_controller.module_names
		self.hooks = {}
		for _dir in ["repo.postsync.d", "postsync.d"]:
			postsync_dir = os.path.join(self.settings["PORTAGE_CONFIGROOT"],
				portage.USER_CONFIG_PATH, _dir)
			hooks = OrderedDict()
			for filepath in util._recursive_file_list(postsync_dir):
				name = filepath.split(postsync_dir)[1].lstrip(os.sep)
				if os.access(filepath, os.X_OK):
					hooks[filepath] = name
				else:
					writemsg_level(" %s %s hook: '%s' is not executable\n"
						% (warn("*"), _dir, _unicode_decode(name),),
						level=logging.WARN, noiselevel=2)
			self.hooks[_dir] = hooks

	def __getattr__(self, name):
		if name == 'async':
			warnings.warn("portage.sync.controller.SyncManager.async "
				"has been renamed to sync_async",
				DeprecationWarning, stacklevel=2)
			return self.sync_async
		else:
			raise AttributeError(name)

	def get_module_descriptions(self, mod):
		desc = self.module_controller.get_func_descriptions(mod)
		if desc:
			return desc
		return []

	def sync_async(self, emerge_config=None, repo=None, master_hooks=True):
		self.emerge_config = emerge_config
		self.settings, self.trees, self.mtimedb = emerge_config
		self.xterm_titles = "notitles" not in self.settings.features
		self.portdb = self.trees[self.settings['EROOT']]['porttree'].dbapi
		return SyncRepo(sync_task=AsyncFunction(target=self.sync,
			kwargs=dict(emerge_config=emerge_config, repo=repo,
			master_hooks=master_hooks)),
			sync_callback=self._sync_callback)

	def sync(self, emerge_config=None, repo=None, master_hooks=True):
		self.callback = None
		self.repo = repo
		self.exitcode = 1
		self.updatecache_flg = False
		hooks_enabled = master_hooks or not repo.sync_hooks_only_on_change
		if repo.sync_type in self.module_names:
			tasks = [self.module_controller.get_class(repo.sync_type)]
		else:
			msg = "\n%s: Sync module '%s' is not an installed/known type'\n" \
				% (bad("ERROR"), repo.sync_type)
			return self.exitcode, msg, self.updatecache_flg, hooks_enabled

		rval = self.pre_sync(repo)
		if rval != os.EX_OK:
			return rval, None, self.updatecache_flg, hooks_enabled

		# need to pass the kwargs dict to the modules
		# so they are available if needed.
		task_opts = {
			'emerge_config': emerge_config,
			'logger': self.logger,
			'portdb': self.portdb,
			'repo': repo,
			'settings': self.settings,
			'spawn_kwargs': self.spawn_kwargs,
			'usersync_uid': self.usersync_uid,
			'xterm_titles': self.xterm_titles,
			}
		func = 'sync'
		status = None
		taskmaster = TaskHandler(callback=self.do_callback)
		taskmaster.run_tasks(tasks, func, status, options=task_opts)

		if (master_hooks or self.updatecache_flg or
			not repo.sync_hooks_only_on_change):
			hooks_enabled = True
			self.perform_post_sync_hook(
				repo.name, repo.sync_uri, repo.location)

		return self.exitcode, None, self.updatecache_flg, hooks_enabled


	def do_callback(self, result):
		#print("result:", result, "callback()", self.callback)
		exitcode, updatecache_flg = result
		self.exitcode = exitcode
		self.updatecache_flg = updatecache_flg
		if exitcode == 0:
			msg = "=== Sync completed for %s" % self.repo.name
			self.logger(self.xterm_titles, msg)
			writemsg_level(msg + "\n")
		if self.callback:
			self.callback(exitcode, updatecache_flg)
		return


	def perform_post_sync_hook(self, reponame, dosyncuri='', repolocation=''):
		succeeded = os.EX_OK
		if reponame:
			_hooks = self.hooks["repo.postsync.d"]
		else:
			_hooks = self.hooks["postsync.d"]
		for filepath in _hooks:
			writemsg_level("Spawning post_sync hook: %s\n"
				% (_unicode_decode(_hooks[filepath])),
				level=logging.ERROR, noiselevel=4)
			if reponame:
				retval = portage.process.spawn(
					[filepath, reponame, dosyncuri, repolocation],
					env=self.settings.environ())
			else:
				retval = portage.process.spawn([filepath],
					env=self.settings.environ())
			if retval != os.EX_OK:
				writemsg_level(" %s Spawn failed for: %s, %s\n" % (bad("*"),
					_unicode_decode(_hooks[filepath]), filepath),
					level=logging.ERROR, noiselevel=-1)
				succeeded = retval
		return succeeded


	def pre_sync(self, repo):
		msg = ">>> Syncing repository '%s' into '%s'..." \
			% (repo.name, repo.location)
		self.logger(self.xterm_titles, msg)
		writemsg_level(msg + "\n")
		try:
			st = os.stat(repo.location)
		except OSError:
			st = None

		self.usersync_uid = None
		spawn_kwargs = {}
		# Redirect command stderr to stdout, in order to prevent
		# spurious cron job emails (bug 566132).
		spawn_kwargs["fd_pipes"] = {
			0: sys.__stdin__.fileno(),
			1: sys.__stdout__.fileno(),
			2: sys.__stdout__.fileno()
		}
		spawn_kwargs["env"] = self.settings.environ()
		if repo.sync_user is not None:
			def get_sync_user_data(sync_user):
				user = None
				group = None
				home = None
				logname = None

				spl = sync_user.split(':', 1)
				if spl[0]:
					username = spl[0]
					try:
						try:
							pw = pwd.getpwnam(username)
						except KeyError:
							pw = pwd.getpwuid(int(username))
					except (ValueError, KeyError):
						writemsg("!!! User '%s' invalid or does not exist\n"
								% username, noiselevel=-1)
						return (logname, user, group, home)
					user = pw.pw_uid
					group = pw.pw_gid
					home = pw.pw_dir
					logname = pw.pw_name

				if len(spl) > 1:
					groupname = spl[1]
					try:
						try:
							gp = grp.getgrnam(groupname)
						except KeyError:
							pw = grp.getgrgid(int(groupname))
					except (ValueError, KeyError):
						writemsg("!!! Group '%s' invalid or does not exist\n"
								% groupname, noiselevel=-1)
						return (logname, user, group, home)

					group = gp.gr_gid

				return (logname, user, group, home)

			# user or user:group
			(logname, uid, gid, home) = get_sync_user_data(
				repo.sync_user)
			if uid is not None:
				spawn_kwargs["uid"] = uid
				self.usersync_uid = uid
			if gid is not None:
				spawn_kwargs["gid"] = gid
				spawn_kwargs["groups"] = [gid]
			if home is not None:
				spawn_kwargs["env"]["HOME"] = home
			if logname is not None:
				spawn_kwargs["env"]["LOGNAME"] = logname

		if st is None:
			perms = {'mode': 0o755}
			# respect sync-user if set
			if 'umask' in spawn_kwargs:
				perms['mode'] &= ~spawn_kwargs['umask']
			if 'uid' in spawn_kwargs:
				perms['uid'] = spawn_kwargs['uid']
			if 'gid' in spawn_kwargs:
				perms['gid'] = spawn_kwargs['gid']

			portage.util.ensure_dirs(repo.location, **perms)
			st = os.stat(repo.location)

		if (repo.sync_user is None and
			'usersync' in self.settings.features and
			portage.data.secpass >= 2 and
			(st.st_uid != os.getuid() and st.st_mode & 0o700 or
			st.st_gid != os.getgid() and st.st_mode & 0o070)):
			try:
				pw = pwd.getpwuid(st.st_uid)
			except KeyError:
				pass
			else:
				# Drop privileges when syncing, in order to match
				# existing uid/gid settings.
				self.usersync_uid = st.st_uid
				spawn_kwargs["uid"]    = st.st_uid
				spawn_kwargs["gid"]    = st.st_gid
				spawn_kwargs["groups"] = [st.st_gid]
				spawn_kwargs["env"]["HOME"] = pw.pw_dir
				spawn_kwargs["env"]["LOGNAME"] = pw.pw_name
				umask = 0o002
				if not st.st_mode & 0o020:
					umask = umask | 0o020
				spawn_kwargs["umask"] = umask
		# override the defaults when sync_umask is set
		if repo.sync_umask is not None:
			spawn_kwargs["umask"] = int(repo.sync_umask, 8)
		self.spawn_kwargs = spawn_kwargs

		if self.usersync_uid is not None:
			# PORTAGE_TMPDIR is used below, so validate it and
			# bail out if necessary.
			rval = _check_temp_dir(self.settings)
			if rval != os.EX_OK:
				return rval

		os.umask(0o022)
		return os.EX_OK

	def _sync_callback(self, proc):
		"""
		This is called in the parent process, serially, for each of the
		sync jobs when they complete. Some cache backends such as sqlite
		may require that cache access be performed serially in the
		parent process like this.
		"""
		repo = proc.kwargs['repo']
		exitcode = proc.returncode
		updatecache_flg = False
		if proc.returncode == os.EX_OK:
			exitcode, message, updatecache_flg, hooks_enabled = proc.result

		if updatecache_flg and "metadata-transfer" not in self.settings.features:
			updatecache_flg = False

		if updatecache_flg and \
			os.path.exists(os.path.join(
			repo.location, 'metadata', 'md5-cache')):

			# Only update cache for repo.location since that's
			# the only one that's been synced here.
			action_metadata(self.settings, self.portdb, self.emerge_config.opts,
				porttrees=[repo.location])


class SyncRepo(CompositeTask):
	"""
	Encapsulates a sync operation and the callback which executes afterwards,
	so both can be considered as a single composite task. This is useful
	since we don't want to consider a particular repo's sync operation as
	complete until after the callback has executed (bug 562264).

	The kwargs and result properties expose attributes that are accessed
	by SyncScheduler.
	"""

	__slots__ = ('sync_task', 'sync_callback')

	@property
	def kwargs(self):
		return self.sync_task.kwargs

	@property
	def result(self):
		return self.sync_task.result

	def _start(self):
		self._start_task(self.sync_task, self._sync_task_exit)

	def _sync_task_exit(self, sync_task):
		self._current_task = None
		self.returncode = sync_task.returncode
		self.sync_callback(self.sync_task)
		self._async_wait()

