guix_mirror_bot pushed a commit to branch master
in repository guix.
commit 2949c187f600841cdcddfc4f955506b34b79244f
Author: Sergio Pastor Pérez <[email protected]>
AuthorDate: Sat Jun 6 14:13:26 2026 +0200
pull: Add channel filtering options to the CLI.
* doc/guix.texi (Invoking guix pull): Document channel selection and
exclusion
flags.
* etc/news.scm: Add entry.
* guix/scripts/pull.scm (show-help): Add help strings for channel selection
and exclusion flags.
(%options): Handle channel selection and exclusion flags.
(collect-alist-values): New procedure.
(options->channel-transformation): New procedure.
(channel-list): Implement channel selection and exclusion logic.
* guix/scripts/time-machine.scm (show-help): Add help strings for channel
selection and exclusion flags.
(%options): Handle channel selection and exclusion flags.
Change-Id: Ia22c5c38903ed1a2b9a9353ff94b70795820376d
Signed-off-by: Ludovic Courtès <[email protected]>
Modified-by: Ludovic Courtès <[email protected]>
---
doc/guix.texi | 24 ++++++++-
guix/scripts/pull.scm | 117 ++++++++++++++++++++++++++++++++++++++----
guix/scripts/time-machine.scm | 10 ++++
3 files changed, 140 insertions(+), 11 deletions(-)
diff --git a/doc/guix.texi b/doc/guix.texi
index 7950843c3c..127c87f7f4 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -140,7 +140,7 @@ Copyright @copyright{} 2024 Greg Hogan@*
Copyright @copyright{} 2025 Sören Tempel@*
Copyright @copyright{} 2025 Rostislav Svoboda@*
Copyright @copyright{} 2025 Zacchaeus@*
-Copyright @copyright{} 2025 Sergio Pastor Pérez@*
+Copyright @copyright{} 2025, 2026 Sergio Pastor Pérez@*
Copyright @copyright{} 2024 Evgeny Pisemsky@*
Copyright @copyright{} 2025 jgart@*
Copyright @copyright{} 2025 Artur Wroblewski@*
@@ -5014,6 +5014,21 @@ understand the code of the channel files you use!
Inhibit loading of the user and system channel files,
@file{~/.config/guix/channels.scm} and @file{/etc/guix/channels.scm}.
+@cindex pinning channels, with @command{guix pull}
+@anchor{pull-select}
+@item --select=@var{channel}
+@itemx -e
+Update only @var{channel}, keeping the commit of any other non-selected
+channel unchanged. In other words, any channel not selected with this
+option is effectively @dfn{pinned} to its current commit. This option
+can be repeated.
+
+@item --exclude=@var{channel}
+@itemx -x
+Prevent @var{channel} from being updated, effectively @dfn{pinning} it
+to its current commit as shown by @command{guix describe}. All the
+other channels will be updated. This option can be repeated.
+
@cindex channel news
@item --news
@itemx -N
@@ -5325,6 +5340,13 @@ Substitution,,, bash, The GNU Bash Reference Manual}):
guix time-machine -C <(echo %default-channels) @dots{}
@end example
+@item --select
+@itemx -e
+@itemx --exclude
+@itemx -x
+Select or exclude channels that need to be updated. @xref{pull-select}, for
+more info.
+
@end table
Note that @command{guix time-machine} can trigger builds of channels and
diff --git a/guix/scripts/pull.scm b/guix/scripts/pull.scm
index 7fba0efa2a..681354f6e3 100644
--- a/guix/scripts/pull.scm
+++ b/guix/scripts/pull.scm
@@ -2,6 +2,7 @@
;;; Copyright © 2013-2015, 2017-2024, 2026 Ludovic Courtès <[email protected]>
;;; Copyright © 2017 Marius Bakke <[email protected]>
;;; Copyright © 2020, 2021 Tobias Geerinckx-Rice <[email protected]>
+;;; Copyright © 2026 Sergio Pastor Pérez <[email protected]>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -93,6 +94,10 @@ Download and deploy the latest version of Guix.\n"))
(display (G_ "
-q, --no-channel-files
inhibit loading of user and system 'channels.scm'"))
+ (display (G_ "
+ -e, --select=CHANNEL select CHANNEL to update"))
+ (display (G_ "
+ -x, --exclude=CHANNEL exclude CHANNEL from being updated"))
(display (G_ "
--url=URL download \"guix\" channel from the Git repository at
URL"))
(display (G_ "
@@ -155,6 +160,12 @@ Download and deploy the latest version of Guix.\n"))
(option '(#\q "no-channel-files") #f #f
(lambda (opt name arg result)
(alist-cons 'ignore-channel-files? #t result)))
+ (option '(#\e "select") #t #f
+ (lambda (opt name arg result)
+ (alist-cons 'select (string->symbol arg) result)))
+ (option '(#\x "exclude") #t #f
+ (lambda (opt name arg result)
+ (alist-cons 'exclude (string->symbol arg) result)))
(option '(#\l "list-generations") #f #t
(lambda (opt name arg result)
(cons `(query list-generations ,arg)
@@ -807,6 +818,69 @@ identifier."
(#f (leave (G_ "~a: invalid content SWHID~%") swhid))
(port port)))
+(define (collect-alist-values key alist)
+ "Return a list of all values from ALIST that matches KEY."
+ (filter-map (match-lambda
+ ((k . value)
+ (and (eq? k key) value)))
+ alist))
+
+(define (options->channel-transformation opts)
+ "Return a procedure that, when passed a channel, applies the transformations
+specified by OPTS and returns the resulting channel. OPTS must be a list of
+symbol/string pairs such as:
+
+ ((select . \"channelA\")
+ (exclude . \"channelB\"))
+
+Each symbol names a transformation and the corresponding string is an argument
+to that transformation."
+ (define selected-channels
+ (collect-alist-values 'select opts))
+
+ (define excluded-channels
+ (collect-alist-values 'exclude opts))
+
+ (define current-channels
+ (let ((profile (or (assoc-ref opts 'profile) %current-profile)))
+ (profile-channels profile)))
+
+ (define (find-channel name lst)
+ (find (lambda (c)
+ (eq? (channel-name c) name))
+ lst))
+
+ (when (and (not (null? selected-channels))
+ (not (null? excluded-channels)))
+ (raise
+ (condition
+ (&message
+ (message (G_ "mixing incompatible '--select' and '--exclude'
options"))))))
+
+ (lambda (c)
+ (let* ((name (channel-name c))
+ (raise-unknown (lambda ()
+ (raise
+ (make-exception
+ (formatted-message
+ (G_ "unknown channel '~a': cannot \
+select/exclude a channel that has never been pulled")
+ name))))))
+ (cond
+ ;; Selection.
+ ((not (null? selected-channels))
+ (if (member name selected-channels)
+ (channel (inherit c) (commit #f)) ;unpin selected.
+ (or (find-channel name current-channels) ;pin others.
+ (raise-unknown))))
+ ;; Exclusion.
+ ((not (null? excluded-channels))
+ (if (member name excluded-channels)
+ (or (find-channel name current-channels) ;pin excluded.
+ (raise-unknown))
+ (channel (inherit c) (commit #f)))) ;unpin others.
+ (else c))))) ;do nothing.
+
(define (channel-list opts)
"Return the list of channels to use. If OPTS specify a channel file,
channels are read from there; otherwise, if ~/.config/guix/channels.scm
@@ -856,17 +930,40 @@ transformations specified in OPTS (resulting from
'--url', '--commit', or
result)
(leave (G_ "'~a' did not return a list of channels~%") file))))
+ (define selected-channels
+ (collect-alist-values 'select opts))
+
+ (define excluded-channels
+ (collect-alist-values 'exclude opts))
+
(define channels
- (cond (file
- (load-channels file))
- ((and (not ignore-channel-files?)
- (file-exists? default-file))
- (load-channels default-file))
- ((and (not ignore-channel-files?)
- (file-exists? global-file))
- (load-channels global-file))
- (else
- %default-channels)))
+ (let* ((channels (cond (file
+ (load-channels file))
+ ((and (not ignore-channel-files?)
+ (file-exists? default-file))
+ (load-channels default-file))
+ ((and (not ignore-channel-files?)
+ (file-exists? global-file))
+ (load-channels global-file))
+ (else
+ %default-channels))))
+ ;; Validate options.
+ (let ((names (cond
+ ((not (null? selected-channels))
+ selected-channels)
+ ((not (null? excluded-channels))
+ excluded-channels)
+ (else '())))
+ (valid-names (map channel-name channels)))
+ (unless (null? names)
+ (for-each
+ (lambda (name)
+ (unless (member name valid-names)
+ (leave (G_ "channel '~a' is missing from channel list~%")
+ name)))
+ names)))
+
+ (map (options->channel-transformation opts) channels)))
(define (environment-variable)
(match (getenv "GUIX_PULL_URL")
diff --git a/guix/scripts/time-machine.scm b/guix/scripts/time-machine.scm
index ffba7ffc35..030819f605 100644
--- a/guix/scripts/time-machine.scm
+++ b/guix/scripts/time-machine.scm
@@ -61,6 +61,10 @@ If COMMAND is not provided, print path to the time-machine
profile.\n"))
(display (G_ "
-q, --no-channel-files
inhibit loading of user and system 'channels.scm'"))
+ (display (G_ "
+ -e, --select=CHANNEL select CHANNEL to update"))
+ (display (G_ "
+ -x, --exclude=CHANNEL exclude CHANNEL from being updated"))
(display (G_ "
--url=URL use the Git repository at URL"))
(display (G_ "
@@ -98,6 +102,12 @@ If COMMAND is not provided, print path to the time-machine
profile.\n"))
(option '(#\q "no-channel-files") #f #f
(lambda (opt name arg result)
(alist-cons 'ignore-channel-files? #t result)))
+ (option '(#\e "select") #t #f
+ (lambda (opt name arg result)
+ (alist-cons 'select (string->symbol arg) result)))
+ (option '(#\x "exclude") #t #f
+ (lambda (opt name arg result)
+ (alist-cons 'exclude (string->symbol arg) result)))
(option '("url") #t #f
(lambda (opt name arg result)
(alist-cons 'repository-url arg