gnupg: Automatically fallback to 'always policy when non-interactive.

Previously to this change, the 'guix refresh' download
policy (--key-download)would default to 'interactive', which would throw a
backtrace when guix was invoked with its stdin not connected to a peusdo
terminal (tty).  This change makes the new default value 'auto' use
interactive only in an interactive environment, with 'always' used as
fallback.

* doc/guix.texi (Invoking guix refresh): Adjust doc.
* etc/completion/fish/guix.fish: Adjust accordingly.
* etc/completion/zsh/_guix (_guix_list_installed_packages): Likewise.
* guix/gnupg.scm (gnupg-verify*): Change default #:key-download argument value
to 'auto.  Update doc.  Validate argument.  Raise an error in case read-line
returns #<eof>.
* guix/import/gnu.scm (gnu-package->sexp): <#:key-download>: Change default
value to 'auto.
* guix/import/gnu.scm (gnu->guix-package): <#:key-download>: Likewise.
* guix/scripts/import/gnu.scm (%options): Add "auto" to accepted
--key-download values.
(%default-options): Set default key-download option to the 'auto value.
(show-help): Update doc.
* guix/scripts/refresh.scm (show-help): Update doc.
(update-package) <#:key-download>: Change default value to 'auto.  Update doc.
* guix/upstream.scm (download-tarball): <#:key-download>: Likewise.
(package-update): Likewise.

Change-Id: Id1ca8fd6d453ca4bc5b372534445e3beab9133a8
Fixes: https://issues.guix.gnu.org/76112
Reviewed-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
Maxim Cournoyer 2025-02-07 15:01:36 +09:00
parent 99bf56fd50
commit 79a46d6537
No known key found for this signature in database
GPG key ID: 1260E46482E63562
8 changed files with 59 additions and 28 deletions

View file

@ -15335,7 +15335,12 @@ Never try to download missing OpenPGP keys. Instead just bail out.
@item interactive
When a package signed with an unknown OpenPGP key is encountered, ask
the user whether to download it or not. This is the default behavior.
the user whether to download it or not.
@item auto
Automatically selects the @code{interactive} policy when the standard
input is connected to a pseudo terminal (TTY), else @code{always}. This
is the default behavior.
@end table
@item --key-server=@var{host}

View file

@ -284,7 +284,7 @@ complete -f -c guix -n '__fish_guix_using_command refresh' -l list-updaters -d '
complete -f -c guix -n '__fish_guix_using_command refresh' -l list-dependent -d 'list top-level dependent packages that would need to be rebuilt as a result of upgrading PACKAGE'
complete -f -c guix -n '__fish_guix_using_command refresh' -a "--key-server=" -d 'use HOST as the OpenPGP key server'
complete -f -c guix -n '__fish_guix_using_command refresh' -a "--gpg=" -d 'use COMMAND as the GnuPG 2.x command'
complete -f -c guix -n '__fish_guix_using_command refresh' -a "--key-download=" -d 'handle missing OpenPGP keys according to POLICY.' --exclusive --arguments "always never interactive"
complete -f -c guix -n '__fish_guix_using_command refresh' -a "--key-download=" -d 'handle missing OpenPGP keys according to POLICY.' --exclusive --arguments "always auto never interactive"
#### publish
set -l remotecommands port= listen= user= compression ttl= repl
@ -321,7 +321,7 @@ set -l remotecommands import gnu nix pypi cpan hackage elpa gem cran crate texli
complete -f -c guix -n '__fish_guix_needs_command' -a import -d 'Run IMPORTER with ARGS'
##### import gnu
complete -f -c guix -n '__fish_guix_using_command import; and not __fish_seen_subcommand_from $remotecommands' -a gnu -d 'Return a package declaration template for PACKAGE, a GNU package.'
complete -f -c guix -n '__fish_guix_using_command import; and __fish_seen_subcommand_from gnu' -a "--key-download=" -d 'handle missing OpenPGP keys according to POLICY: "always", "never", and "interactive", which is also used when "key-download" is not specified.'
complete -f -c guix -n '__fish_guix_using_command import; and __fish_seen_subcommand_from gnu' -a "--key-download=" -d 'handle missing OpenPGP keys according to POLICY: "always", "auto", "never", and "interactive", which is also used when "key-download" is not specified.'
##### import pypi
complete -f -c guix -n '__fish_guix_using_command import; and not __fish_seen_subcommand_from $remotecommands' -a pypi -d 'Import and convert the PyPI package for PACKAGE-NAME.'
##### import cpan

View file

@ -507,7 +507,7 @@ _guix_list_installed_packages()
'--keyring=[use FILE as the keyring of upstream OpenPGP keys]:FILE:_files' \
'--key-server=[use HOST as the OpenPGP key server]:HOST_hosts' \
'--gpg=[use COMMAND as the GnuPG 2.x command]:COMMAND' \
'--key-download=[handle missing OpenPGP keys according to POLICY:]:POLICY:(always interactive never)' \
'--key-download=[handle missing OpenPGP keys according to POLICY:]:POLICY:(always auto interactive never)' \
'--load-path=[prepend DIR to the package module search path]:DIR:_files -/' \
{-V,--version}'[display version information and exit]' \
'*:package:->packages'

View file

@ -2,7 +2,7 @@
;;; Copyright © 2010, 2011, 2013, 2014, 2016, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2021, 2025 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@ -26,6 +26,8 @@
#:use-module (ice-9 rdelim)
#:use-module (ice-9 i18n)
#:use-module (srfi srfi-1)
#:use-module ((srfi srfi-34) #:select (raise))
#:use-module (guix diagnostics)
#:use-module (guix i18n)
#:use-module ((guix utils) #:select (config-directory))
#:use-module ((guix build utils) #:select (mkdir-p))
@ -201,7 +203,7 @@ GnuPG's default/configured one. The key is added to KEYRING."
(define* (gnupg-verify* sig file
#:key
(key-download 'interactive)
(key-download 'auto)
server
(keyring (current-keyring)))
"Like `gnupg-verify', but try downloading the public key if it's missing.
@ -210,9 +212,29 @@ Return two values: 'valid-signature and a fingerprint/name pair upon success,
'invalid-signature with a fingerprint if the signature is invalid.
KEY-DOWNLOAD specifies a download policy for missing OpenPGP keys; allowed
values: 'always', 'never', and 'interactive' (default). Return a
values: 'auto', 'always', 'never', and 'interactive' The default policy is
auto, which automatically selects the interactive policy when a TTY is
connected to the standard input, or the always policy otherwise. Return a
fingerprint/user name pair on success and #f otherwise."
(let ((status (gnupg-verify sig file)))
(let* ((interactive? (isatty? (current-input-port)))
;; Validate or compute (in the case of 'auto) the KEY-DOWNLOAD
;; argument.
(key-download (match key-download
('auto (if interactive?
'interactive
'always))
('interactive
(unless interactive?
(raise (formatted-message
(G_ "cannot use interactive policy\
without TTY input")))))
((or 'always 'never)
key-download)
(_
(raise (formatted-message
(G_ "invalid key-download policy: ~a")
key-download)))))
(status (gnupg-verify sig file)))
(match (gnupg-status-good-signature? status)
((fingerprint . user)
(values 'valid-signature (cons fingerprint user)))
@ -236,7 +258,10 @@ fingerprint/user name pair on success and #f otherwise."
(format #t (G_ "Would you like to add this key \
to keyring '~a'?~%")
keyring)
(read-line))))
(match (read-line)
((? eof-object?)
(error "read-line unexpectedly returned #<eof>"))
(other other)))))
(string-match (locale-yes-regexp) answer)))
(case key-download
@ -244,7 +269,7 @@ to keyring '~a'?~%")
(values 'missing-key missing))
((always)
(download-and-try-again))
(else
(else ;interactive
(if (receive?)
(download-and-try-again)
(values 'missing-key missing)))))))))

View file

@ -1,7 +1,7 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2021 Simon Tournier <zimon.toutoune@gmail.com>
;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2021, 2025 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@ -54,7 +54,7 @@
'("xz" "lz" "bz2" "tbz2" "gz" "tgz" "Z")))
(define* (gnu-package->sexp package release
#:key (key-download 'interactive))
#:key (key-download 'auto))
"Return the 'package' sexp for the RELEASE (a <gnu-release>) of PACKAGE (a
<gnu-package>), or #f upon failure. Use KEY-DOWNLOAD as the OpenPGP key
download policy (see 'download-tarball' for details.)"
@ -106,7 +106,7 @@ download policy (see 'download-tarball' for details.)"
#f))))
(define* (gnu->guix-package name
#:key (key-download 'interactive)
#:key (key-download 'auto)
#:allow-other-keys)
"Return the package declaration for NAME as an s-expression. Use
KEY-DOWNLOAD as the OpenPGP key download policy (see 'download-tarball' for

View file

@ -35,7 +35,7 @@
;;;
(define %default-options
'((key-download . interactive)))
'((key-download . auto)))
(define (show-help)
(display (G_ "Usage: guix import gnu [OPTION...] PACKAGE
@ -44,8 +44,8 @@ Return a package declaration template for PACKAGE, a GNU package.\n"))
(display (G_ "
--key-download=POLICY
handle missing OpenPGP keys according to POLICY:
'always', 'never', and 'interactive', which is also
used when 'key-download' is not specified"))
'auto' (default), 'always', 'never', and
'interactive'"))
(newline)
(display (G_ "
-h, --help display this help and exit"))
@ -66,7 +66,7 @@ Return a package declaration template for PACKAGE, a GNU package.\n"))
(option '("key-download") #t #f ;from (guix scripts refresh)
(lambda (opt name arg result)
(match arg
((or "interactive" "always" "never")
((or "auto" "interactive" "always" "never")
(alist-cons 'key-download (string->symbol arg)
result))
(x

View file

@ -10,7 +10,7 @@
;;; Copyright © 2020 Simon Tournier <zimon.toutoune@gmail.com>
;;; Copyright © 2021 Sarah Morgensen <iskarian@mgsn.dev>
;;; Copyright © 2022 Hartmut Goebel <h.goebel@crazy-compilers.com>
;;; Copyright © 2023 Maxim Cournoyer maxim.cournoyer@gmail.com>
;;; Copyright © 2023, 2025 Maxim Cournoyer maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@ -193,8 +193,9 @@ specified with `--select'.\n"))
(display (G_ "
--key-download=POLICY
handle missing OpenPGP keys according to POLICY:
'always', 'never', and 'interactive', which is also
used when 'key-download' is not specified"))
'auto', 'always', 'never', and 'interactive'.
When left unspecified, the default policy is 'auto',
which automatically selects interactive or always."))
(newline)
(display (G_ "
-L, --load-path=DIR prepend DIR to the package module search path"))
@ -364,12 +365,12 @@ update would trigger a complete rebuild."
(package-name package)))
(define* (update-package store package version updaters
#:key (key-download 'interactive) key-server
#:key (key-download 'auto) key-server
warn?)
"Update the source file that defines PACKAGE with the new version.
KEY-DOWNLOAD specifies a download policy for missing OpenPGP keys; allowed
values: 'interactive' (default), 'always', and 'never'. When WARN? is true,
warn about packages that have no matching updater."
values: 'auto' (default), interactive', 'always', and 'never'. When WARN? is
true, warn about packages that have no matching updater."
(if (lookup-updater package updaters)
(let ((version output source
(package-update store package updaters

View file

@ -314,14 +314,14 @@ than that of PACKAGE."
#$output)))))
(define* (download-tarball store url signature-url
#:key (key-download 'interactive) key-server)
#:key (key-download 'auto) key-server)
"Download the tarball at URL to the store; check its OpenPGP signature at
SIGNATURE-URL, unless SIGNATURE-URL is false. On success, return the tarball
file name; return #f on failure (network failure or authentication failure).
KEY-DOWNLOAD specifies a download policy for missing OpenPGP keys; allowed
values: 'interactive' (default), 'always', and 'never'; KEY-SERVER specifies
the OpenPGP key server where the key should be looked up."
values: 'auto' (default), 'always', 'interactive' and 'never'; KEY-SERVER
specifies the OpenPGP key server where the key should be looked up."
(let ((tarball (download-to-store store url)))
(if (not signature-url)
tarball
@ -512,12 +512,12 @@ SOURCE, an <upstream-source>."
(define* (package-update store package
#:optional (updaters (force %updaters))
#:key (version #f)
(key-download 'interactive) key-server)
(key-download 'auto) key-server)
"Return the new version, the file name of the new version tarball, and input
changes for PACKAGE; return #f (three values) when PACKAGE is up-to-date;
raise an error when the updater could not determine available releases.
KEY-DOWNLOAD specifies a download policy for missing OpenPGP keys; allowed
values: 'always', 'never', and 'interactive' (default).
values: 'always', 'auto' (default), 'never', and 'interactive'.
When VERSION is specified, update PACKAGE to that version, even if that is a
downgrade."