summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2021-01-10 22:13:04 +0100
committerLudovic Courtès <ludo@gnu.org>2021-02-01 17:32:35 +0100
commitaedbc5ff32a62f45aeed74c6833399a6cf2c22dc (patch)
tree2fde6bc10da72d4aa16902f5b70c175a50eccda6
parent60d72f536437bcef2a4e02faa1fe0c8076049fcc (diff)
guix package: Add '--export-channels'.
* guix/channels.scm (sexp->channel): Export. * guix/describe.scm: Use (guix channels). (manifest-entry-provenance): New procedure. * guix/scripts/package.scm (channel=?, export-channels): New procedures. (show-help, %options): Add '--export-channels'. (process-query): Honor it. * build-aux/build-self.scm (build-program)[select?]: Exclude (guix channels) to account for the (guix describe) change above. * doc/guix.texi (Invoking guix package): Document it.
-rw-r--r--build-aux/build-self.scm3
-rw-r--r--doc/guix.texi26
-rw-r--r--guix/channels.scm1
-rw-r--r--guix/describe.scm34
-rw-r--r--guix/scripts/package.scm61
5 files changed, 122 insertions, 3 deletions
diff --git a/build-aux/build-self.scm b/build-aux/build-self.scm
index 4b6e2bfae52..d5bc5fb46e4 100644
--- a/build-aux/build-self.scm
+++ b/build-aux/build-self.scm
@@ -245,8 +245,11 @@ interface (FFI) of Guile.")
245 "Return a program that computes the derivation to build Guix from SOURCE." 245 "Return a program that computes the derivation to build Guix from SOURCE."
246 (define select? 246 (define select?
247 ;; Select every module but (guix config) and non-Guix modules. 247 ;; Select every module but (guix config) and non-Guix modules.
248 ;; Also exclude (guix channels): it is autoloaded by (guix describe), but
249 ;; only for peripheral functionality.
248 (match-lambda 250 (match-lambda
249 (('guix 'config) #f) 251 (('guix 'config) #f)
252 (('guix 'channels) #f)
250 (('guix _ ...) #t) 253 (('guix _ ...) #t)
251 (('gnu _ ...) #t) 254 (('gnu _ ...) #t)
252 (_ #f))) 255 (_ #f)))
diff --git a/doc/guix.texi b/doc/guix.texi
index e5872b5f247..9e62da438ee 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -3616,7 +3616,31 @@ exactly what you specified.
3616 3616
3617Keep in mind that a manifest is purely symbolic: it only contains 3617Keep in mind that a manifest is purely symbolic: it only contains
3618package names and possibly versions, and their meaning varies over time. 3618package names and possibly versions, and their meaning varies over time.
3619 3619If you wish to ``pin'' channels to the revisions that were used to build
3620the profile(s), see @option{--export-channels} below.
3621
3622@cindex pinning, channel revisions of a profile
3623@item --export-channels
3624Write to standard output the list of channels used by the chosen
3625profile(s), in a format suitable for @command{guix pull --channels} or
3626@command{guix time-machine --channels} (@pxref{Channels}).
3627
3628Together with @option{--export-manifest}, this option provides
3629information allowing you to replicate the current profile
3630(@pxref{Replicating Guix}).
3631
3632However, note that the output of this command @emph{approximates} what
3633was actually used to build this profile. In particular, a single
3634profile might have been built from several different revisions of the
3635same channel. In that case, @option{--export-manifest} chooses the last
3636one and writes the list of other revisions in a comment. If you really
3637need to pick packages from different channel revisions, you can use
3638inferiors in your manifest to do so (@pxref{Inferiors}).
3639
3640Together with @option{--export-manifest}, this is a good starting point
3641if you are willing to migrate from the ``imperative'' model to the fully
3642declarative model consisting of a manifest file along with a channels
3643file pinning the exact channel revision(s) you want.
3620@end table 3644@end table
3621 3645
3622Finally, since @command{guix package} may actually start build 3646Finally, since @command{guix package} may actually start build
diff --git a/guix/channels.scm b/guix/channels.scm
index cdef77637d3..e7e1eb6fd01 100644
--- a/guix/channels.scm
+++ b/guix/channels.scm
@@ -92,6 +92,7 @@
92 92
93 profile-channels 93 profile-channels
94 manifest-entry-channel 94 manifest-entry-channel
95 sexp->channel
95 channel->code 96 channel->code
96 97
97 channel-news-entry? 98 channel-news-entry?
diff --git a/guix/describe.scm b/guix/describe.scm
index 05bf99eb58e..ac89fc0d7c9 100644
--- a/guix/describe.scm
+++ b/guix/describe.scm
@@ -1,5 +1,5 @@
1;;; GNU Guix --- Functional package management for GNU 1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org> 2;;; Copyright © 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
3;;; 3;;;
4;;; This file is part of GNU Guix. 4;;; This file is part of GNU Guix.
5;;; 5;;;
@@ -23,6 +23,7 @@
23 #:use-module ((guix utils) #:select (location-file)) 23 #:use-module ((guix utils) #:select (location-file))
24 #:use-module ((guix store) #:select (%store-prefix store-path?)) 24 #:use-module ((guix store) #:select (%store-prefix store-path?))
25 #:use-module ((guix config) #:select (%state-directory)) 25 #:use-module ((guix config) #:select (%state-directory))
26 #:autoload (guix channels) (sexp->channel)
26 #:use-module (srfi srfi-1) 27 #:use-module (srfi srfi-1)
27 #:use-module (ice-9 match) 28 #:use-module (ice-9 match)
28 #:export (current-profile 29 #:export (current-profile
@@ -31,7 +32,8 @@
31 package-path-entries 32 package-path-entries
32 33
33 package-provenance 34 package-provenance
34 manifest-entry-with-provenance)) 35 manifest-entry-with-provenance
36 manifest-entry-provenance))
35 37
36;;; Commentary: 38;;; Commentary:
37;;; 39;;;
@@ -166,3 +168,31 @@ there."
166 (#f properties) 168 (#f properties)
167 (sexp `((provenance ,@sexp) 169 (sexp `((provenance ,@sexp)
168 ,@properties))))))))) 170 ,@properties)))))))))
171
172(define (manifest-entry-provenance entry)
173 "Return the list of channels ENTRY comes from. Return the empty list if
174that information is missing."
175 (match (assq-ref (manifest-entry-properties entry) 'provenance)
176 ((main extras ...)
177 ;; XXX: Until recently, channel sexps lacked the channel name. For
178 ;; entries created by 'manifest-entry-with-provenance', the first sexp
179 ;; is known to be the 'guix channel, and for the other ones, invent a
180 ;; fallback name (it's OK as the name is just a "pet name").
181 (match (sexp->channel main 'guix)
182 (#f '())
183 (channel
184 (let loop ((extras extras)
185 (counter 1)
186 (channels (list channel)))
187 (match extras
188 (()
189 (reverse channels))
190 ((head . tail)
191 (let* ((name (string->symbol
192 (format #f "channel~a" counter)))
193 (extra (sexp->channel head name)))
194 (if extra
195 (loop tail (+ 1 counter) (cons extra channels))
196 (loop tail counter channels)))))))))
197 (_
198 '())))
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index 2b52016c671..8234a1703de 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -43,6 +43,7 @@
43 #:use-module (guix scripts build) 43 #:use-module (guix scripts build)
44 #:use-module (guix transformations) 44 #:use-module (guix transformations)
45 #:use-module (guix describe) 45 #:use-module (guix describe)
46 #:autoload (guix channels) (channel-name channel-commit channel->code)
46 #:autoload (guix store roots) (gc-roots user-owned?) 47 #:autoload (guix store roots) (gc-roots user-owned?)
47 #:use-module ((guix build utils) 48 #:use-module ((guix build utils)
48 #:select (directory-exists? mkdir-p)) 49 #:select (directory-exists? mkdir-p))
@@ -363,6 +364,54 @@ Alternately, see @command{guix package --search-paths -p ~s}.")
363 (pretty-print exp port)) 364 (pretty-print exp port))
364 exp)))) 365 exp))))
365 366
367(define (channel=? a b)
368 (and (channel-commit a) (channel-commit b)
369 (string=? (channel-commit a) (channel-commit b))))
370
371(define* (export-channels manifest
372 #:optional (port (current-output-port)))
373 (define channels
374 (delete-duplicates
375 (append-map manifest-entry-provenance (manifest-entries manifest))
376 channel=?))
377
378 (define channel-names
379 (delete-duplicates (map channel-name channels)))
380
381 (define table
382 (fold (lambda (channel table)
383 (vhash-consq (channel-name channel) channel table))
384 vlist-null
385 channels))
386
387 (when (null? channels)
388 (leave (G_ "no provenance information for this profile~%")))
389
390 (format port (G_ "\
391;; This channel file can be passed to 'guix pull -C' or to
392;; 'guix time-machine -C' to obtain the Guix revision that was
393;; used to populate this profile.\n"))
394 (newline port)
395 (display "(list\n" port)
396 (for-each (lambda (name)
397 (define indent " ")
398 (match (vhash-foldq* cons '() name table)
399 ((channel extra ...)
400 (unless (null? extra)
401 (display indent port)
402 (format port (G_ "\
403;; Note: these other commits were also used to install \
404some of the packages in this profile:~%"))
405 (for-each (lambda (channel)
406 (format port "~a;; ~s~%"
407 indent (channel-commit channel)))
408 extra))
409 (pretty-print (channel->code channel) port
410 #:per-line-prefix indent))))
411 channel-names)
412 (display ")\n" port)
413 #t)
414
366 415
367;;; 416;;;
368;;; Command-line options. 417;;; Command-line options.
@@ -419,6 +468,8 @@ Install, remove, or upgrade packages in a single transaction.\n"))
419 (display (G_ " 468 (display (G_ "
420 --export-manifest print a manifest for the chosen profile")) 469 --export-manifest print a manifest for the chosen profile"))
421 (display (G_ " 470 (display (G_ "
471 --export-channels print channels for the chosen profile"))
472 (display (G_ "
422 -p, --profile=PROFILE use PROFILE instead of the user's default profile")) 473 -p, --profile=PROFILE use PROFILE instead of the user's default profile"))
423 (display (G_ " 474 (display (G_ "
424 --list-profiles list the user's profiles")) 475 --list-profiles list the user's profiles"))
@@ -556,6 +607,10 @@ kind of search path~%")
556 (lambda (opt name arg result arg-handler) 607 (lambda (opt name arg result arg-handler)
557 (values (cons `(query export-manifest) result) 608 (values (cons `(query export-manifest) result)
558 #f))) 609 #f)))
610 (option '("export-channels") #f #f
611 (lambda (opt name arg result arg-handler)
612 (values (cons `(query export-channels) result)
613 #f)))
559 (option '(#\p "profile") #t #f 614 (option '(#\p "profile") #t #f
560 (lambda (opt name arg result arg-handler) 615 (lambda (opt name arg result arg-handler)
561 (values (alist-cons 'profile (canonicalize-profile arg) 616 (values (alist-cons 'profile (canonicalize-profile arg)
@@ -882,6 +937,12 @@ processed, #f otherwise."
882 (export-manifest manifest (current-output-port)) 937 (export-manifest manifest (current-output-port))
883 #t)) 938 #t))
884 939
940 (('export-channels)
941 (let ((manifest (concatenate-manifests
942 (map profile-manifest profiles))))
943 (export-channels manifest (current-output-port))
944 #t))
945
885 (_ #f)))) 946 (_ #f))))
886 947
887 948