summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergio Pastor Pérez <sergio.pastorperez@gmail.com>2026-06-06 14:13:26 +0200
committerLudovic Courtès <ludo@gnu.org>2026-06-24 15:34:44 +0200
commit2949c187f600841cdcddfc4f955506b34b79244f (patch)
tree31fe464218cbd4ecd9877dd4114187fb4d9c4cd0
parent247245fbef1923a3bc17a23627e9c016900b4edc (diff)
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 <ludo@gnu.org> Modified-by: Ludovic Courtès <ludo@gnu.org>
-rw-r--r--doc/guix.texi24
-rw-r--r--guix/scripts/pull.scm117
-rw-r--r--guix/scripts/time-machine.scm10
3 files changed, 140 insertions, 11 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index 7950843c3c2..127c87f7f48 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -140,7 +140,7 @@ Copyright @copyright{} 2024 Greg Hogan@*
140Copyright @copyright{} 2025 Sören Tempel@* 140Copyright @copyright{} 2025 Sören Tempel@*
141Copyright @copyright{} 2025 Rostislav Svoboda@* 141Copyright @copyright{} 2025 Rostislav Svoboda@*
142Copyright @copyright{} 2025 Zacchaeus@* 142Copyright @copyright{} 2025 Zacchaeus@*
143Copyright @copyright{} 2025 Sergio Pastor Pérez@* 143Copyright @copyright{} 2025, 2026 Sergio Pastor Pérez@*
144Copyright @copyright{} 2024 Evgeny Pisemsky@* 144Copyright @copyright{} 2024 Evgeny Pisemsky@*
145Copyright @copyright{} 2025 jgart@* 145Copyright @copyright{} 2025 jgart@*
146Copyright @copyright{} 2025 Artur Wroblewski@* 146Copyright @copyright{} 2025 Artur Wroblewski@*
@@ -5014,6 +5014,21 @@ understand the code of the channel files you use!
5014Inhibit loading of the user and system channel files, 5014Inhibit loading of the user and system channel files,
5015@file{~/.config/guix/channels.scm} and @file{/etc/guix/channels.scm}. 5015@file{~/.config/guix/channels.scm} and @file{/etc/guix/channels.scm}.
5016 5016
5017@cindex pinning channels, with @command{guix pull}
5018@anchor{pull-select}
5019@item --select=@var{channel}
5020@itemx -e
5021Update only @var{channel}, keeping the commit of any other non-selected
5022channel unchanged. In other words, any channel not selected with this
5023option is effectively @dfn{pinned} to its current commit. This option
5024can be repeated.
5025
5026@item --exclude=@var{channel}
5027@itemx -x
5028Prevent @var{channel} from being updated, effectively @dfn{pinning} it
5029to its current commit as shown by @command{guix describe}. All the
5030other channels will be updated. This option can be repeated.
5031
5017@cindex channel news 5032@cindex channel news
5018@item --news 5033@item --news
5019@itemx -N 5034@itemx -N
@@ -5325,6 +5340,13 @@ Substitution,,, bash, The GNU Bash Reference Manual}):
5325guix time-machine -C <(echo %default-channels) @dots{} 5340guix time-machine -C <(echo %default-channels) @dots{}
5326@end example 5341@end example
5327 5342
5343@item --select
5344@itemx -e
5345@itemx --exclude
5346@itemx -x
5347Select or exclude channels that need to be updated. @xref{pull-select}, for
5348more info.
5349
5328@end table 5350@end table
5329 5351
5330Note that @command{guix time-machine} can trigger builds of channels and 5352Note that @command{guix time-machine} can trigger builds of channels and
diff --git a/guix/scripts/pull.scm b/guix/scripts/pull.scm
index 7fba0efa2a6..681354f6e3e 100644
--- a/guix/scripts/pull.scm
+++ b/guix/scripts/pull.scm
@@ -2,6 +2,7 @@
2;;; Copyright © 2013-2015, 2017-2024, 2026 Ludovic Courtès <ludo@gnu.org> 2;;; Copyright © 2013-2015, 2017-2024, 2026 Ludovic Courtès <ludo@gnu.org>
3;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com> 3;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
4;;; Copyright © 2020, 2021 Tobias Geerinckx-Rice <me@tobias.gr> 4;;; Copyright © 2020, 2021 Tobias Geerinckx-Rice <me@tobias.gr>
5;;; Copyright © 2026 Sergio Pastor Pérez <sergio.pastorperez@gmail.com>
5;;; 6;;;
6;;; This file is part of GNU Guix. 7;;; This file is part of GNU Guix.
7;;; 8;;;
@@ -94,6 +95,10 @@ Download and deploy the latest version of Guix.\n"))
94 -q, --no-channel-files 95 -q, --no-channel-files
95 inhibit loading of user and system 'channels.scm'")) 96 inhibit loading of user and system 'channels.scm'"))
96 (display (G_ " 97 (display (G_ "
98 -e, --select=CHANNEL select CHANNEL to update"))
99 (display (G_ "
100 -x, --exclude=CHANNEL exclude CHANNEL from being updated"))
101 (display (G_ "
97 --url=URL download \"guix\" channel from the Git repository at URL")) 102 --url=URL download \"guix\" channel from the Git repository at URL"))
98 (display (G_ " 103 (display (G_ "
99 --commit=COMMIT download the specified \"guix\" channel COMMIT")) 104 --commit=COMMIT download the specified \"guix\" channel COMMIT"))
@@ -155,6 +160,12 @@ Download and deploy the latest version of Guix.\n"))
155 (option '(#\q "no-channel-files") #f #f 160 (option '(#\q "no-channel-files") #f #f
156 (lambda (opt name arg result) 161 (lambda (opt name arg result)
157 (alist-cons 'ignore-channel-files? #t result))) 162 (alist-cons 'ignore-channel-files? #t result)))
163 (option '(#\e "select") #t #f
164 (lambda (opt name arg result)
165 (alist-cons 'select (string->symbol arg) result)))
166 (option '(#\x "exclude") #t #f
167 (lambda (opt name arg result)
168 (alist-cons 'exclude (string->symbol arg) result)))
158 (option '(#\l "list-generations") #f #t 169 (option '(#\l "list-generations") #f #t
159 (lambda (opt name arg result) 170 (lambda (opt name arg result)
160 (cons `(query list-generations ,arg) 171 (cons `(query list-generations ,arg)
@@ -807,6 +818,69 @@ identifier."
807 (#f (leave (G_ "~a: invalid content SWHID~%") swhid)) 818 (#f (leave (G_ "~a: invalid content SWHID~%") swhid))
808 (port port))) 819 (port port)))
809 820
821(define (collect-alist-values key alist)
822 "Return a list of all values from ALIST that matches KEY."
823 (filter-map (match-lambda
824 ((k . value)
825 (and (eq? k key) value)))
826 alist))
827
828(define (options->channel-transformation opts)
829 "Return a procedure that, when passed a channel, applies the transformations
830specified by OPTS and returns the resulting channel. OPTS must be a list of
831symbol/string pairs such as:
832
833 ((select . \"channelA\")
834 (exclude . \"channelB\"))
835
836Each symbol names a transformation and the corresponding string is an argument
837to that transformation."
838 (define selected-channels
839 (collect-alist-values 'select opts))
840
841 (define excluded-channels
842 (collect-alist-values 'exclude opts))
843
844 (define current-channels
845 (let ((profile (or (assoc-ref opts 'profile) %current-profile)))
846 (profile-channels profile)))
847
848 (define (find-channel name lst)
849 (find (lambda (c)
850 (eq? (channel-name c) name))
851 lst))
852
853 (when (and (not (null? selected-channels))
854 (not (null? excluded-channels)))
855 (raise
856 (condition
857 (&message
858 (message (G_ "mixing incompatible '--select' and '--exclude' options"))))))
859
860 (lambda (c)
861 (let* ((name (channel-name c))
862 (raise-unknown (lambda ()
863 (raise
864 (make-exception
865 (formatted-message
866 (G_ "unknown channel '~a': cannot \
867select/exclude a channel that has never been pulled")
868 name))))))
869 (cond
870 ;; Selection.
871 ((not (null? selected-channels))
872 (if (member name selected-channels)
873 (channel (inherit c) (commit #f)) ;unpin selected.
874 (or (find-channel name current-channels) ;pin others.
875 (raise-unknown))))
876 ;; Exclusion.
877 ((not (null? excluded-channels))
878 (if (member name excluded-channels)
879 (or (find-channel name current-channels) ;pin excluded.
880 (raise-unknown))
881 (channel (inherit c) (commit #f)))) ;unpin others.
882 (else c))))) ;do nothing.
883
810(define (channel-list opts) 884(define (channel-list opts)
811 "Return the list of channels to use. If OPTS specify a channel file, 885 "Return the list of channels to use. If OPTS specify a channel file,
812channels are read from there; otherwise, if ~/.config/guix/channels.scm 886channels are read from there; otherwise, if ~/.config/guix/channels.scm
@@ -856,17 +930,40 @@ transformations specified in OPTS (resulting from '--url', '--commit', or
856 result) 930 result)
857 (leave (G_ "'~a' did not return a list of channels~%") file)))) 931 (leave (G_ "'~a' did not return a list of channels~%") file))))
858 932
933 (define selected-channels
934 (collect-alist-values 'select opts))
935
936 (define excluded-channels
937 (collect-alist-values 'exclude opts))
938
859 (define channels 939 (define channels
860 (cond (file 940 (let* ((channels (cond (file
861 (load-channels file)) 941 (load-channels file))
862 ((and (not ignore-channel-files?) 942 ((and (not ignore-channel-files?)
863 (file-exists? default-file)) 943 (file-exists? default-file))
864 (load-channels default-file)) 944 (load-channels default-file))
865 ((and (not ignore-channel-files?) 945 ((and (not ignore-channel-files?)
866 (file-exists? global-file)) 946 (file-exists? global-file))
867 (load-channels global-file)) 947 (load-channels global-file))
868 (else 948 (else
869 %default-channels))) 949 %default-channels))))
950 ;; Validate options.
951 (let ((names (cond
952 ((not (null? selected-channels))
953 selected-channels)
954 ((not (null? excluded-channels))
955 excluded-channels)
956 (else '())))
957 (valid-names (map channel-name channels)))
958 (unless (null? names)
959 (for-each
960 (lambda (name)
961 (unless (member name valid-names)
962 (leave (G_ "channel '~a' is missing from channel list~%")
963 name)))
964 names)))
965
966 (map (options->channel-transformation opts) channels)))
870 967
871 (define (environment-variable) 968 (define (environment-variable)
872 (match (getenv "GUIX_PULL_URL") 969 (match (getenv "GUIX_PULL_URL")
diff --git a/guix/scripts/time-machine.scm b/guix/scripts/time-machine.scm
index ffba7ffc355..030819f6052 100644
--- a/guix/scripts/time-machine.scm
+++ b/guix/scripts/time-machine.scm
@@ -62,6 +62,10 @@ If COMMAND is not provided, print path to the time-machine profile.\n"))
62 -q, --no-channel-files 62 -q, --no-channel-files
63 inhibit loading of user and system 'channels.scm'")) 63 inhibit loading of user and system 'channels.scm'"))
64 (display (G_ " 64 (display (G_ "
65 -e, --select=CHANNEL select CHANNEL to update"))
66 (display (G_ "
67 -x, --exclude=CHANNEL exclude CHANNEL from being updated"))
68 (display (G_ "
65 --url=URL use the Git repository at URL")) 69 --url=URL use the Git repository at URL"))
66 (display (G_ " 70 (display (G_ "
67 --commit=COMMIT use the specified COMMIT")) 71 --commit=COMMIT use the specified COMMIT"))
@@ -98,6 +102,12 @@ If COMMAND is not provided, print path to the time-machine profile.\n"))
98 (option '(#\q "no-channel-files") #f #f 102 (option '(#\q "no-channel-files") #f #f
99 (lambda (opt name arg result) 103 (lambda (opt name arg result)
100 (alist-cons 'ignore-channel-files? #t result))) 104 (alist-cons 'ignore-channel-files? #t result)))
105 (option '(#\e "select") #t #f
106 (lambda (opt name arg result)
107 (alist-cons 'select (string->symbol arg) result)))
108 (option '(#\x "exclude") #t #f
109 (lambda (opt name arg result)
110 (alist-cons 'exclude (string->symbol arg) result)))
101 (option '("url") #t #f 111 (option '("url") #t #f
102 (lambda (opt name arg result) 112 (lambda (opt name arg result)
103 (alist-cons 'repository-url arg 113 (alist-cons 'repository-url arg