aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2012-10-16 06:46:41 (GMT)
committerZac Medico <zmedico@gentoo.org>2012-10-16 06:47:09 (GMT)
commit84ea673c632dea0bc9af61c371f71ca86cc19e1a (patch)
tree749746b7e6a93abf3e6d268dd22246ab46460926
parentAdd Display._append_repository() to avoid duplication of some code. (diff)
downloadportage-84ea673c632dea0bc9af61c371f71ca86cc19e1a.zip
portage-84ea673c632dea0bc9af61c371f71ca86cc19e1a.tar.gz
portage-84ea673c632dea0bc9af61c371f71ca86cc19e1a.tar.bz2
egencache --update-manifests: re-sign when needed
If the Manifest is signed with a different key from the one specified by --gpg-key or PORTAGE_GPG_KEY, strip the existing signature and re-sign the Manifest.
-rwxr-xr-xbin/egencache4
-rw-r--r--pym/portage/package/ebuild/_parallel_manifest/ManifestScheduler.py6
-rw-r--r--pym/portage/package/ebuild/_parallel_manifest/ManifestTask.py86
3 files changed, 92 insertions, 4 deletions
diff --git a/bin/egencache b/bin/egencache
index 15571cb..9d88237 100755
--- a/bin/egencache
+++ b/bin/egencache
@@ -969,6 +969,7 @@ def egencache_main(args):
gpg_cmd = None
gpg_vars = None
+ force_sign_key = None
if options.update_manifests:
if repo_config.sign_manifest:
@@ -1024,6 +1025,8 @@ def egencache_main(args):
if v is not None:
gpg_vars[k] = v
+ force_sign_key = gpg_vars.get("PORTAGE_GPG_KEY")
+
ret = [os.EX_OK]
if options.update:
@@ -1050,6 +1053,7 @@ def egencache_main(args):
event_loop = global_event_loop()
scheduler = ManifestScheduler(portdb, cp_iter=cp_iter,
gpg_cmd=gpg_cmd, gpg_vars=gpg_vars,
+ force_sign_key=force_sign_key,
max_jobs=options.jobs,
max_load=options.load_average,
event_loop=event_loop)
diff --git a/pym/portage/package/ebuild/_parallel_manifest/ManifestScheduler.py b/pym/portage/package/ebuild/_parallel_manifest/ManifestScheduler.py
index 77d4133..3dc9556 100644
--- a/pym/portage/package/ebuild/_parallel_manifest/ManifestScheduler.py
+++ b/pym/portage/package/ebuild/_parallel_manifest/ManifestScheduler.py
@@ -12,7 +12,7 @@ from .ManifestTask import ManifestTask
class ManifestScheduler(AsyncScheduler):
def __init__(self, portdb, cp_iter=None,
- gpg_cmd=None, gpg_vars=None, **kwargs):
+ gpg_cmd=None, gpg_vars=None, force_sign_key=None, **kwargs):
AsyncScheduler.__init__(self, **kwargs)
@@ -23,6 +23,7 @@ class ManifestScheduler(AsyncScheduler):
self._cp_iter = cp_iter
self._gpg_cmd = gpg_cmd
self._gpg_vars = gpg_vars
+ self._force_sign_key = force_sign_key
self._task_iter = self._iter_tasks()
def _next_task(self):
@@ -76,7 +77,8 @@ class ManifestScheduler(AsyncScheduler):
yield ManifestTask(cp=cp, distdir=distdir,
fetchlist_dict=fetchlist_dict, repo_config=repo_config,
- gpg_cmd=self._gpg_cmd, gpg_vars=self._gpg_vars)
+ gpg_cmd=self._gpg_cmd, gpg_vars=self._gpg_vars,
+ force_sign_key=self._force_sign_key)
def _task_exit(self, task):
diff --git a/pym/portage/package/ebuild/_parallel_manifest/ManifestTask.py b/pym/portage/package/ebuild/_parallel_manifest/ManifestTask.py
index 1b954f0..fbb3c88 100644
--- a/pym/portage/package/ebuild/_parallel_manifest/ManifestTask.py
+++ b/pym/portage/package/ebuild/_parallel_manifest/ManifestTask.py
@@ -2,20 +2,28 @@
# 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.util import shlex_split, varexpand, writemsg
+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 _emerge.SpawnProcess import SpawnProcess
from .ManifestProcess import ManifestProcess
class ManifestTask(CompositeTask):
__slots__ = ("cp", "distdir", "fetchlist_dict", "gpg_cmd",
- "gpg_vars", "repo_config", "_manifest_path")
+ "gpg_vars", "repo_config", "force_sign_key", "_manifest_path",
+ "_proc")
_PGP_HEADER = b"BEGIN PGP SIGNED MESSAGE"
+ _manifest_line_re = re.compile(r'^(%s) ' % "|".join(MANIFEST2_IDENTIFIERS))
def _start(self):
self._manifest_path = os.path.join(self.repo_config.location,
@@ -25,6 +33,16 @@ class ManifestTask(CompositeTask):
scheduler=self.scheduler)
self._start_task(manifest_proc, self._manifest_proc_exit)
+ def _cancel(self):
+ if self._proc is not None:
+ self._proc.cancel()
+ CompositeTask._cancel(self)
+
+ def _proc_wait(self):
+ if self._proc is not None:
+ self._proc.wait()
+ self._proc = None
+
def _manifest_proc_exit(self, manifest_proc):
self._assert_current(manifest_proc)
if manifest_proc.returncode not in (os.EX_OK, manifest_proc.MODIFIED):
@@ -38,6 +56,10 @@ class ManifestTask(CompositeTask):
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
@@ -47,6 +69,64 @@ class ManifestTask(CompositeTask):
self._start_gpg_proc()
+ def _check_sig_key(self):
+ self._proc = PopenProcess(proc=subprocess.Popen(
+ ["gpg", "--verify", self._manifest_path],
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT),
+ scheduler=self.scheduler)
+ pipe_reader = PipeReader(
+ input_files={"producer" : self._proc.proc.stdout},
+ scheduler=self.scheduler)
+ self._start_task(pipe_reader, self._check_sig_key_exit)
+
+ @staticmethod
+ def _parse_gpg_key(output):
+ """
+ Returns the last token of the first line, or None if there
+ is no such token.
+ """
+ output = output.splitlines()
+ if output:
+ output = output[0].split()
+ if output:
+ return output[-1]
+ return None
+
+ def _check_sig_key_exit(self, pipe_reader):
+ self._assert_current(pipe_reader)
+
+ parsed_key = self._parse_gpg_key(
+ pipe_reader.getvalue().decode('utf_8', 'replace'))
+ if parsed_key is not None and \
+ parsed_key.lower() in self.force_sign_key.lower():
+ self.returncode = os.EX_OK
+ self._current_task = None
+ self._proc_wait()
+ 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:
@@ -62,6 +142,7 @@ class ManifestTask(CompositeTask):
def _gpg_proc_exit(self, gpg_proc):
if self._default_exit(gpg_proc) != os.EX_OK:
+ self._proc_wait()
self.wait()
return
@@ -80,6 +161,7 @@ class ManifestTask(CompositeTask):
self.returncode = os.EX_OK
self._current_task = None
+ self._proc_wait()
self.wait()
def _need_signature(self):