[bug#78580,v5] pull: allow filtering which channels to pull from the CLI
Commit Message
* guix/scripts/pull.scm (guix-pull): Treat non-prefix CLI arguments as a list
of channels to pull.
* doc/guix.texi (guix pull): Document new command syntax and behavior for
filtering pulled channels by name.
Change-Id: I5d08c4b1cc84ab58a9c4e7600eb86468f92d10f0
---
doc/guix.texi | 18 ++++++++++++++--
guix/scripts/pull.scm | 50 ++++++++++++++++++++++++++++++++++++-------
2 files changed, 58 insertions(+), 10 deletions(-)
base-commit: ed5988f0d2cf14e3cc35a32e6ad91d7cbf535e2f
@@ -4656,8 +4656,22 @@ Invoking guix pull
deleting /var/guix/profiles/per-user/charlie/current-guix-1-link
@end example
-The @command{guix pull} command is usually invoked with no arguments,
-but it supports the following options:
+The general syntax is:
+
+@example
+guix pull [@var{options}] [@var{channels}@dots{}]
+@end example
+
+The optional @var{channels} argument filters the list of pulled channels
+to those whose names match the given list.
+
+For example, given a list of channels with names A B C:
+
+@example
+guix pull A B
+@end example
+
+would update channels A and B while keeping C unchanged.
@table @code
@item --url=@var{url}
@@ -2,6 +2,7 @@
;;; Copyright © 2013-2015, 2017-2024 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
;;; Copyright © 2020, 2021 Tobias Geerinckx-Rice <me@tobias.gr>
+;;; Copyright © 2025 Sergio Pastor Pérez <sergio.pastorperez@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -81,8 +82,8 @@ (define %default-options
(validate-pull . ,ensure-forward-channel-update)))
(define (show-help)
- (display (G_ "Usage: guix pull [OPTION]...
-Download and deploy the latest version of Guix.\n"))
+ (display (G_ "Usage: guix pull [OPTION]... [CHANNELS...]
+Download and deploy the latest version of Guix, possibly limited to CHANNELS.\n"))
(display (G_ "
-C, --channels=FILE deploy the channels defined in FILE"))
(display (G_ "
@@ -839,21 +840,52 @@ (define (validate-cache-directory-ownership)
(define-command (guix-pull . args)
(synopsis "pull the latest revision of Guix")
- (define (no-arguments arg _)
- (leave (G_ "~A: extraneous argument~%") arg))
+ ;; Unpin CHANNELS whose name symbol is present in the NAMES list. If NAMES
+ ;; is an empty list, do not filter anything. Warn if a name is not available
+ ;; in the channels list.
+ (define (unpin-channels channels current-channels names)
+ (if (null? names)
+ channels
+ (let ((available-names (map channel-name
+ channels))
+ (selected-channels (filter (lambda (channel)
+ (member (channel-name channel)
+ names))
+ channels)))
+ (for-each (lambda (name)
+ (unless (member name available-names)
+ (warning (G_ "channel '~a~' selected but missing from channel list~%")
+ name)))
+ names)
+
+ (map (lambda (channel)
+ (let ((selected-channel (find (lambda (ch)
+ (eq? (channel-name ch)
+ (channel-name channel)))
+ selected-channels)))
+ ;; If the user selected this channel, follow channel file
+ ;; specification. Otherwise, leave the channel pinned as
+ ;; defined by the current profile.
+ (or selected-channel
+ channel)))
+ current-channels))))
(with-error-handling
(with-git-error-handling
(let* ((opts (parse-command-line args %options
- (list %default-options)
- #:argument-handler no-arguments))
+ (list %default-options)))
(substitutes? (assoc-ref opts 'substitutes?))
(dry-run? (assoc-ref opts 'dry-run?))
(profile (or (assoc-ref opts 'profile) %current-profile))
(current-channels (profile-channels profile))
(validate-pull (assoc-ref opts 'validate-pull))
(authenticate? (assoc-ref opts 'authenticate-channels?))
- (verify-certificate? (assoc-ref opts 'verify-certificate?)))
+ (verify-certificate? (assoc-ref opts 'verify-certificate?))
+ (selected-channels (filter-map
+ (match-lambda
+ (('argument . name) (string->symbol name))
+ (_ #f))
+ opts)))
(cond
((assoc-ref opts 'query)
(process-query opts profile))
@@ -877,7 +909,9 @@ (define-command (guix-pull . args)
(ensure-default-profile)
(honor-x509-certificates store)
- (let* ((channels (channel-list opts))
+ (let* ((channels (unpin-channels (channel-list opts)
+ current-channels
+ selected-channels))
(instances
(latest-channel-instances store channels
#:current-channels