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. Fixes: https://issues.guix.gnu.org/76112 Change-Id: Id1ca8fd6d453ca4bc5b372534445e3beab9133a8 --- doc/guix.texi | 7 ++++++- etc/completion/fish/guix.fish | 4 ++-- etc/completion/zsh/_guix | 2 +- guix/gnupg.scm | 37 +++++++++++++++++++++++++++++------ guix/import/gnu.scm | 6 +++--- guix/scripts/import/gnu.scm | 8 ++++---- guix/scripts/refresh.scm | 13 ++++++------ guix/upstream.scm | 10 +++++----- 8 files changed, 59 insertions(+), 28 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 9f1e4bf0f0..c2c68d313b 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -15321,7 +15321,12 @@ Invoking guix refresh @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} diff --git a/etc/completion/fish/guix.fish b/etc/completion/fish/guix.fish index e6c290256f..9e3b3211ea 100644 --- a/etc/completion/fish/guix.fish +++ b/etc/completion/fish/guix.fish @@ -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 diff --git a/etc/completion/zsh/_guix b/etc/completion/zsh/_guix index 9b1f16c664..42b92475a9 100644 --- a/etc/completion/zsh/_guix +++ b/etc/completion/zsh/_guix @@ -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' diff --git a/guix/gnupg.scm b/guix/gnupg.scm index 088bebc0de..ef9b71a2cb 100644 --- a/guix/gnupg.scm +++ b/guix/gnupg.scm @@ -2,7 +2,7 @@ ;;; Copyright © 2010, 2011, 2013, 2014, 2016, 2018, 2019 Ludovic Courtès <l...@gnu.org> ;;; Copyright © 2013 Nikita Karetnikov <nik...@karetnikov.org> ;;; Copyright © 2020 Tobias Geerinckx-Rice <m...@tobias.gr> -;;; Copyright © 2021 Maxim Cournoyer <maxim.courno...@gmail.com> +;;; Copyright © 2021, 2025 Maxim Cournoyer <maxim.courno...@gmail.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -26,6 +26,8 @@ (define-module (guix gnupg) #: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 @@ (define* (gnupg-receive-keys fingerprint/key-id (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 @@ (define* (gnupg-verify* sig file '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 @@ (define* (gnupg-verify* sig file (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 @@ (define* (gnupg-verify* sig file (values 'missing-key missing)) ((always) (download-and-try-again)) - (else + (else ;interactive (if (receive?) (download-and-try-again) (values 'missing-key missing))))))))) diff --git a/guix/import/gnu.scm b/guix/import/gnu.scm index fb61332fb8..e68dc06824 100644 --- a/guix/import/gnu.scm +++ b/guix/import/gnu.scm @@ -1,7 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2014, 2015, 2016 Ludovic Courtès <l...@gnu.org> ;;; Copyright © 2021 Simon Tournier <zimon.touto...@gmail.com> -;;; Copyright © 2021 Maxim Cournoyer <maxim.courno...@gmail.com> +;;; Copyright © 2021, 2025 Maxim Cournoyer <maxim.courno...@gmail.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -54,7 +54,7 @@ (define (preferred-archive-type release) '("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 @@ (define* (gnu-package->sexp package release #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 diff --git a/guix/scripts/import/gnu.scm b/guix/scripts/import/gnu.scm index 344e363abe..93ab6043c7 100644 --- a/guix/scripts/import/gnu.scm +++ b/guix/scripts/import/gnu.scm @@ -35,7 +35,7 @@ (define-module (guix scripts import gnu) ;;; (define %default-options - '((key-download . interactive))) + '((key-download . auto))) (define (show-help) (display (G_ "Usage: guix import gnu [OPTION...] PACKAGE @@ -44,8 +44,8 @@ (define (show-help) (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 @@ (define %options (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 diff --git a/guix/scripts/refresh.scm b/guix/scripts/refresh.scm index 8c72d0c545..6532feef25 100644 --- a/guix/scripts/refresh.scm +++ b/guix/scripts/refresh.scm @@ -10,7 +10,7 @@ ;;; Copyright © 2020 Simon Tournier <zimon.touto...@gmail.com> ;;; Copyright © 2021 Sarah Morgensen <iskar...@mgsn.dev> ;;; Copyright © 2022 Hartmut Goebel <h.goe...@crazy-compilers.com> -;;; Copyright © 2023 Maxim Cournoyer maxim.courno...@gmail.com> +;;; Copyright © 2023, 2025 Maxim Cournoyer maxim.courno...@gmail.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -193,8 +193,9 @@ (define (show-help) (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 @@ (define (warn-no-updater package) (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 diff --git a/guix/upstream.scm b/guix/upstream.scm index 62ba6c9d39..169d260c2d 100644 --- a/guix/upstream.scm +++ b/guix/upstream.scm @@ -314,14 +314,14 @@ (define (uncompressed-tarball name tarball) #$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 @@ (define %method-updates (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." base-commit: 220ef58440668c39ddf7c6434c0fbfc82d3dd507 -- 2.48.1