# Copyright 2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

import errno
import re
import subprocess

from portage import os
from portage import _unicode_encode, _encodings
from portage.const import MANIFEST2_IDENTIFIERS
from portage.util import (atomic_ofstream, grablines,
	shlex_split, varexpand, writemsg)
from portage.util._async.PopenProcess import PopenProcess
from _emerge.CompositeTask import CompositeTask
from _emerge.PipeReader import PipeReader
from .ManifestProcess import ManifestProcess

class ManifestTask(CompositeTask):

	__slots__ = ("cp", "distdir", "fetchlist_dict", "gpg_cmd",
		"gpg_vars", "repo_config", "force_sign_key", "_manifest_path")

	_PGP_HEADER = b"BEGIN PGP SIGNED MESSAGE"
	_manifest_line_re = re.compile(r'^(%s) ' % "|".join(MANIFEST2_IDENTIFIERS))
	_gpg_key_id_re = re.compile(r'^[0-9A-F]*$')
	_gpg_key_id_lengths = (8, 16, 24, 32, 40)

	def _start(self):
		self._manifest_path = os.path.join(self.repo_config.location,
			self.cp, "Manifest")
		manifest_proc = ManifestProcess(cp=self.cp, distdir=self.distdir,
			fetchlist_dict=self.fetchlist_dict, repo_config=self.repo_config,
			scheduler=self.scheduler)
		self._start_task(manifest_proc, self._manifest_proc_exit)

	def _manifest_proc_exit(self, manifest_proc):
		self._assert_current(manifest_proc)
		if manifest_proc.returncode not in (os.EX_OK, manifest_proc.MODIFIED):
			self.returncode = manifest_proc.returncode
			self._current_task = None
			self.wait()
			return

		modified = manifest_proc.returncode == manifest_proc.MODIFIED
		sign = self.gpg_cmd is not None

		if not modified and sign:
			sign = self._need_signature()
			if not sign and self.force_sign_key is not None \
				and os.path.exists(self._manifest_path):
				self._check_sig_key()
				return

		if not sign or not os.path.exists(self._manifest_path):
			self.returncode = os.EX_OK
			self._current_task = None
			self.wait()
			return

		self._start_gpg_proc()

	def _check_sig_key(self):
		null_fd = os.open('/dev/null', os.O_RDONLY)
		popen_proc = PopenProcess(proc=subprocess.Popen(
			["gpg", "--verify", self._manifest_path],
			stdin=null_fd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT),
			pipe_reader=PipeReader())
		os.close(null_fd)
		popen_proc.pipe_reader.input_files = {
			"producer" : popen_proc.proc.stdout}
		self._start_task(popen_proc, self._check_sig_key_exit)

	@staticmethod
	def _parse_gpg_key(output):
		"""
		Returns the first token which appears to represent a gpg key
		id, or None if there is no such token.
		"""
		regex = ManifestTask._gpg_key_id_re
		lengths = ManifestTask._gpg_key_id_lengths
		for token in output.split():
			m = regex.match(token)
			if m is not None and len(m.group(0)) in lengths:
				return m.group(0)
		return None

	@staticmethod
	def _normalize_gpg_key(key_str):
		"""
		Strips leading "0x" and trailing "!", and converts to uppercase
		(intended to be the same format as that in gpg --verify output).
		"""
		key_str = key_str.upper()
		if key_str.startswith("0X"):
			key_str = key_str[2:]
		key_str = key_str.rstrip("!")
		return key_str

	def _check_sig_key_exit(self, proc):
		self._assert_current(proc)

		parsed_key = self._parse_gpg_key(
			proc.pipe_reader.getvalue().decode('utf_8', 'replace'))
		if parsed_key is not None and \
			self._normalize_gpg_key(parsed_key) == \
			self._normalize_gpg_key(self.force_sign_key):
			self.returncode = os.EX_OK
			self._current_task = None
			self.wait()
			return

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

		self._strip_sig(self._manifest_path)
		self._start_gpg_proc()

	@staticmethod
	def _strip_sig(manifest_path):
		"""
		Strip an existing signature from a Manifest file.
		"""
		line_re = ManifestTask._manifest_line_re
		lines = grablines(manifest_path)
		f = None
		try:
			f = atomic_ofstream(manifest_path)
			for line in lines:
				if line_re.match(line) is not None:
					f.write(line)
			f.close()
			f = None
		finally:
			if f is not None:
				f.abort()

	def _start_gpg_proc(self):
		gpg_vars = self.gpg_vars
		if gpg_vars is None:
			gpg_vars = {}
		else:
			gpg_vars = gpg_vars.copy()
		gpg_vars["FILE"] = self._manifest_path
		gpg_cmd = varexpand(self.gpg_cmd, mydict=gpg_vars)
		gpg_cmd = shlex_split(gpg_cmd)
		gpg_proc = PopenProcess(proc=subprocess.Popen(gpg_cmd))
		self._start_task(gpg_proc, self._gpg_proc_exit)

	def _gpg_proc_exit(self, gpg_proc):
		if self._default_exit(gpg_proc) != os.EX_OK:
			self.wait()
			return

		rename_args = (self._manifest_path + ".asc", self._manifest_path)
		try:
			os.rename(*rename_args)
		except OSError as e:
			writemsg("!!! rename('%s', '%s'): %s\n" % rename_args + (e,),
				noiselevel=-1)
			try:
				os.unlink(self._manifest_path + ".asc")
			except OSError:
				pass
			self.returncode = 1
		else:
			self.returncode = os.EX_OK

		self._current_task = None
		self.wait()

	def _need_signature(self):
		try:
			with open(_unicode_encode(self._manifest_path,
				encoding=_encodings['fs'], errors='strict'), 'rb') as f:
				return self._PGP_HEADER not in f.readline()
		except IOError as e:
			if e.errno in (errno.ENOENT, errno.ESTALE):
				return False
			raise
