Skip to content

Instantly share code, notes, and snippets.

@robbat2
Created May 9, 2018 21:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robbat2/551fc8ea56408ee48e99909f9c26c13e to your computer and use it in GitHub Desktop.
Save robbat2/551fc8ea56408ee48e99909f9c26c13e to your computer and use it in GitHub Desktop.
portage --refresh-keys
diff --git a/cnf/repos.conf b/cnf/repos.conf
index 987be6462..f720dc906 100644
--- a/cnf/repos.conf
+++ b/cnf/repos.conf
@@ -10,6 +10,7 @@ sync-rsync-verify-jobs = 1
sync-rsync-verify-metamanifest = yes
sync-rsync-verify-max-age = 24
sync-openpgp-key-path = /var/lib/gentoo/gkeys/keyrings/gentoo/release/pubring.gpg
+sync-openpgp-key-refresh = true
sync-openpgp-key-refresh-retry-count = 40
sync-openpgp-key-refresh-retry-overall-timeout = 1200
sync-openpgp-key-refresh-retry-delay-exp-base = 2
diff --git a/man/emerge.1 b/man/emerge.1
index f53ba92f5..fef3e390a 100644
--- a/man/emerge.1
+++ b/man/emerge.1
@@ -746,6 +746,14 @@ matching packages due to \fB\-\-rebuild\fR.
A space separated list of package names or slot atoms. Emerge will not rebuild
packages that depend on matching packages due to \fB\-\-rebuild\fR.
.TP
+.BR "\-\-refresh\-keys [ y | n ]"
+If specified as a standalone action, starts a OpenPGP key refresh.
+
+If combined with the \fB\-\-sync\fR action , allows the user to globally
+disable OpenPGP key refresh during repositories sync. See also
+\fBsync\-openpgp\-key\-refresh\fR in \fBportage\fR(5) for more finely grained
+control.
+.TP
.BR \-\-oneshot ", " \-1
Emerge as normal, but do not add the packages to the world file
for later updating.
diff --git a/man/portage.5 b/man/portage.5
index 5adb07d82..c2a19e1f2 100644
--- a/man/portage.5
+++ b/man/portage.5
@@ -1081,6 +1081,9 @@ only for protocols supporting cryptographic verification, provided
that the respective verification option is enabled. If unset, the user's
keyring is used.
.TP
+.B sync\-openpgp\-key\-refresh = true|false
+Controls automatic OpenPGP key refresh for this repository. Defaults to true.
+.TP
.B sync\-openpgp\-key\-refresh\-retry\-count = 40
Maximum number of times to retry key refresh if it fails. Between each
key refresh attempt, there is an exponential delay with a constant
diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py
index 70fb8d3b4..61497274c 100644
--- a/pym/_emerge/actions.py
+++ b/pym/_emerge/actions.py
@@ -1976,6 +1976,10 @@ def action_info(settings, trees, myopts, myfiles):
tree="bintree")
shutil.rmtree(tmpdir)
+def action_refresh_keys(emerge_config):
+ # TODO
+ pass
+
def action_regen(settings, portdb, max_jobs, max_load):
xterm_titles = "notitles" not in settings.features
emergelog(xterm_titles, " === regen")
@@ -3201,6 +3205,9 @@ def run_action(emerge_config):
emerge_config.target_config.trees['porttree'].dbapi,
emerge_config.opts.get("--jobs"),
emerge_config.opts.get("--load-average"))
+ # REFRESH_KEYS action
+ elif "refresh_keys" == emerge_config.action:
+ return action_refresh_keys(emerge_config)
# HELP action
elif "config" == emerge_config.action:
validate_ebuild_environment(emerge_config.trees)
diff --git a/pym/_emerge/main.py b/pym/_emerge/main.py
index e8b2c2e13..fd7ed8438 100644
--- a/pym/_emerge/main.py
+++ b/pym/_emerge/main.py
@@ -162,6 +162,7 @@ def insert_optional_args(args):
'--rebuild-if-new-ver' : y_or_n,
'--rebuild-if-unbuilt' : y_or_n,
'--rebuilt-binaries' : y_or_n,
+ '--refresh-keys' : y_or_n,
'--root-deps' : ('rdeps',),
'--select' : y_or_n,
'--selective' : y_or_n,
@@ -306,6 +307,9 @@ def parse_opts(tmpcmdline, silent=False):
"info", "list-sets", "metadata", "moo",
"prune", "rage-clean", "regen", "search",
"sync", "unmerge", "version",
+ # The following are both valid options AND actions:
+ # --refresh-keys
+ # --deselect
])
longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
@@ -692,6 +696,11 @@ def parse_opts(tmpcmdline, silent=False):
"action" : "store"
},
+ "--refresh-keys": {
+ "help" : "refresh OpenPGP keys as needed to verify repos",
+ "choices" : true_y_or_n
+ },
+
"--root": {
"help" : "specify the target root filesystem for merging packages",
"action" : "store"
@@ -915,6 +924,9 @@ def parse_opts(tmpcmdline, silent=False):
parser.error("Invalid Atom(s) in --rebuild-ignore parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
(",".join(bad_atoms),))
+ if myoptions.refresh_keys is None or myoptions.refresh_keys in true_y:
+ myoptions.refresh_keys = True # refresh keys by default, or if set to true/yes
+
if myoptions.usepkg_exclude:
bad_atoms = _find_bad_atoms(myoptions.usepkg_exclude)
if bad_atoms and not silent:
@@ -1155,6 +1167,9 @@ def parse_opts(tmpcmdline, silent=False):
if myaction is None and myoptions.deselect is True:
myaction = 'deselect'
+ if myaction is None and '--refresh-keys' in tmpcmdline and myoptions.refresh_keys is True:
+ myaction = 'refresh_keys'
+
myfiles += myargs
return myaction, myopts, myfiles
diff --git a/pym/portage/repository/config.py b/pym/portage/repository/config.py
index 1d897bb90..f82fc16e3 100644
--- a/pym/portage/repository/config.py
+++ b/pym/portage/repository/config.py
@@ -87,6 +87,7 @@ class RepoConfig(object):
'update_changelog', '_eapis_banned', '_eapis_deprecated',
'_masters_orig', 'module_specific_options', 'manifest_required_hashes',
'sync_openpgp_key_path',
+ 'sync_openpgp_key_refresh',
'sync_openpgp_key_refresh_retry_count',
'sync_openpgp_key_refresh_retry_delay_max',
'sync_openpgp_key_refresh_retry_delay_exp_base',
@@ -191,6 +192,9 @@ class RepoConfig(object):
self.sync_openpgp_key_path = repo_opts.get(
'sync-openpgp-key-path', None)
+ self.sync_openpgp_key_refresh = repo_opts.get(
+ 'sync-openpgp-key-refresh', 'true').lower() == 'true'
+
for k in ('sync_openpgp_key_refresh_retry_count',
'sync_openpgp_key_refresh_retry_delay_max',
'sync_openpgp_key_refresh_retry_delay_exp_base',
diff --git a/pym/portage/sync/modules/git/git.py b/pym/portage/sync/modules/git/git.py
index 160137a6d..9b9d566f1 100644
--- a/pym/portage/sync/modules/git/git.py
+++ b/pym/portage/sync/modules/git/git.py
@@ -147,6 +147,9 @@ class GitSync(NewBase):
return (os.EX_OK, current_rev != previous_rev)
def verify_head(self):
+ opts = self.options.get('emerge_config').opts
+ openpgp_refresh = '--refresh-keys' in opts
+
if (self.repo.module_specific_options.get(
'sync-git-verify-commit-signature', 'false') != 'true'):
return True
@@ -168,9 +171,10 @@ class GitSync(NewBase):
out.einfo('Using keys from %s' % (self.repo.sync_openpgp_key_path,))
with io.open(self.repo.sync_openpgp_key_path, 'rb') as f:
openpgp_env.import_key(f)
- out.ebegin('Refreshing keys from keyserver')
- openpgp_env.refresh_keys()
- out.eend(0)
+ if self.repo.sync_openpgp_key_refresh and openpgp_refresh:
+ out.ebegin('Refreshing keys from keyserver')
+ openpgp_env.refresh_keys()
+ out.eend(0)
except GematoException as e:
writemsg_level("!!! Verification impossible due to keyring problem:\n%s\n"
% (e,),
diff --git a/pym/portage/sync/modules/rsync/rsync.py b/pym/portage/sync/modules/rsync/rsync.py
index 382a1eaae..6d7108721 100644
--- a/pym/portage/sync/modules/rsync/rsync.py
+++ b/pym/portage/sync/modules/rsync/rsync.py
@@ -67,6 +67,7 @@ class RsyncSync(NewBase):
opts = self.options.get('emerge_config').opts
self.usersync_uid = self.options.get('usersync_uid', None)
enter_invalid = '--ask-enter-invalid' in opts
+ openpgp_refresh = '--refresh-keys' in opts
quiet = '--quiet' in opts
out = portage.output.EOutput(quiet=quiet)
syncuri = self.repo.sync_uri
@@ -154,34 +155,35 @@ class RsyncSync(NewBase):
out.einfo('Using keys from %s' % (self.repo.sync_openpgp_key_path,))
with io.open(self.repo.sync_openpgp_key_path, 'rb') as f:
openpgp_env.import_key(f)
- out.ebegin('Refreshing keys from keyserver')
- retry_decorator = self._key_refresh_retry_decorator()
- if retry_decorator is None:
- openpgp_env.refresh_keys()
- else:
- def noisy_refresh_keys():
- """
- Since retry does not help for some types of
- errors, display errors as soon as they occur.
- """
- try:
- openpgp_env.refresh_keys()
- except Exception as e:
- writemsg_level("%s\n" % (e,),
- level=logging.ERROR, noiselevel=-1)
- raise # retry
-
- # The ThreadPoolExecutor that asyncio uses by default
- # does not support cancellation of tasks, therefore
- # use ForkExecutor for task cancellation support, in
- # order to enforce timeouts.
- loop = global_event_loop()
- with ForkExecutor(loop=loop) as executor:
- func_coroutine = functools.partial(loop.run_in_executor,
- executor, noisy_refresh_keys)
- decorated_func = retry_decorator(func_coroutine, loop=loop)
- loop.run_until_complete(decorated_func())
- out.eend(0)
+ if self.repo.sync_openpgp_key_refresh and openpgp_refresh:
+ out.ebegin('Refreshing keys from keyserver')
+ retry_decorator = self._key_refresh_retry_decorator()
+ if retry_decorator is None:
+ openpgp_env.refresh_keys()
+ else:
+ def noisy_refresh_keys():
+ """
+ Since retry does not help for some types of
+ errors, display errors as soon as they occur.
+ """
+ try:
+ openpgp_env.refresh_keys()
+ except Exception as e:
+ writemsg_level("%s\n" % (e,),
+ level=logging.ERROR, noiselevel=-1)
+ raise # retry
+
+ # The ThreadPoolExecutor that asyncio uses by default
+ # does not support cancellation of tasks, therefore
+ # use ForkExecutor for task cancellation support, in
+ # order to enforce timeouts.
+ loop = global_event_loop()
+ with ForkExecutor(loop=loop) as executor:
+ func_coroutine = functools.partial(loop.run_in_executor,
+ executor, noisy_refresh_keys)
+ decorated_func = retry_decorator(func_coroutine, loop=loop)
+ loop.run_until_complete(decorated_func())
+ out.eend(0)
except (GematoException, asyncio.TimeoutError) as e:
writemsg_level("!!! Manifest verification impossible due to keyring problem:\n%s\n"
% (e,),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment