GNU bug report logs - #45919
[PATCH 0/8] Exporting a manifest and channels from a profile

Previous Next

Package: guix-patches;

Reported by: Ludovic Courtès <ludo <at> gnu.org>

Date: Sat, 16 Jan 2021 18:31:02 UTC

Severity: normal

Tags: patch

Done: Ludovic Courtès <ludo <at> gnu.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 45919 in the body.
You can then email your comments to 45919 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sat, 16 Jan 2021 18:31:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Ludovic Courtès <ludo <at> gnu.org>:
New bug report received and forwarded. Copy sent to guix-patches <at> gnu.org. (Sat, 16 Jan 2021 18:31:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: guix-patches <at> gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 0/8] Exporting a manifest and channels from a profile
Date: Sat, 16 Jan 2021 19:29:57 +0100
Hi there!

Here’s a simple but oft-requested feature (I remember discussing
with Pierre and Simon a year ago at the Guix Days about ways to
implement it—time flies!): these patches provide ‘guix package
--export-manifest’ and ‘--export-channels’.  These options spit
a manifest and a channel spec, respectively, with the goal of
helping users who wish to migrate to the declarative model.

‘--export-manifest’ honors transformations: if entries in the
profile have associated transformations, those are preserved in
the generated manifest.  It also honors version specifiers (to
some extent); for example, if you have guile <at> 2.2 in your profile,
it’ll put “guile <at> 2.2” in the manifest, where “2.2” is the
shortest prefix to disambiguate it from the other available
versions of “guile”.

‘--export-channels’ does what you expect.  When several commits
of the same channel were used to build your profile, it picks
the last one and adds the other one in a comment.

There’s a catch though: it’s easy to get a large number of
commits.  For example, my main profile contains ~300 packages.
I usually upgrade everything at once, so you’d expect to see
a single commit for the ‘guix’ channel.  But that’s not the
case: when running ‘guix upgrade’, entries that do not need
to be upgraded are left unchanged, and thus they carry their
original commit.  For my profile, the result is:

--8<---------------cut here---------------start------------->8---
$ guix package --export-channels
;; This channel file can be passed to 'guix pull -C' or to
;; 'guix time-machine -C' to obtain the Guix revision that was
;; used to populate this profile.

(list
     ;; Note: these other commits were also used to install some of the packages in this profile:
     ;;   "458cb25b9e7e7c954f468023abea2bebb5d8c75b"
     ;;   "4969b51d175497bfcc354c91803e9d70542b7113"
     ;;   "3d85c3ec652feb22824f355538b51e6955ded361"
     ;;   "3462678bc346c2f6ea81245d6842264b6dccd945"
     ;;   "74eeb11daee906cb012f10b6bb3afd254f9ea5c2"
     ;;   "e1f5c2292b88525414b5d0336a00bfa6741d4f14"
     ;;   "3bdb2a026bc9d3967a31a2ccbcd670c018f85d3d"
     ;;   "bf986c3e4325594c1c6a43cf0b67b92262842863"
     ;;   "7607ace5091aea0157ba5c8a508129cc5fc4f931"
     ;;   "98b89f432103b66efacee0bcba41a94148b8e870"
     ;;   "7090159c23d6345992ab976d71fefeb1583cfcdf"
     ;;   "c6872990b51971922f3064cba54ab752fcdc1559"
     ;;   "6ee7468758d7c043692ae8c0b5e130fa4eabe94c"
     ;;   "9744cc7b4636fafb772c94adb8f05961b5b39f16"
     ;;   "d8feee9f18ede0d1ea4d0e4876f09a0dab770295"
     ;;   "b76b1d3fb65fec98b96a2b4cfa984316dd956a29"
     (channel
       (name 'guix)
       (url "/home/ludo/src/guix")
       (commit
         "c6ca0fceb715340cfb2ba01bfec128aa8d385b92")
       (introduction
         (make-channel-introduction
           "9edb3f66fd807b096b48283debdcddccfea34bad"
           (openpgp-fingerprint
             "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA"))))
)
--8<---------------cut here---------------end--------------->8---

The long commit list doesn’t look great, but in fact the chosen
commit is almost certainly good enough.

I looked into ‘guix package’ to see if we could update provenance
data for manifest entries that are not upgraded because they’re
already up-to-date (so that we end up with fewer different commits),
and it’s tricky to do that, and maybe not desirable.  So I left it
at that.

Anyway, for me the goal of these options is not “disassemble” the
profile and provide its exact source code, but rather to help
migrate to the declarative model.  I think it does a good job
at that.

Thoughts?

Ludo’.

Ludovic Courtès (8):
  profiles: Add 'manifest->code'.
  utils: Add 'version-unique-prefix'.
  guix package: Add '--export-manifest'.
  channels: Factorize 'manifest-entry-channel' and channel
    serialization.
  channels: Add the channel name to channel sexps.
  guix describe: Use 'manifest-entry-channel'.
  channels: Add 'channel->code'.
  guix package: Add '--export-channels'.

 build-aux/build-self.scm  |   3 +
 doc/guix.texi             |  45 +++++++++++++
 guix/build/profiles.scm   |   6 +-
 guix/channels.scm         | 134 ++++++++++++++++++++++++++------------
 guix/describe.scm         |  34 +++++++++-
 guix/profiles.scm         |  86 +++++++++++++++++++++++-
 guix/scripts/describe.scm |  52 +++++----------
 guix/scripts/package.scm  | 118 ++++++++++++++++++++++++++++++++-
 guix/utils.scm            |  35 +++++++++-
 tests/guix-package.sh     |  10 ++-
 tests/profiles.scm        |  30 ++++++++-
 tests/utils.scm           |   8 ++-
 12 files changed, 471 insertions(+), 90 deletions(-)

-- 
2.30.0





Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sat, 16 Jan 2021 18:35:01 GMT) Full text and rfc822 format available.

Message #8 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 45919 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 1/8] profiles: Add 'manifest->code'.
Date: Sat, 16 Jan 2021 19:34:02 +0100
* guix/profiles.scm (manifest->code): New procedure.
* tests/profiles.scm ("manifest->code, simple")
("manifest->code, simple, versions")
("manifest->code, transformations"): New tests.
---
 guix/profiles.scm  | 86 +++++++++++++++++++++++++++++++++++++++++++++-
 tests/profiles.scm | 30 +++++++++++++++-
 2 files changed, 114 insertions(+), 2 deletions(-)

diff --git a/guix/profiles.scm b/guix/profiles.scm
index 59a313ea08..ea8bc6e593 100644
--- a/guix/profiles.scm
+++ b/guix/profiles.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo <at> gnu.org>
+;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo <at> gnu.org>
 ;;; Copyright © 2013 Nikita Karetnikov <nikita <at> karetnikov.org>
 ;;; Copyright © 2014, 2016 Alex Kost <alezost <at> gmail.com>
 ;;; Copyright © 2015 Mark H Weaver <mhw <at> netris.org>
@@ -107,6 +107,8 @@
             manifest-search-paths
             check-for-collisions
 
+            manifest->code
+
             manifest-transaction
             manifest-transaction?
             manifest-transaction-install
@@ -667,6 +669,88 @@ including the search path specification for $PATH."
          (append-map manifest-entry-search-paths
                      (manifest-entries manifest)))))
 
+(define* (manifest->code manifest
+                         #:key (entry-package-version (const "")))
+  "Return an sexp representing code to build an approximate version of
+MANIFEST; the code is wrapped in a top-level 'begin' form.  Call
+ENTRY-PACKAGE-VERSION to determine the version number to use in the spec for a
+given entry; it can be set to 'manifest-entry-version' for fully-specified
+version numbers, or to some other procedure to disambiguate versions for
+packages for which several versions are available."
+  (define (entry-transformations entry)
+    ;; Return the transformations that apply to ENTRY.
+    (assoc-ref (manifest-entry-properties entry) 'transformations))
+
+  (define transformation-procedures
+    ;; List of transformation options/procedure name pairs.
+    (let loop ((entries (manifest-entries manifest))
+               (counter 1)
+               (result  '()))
+      (match entries
+        (() result)
+        ((entry . tail)
+         (match (entry-transformations entry)
+           (#f
+            (loop tail counter result))
+           (options
+            (if (assoc-ref result options)
+                (loop tail counter result)
+                (loop tail (+ 1 counter)
+                      (alist-cons options
+                                  (string->symbol
+                                   (format #f "transform~a" counter))
+                                  result)))))))))
+
+  (define (qualified-name entry)
+    ;; Return the name of ENTRY possibly with "@" followed by a version.
+    (match (entry-package-version entry)
+      (""      (manifest-entry-name entry))
+      (version (string-append (manifest-entry-name entry)
+                              "@" version))))
+
+  (if (null? transformation-procedures)
+      `(begin                                     ;simplest case
+         (specifications->manifest
+          (list ,@(map (lambda (entry)
+                         (match (manifest-entry-output entry)
+                           ("out"  (qualified-name entry))
+                           (output (string-append (qualified-name entry)
+                                                  ":" output))))
+                       (manifest-entries manifest)))))
+      (let* ((transform (lambda (options exp)
+                          (if (not options)
+                              exp
+                              (let ((proc (assoc-ref transformation-procedures
+                                                     options)))
+                                `(,proc ,exp))))))
+        `(begin                                   ;transformations apply
+           (use-modules (guix transformations))
+
+           ,@(map (match-lambda
+                    ((options . name)
+                     `(define ,name
+                        (options->transformation ',options))))
+                  transformation-procedures)
+
+           (packages->manifest
+            (list ,@(map (lambda (entry)
+                           (define options
+                             (entry-transformations entry))
+
+                           (define name
+                             (qualified-name entry))
+
+                           (match (manifest-entry-output entry)
+                             ("out"
+                              (transform options
+                                         `(specification->package ,name)))
+                             (output
+                              `(list ,(transform
+                                       options
+                                       `(specification->package ,name))
+                                     ,output))))
+                         (manifest-entries manifest))))))))
+
 
 ;;;
 ;;; Manifest transactions.
diff --git a/tests/profiles.scm b/tests/profiles.scm
index 2dec42bec1..ce77711d63 100644
--- a/tests/profiles.scm
+++ b/tests/profiles.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo <at> gnu.org>
+;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo <at> gnu.org>
 ;;; Copyright © 2014 Alex Kost <alezost <at> gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -154,6 +154,34 @@
   (manifest-entries (manifest-add (manifest '())
                                   (list guile-2.0.9 guile-2.0.9))))
 
+(test-equal "manifest->code, simple"
+  '(begin
+     (specifications->manifest (list "guile" "guile:debug" "glibc")))
+  (manifest->code (manifest (list guile-2.0.9 guile-2.0.9:debug glibc))))
+
+(test-equal "manifest->code, simple, versions"
+  '(begin
+     (specifications->manifest (list "guile <at> 2.0.9" "guile <at> 2.0.9:debug"
+                                     "glibc <at> 2.19")))
+  (manifest->code (manifest (list guile-2.0.9 guile-2.0.9:debug glibc))
+                  #:entry-package-version manifest-entry-version))
+
+(test-equal "manifest->code, transformations"
+  '(begin
+     (use-modules (guix transformations))
+
+     (define transform1
+       (options->transformation '((foo . "bar"))))
+
+     (packages->manifest
+      (list (transform1 (specification->package "guile"))
+            (specification->package "glibc"))))
+  (manifest->code (manifest (list (manifest-entry
+                                    (inherit guile-2.0.9)
+                                    (properties `((transformations
+                                                   . ((foo . "bar"))))))
+                                  glibc))))
+
 (test-assert "manifest-perform-transaction"
   (let* ((m0 (manifest (list guile-2.0.9 guile-2.0.9:debug)))
          (t1 (manifest-transaction
-- 
2.30.0





Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sat, 16 Jan 2021 18:35:02 GMT) Full text and rfc822 format available.

Message #11 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 45919 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 2/8] utils: Add 'version-unique-prefix'.
Date: Sat, 16 Jan 2021 19:34:03 +0100
* guix/utils.scm (version-unique-prefix): New procedure.
* tests/utils.scm ("version-unique-prefix"): New test.
---
 guix/utils.scm  | 35 ++++++++++++++++++++++++++++++++++-
 tests/utils.scm |  8 +++++++-
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/guix/utils.scm b/guix/utils.scm
index f8b05e7e80..a85e2f495c 100644
--- a/guix/utils.scm
+++ b/guix/utils.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo <at> gnu.org>
+;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo <at> gnu.org>
 ;;; Copyright © 2013, 2014, 2015 Mark H Weaver <mhw <at> netris.org>
 ;;; Copyright © 2014 Eric Bavier <bavier <at> member.fsf.org>
 ;;; Copyright © 2014 Ian Denhardt <ian <at> zenhack.net>
@@ -88,6 +88,7 @@
             version-major+minor+point
             version-major+minor
             version-major
+            version-unique-prefix
             guile-version>?
             version-prefix?
             string-replace-substring
@@ -589,6 +590,38 @@ minor version numbers from version-string."
   "Return the major version number as string from the version-string."
   (version-prefix version-string 1))
 
+(define (version-unique-prefix version versions)
+  "Return the shortest version prefix to unambiguously identify VERSION among
+VERSIONS.  For example:
+
+  (version-unique-prefix \"2.0\" '(\"3.0\" \"2.0\"))
+  => \"2\"
+
+  (version-unique-prefix \"2.2\" '(\"3.0.5\" \"2.0.9\" \"2.2.7\"))
+  => \"2.2\"
+
+  (version-unique-prefix \"27.1\" '(\"27.1\"))
+  => \"\"
+"
+  (define not-dot
+    (char-set-complement (char-set #\.)))
+
+  (define other-versions
+    (delete version versions))
+
+  (let loop ((prefix     '())
+             (components (string-tokenize version not-dot)))
+    (define prefix-str
+      (string-join prefix "."))
+
+    (if (any (cut string-prefix? prefix-str <>) other-versions)
+        (match components
+          ((head . tail)
+           (loop `(,@prefix ,head) tail))
+          (()
+           version))
+        prefix-str)))
+
 (define (version>? a b)
   "Return #t when A denotes a version strictly newer than B."
   (eq? '> (version-compare a b)))
diff --git a/tests/utils.scm b/tests/utils.scm
index 9bce446d98..62ec7e8b4c 100644
--- a/tests/utils.scm
+++ b/tests/utils.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo <at> gnu.org>
+;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo <at> gnu.org>
 ;;; Copyright © 2014 Eric Bavier <bavier <at> member.fsf.org>
 ;;; Copyright © 2016 Mathieu Lirzin <mthl <at> gnu.org>
 ;;;
@@ -78,6 +78,12 @@
        (not (version-prefix? "4.1" "4.16.2"))
        (not (version-prefix? "4.1" "4"))))
 
+(test-equal "version-unique-prefix"
+  '("2" "2.2" "")
+  (list (version-unique-prefix "2.0" '("3.0" "2.0"))
+        (version-unique-prefix "2.2" '("3.0.5" "2.0.9" "2.2.7"))
+        (version-unique-prefix "27.1" '("27.1"))))
+
 (test-equal "string-tokenize*"
   '(("foo")
     ("foo" "bar" "baz")
-- 
2.30.0





Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sat, 16 Jan 2021 18:35:02 GMT) Full text and rfc822 format available.

Message #14 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 45919 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 3/8] guix package: Add '--export-manifest'.
Date: Sat, 16 Jan 2021 19:34:04 +0100
* guix/scripts/package.scm (export-manifest): New procedure.
(show-help, %options): Add '--export-manifest'.
(process-query): Honor it.
* guix/build/profiles.scm (build-profile): Mention it.
* tests/guix-package.sh: Test it.
* doc/guix.texi (Invoking guix package): Document it.
---
 doc/guix.texi            | 21 +++++++++++++++
 guix/build/profiles.scm  |  6 +++--
 guix/scripts/package.scm | 57 +++++++++++++++++++++++++++++++++++++++-
 tests/guix-package.sh    | 10 ++++++-
 4 files changed, 90 insertions(+), 4 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index cea7f8a8cf..e524464e9f 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -3269,6 +3269,9 @@ objects, like this:
  '("emacs" "guile@@2.2" "guile@@2.2:debug"))
 @end lisp
 
+@xref{export-manifest, @option{--export-manifest}}, to learn how to
+obtain a manifest file from an existing profile.
+
 @item --roll-back
 @cindex rolling back
 @cindex undoing transactions
@@ -3571,6 +3574,24 @@ zeroth generation is never deleted.
 Note that deleting generations prevents rolling back to them.
 Consequently, this command must be used with care.
 
+@cindex manifest, exporting
+@anchor{export-manifest}
+@item --export-manifest
+Write to standard output a manifest suitable for @option{--manifest}
+corresponding to the chosen profile(s).
+
+This option is meant to help you migrate from the ``imperative''
+operating mode---running @command{guix install}, @command{guix upgrade},
+etc.---to the declarative mode that @option{--manifest} offers.
+
+Be aware that the resulting manifest @emph{approximates} what your
+profile actually contains; for instance, depending on how your profile
+was created, it can refer to packages or package versions that are not
+exactly what you specified.
+
+Keep in mind that a manifest is purely symbolic: it only contains
+package names and possibly versions, and their meaning varies over time.
+
 @end table
 
 Finally, since @command{guix package} may actually start build
diff --git a/guix/build/profiles.scm b/guix/build/profiles.scm
index 67ee9b665a..b42f498a80 100644
--- a/guix/build/profiles.scm
+++ b/guix/build/profiles.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2015, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo <at> gnu.org>
+;;; Copyright © 2015, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo <at> gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -169,7 +169,9 @@ SEARCH-PATHS."
     (lambda (p)
       (display "\
 ;; This file was automatically generated and is for internal use only.
-;; It cannot be passed to the '--manifest' option.\n\n"
+;; It cannot be passed to the '--manifest' option.
+;; Run 'guix package --export-manifest' if to export a file suitable
+;; for '--manifest'.\n\n"
                p)
       (pretty-print manifest p)))
 
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index 6faf2adb7a..2b52016c67 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo <at> gnu.org>
+;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo <at> gnu.org>
 ;;; Copyright © 2013 Nikita Karetnikov <nikita <at> karetnikov.org>
 ;;; Copyright © 2013, 2015 Mark H Weaver <mhw <at> netris.org>
 ;;; Copyright © 2014, 2016 Alex Kost <alezost <at> gmail.com>
@@ -48,6 +48,7 @@
                 #:select (directory-exists? mkdir-p))
   #:use-module (ice-9 format)
   #:use-module (ice-9 match)
+  #:autoload   (ice-9 pretty-print) (pretty-print)
   #:use-module (ice-9 regex)
   #:use-module (ice-9 vlist)
   #:use-module (srfi srfi-1)
@@ -320,6 +321,48 @@ GUIX_PROFILE=\"~a\"
 Alternately, see @command{guix package --search-paths -p ~s}.")
                             profile profile)))))
 
+
+;;;
+;;; Export a manifest.
+;;;
+
+(define* (export-manifest manifest
+                          #:optional (port (current-output-port)))
+  "Write to PORT a manifest corresponding to MANIFEST."
+  (define (version-spec entry)
+    (let ((name (manifest-entry-name entry)))
+      (match (map package-version (find-packages-by-name name))
+        ((_)
+         ;; A single version of NAME is available, so do not specify the
+         ;; version number, even if the available version doesn't match ENTRY.
+         "")
+        (versions
+         ;; If ENTRY uses the latest version, don't specify any version.
+         ;; Otherwise return the shortest unique version prefix.  Note that
+         ;; this is based on the currently available packages, which could
+         ;; differ from the packages available in the revision that was used
+         ;; to build MANIFEST.
+         (let ((current (manifest-entry-version entry)))
+           (if (every (cut version>? current <>)
+                      (delete current versions))
+               ""
+               (version-unique-prefix (manifest-entry-version entry)
+                                      versions)))))))
+
+  (match (manifest->code manifest
+                         #:entry-package-version version-spec)
+    (('begin exp ...)
+     (format port (G_ "\
+;; This \"manifest\" file can be passed to 'guix package -m' to reproduce
+;; the content of your profile.  This is \"symbolic\": it only specifies
+;; package names.  To reproduce the exact same profile, you also need to
+;; capture the channels being used, as returned by \"guix describe\".
+;; See the \"Replicating Guix\" section in the manual.\n"))
+     (for-each (lambda (exp)
+                 (newline port)
+                 (pretty-print exp port))
+               exp))))
+
 
 ;;;
 ;;; Command-line options.
@@ -373,6 +416,8 @@ Install, remove, or upgrade packages in a single transaction.\n"))
   (display (G_ "
   -S, --switch-generation=PATTERN
                          switch to a generation matching PATTERN"))
+  (display (G_ "
+      --export-manifest  print a manifest for the chosen profile"))
   (display (G_ "
   -p, --profile=PROFILE  use PROFILE instead of the user's default profile"))
   (display (G_ "
@@ -507,6 +552,10 @@ kind of search path~%")
                      (values (cons `(query search-paths ,kind)
                                    result)
                              #f))))
+         (option '("export-manifest") #f #f
+                 (lambda (opt name arg result arg-handler)
+                   (values (cons `(query export-manifest) result)
+                           #f)))
          (option '(#\p "profile") #t #f
                  (lambda (opt name arg result arg-handler)
                    (values (alist-cons 'profile (canonicalize-profile arg)
@@ -827,6 +876,12 @@ processed, #f otherwise."
          (format #t "~{~a~%~}" settings)
          #t))
 
+      (('export-manifest)
+       (let* ((manifest (concatenate-manifests
+                         (map profile-manifest profiles))))
+         (export-manifest manifest (current-output-port))
+         #t))
+
       (_ #f))))
 
 
diff --git a/tests/guix-package.sh b/tests/guix-package.sh
index 3e5fa71d20..7eaad6823f 100644
--- a/tests/guix-package.sh
+++ b/tests/guix-package.sh
@@ -1,5 +1,5 @@
 # GNU Guix --- Functional package management for GNU
-# Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo <at> gnu.org>
+# Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo <at> gnu.org>
 # Copyright © 2013 Nikita Karetnikov <nikita <at> karetnikov.org>
 #
 # This file is part of GNU Guix.
@@ -395,6 +395,14 @@ EOF
 guix package --bootstrap -m "$module_dir/manifest.scm"
 guix package -I | grep guile
 test `guix package -I | wc -l` -eq 1
+
+# Export a manifest, instantiate it, and make sure we get the same profile.
+profile_directory="$(readlink -f "$default_profile")"
+guix package --export-manifest > "$tmpfile"
+guix package --rollback --bootstrap
+guix package --bootstrap -m "$tmpfile"
+test "$(readlink -f "$default_profile")" = "$profile_directory"
+
 guix package --rollback --bootstrap
 
 # Applying two manifests.
-- 
2.30.0





Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sat, 16 Jan 2021 18:35:02 GMT) Full text and rfc822 format available.

Message #17 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 45919 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 4/8] channels: Factorize 'manifest-entry-channel' and channel
 serialization.
Date: Sat, 16 Jan 2021 19:34:05 +0100
* guix/channels.scm (sexp->channel, manifest-entry-channel): New
procedures.
(profile-channels): Replace lambda by 'manifest-entry-channel'.
(channel-instance->sexp): New procedure.
(channel-instances->manifest)[instance->entry]: Use
'channel-instance->sexp' instead of inline code.
---
 guix/channels.scm | 106 +++++++++++++++++++++++++++-------------------
 1 file changed, 63 insertions(+), 43 deletions(-)

diff --git a/guix/channels.scm b/guix/channels.scm
index 0c84eed477..65a0d849ec 100644
--- a/guix/channels.scm
+++ b/guix/channels.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2018, 2019, 2020 Ludovic Courtès <ludo <at> gnu.org>
+;;; Copyright © 2018, 2019, 2020, 2021 Ludovic Courtès <ludo <at> gnu.org>
 ;;; Copyright © 2018 Ricardo Wurmus <rekado <at> elephly.net>
 ;;; Copyright © 2019 Jan (janneke) Nieuwenhuizen <janneke <at> gnu.org>
 ;;;
@@ -802,13 +802,35 @@ derivation."
                           (derivation-input-derivation input))))
              (derivation-inputs drv))))
 
+(define (channel-instance->sexp instance)
+  "Return an sexp representation of INSTANCE, a channel instance."
+  (let* ((commit  (channel-instance-commit instance))
+         (channel (channel-instance-channel instance))
+         (intro   (channel-introduction channel)))
+    `(repository
+      (version 0)
+      (url ,(channel-url channel))
+      (branch ,(channel-branch channel))
+      (commit ,commit)
+      ,@(if intro
+            `((introduction
+               (channel-introduction
+                (version 0)
+                (commit
+                 ,(channel-introduction-first-signed-commit
+                   intro))
+                (signer
+                 ,(openpgp-format-fingerprint
+                   (channel-introduction-first-commit-signer
+                    intro))))))
+            '()))))
+
 (define (channel-instances->manifest instances)
   "Return a profile manifest with entries for all of INSTANCES, a list of
 channel instances."
   (define (instance->entry instance drv)
-    (let* ((commit  (channel-instance-commit instance))
-           (channel (channel-instance-channel instance))
-           (intro   (channel-introduction channel)))
+    (let ((commit  (channel-instance-commit instance))
+          (channel (channel-instance-channel instance)))
       (manifest-entry
         (name (symbol->string (channel-name channel)))
         (version (string-take commit 7))
@@ -819,23 +841,7 @@ channel instances."
                       drv)
                   drv))
         (properties
-         `((source (repository
-                    (version 0)
-                    (url ,(channel-url channel))
-                    (branch ,(channel-branch channel))
-                    (commit ,commit)
-                    ,@(if intro
-                          `((introduction
-                             (channel-introduction
-                              (version 0)
-                              (commit
-                               ,(channel-introduction-first-signed-commit
-                                 intro))
-                              (signer
-                               ,(openpgp-format-fingerprint
-                                 (channel-introduction-first-commit-signer
-                                  intro))))))
-                          '()))))))))
+         `((source ,(channel-instance->sexp instance)))))))
 
   (mlet* %store-monad ((derivations (channel-instance-derivations instances))
                        (entries ->  (map instance->entry instances derivations)))
@@ -900,31 +906,45 @@ to 'latest-channel-instances'."
                                                   validate-pull)))
     (channel-instances->derivation instances)))
 
+(define* (sexp->channel sexp #:optional (name 'channel))
+  "Read SEXP, a provenance sexp as created by 'channel-instance->sexp',
+and return a channel called NAME.  Return #f if the sexp does not have the
+expected structure."
+  (match sexp
+    (('repository ('version 0)
+                  ('url url)
+                  ('branch branch)
+                  ('commit commit)
+                  rest ...)
+     (channel (name name)
+              (url url)
+              (commit commit)
+              (introduction
+               (match (assq 'introduction rest)
+                 (#f #f)
+                 (('introduction intro)
+                  (sexp->channel-introduction intro))))))
+
+    (_ #f)))
+
+(define (manifest-entry-channel entry)
+  "Return the channel ENTRY corresponds to, or #f if that information is
+missing or unreadable.  ENTRY must be an entry created by
+'channel-instances->manifest', with the 'source' property."
+  (let ((name (string->symbol (manifest-entry-name entry))))
+    (match (assq-ref (manifest-entry-properties entry) 'source)
+      ((sexp)
+       (sexp->channel sexp name))
+      (_
+       ;; No channel information for this manifest entry.
+       ;; XXX: Pre-0.15.0 Guix did not provide that information,
+       ;; but there's not much we can do in that case.
+       #f))))
+
 (define (profile-channels profile)
   "Return the list of channels corresponding to entries in PROFILE.  If
 PROFILE is not a profile created by 'guix pull', return the empty list."
-  (filter-map (lambda (entry)
-                (match (assq 'source (manifest-entry-properties entry))
-                  (('source ('repository ('version 0)
-                                         ('url url)
-                                         ('branch branch)
-                                         ('commit commit)
-                                         rest ...))
-                   (channel (name (string->symbol
-                                   (manifest-entry-name entry)))
-                            (url url)
-                            (commit commit)
-                            (introduction
-                             (match (assq 'introduction rest)
-                               (#f #f)
-                               (('introduction intro)
-                                (sexp->channel-introduction intro))))))
-
-                  ;; No channel information for this manifest entry.
-                  ;; XXX: Pre-0.15.0 Guix did not provide that information,
-                  ;; but there's not much we can do in that case.
-                  (_ #f)))
-
+  (filter-map manifest-entry-channel
               ;; Show most recently installed packages last.
               (reverse
                (manifest-entries (profile-manifest profile)))))
-- 
2.30.0





Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sat, 16 Jan 2021 18:35:03 GMT) Full text and rfc822 format available.

Message #20 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 45919 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 5/8] channels: Add the channel name to channel sexps.
Date: Sat, 16 Jan 2021 19:34:06 +0100
* guix/channels.scm (channel-instance->sexp): Add 'name'.
(sexp->channel): Extract the name from SEXP, using the optional argument
as a fallback.
---
 guix/channels.scm | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/guix/channels.scm b/guix/channels.scm
index 65a0d849ec..6449221c3f 100644
--- a/guix/channels.scm
+++ b/guix/channels.scm
@@ -812,6 +812,7 @@ derivation."
       (url ,(channel-url channel))
       (branch ,(channel-branch channel))
       (commit ,commit)
+      (name ,(channel-name channel))
       ,@(if intro
             `((introduction
                (channel-introduction
@@ -907,16 +908,22 @@ to 'latest-channel-instances'."
     (channel-instances->derivation instances)))
 
 (define* (sexp->channel sexp #:optional (name 'channel))
-  "Read SEXP, a provenance sexp as created by 'channel-instance->sexp',
-and return a channel called NAME.  Return #f if the sexp does not have the
-expected structure."
+  "Read SEXP, a provenance sexp as created by 'channel-instance->sexp'; use
+NAME as the channel name if SEXP does not specify it.  Return #f if the sexp
+does not have the expected structure."
   (match sexp
     (('repository ('version 0)
                   ('url url)
                   ('branch branch)
                   ('commit commit)
                   rest ...)
-     (channel (name name)
+     ;; Historically channel sexps did not include the channel name.  It's OK
+     ;; for channels created by 'channel-instances->manifest' because the
+     ;; entry name is the channel name, but it was missing for entries created
+     ;; by 'manifest-entry-with-provenance'.
+     (channel (name (match (assq 'name rest)
+                      (#f name)
+                      (('name name) name)))
               (url url)
               (commit commit)
               (introduction
-- 
2.30.0





Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sat, 16 Jan 2021 18:35:03 GMT) Full text and rfc822 format available.

Message #23 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 45919 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 6/8] guix describe: Use 'manifest-entry-channel'.
Date: Sat, 16 Jan 2021 19:34:07 +0100
* guix/channels.scm (manifest-entry-channel): Export.
* guix/scripts/describe.scm (display-profile-content): Use it.
---
 guix/channels.scm         |  1 +
 guix/scripts/describe.scm | 30 ++++++++++++------------------
 2 files changed, 13 insertions(+), 18 deletions(-)

diff --git a/guix/channels.scm b/guix/channels.scm
index 6449221c3f..743b4a25b7 100644
--- a/guix/channels.scm
+++ b/guix/channels.scm
@@ -91,6 +91,7 @@
             ensure-forward-channel-update
 
             profile-channels
+            manifest-entry-channel
 
             channel-news-entry?
             channel-news-entry-commit
diff --git a/guix/scripts/describe.scm b/guix/scripts/describe.scm
index c3667516eb..b7ec029ba8 100644
--- a/guix/scripts/describe.scm
+++ b/guix/scripts/describe.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2018, 2019, 2020 Ludovic Courtès <ludo <at> gnu.org>
+;;; Copyright © 2018, 2019, 2020, 2021 Ludovic Courtès <ludo <at> gnu.org>
 ;;; Copyright © 2018 Oleg Pykhalov <go.wigust <at> gmail.com>
 ;;; Copyright © 2020 Ekaitz Zarraga <ekaitz <at> elenq.tech>
 ;;;
@@ -237,23 +237,17 @@ way and displaying details about the channel's source code."
               (format #t "  ~a ~a~%"
                       (manifest-entry-name entry)
                       (manifest-entry-version entry))
-              (match (assq 'source (manifest-entry-properties entry))
-                (('source ('repository ('version 0)
-                                       ('url url)
-                                       ('branch branch)
-                                       ('commit commit)
-                                       _ ...))
-                 (let ((channel (channel (name 'nameless)
-                                         (url url)
-                                         (branch branch)
-                                         (commit commit))))
-                   (format #t (G_ "    repository URL: ~a~%") url)
-                   (when branch
-                     (format #t (G_ "    branch: ~a~%") branch))
-                   (format #t (G_ "    commit: ~a~%")
-                           (if (supports-hyperlinks?)
-                               (channel-commit-hyperlink channel commit)
-                               commit))))
+              (match (manifest-entry-channel entry)
+                ((? channel? channel)
+                 (format #t (G_ "    repository URL: ~a~%")
+                         (channel-url channel))
+                 (when (channel-branch channel)
+                   (format #t (G_ "    branch: ~a~%")
+                           (channel-branch channel)))
+                 (format #t (G_ "    commit: ~a~%")
+                         (if (supports-hyperlinks?)
+                             (channel-commit-hyperlink channel)
+                             (channel-commit channel))))
                 (_ #f)))
 
             ;; Show most recently installed packages last.
-- 
2.30.0





Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sat, 16 Jan 2021 18:35:04 GMT) Full text and rfc822 format available.

Message #26 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 45919 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 7/8] channels: Add 'channel->code'.
Date: Sat, 16 Jan 2021 19:34:08 +0100
* guix/channels.scm (channel->code): New procedure, taken from...
* guix/scripts/describe.scm (channel->sexp): ... here.
Adjust callers accordingly.
---
 guix/channels.scm         | 19 +++++++++++++++++++
 guix/scripts/describe.scm | 22 +++-------------------
 2 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/guix/channels.scm b/guix/channels.scm
index 743b4a25b7..cdef77637d 100644
--- a/guix/channels.scm
+++ b/guix/channels.scm
@@ -92,6 +92,7 @@
 
             profile-channels
             manifest-entry-channel
+            channel->code
 
             channel-news-entry?
             channel-news-entry-commit
@@ -957,6 +958,24 @@ PROFILE is not a profile created by 'guix pull', return the empty list."
               (reverse
                (manifest-entries (profile-manifest profile)))))
 
+(define* (channel->code channel #:key (include-introduction? #t))
+  "Return code (an sexp) to build CHANNEL.  When INCLUDE-INTRODUCTION? is
+true, include its introduction, if any."
+  (let ((intro (and include-introduction?
+                    (channel-introduction channel))))
+    `(channel
+      (name ',(channel-name channel))
+      (url ,(channel-url channel))
+      (commit ,(channel-commit channel))
+      ,@(if intro
+            `((introduction (make-channel-introduction
+                             ,(channel-introduction-first-signed-commit intro)
+                             (openpgp-fingerprint
+                              ,(openpgp-format-fingerprint
+                                (channel-introduction-first-commit-signer
+                                 intro))))))
+            '()))))
+
 
 ;;;
 ;;; News.
diff --git a/guix/scripts/describe.scm b/guix/scripts/describe.scm
index b7ec029ba8..e47d207ee0 100644
--- a/guix/scripts/describe.scm
+++ b/guix/scripts/describe.scm
@@ -113,22 +113,6 @@ Display information about the channels currently in use.\n"))
        (_
         (warning (G_ "'GUIX_PACKAGE_PATH' is set but it is not captured~%")))))))
 
-(define* (channel->sexp channel #:key (include-introduction? #t))
-  (let ((intro (and include-introduction?
-                    (channel-introduction channel))))
-    `(channel
-      (name ',(channel-name channel))
-      (url ,(channel-url channel))
-      (commit ,(channel-commit channel))
-      ,@(if intro
-            `((introduction (make-channel-introduction
-                             ,(channel-introduction-first-signed-commit intro)
-                             (openpgp-fingerprint
-                              ,(openpgp-format-fingerprint
-                                (channel-introduction-first-commit-signer
-                                 intro))))))
-            '()))))
-
 (define (channel->json channel)
   (scm->json-string
    (let ((intro (channel-introduction channel)))
@@ -183,7 +167,7 @@ string is ~a.~%")
        (format #t (G_ "  branch: ~a~%") (reference-shorthand head))
        (format #t (G_ "  commit: ~a~%") commit))
       ('channels
-       (pretty-print `(list ,(channel->sexp (channel (name 'guix)
+       (pretty-print `(list ,(channel->code (channel (name 'guix)
                                                      (url (dirname directory))
                                                      (commit commit))))))
       ('json
@@ -213,9 +197,9 @@ in the format specified by FMT."
     ('human
      (display-profile-content profile number))
     ('channels
-     (pretty-print `(list ,@(map channel->sexp channels))))
+     (pretty-print `(list ,@(map channel->code channels))))
     ('channels-sans-intro
-     (pretty-print `(list ,@(map (cut channel->sexp <>
+     (pretty-print `(list ,@(map (cut channel->code <>
                                       #:include-introduction? #f)
                                  channels))))
     ('json
-- 
2.30.0





Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sat, 16 Jan 2021 18:35:04 GMT) Full text and rfc822 format available.

Message #29 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 45919 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 8/8] guix package: Add '--export-channels'.
Date: Sat, 16 Jan 2021 19:34:09 +0100
* 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.
---
 build-aux/build-self.scm |  3 ++
 doc/guix.texi            | 24 ++++++++++++++++
 guix/channels.scm        |  1 +
 guix/describe.scm        | 34 ++++++++++++++++++++--
 guix/scripts/package.scm | 61 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 121 insertions(+), 2 deletions(-)

diff --git a/build-aux/build-self.scm b/build-aux/build-self.scm
index 4b6e2bfae5..d5bc5fb46e 100644
--- a/build-aux/build-self.scm
+++ b/build-aux/build-self.scm
@@ -245,8 +245,11 @@ interface (FFI) of Guile.")
   "Return a program that computes the derivation to build Guix from SOURCE."
   (define select?
     ;; Select every module but (guix config) and non-Guix modules.
+    ;; Also exclude (guix channels): it is autoloaded by (guix describe), but
+    ;; only for peripheral functionality.
     (match-lambda
       (('guix 'config) #f)
+      (('guix 'channels) #f)
       (('guix _ ...)   #t)
       (('gnu _ ...)    #t)
       (_               #f)))
diff --git a/doc/guix.texi b/doc/guix.texi
index e524464e9f..cfb2f8a296 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -3591,7 +3591,31 @@ exactly what you specified.
 
 Keep in mind that a manifest is purely symbolic: it only contains
 package names and possibly versions, and their meaning varies over time.
+If you wish to ``pin'' channels to the revisions that were used to build
+the profile(s), see @option{--export-channels} below.
 
+@cindex pinning, channel revisions of a profile
+@item --export-channels
+Write to standard output the list of channels used by the chosen
+profile(s), in a format suitable for @command{guix pull --channels} or
+@command{guix time-machine --channels} (@pxref{Channels}).
+
+Together with @option{--export-manifest}, this option provides
+information allowing you to replicate the current profile
+(@pxref{Replicating Guix}).
+
+However, note that the output of this command @emph{approximates} what
+was actually used to build this profile.  In particular, a single
+profile might have been built from several different revisions of the
+same channel.  In that case, @option{--export-manifest} chooses the last
+one and writes the list of other revisions in a comment.  If you really
+need to pick packages from different channel revisions, you can use
+inferiors in your manifest to do so (@pxref{Inferiors}).
+
+Together with @option{--export-manifest}, this is a good starting point
+if you are willing to migrate from the ``imperative'' model to the fully
+declarative model consisting of a manifest file along with a channels
+file pinning the exact channel revision(s) you want.
 @end table
 
 Finally, since @command{guix package} may actually start build
diff --git a/guix/channels.scm b/guix/channels.scm
index cdef77637d..e7e1eb6fd0 100644
--- a/guix/channels.scm
+++ b/guix/channels.scm
@@ -92,6 +92,7 @@
 
             profile-channels
             manifest-entry-channel
+            sexp->channel
             channel->code
 
             channel-news-entry?
diff --git a/guix/describe.scm b/guix/describe.scm
index 05bf99eb58..ac89fc0d7c 100644
--- a/guix/describe.scm
+++ b/guix/describe.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2018, 2019, 2020 Ludovic Courtès <ludo <at> gnu.org>
+;;; Copyright © 2018, 2019, 2020, 2021 Ludovic Courtès <ludo <at> gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -23,6 +23,7 @@
   #:use-module ((guix utils) #:select (location-file))
   #:use-module ((guix store) #:select (%store-prefix store-path?))
   #:use-module ((guix config) #:select (%state-directory))
+  #:autoload   (guix channels) (sexp->channel)
   #:use-module (srfi srfi-1)
   #:use-module (ice-9 match)
   #:export (current-profile
@@ -31,7 +32,8 @@
             package-path-entries
 
             package-provenance
-            manifest-entry-with-provenance))
+            manifest-entry-with-provenance
+            manifest-entry-provenance))
 
 ;;; Commentary:
 ;;;
@@ -166,3 +168,31 @@ there."
                (#f   properties)
                (sexp `((provenance ,@sexp)
                        ,@properties)))))))))
+
+(define (manifest-entry-provenance entry)
+  "Return the list of channels ENTRY comes from.  Return the empty list if
+that information is missing."
+  (match (assq-ref (manifest-entry-properties entry) 'provenance)
+    ((main extras ...)
+     ;; XXX: Until recently, channel sexps lacked the channel name.  For
+     ;; entries created by 'manifest-entry-with-provenance', the first sexp
+     ;; is known to be the 'guix channel, and for the other ones, invent a
+     ;; fallback name (it's OK as the name is just a "pet name").
+     (match (sexp->channel main 'guix)
+       (#f '())
+       (channel
+        (let loop ((extras   extras)
+                   (counter  1)
+                   (channels (list channel)))
+          (match extras
+            (()
+             (reverse channels))
+            ((head . tail)
+             (let* ((name  (string->symbol
+                            (format #f "channel~a" counter)))
+                    (extra (sexp->channel head name)))
+               (if extra
+                   (loop tail (+ 1 counter) (cons extra channels))
+                   (loop tail counter channels)))))))))
+    (_
+     '())))
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index 2b52016c67..8234a1703d 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -43,6 +43,7 @@
   #:use-module (guix scripts build)
   #:use-module (guix transformations)
   #:use-module (guix describe)
+  #:autoload   (guix channels) (channel-name channel-commit channel->code)
   #:autoload   (guix store roots) (gc-roots user-owned?)
   #:use-module ((guix build utils)
                 #:select (directory-exists? mkdir-p))
@@ -363,6 +364,54 @@ Alternately, see @command{guix package --search-paths -p ~s}.")
                  (pretty-print exp port))
                exp))))
 
+(define (channel=? a b)
+  (and (channel-commit a) (channel-commit b)
+       (string=? (channel-commit a) (channel-commit b))))
+
+(define* (export-channels manifest
+                          #:optional (port (current-output-port)))
+  (define channels
+    (delete-duplicates
+     (append-map manifest-entry-provenance (manifest-entries manifest))
+     channel=?))
+
+  (define channel-names
+    (delete-duplicates (map channel-name channels)))
+
+  (define table
+    (fold (lambda (channel table)
+            (vhash-consq (channel-name channel) channel table))
+          vlist-null
+          channels))
+
+  (when (null? channels)
+    (leave (G_ "no provenance information for this profile~%")))
+
+  (format port (G_ "\
+;; This channel file can be passed to 'guix pull -C' or to
+;; 'guix time-machine -C' to obtain the Guix revision that was
+;; used to populate this profile.\n"))
+  (newline port)
+  (display "(list\n" port)
+  (for-each (lambda (name)
+              (define indent "     ")
+              (match (vhash-foldq* cons '() name table)
+                ((channel extra ...)
+                 (unless (null? extra)
+                   (display indent port)
+                   (format port (G_ "\
+;; Note: these other commits were also used to install \
+some of the packages in this profile:~%"))
+                   (for-each (lambda (channel)
+                               (format port "~a;;   ~s~%"
+                                       indent (channel-commit channel)))
+                             extra))
+                 (pretty-print (channel->code channel) port
+                               #:per-line-prefix indent))))
+            channel-names)
+  (display ")\n" port)
+  #t)
+
 
 ;;;
 ;;; Command-line options.
@@ -418,6 +467,8 @@ Install, remove, or upgrade packages in a single transaction.\n"))
                          switch to a generation matching PATTERN"))
   (display (G_ "
       --export-manifest  print a manifest for the chosen profile"))
+  (display (G_ "
+      --export-channels  print channels for the chosen profile"))
   (display (G_ "
   -p, --profile=PROFILE  use PROFILE instead of the user's default profile"))
   (display (G_ "
@@ -556,6 +607,10 @@ kind of search path~%")
                  (lambda (opt name arg result arg-handler)
                    (values (cons `(query export-manifest) result)
                            #f)))
+         (option '("export-channels") #f #f
+                 (lambda (opt name arg result arg-handler)
+                   (values (cons `(query export-channels) result)
+                           #f)))
          (option '(#\p "profile") #t #f
                  (lambda (opt name arg result arg-handler)
                    (values (alist-cons 'profile (canonicalize-profile arg)
@@ -882,6 +937,12 @@ processed, #f otherwise."
          (export-manifest manifest (current-output-port))
          #t))
 
+      (('export-channels)
+       (let ((manifest (concatenate-manifests
+                        (map profile-manifest profiles))))
+         (export-channels manifest (current-output-port))
+         #t))
+
       (_ #f))))
 
 
-- 
2.30.0





Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Wed, 27 Jan 2021 13:15:02 GMT) Full text and rfc822 format available.

Message #32 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 45919 <at> debbugs.gnu.org
Cc: guix-devel <guix-devel <at> gnu.org>
Subject: Re: bug#45919: [PATCH 0/8] Exporting a manifest and channels from a
 profile
Date: Wed, 27 Jan 2021 14:14:49 +0100
Hi there!

Ludovic Courtès <ludo <at> gnu.org> skribis:

> Here’s a simple but oft-requested feature (I remember discussing
> with Pierre and Simon a year ago at the Guix Days about ways to
> implement it—time flies!): these patches provide ‘guix package
> --export-manifest’ and ‘--export-channels’.  These options spit
> a manifest and a channel spec, respectively, with the goal of
> helping users who wish to migrate to the declarative model.

I’m rather happy with this patch set but since this is something we’ve
discussed several times in the past, I think it’d be great if those
interested could chime in and comment:

  https://issues.guix.gnu.org/45919

I’ll leave a few more days and then… push!

TIA,
Ludo’.




Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Wed, 27 Jan 2021 21:12:01 GMT) Full text and rfc822 format available.

Message #35 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: zimoun <zimon.toutoune <at> gmail.com>
To: Ludovic Courtès <ludo <at> gnu.org>
Cc: guix-devel <guix-devel <at> gnu.org>, 45919 <at> debbugs.gnu.org
Subject: Re: [bug#45919] [PATCH 0/8] Exporting a manifest and channels from
 a profile
Date: Wed, 27 Jan 2021 22:02:53 +0100
Hi Ludo,

On Wed, 27 Jan 2021 at 14:14, Ludovic Courtès <ludo <at> gnu.org> wrote:
> Ludovic Courtès <ludo <at> gnu.org> skribis:
>
>> Here’s a simple but oft-requested feature (I remember discussing
>> with Pierre and Simon a year ago at the Guix Days about ways to
>> implement it—time flies!): these patches provide ‘guix package
>> --export-manifest’ and ‘--export-channels’.  These options spit
>> a manifest and a channel spec, respectively, with the goal of
>> helping users who wish to migrate to the declarative model.
>
> I’m rather happy with this patch set but since this is something we’ve
> discussed several times in the past, I think it’d be great if those
> interested could chime in and comment:
>
>   https://issues.guix.gnu.org/45919
>
> I’ll leave a few more days and then… push!

You are looking at me? :-)

Well, the feature is nice!  At first, I thought that it could be a bit
smarter than using only one commit.  But as you said, the aim is for
transitioning.  Maybe a future improvement should to list somewhere in
the comments which commit provides which set of packages.  It could
help… or not. :-)

Using Docker, it works.  Let describe how in case people are interested.


On machine A, I have:

--8<---------------cut here---------------start------------->8---
$ guix describe -f channels
(list (channel
        (name 'guix)
        (url "https://git.savannah.gnu.org/git/guix.git")
        (commit
          "cb68ae668af2ade4b0777d82f227e5462768e9e5")
        (introduction
          (make-channel-introduction
            "9edb3f66fd807b096b48283debdcddccfea34bad"
            (openpgp-fingerprint
              "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA")))))

$ cat ~/.config/guix/manifests/python.scm
(specifications->manifest
 (append
  '("python"
    )
  (map
   (lambda (pkg)
     (string-append "python-" pkg))
   '("ipython"
     "numpy"
     "matplotlib"
     "scipy"
     "biopython"
  ))))
--8<---------------cut here---------------end--------------->8---

And I generate a Docker pack with:

--8<---------------cut here---------------start------------->8---
$ guix pack -f docker --save-provenance -m ~/.config/guix/manifests/python.scm
/gnu/store/wxymmnxdvdvf08ifsfy39xjaxilhrigk-docker-pack.tar.gz
--8<---------------cut here---------------end--------------->8---


Then on machine B, after fetching this tarball, I run:

--8<---------------cut here---------------start------------->8---
$ docker load < /tmp/img/wxymmnxdvdvf08ifsfy39xjaxilhrigk-docker-pack.tar.gz
$ docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
python-python-ipython-python-numpy   latest              49ddfedf1e27        51 years ago        1.45GB
--8<---------------cut here---------------end--------------->8---

And it works as expected:

--8<---------------cut here---------------start------------->8---
$ docker run -ti python-python-ipython-python-numpy:latest python3
Python 3.8.2 (default, Jan  1 1970, 00:00:01)
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
>>> import numpy as np
>>> A = np.array([[1,0,1],[0,1,0],[0,0,1]])
>>> _, s, _ = np.linalg.svd(A); s; abs(s[0] - 1./s[2])
array([1.61803399, 1.        , 0.61803399])
0.0
>>>
--8<---------------cut here---------------end--------------->8---

Neat!

So far, so good.  Well, let extract the ’manifest’ from this Docker
blob.

--8<---------------cut here---------------start------------->8---
$ docker export -o /tmp/img/re-pack.tar $(docker ps -a --format "{{.ID}}" | head -n1)
$ tar -xf /tmp/img/re-pack.tar $(tar -tf /tmp/img/re-pack.tar | grep 'profile/manifest')
$ cat gnu/store/7frdchgf5sqw8b83azsml3lw0h52gfbk-profile/manifest | grep -E "(\(\"python|cb68ae)" | head -n5
    (("python"
              "cb68ae668af2ade4b0777d82f227e5462768e9e5")
     ("python-ipython"
        (("python-backcall"
         ("python-pyzmq"
--8<---------------cut here---------------end--------------->8---

Now, a trick to get the channels and specifications:

--8<---------------cut here---------------start------------->8---
$ ./pre-inst-env guix package -p /tmp/img/gnu/store/7frdchgf5sqw8b83azsml3lw0h52gfbk-profile --export-channels
;; This channel file can be passed to 'guix pull -C' or to
;; 'guix time-machine -C' to obtain the Guix revision that was
;; used to populate this profile.

(list
     (channel
       (name 'guix)
       (url "https://git.savannah.gnu.org/git/guix.git")
       (commit
         "cb68ae668af2ade4b0777d82f227e5462768e9e5")
       (introduction
         (make-channel-introduction
           "9edb3f66fd807b096b48283debdcddccfea34bad"
           (openpgp-fingerprint
             "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA"))))
)

$ ./pre-inst-env guix package -p /tmp/img/gnu/store/7frdchgf5sqw8b83azsml3lw0h52gfbk-profile --export-manifest
$ ./pre-inst-env guix package -p /tmp/img/gnu/store/7frdchgf5sqw8b83azsml3lw0h52gfbk-profile --export-manifest
;; This "manifest" file can be passed to 'guix package -m' to reproduce
;; the content of your profile.  This is "symbolic": it only specifies
;; package names.  To reproduce the exact same profile, you also need to
;; capture the channels being used, as returned by "guix describe".
;; See the "Replicating Guix" section in the manual.

(specifications->manifest
  (list "python"
        "python-ipython"
        "python-numpy"
        "python-matplotlib"
        "python-scipy"
        "python-biopython"))
--8<---------------cut here---------------end--------------->8---

Awesome!


The unexpected is this channels and manifests files do not reproduce the
same Docker pack tarball:

--8<---------------cut here---------------start------------->8---
$ guix describe
Generation 99   Jan 05 2021 16:56:39    (current)
  guix-past 829923f
    repository URL: https://gitlab.inria.fr/guix-hpc/guix-past
    branch: master
    commit: 829923f01f894f1e687735627025ada26230832f
  guix-bimsb a8b539d
    repository URL: https://github.com/BIMSBbioinfo/guix-bimsb
    branch: master
    commit: a8b539d61a359060c35f3cb34c7edd1d9d14241d
  bimsb-nonfree 4084e63
    repository URL: https://github.com/BIMSBbioinfo/guix-bimsb-nonfree.git
    branch: master
    commit: 4084e63c9c0d662780870aded9f5a6ca1b063780
  guix-science cf87b05
    repository URL: https://github.com/guix-science/guix-science.git
    branch: master
    commit: cf87b0501c4a38b96edf41025a27bf1cb91f521a
  guix 957f0c4
    repository URL: https://git.savannah.gnu.org/git/guix.git
    branch: master
    commit: 957f0c40327ce00f53db22737e3775ce616ac258

$ guix time-machine -C /tmp/img/channels.scm -- pack -f docker --save-provenance -m /tmp/img/manifest.scm
Updating channel 'guix' from Git repository at 'https://git.savannah.gnu.org/git/guix.git'...
/gnu/store/xzk604g8gysv4azn7sf9nylr6iah97gl-docker-pack.tar.gz
--8<---------------cut here---------------end--------------->8---

To compare with
/gnu/store/wxymmnxdvdvf08ifsfy39xjaxilhrigk-docker-pack.tar.gz.

On a third machine, I get:
/gnu/store/wxymmnxdvdvf08ifsfy39xjaxilhrigk-docker-pack.tar.gz

Well, that’s another story and I have not inspected yet the
derivations and what could be wrong on the machine B.


Cheers,
simon




Added indication that bug 45919 blocks45896 Request was from Ludovic Courtès <ludo <at> gnu.org> to control <at> debbugs.gnu.org. (Wed, 27 Jan 2021 21:55:02 GMT) Full text and rfc822 format available.

Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Thu, 28 Jan 2021 15:55:01 GMT) Full text and rfc822 format available.

Message #40 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: zimoun <zimon.toutoune <at> gmail.com>
Cc: guix-devel <guix-devel <at> gnu.org>, 45919 <at> debbugs.gnu.org
Subject: Re: [bug#45919] [PATCH 0/8] Exporting a manifest and channels from
 a profile
Date: Thu, 28 Jan 2021 16:54:26 +0100
Hi,

zimoun <zimon.toutoune <at> gmail.com> skribis:

> On Wed, 27 Jan 2021 at 14:14, Ludovic Courtès <ludo <at> gnu.org> wrote:
>> Ludovic Courtès <ludo <at> gnu.org> skribis:
>>
>>> Here’s a simple but oft-requested feature (I remember discussing
>>> with Pierre and Simon a year ago at the Guix Days about ways to
>>> implement it—time flies!): these patches provide ‘guix package
>>> --export-manifest’ and ‘--export-channels’.  These options spit
>>> a manifest and a channel spec, respectively, with the goal of
>>> helping users who wish to migrate to the declarative model.
>>
>> I’m rather happy with this patch set but since this is something we’ve
>> discussed several times in the past, I think it’d be great if those
>> interested could chime in and comment:
>>
>>   https://issues.guix.gnu.org/45919
>>
>> I’ll leave a few more days and then… push!
>
> You are looking at me? :-)

Yes, but not just.  :-)

> Well, the feature is nice!  At first, I thought that it could be a bit
> smarter than using only one commit.  But as you said, the aim is for
> transitioning.  Maybe a future improvement should to list somewhere in
> the comments which commit provides which set of packages.  It could
> help… or not. :-)
>
> Using Docker, it works.  Let describe how in case people are interested.

[...]

> Awesome!

Woow, thanks for explaining the experiment, it’s a nice one!  Would be
worth turning into a blog post, maybe for hpc.guix.info?

> The unexpected is this channels and manifests files do not reproduce the
> same Docker pack tarball:
>
> $ guix describe
> Generation 99   Jan 05 2021 16:56:39    (current)
>   guix-past 829923f
>     repository URL: https://gitlab.inria.fr/guix-hpc/guix-past
>     branch: master
>     commit: 829923f01f894f1e687735627025ada26230832f
>   guix-bimsb a8b539d
>     repository URL: https://github.com/BIMSBbioinfo/guix-bimsb
>     branch: master
>     commit: a8b539d61a359060c35f3cb34c7edd1d9d14241d
>   bimsb-nonfree 4084e63
>     repository URL: https://github.com/BIMSBbioinfo/guix-bimsb-nonfree.git
>     branch: master
>     commit: 4084e63c9c0d662780870aded9f5a6ca1b063780
>   guix-science cf87b05
>     repository URL: https://github.com/guix-science/guix-science.git
>     branch: master
>     commit: cf87b0501c4a38b96edf41025a27bf1cb91f521a
>   guix 957f0c4
>     repository URL: https://git.savannah.gnu.org/git/guix.git
>     branch: master
>     commit: 957f0c40327ce00f53db22737e3775ce616ac258
>
> $ guix time-machine -C /tmp/img/channels.scm -- pack -f docker --save-provenance -m /tmp/img/manifest.scm
> Updating channel 'guix' from Git repository at 'https://git.savannah.gnu.org/git/guix.git'...
> /gnu/store/xzk604g8gysv4azn7sf9nylr6iah97gl-docker-pack.tar.gz
>
> To compare with
> /gnu/store/wxymmnxdvdvf08ifsfy39xjaxilhrigk-docker-pack.tar.gz.
>
> On a third machine, I get:
> /gnu/store/wxymmnxdvdvf08ifsfy39xjaxilhrigk-docker-pack.tar.gz
>
> Well, that’s another story and I have not inspected yet the
> derivations and what could be wrong on the machine B.

You’d have to check the differences.  It may be that provenance data
differs, for example because the second attempt includes data about
channels that are actually unused.  (That’s the whole problem of
provenance data: it’s not a one-to-one mapping and it’s not a bijection
either.)

Thanks for trying it out!

Ludo’.




Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Thu, 28 Jan 2021 17:05:02 GMT) Full text and rfc822 format available.

Message #43 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Pierre Neidhardt <mail <at> ambrevar.xyz>
To: Ludovic Courtès <ludo <at> gnu.org>, 45919 <at> debbugs.gnu.org
Cc: guix-devel <guix-devel <at> gnu.org>
Subject: Re: bug#45919: [PATCH 0/8] Exporting a manifest and channels from a
 profile
Date: Thu, 28 Jan 2021 18:04:27 +0100
[Message part 1 (text/plain, inline)]
Hi Ludo!

Ludovic Courtès <ludo <at> gnu.org> writes:

> Ludovic Courtès <ludo <at> gnu.org> skribis:
>
>> Here’s a simple but oft-requested feature (I remember discussing
>> with Pierre and Simon a year ago at the Guix Days about ways to
>> implement it—time flies!): these patches provide ‘guix package
>> --export-manifest’ and ‘--export-channels’.  These options spit
>> a manifest and a channel spec, respectively, with the goal of
>> helping users who wish to migrate to the declarative model.
>
> I’m rather happy with this patch set but since this is something we’ve
> discussed several times in the past, I think it’d be great if those
> interested could chime in and comment:
>
>   https://issues.guix.gnu.org/45919
>
> I’ll leave a few more days and then… push!

Thanks a lot for working on this, I'll try to give it a shot tomorrow! :)

-- 
Pierre Neidhardt
https://ambrevar.xyz/
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Thu, 28 Jan 2021 17:58:01 GMT) Full text and rfc822 format available.

Message #46 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Bengt Richter <bokr <at> bokr.com>
To: zimoun <zimon.toutoune <at> gmail.com>
Cc: guix-devel <guix-devel <at> gnu.org>,
 Ludovic Courtès <ludo <at> gnu.org>, 45919 <at> debbugs.gnu.org
Subject: Re: [bug#45919] [PATCH 0/8] Exporting a manifest and channels from a
 profile
Date: Thu, 28 Jan 2021 18:57:26 +0100
Hi zimoun,

Thank you for your tutorial-style and resource-reference-footnoted posts!

I don't know about others, but I save many on my hard disk as reference examples.

I hope this provides positive feedback for your efforts.
Thank you.

On +2021-01-27 22:02:53 +0100, zimoun wrote:
> Hi Ludo,
> 
> On Wed, 27 Jan 2021 at 14:14, Ludovic Courtès <ludo <at> gnu.org> wrote:
> > Ludovic Courtès <ludo <at> gnu.org> skribis:
> >
> >> Here’s a simple but oft-requested feature (I remember discussing
> >> with Pierre and Simon a year ago at the Guix Days about ways to
> >> implement it—time flies!): these patches provide ‘guix package
> >> --export-manifest’ and ‘--export-channels’.  These options spit
> >> a manifest and a channel spec, respectively, with the goal of
> >> helping users who wish to migrate to the declarative model.
> >
> > I’m rather happy with this patch set but since this is something we’ve
> > discussed several times in the past, I think it’d be great if those
> > interested could chime in and comment:
> >
> >   https://issues.guix.gnu.org/45919
> >
> > I’ll leave a few more days and then… push!
> 
> You are looking at me? :-)
> 
> Well, the feature is nice!  At first, I thought that it could be a bit
> smarter than using only one commit.  But as you said, the aim is for
> transitioning.  Maybe a future improvement should to list somewhere in
> the comments which commit provides which set of packages.  It could
> help… or not. :-)
> 
> Using Docker, it works.  Let describe how in case people are interested.
> 
> 
> On machine A, I have:
> 
> --8<---------------cut here---------------start------------->8---
> $ guix describe -f channels
> (list (channel
>         (name 'guix)
>         (url "https://git.savannah.gnu.org/git/guix.git")
>         (commit
>           "cb68ae668af2ade4b0777d82f227e5462768e9e5")
>         (introduction
>           (make-channel-introduction
>             "9edb3f66fd807b096b48283debdcddccfea34bad"
>             (openpgp-fingerprint
>               "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA")))))
> 
> $ cat ~/.config/guix/manifests/python.scm
> (specifications->manifest
>  (append
>   '("python"
>     )
>   (map
>    (lambda (pkg)
>      (string-append "python-" pkg))
>    '("ipython"
>      "numpy"
>      "matplotlib"
>      "scipy"
>      "biopython"
>   ))))
> --8<---------------cut here---------------end--------------->8---
> 
> And I generate a Docker pack with:
> 
> --8<---------------cut here---------------start------------->8---
> $ guix pack -f docker --save-provenance -m ~/.config/guix/manifests/python.scm
> /gnu/store/wxymmnxdvdvf08ifsfy39xjaxilhrigk-docker-pack.tar.gz
> --8<---------------cut here---------------end--------------->8---
> 
> 
> Then on machine B, after fetching this tarball, I run:
> 
> --8<---------------cut here---------------start------------->8---
> $ docker load < /tmp/img/wxymmnxdvdvf08ifsfy39xjaxilhrigk-docker-pack.tar.gz
> $ docker images
> REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
> python-python-ipython-python-numpy   latest              49ddfedf1e27        51 years ago        1.45GB
> --8<---------------cut here---------------end--------------->8---
> 
> And it works as expected:
> 
> --8<---------------cut here---------------start------------->8---
> $ docker run -ti python-python-ipython-python-numpy:latest python3
> Python 3.8.2 (default, Jan  1 1970, 00:00:01)
> [GCC 7.5.0] on linux
> Type "help", "copyright", "credits" or "license" for more information.
> >>> import this
> The Zen of Python, by Tim Peters
> 
> Beautiful is better than ugly.
> Explicit is better than implicit.
> Simple is better than complex.
> Complex is better than complicated.
> Flat is better than nested.
> Sparse is better than dense.
> Readability counts.
> Special cases aren't special enough to break the rules.
> Although practicality beats purity.
> Errors should never pass silently.
> Unless explicitly silenced.
> In the face of ambiguity, refuse the temptation to guess.
> There should be one-- and preferably only one --obvious way to do it.
> Although that way may not be obvious at first unless you're Dutch.
> Now is better than never.
> Although never is often better than *right* now.
> If the implementation is hard to explain, it's a bad idea.
> If the implementation is easy to explain, it may be a good idea.
> Namespaces are one honking great idea -- let's do more of those!
> >>> import numpy as np
> >>> A = np.array([[1,0,1],[0,1,0],[0,0,1]])
> >>> _, s, _ = np.linalg.svd(A); s; abs(s[0] - 1./s[2])
> array([1.61803399, 1.        , 0.61803399])
> 0.0
> >>>
> --8<---------------cut here---------------end--------------->8---
> 
> Neat!
> 
> So far, so good.  Well, let extract the ’manifest’ from this Docker
> blob.
> 
> --8<---------------cut here---------------start------------->8---
> $ docker export -o /tmp/img/re-pack.tar $(docker ps -a --format "{{.ID}}" | head -n1)
> $ tar -xf /tmp/img/re-pack.tar $(tar -tf /tmp/img/re-pack.tar | grep 'profile/manifest')
> $ cat gnu/store/7frdchgf5sqw8b83azsml3lw0h52gfbk-profile/manifest | grep -E "(\(\"python|cb68ae)" | head -n5
>     (("python"
>               "cb68ae668af2ade4b0777d82f227e5462768e9e5")
>      ("python-ipython"
>         (("python-backcall"
>          ("python-pyzmq"
> --8<---------------cut here---------------end--------------->8---
> 
> Now, a trick to get the channels and specifications:
> 
> --8<---------------cut here---------------start------------->8---
> $ ./pre-inst-env guix package -p /tmp/img/gnu/store/7frdchgf5sqw8b83azsml3lw0h52gfbk-profile --export-channels
> ;; This channel file can be passed to 'guix pull -C' or to
> ;; 'guix time-machine -C' to obtain the Guix revision that was
> ;; used to populate this profile.
> 
> (list
>      (channel
>        (name 'guix)
>        (url "https://git.savannah.gnu.org/git/guix.git")
>        (commit
>          "cb68ae668af2ade4b0777d82f227e5462768e9e5")
>        (introduction
>          (make-channel-introduction
>            "9edb3f66fd807b096b48283debdcddccfea34bad"
>            (openpgp-fingerprint
>              "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA"))))
> )
> 
> $ ./pre-inst-env guix package -p /tmp/img/gnu/store/7frdchgf5sqw8b83azsml3lw0h52gfbk-profile --export-manifest
> $ ./pre-inst-env guix package -p /tmp/img/gnu/store/7frdchgf5sqw8b83azsml3lw0h52gfbk-profile --export-manifest
> ;; This "manifest" file can be passed to 'guix package -m' to reproduce
> ;; the content of your profile.  This is "symbolic": it only specifies
> ;; package names.  To reproduce the exact same profile, you also need to
> ;; capture the channels being used, as returned by "guix describe".
> ;; See the "Replicating Guix" section in the manual.
> 
> (specifications->manifest
>   (list "python"
>         "python-ipython"
>         "python-numpy"
>         "python-matplotlib"
>         "python-scipy"
>         "python-biopython"))
> --8<---------------cut here---------------end--------------->8---
> 
> Awesome!
> 
> 
> The unexpected is this channels and manifests files do not reproduce the
> same Docker pack tarball:
> 
> --8<---------------cut here---------------start------------->8---
> $ guix describe
> Generation 99   Jan 05 2021 16:56:39    (current)
>   guix-past 829923f
>     repository URL: https://gitlab.inria.fr/guix-hpc/guix-past
>     branch: master
>     commit: 829923f01f894f1e687735627025ada26230832f
>   guix-bimsb a8b539d
>     repository URL: https://github.com/BIMSBbioinfo/guix-bimsb
>     branch: master
>     commit: a8b539d61a359060c35f3cb34c7edd1d9d14241d
>   bimsb-nonfree 4084e63
>     repository URL: https://github.com/BIMSBbioinfo/guix-bimsb-nonfree.git
>     branch: master
>     commit: 4084e63c9c0d662780870aded9f5a6ca1b063780
>   guix-science cf87b05
>     repository URL: https://github.com/guix-science/guix-science.git
>     branch: master
>     commit: cf87b0501c4a38b96edf41025a27bf1cb91f521a
>   guix 957f0c4
>     repository URL: https://git.savannah.gnu.org/git/guix.git
>     branch: master
>     commit: 957f0c40327ce00f53db22737e3775ce616ac258
> 
> $ guix time-machine -C /tmp/img/channels.scm -- pack -f docker --save-provenance -m /tmp/img/manifest.scm
> Updating channel 'guix' from Git repository at 'https://git.savannah.gnu.org/git/guix.git'...
> /gnu/store/xzk604g8gysv4azn7sf9nylr6iah97gl-docker-pack.tar.gz
> --8<---------------cut here---------------end--------------->8---
> 
> To compare with
> /gnu/store/wxymmnxdvdvf08ifsfy39xjaxilhrigk-docker-pack.tar.gz.
> 
> On a third machine, I get:
> /gnu/store/wxymmnxdvdvf08ifsfy39xjaxilhrigk-docker-pack.tar.gz
> 
> Well, that’s another story and I have not inspected yet the
> derivations and what could be wrong on the machine B.
> 
> 
> Cheers,
> simon
> 

KUTGW ;-)

-- 
Regards,
Bengt Richter




Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Fri, 29 Jan 2021 17:58:02 GMT) Full text and rfc822 format available.

Message #49 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Pierre Neidhardt <mail <at> ambrevar.xyz>
To: Ludovic Courtès <ludo <at> gnu.org>, 45919 <at> debbugs.gnu.org
Cc: guix-devel <guix-devel <at> gnu.org>
Subject: Re: bug#45919: [PATCH 0/8] Exporting a manifest and channels from a
 profile
Date: Fri, 29 Jan 2021 18:57:48 +0100
[Message part 1 (text/plain, inline)]
Hi again!

I just had a cursory look, and my main concern is that maybe exposing
commands is one more thing to learn for the user, and one more step to
run to get a simple file.

Instead, what about doing what system profiles already do with

  /run/current-system/channels.scm
  /run/current-system/configuration.scm

and store the result of the proposed commands directly in
$PROFILE/channels.scm and $PROFILE/manifest-spec.scm, on each profile
upgrade?

We could add a warning comment at the top, explaining the limitations of
these files (that it does not represent the profile faithfully).

Thoughts?

Last, just a nit: what about listing the packages corresponding to the
commented commits next to them?  For instance

--8<---------------cut here---------------start------------->8---
(list
 ;; Note: these other commits were also used to install some of the packages in this profile:
 ;;   "458cb25b9e7e7c954f468023abea2bebb5d8c75b" monolith obs calibre
 ;;   "4969b51d175497bfcc354c91803e9d70542b7113" 0ad augustus
 ;;   "3d85c3ec652feb22824f355538b51e6955ded361" nyxt
 ;; ...
 ;;   "b76b1d3fb65fec98b96a2b4cfa984316dd956a29" tectonic
 (channel
  (name 'guix)
  ...
--8<---------------cut here---------------end--------------->8---

Thanks for working on this, Ludo!

Cheers!

-- 
Pierre Neidhardt
https://ambrevar.xyz/
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Fri, 29 Jan 2021 19:02:01 GMT) Full text and rfc822 format available.

Message #52 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: zimoun <zimon.toutoune <at> gmail.com>
To: Pierre Neidhardt <mail <at> ambrevar.xyz>, Ludovic Courtès
 <ludo <at> gnu.org>, 45919 <at> debbugs.gnu.org
Cc: guix-devel <guix-devel <at> gnu.org>
Subject: Re: [bug#45919] [PATCH 0/8] Exporting a manifest and channels from
 a profile
Date: Fri, 29 Jan 2021 19:57:40 +0100
Hi Pierre and Ludo,

On Fri, 29 Jan 2021 at 18:57, Pierre Neidhardt <mail <at> ambrevar.xyz> wrote:
> Hi again!
>
> I just had a cursory look, and my main concern is that maybe exposing
> commands is one more thing to learn for the user, and one more step to
> run to get a simple file.
>
> Instead, what about doing what system profiles already do with
>
>   /run/current-system/channels.scm
>   /run/current-system/configuration.scm
>
> and store the result of the proposed commands directly in
> $PROFILE/channels.scm and $PROFILE/manifest-spec.scm, on each profile
> upgrade?

If I understand correctly, Pierre, you are proposing 2 things: 1) only
one command and 2) export by default in $PROFILE.  Right?

Yeah, sounds a good idea to me.  Even if #2 seems a bit of re-work for
the patch set. :-)

> Last, just a nit: what about listing the packages corresponding to the
> commented commits next to them?  For instance
>
> --8<---------------cut here---------------start------------->8---
> (list
>  ;; Note: these other commits were also used to install some of the packages in this profile:
>  ;;   "458cb25b9e7e7c954f468023abea2bebb5d8c75b" monolith obs calibre
>  ;;   "4969b51d175497bfcc354c91803e9d70542b7113" 0ad augustus
>  ;;   "3d85c3ec652feb22824f355538b51e6955ded361" nyxt
>  ;; ...
>  ;;   "b76b1d3fb65fec98b96a2b4cfa984316dd956a29" tectonic
>  (channel
>   (name 'guix)
>   ...
> --8<---------------cut here---------------end--------------->8---

I agree.  I did the same note. :-)


Cheers,
simon




Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Fri, 29 Jan 2021 19:24:02 GMT) Full text and rfc822 format available.

Message #55 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: zimoun <zimon.toutoune <at> gmail.com>
To: Bengt Richter <bokr <at> bokr.com>
Cc: guix-devel <guix-devel <at> gnu.org>,
 Ludovic Courtès <ludo <at> gnu.org>, 45919 <at> debbugs.gnu.org
Subject: Re: [bug#45919] [PATCH 0/8] Exporting a manifest and channels from
 a profile
Date: Fri, 29 Jan 2021 20:13:34 +0100
Hi Bengt,

On Thu, 28 Jan 2021 at 18:57, Bengt Richter <bokr <at> bokr.com> wrote:

> Thank you for your tutorial-style and resource-reference-footnoted
> posts!

Thanks!  I am happy if it helps.  «Déformation professionnelle»¹ :-)

Cheers,
simon


¹: French pun with «professional training» and «stretched profession».




Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Fri, 29 Jan 2021 21:53:01 GMT) Full text and rfc822 format available.

Message #58 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Pierre Neidhardt <mail <at> ambrevar.xyz>
To: zimoun <zimon.toutoune <at> gmail.com>, Ludovic Courtès
 <ludo <at> gnu.org>, 45919 <at> debbugs.gnu.org
Cc: guix-devel <guix-devel <at> gnu.org>
Subject: Re: [bug#45919] [PATCH 0/8] Exporting a manifest and channels from
 a profile
Date: Fri, 29 Jan 2021 22:51:57 +0100
[Message part 1 (text/plain, inline)]
zimoun <zimon.toutoune <at> gmail.com> writes:

>> I just had a cursory look, and my main concern is that maybe exposing
>> commands is one more thing to learn for the user, and one more step to
>> run to get a simple file.
>>
>> Instead, what about doing what system profiles already do with
>>
>>   /run/current-system/channels.scm
>>   /run/current-system/configuration.scm
>>
>> and store the result of the proposed commands directly in
>> $PROFILE/channels.scm and $PROFILE/manifest-spec.scm, on each profile
>> upgrade?
>
> If I understand correctly, Pierre, you are proposing 2 things: 1) only
> one command and 2) export by default in $PROFILE.  Right?
>
> Yeah, sounds a good idea to me.  Even if #2 seems a bit of re-work for
> the patch set. :-)

Sorry, misunderstanding :)
I'm proposing:

1) Zero command :p

2) On every profile modification (install, upgrade, removal), store the
channel description and the manifest specification (as produced by this
patch commands) to $GUIX_PROFILE/channels.scm and
$GUIX_PROFILE/manifest-spec.scm, respectively.

($GUIX_PROFILE being the target profile, of course.)

Does that make more sense?

-- 
Pierre Neidhardt
https://ambrevar.xyz/
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sat, 30 Jan 2021 13:56:01 GMT) Full text and rfc822 format available.

Message #61 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: Pierre Neidhardt <mail <at> ambrevar.xyz>
Cc: guix-devel <guix-devel <at> gnu.org>, 45919 <at> debbugs.gnu.org
Subject: Re: bug#45919: [PATCH 0/8] Exporting a manifest and channels from a
 profile
Date: Sat, 30 Jan 2021 14:55:16 +0100
Hi Pierre,

Pierre Neidhardt <mail <at> ambrevar.xyz> skribis:

> I just had a cursory look, and my main concern is that maybe exposing
> commands is one more thing to learn for the user, and one more step to
> run to get a simple file.
>
> Instead, what about doing what system profiles already do with
>
>   /run/current-system/channels.scm
>   /run/current-system/configuration.scm
>
> and store the result of the proposed commands directly in
> $PROFILE/channels.scm and $PROFILE/manifest-spec.scm, on each profile
> upgrade?
>
> We could add a warning comment at the top, explaining the limitations of
> these files (that it does not represent the profile faithfully).
>
> Thoughts?

Here are practical issues that come to mind:

  • It would only work for newer profiles, created after the feature has
    been implemented (maybe that’s okay).

  • The generated files might use APIs that, in the meantime, got
    deprecated or changed somehow.  This is in contrast with
    ‘--export-profile’, which interprets ‘manifest’ (a versioned file
    format) and produces code that can use the API du jour.

  • One would still have to learn about these two files, and pick the
    right “manifest” file.

  • For users of ‘-m my-manifest.scm’, we would need to store
    ‘my-manifest.scm’ as is instead of generating an approximation
    thereof.

We already discussed these issues at length earlier.  :-)  Again, I agree
that following what we do with /run/current-system would be nice, but
the situation is different due to imperative operations.

Hmm, needs more thought…

> Last, just a nit: what about listing the packages corresponding to the
> commented commits next to them?  For instance
>
> (list
>  ;; Note: these other commits were also used to install some of the packages in this profile:
>  ;;   "458cb25b9e7e7c954f468023abea2bebb5d8c75b" monolith obs calibre
>  ;;   "4969b51d175497bfcc354c91803e9d70542b7113" 0ad augustus
>  ;;   "3d85c3ec652feb22824f355538b51e6955ded361" nyxt
>  ;; ...
>  ;;   "b76b1d3fb65fec98b96a2b4cfa984316dd956a29" tectonic
>  (channel
>   (name 'guix)
>   ...

Would be nice.

Thanks for your feedback!

Ludo’.




Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sat, 30 Jan 2021 14:39:01 GMT) Full text and rfc822 format available.

Message #64 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: zimoun <zimon.toutoune <at> gmail.com>
To: Pierre Neidhardt <mail <at> ambrevar.xyz>, Ludovic Courtès
 <ludo <at> gnu.org>, 45919 <at> debbugs.gnu.org
Cc: guix-devel <guix-devel <at> gnu.org>
Subject: Re: [bug#45919] [PATCH 0/8] Exporting a manifest and channels from
 a profile
Date: Sat, 30 Jan 2021 15:31:27 +0100
Hi,

On Fri, 29 Jan 2021 at 22:51, Pierre Neidhardt <mail <at> ambrevar.xyz> wrote:

> Sorry, misunderstanding :)

Have a drink together is missing because these times we have
communication issues. :-)

> I'm proposing:
>
> 1) Zero command :p
>
> 2) On every profile modification (install, upgrade, removal), store the
> channel description and the manifest specification (as produced by this
> patch commands) to $GUIX_PROFILE/channels.scm and
> $GUIX_PROFILE/manifest-spec.scm, respectively.
>
> ($GUIX_PROFILE being the target profile, of course.)
>
> Does that make more sense?

Yes, but it needs a lot of re-work and change, IMHO.  And we ends with 3
files: $GUIX_PROFILE/manifest capturing the states of $GUIX_PROFILE and
the 2 others deducing an approximation of these states.  Well, IMHO,
automatically produce this approximation at each «action» on the profile
adds complexity and I am not convinced it is worth.

Cheers,
simon




Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sat, 30 Jan 2021 21:24:02 GMT) Full text and rfc822 format available.

Message #67 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: zimoun <zimon.toutoune <at> gmail.com>
Cc: guix-devel <guix-devel <at> gnu.org>, Pierre Neidhardt <mail <at> ambrevar.xyz>,
 45919 <at> debbugs.gnu.org
Subject: Re: bug#45919: [PATCH 0/8] Exporting a manifest and channels from a
 profile
Date: Sat, 30 Jan 2021 22:23:42 +0100
Hi,

zimoun <zimon.toutoune <at> gmail.com> skribis:

> Yes, but it needs a lot of re-work and change, IMHO.  And we ends with 3
> files: $GUIX_PROFILE/manifest capturing the states of $GUIX_PROFILE and
> the 2 others deducing an approximation of these states.  Well, IMHO,
> automatically produce this approximation at each «action» on the profile
> adds complexity and I am not convinced it is worth.

Yeah.

Actually, part of the code would be shared anyway, so we could always go
with ‘--export-manifest’ first and think about adding the extra files
later.  (Though I’m still unsure about these extra files, TBH.)

Ludo’.




Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sun, 31 Jan 2021 08:58:04 GMT) Full text and rfc822 format available.

Message #70 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ryan Prior <ryanprior <at> hey.com>
To: zimoun <zimon.toutoune <at> gmail.com>, 
 Ludovic Courtès <ludo <at> gnu.org>
Cc: Development of GNU Guix and the GNU System distribution
 <guix-devel <at> gnu.org>, 45919 <at> debbugs.gnu.org
Subject: Re: bug#45919: [PATCH 0/8] Exporting a manifest and channels from a
 profile
Date: Sun, 31 Jan 2021 05:08:20 +0000
[Message part 1 (text/plain, inline)]
On January 30, 2021, "Ludovic Courtès" <ludo <at> gnu.org> wrote:
> Actually, part of the code would be shared anyway, so we could always
> go
> with ‘--export-manifest’ first and think about adding the extra files
> later. (Though I’m still unsure about these extra files, TBH.)

I do like the extra files. It feels cozy to me, like you have your
little profile directory and it has a manifest and a list of channels in
it, that makes it feel more complete. Like having the family pictures on
the wall.

The question of what happens if you don't update a profile for a long
time and how Guix handles those files moves on is a good one. I think
those files should have an indication in there of what version of Guix
was used to produce them, such that you can time-machine back to ensure
you're compatible.

I don't think there's much drawback to having both the auto-generated
files and a command that generates them. That seems more discoverable -
you might happen across the files when you poke into a profile, or you
might notice the command while reading the docs or the help output.

Glad to see this capability land any which way, this is something that
comes up often!

While we're considering putting a manifest in the profile, is this a
good time to also bring up the idea of renaming the "manifest" file? It
confuses more people all the time. I'd be inclined to rename it
"profile-metadata" or "lockfile". 
[Message part 2 (text/html, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Sun, 31 Jan 2021 17:27:01 GMT) Full text and rfc822 format available.

Message #73 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Pierre Neidhardt <mail <at> ambrevar.xyz>
To: Ludovic Courtès <ludo <at> gnu.org>
Cc: guix-devel <guix-devel <at> gnu.org>, 45919 <at> debbugs.gnu.org
Subject: Re: bug#45919: [PATCH 0/8] Exporting a manifest and channels from a
 profile
Date: Sun, 31 Jan 2021 18:26:10 +0100
[Message part 1 (text/plain, inline)]
Hi!

Ludovic Courtès <ludo <at> gnu.org> writes:

> Here are practical issues that come to mind:
>
>   • It would only work for newer profiles, created after the feature has
>     been implemented (maybe that’s okay).

Indeed, I think it's OK! :)

>   • The generated files might use APIs that, in the meantime, got
>     deprecated or changed somehow.  This is in contrast with
>     ‘--export-profile’, which interprets ‘manifest’ (a versioned file
>     format) and produces code that can use the API du jour.

/run/current-system/configuration.scm suffers from the same problem.
But with the manifest we could do better, we could include a version
number one way or another.
Besides, since it comes together with channels.scm, we know which Guix
was used, so we always have access to the Guix with the right API to
install the manifest.

All in all, I think this is not a problem.

>   • One would still have to learn about these two files, and pick the
>     right “manifest” file.

I think it would be easier than a command. See below.

>   • For users of ‘-m my-manifest.scm’, we would need to store
>     ‘my-manifest.scm’ as is instead of generating an approximation
>     thereof.

Which seems easy to do, isn't it?


Another use-case which I find useful and comes close to this feature is
that of channel/manifest versioning, in the sense of keeping these files
under version control for instance in a Git repository.  This can be
useful to keep the history of everything, even deleted generations, or
even in case of hardware failure.

To that end, it'd be nice if we could export these files automatically
to a designated location.

Example: I update ~/my-profile and it automatically produces / overwrite
~/repos/guix-profile-metadata.git/my-profile/channels.scm and
~/repos/guix-profile-metadata.git/my-profile/manifest.scm.

This way I can commit these 2 files in my guix-profile-metadata.git
repository.

Food for thoughts :)

-- 
Pierre Neidhardt
https://ambrevar.xyz/
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Mon, 01 Feb 2021 13:27:01 GMT) Full text and rfc822 format available.

Message #76 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: Pierre Neidhardt <mail <at> ambrevar.xyz>
Cc: guix-devel <guix-devel <at> gnu.org>, 45919 <at> debbugs.gnu.org
Subject: Re: bug#45919: [PATCH 0/8] Exporting a manifest and channels from a
 profile
Date: Mon, 01 Feb 2021 14:25:54 +0100
Hi,

Pierre Neidhardt <mail <at> ambrevar.xyz> skribis:

> Ludovic Courtès <ludo <at> gnu.org> writes:

[...]

>>   • The generated files might use APIs that, in the meantime, got
>>     deprecated or changed somehow.  This is in contrast with
>>     ‘--export-profile’, which interprets ‘manifest’ (a versioned file
>>     format) and produces code that can use the API du jour.
>
> /run/current-system/configuration.scm suffers from the same problem.

Not really because it’s precisely the file that you gave to build the
system.  So you know you can run:

  cd /run/current-system
  guix time-machine -C channels.scm -- system reconfigure configuration.scm

and it’ll work (modulo the documented caveats).

> But with the manifest we could do better, we could include a version
> number one way or another.
> Besides, since it comes together with channels.scm, we know which Guix
> was used, so we always have access to the Guix with the right API to
> install the manifest.

Right.

>>   • One would still have to learn about these two files, and pick the
>>     right “manifest” file.
>
> I think it would be easier than a command. See below.
>
>>   • For users of ‘-m my-manifest.scm’, we would need to store
>>     ‘my-manifest.scm’ as is instead of generating an approximation
>>     thereof.
>
> Which seems easy to do, isn't it?

I take it that you’re volunteering?  :-)

Nothing’s difficult, but in this case we’d need to pass the original
manifest down to ‘profile-generation’.  Requires some redesign.

> Another use-case which I find useful and comes close to this feature is
> that of channel/manifest versioning, in the sense of keeping these files
> under version control for instance in a Git repository.  This can be
> useful to keep the history of everything, even deleted generations, or
> even in case of hardware failure.
>
> To that end, it'd be nice if we could export these files automatically
> to a designated location.
>
> Example: I update ~/my-profile and it automatically produces / overwrite
> ~/repos/guix-profile-metadata.git/my-profile/channels.scm and
> ~/repos/guix-profile-metadata.git/my-profile/manifest.scm.
>
> This way I can commit these 2 files in my guix-profile-metadata.git
> repository.

I guess you could do that either with ‘cp
~/.guix-profile/{channels,manifest.scm …’ or with ‘guix package
--export-manifest … > …’.

But again, that’s not really the goal here.  The goal is to help users
willing to migrate from the “imperative” mode to the declarative mode.
Once you’re using a manifest, probably you’ll want to put that under
version control, but that’s already the case.

Thanks,
Ludo’.




Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Mon, 01 Feb 2021 13:31:01 GMT) Full text and rfc822 format available.

Message #79 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: Ryan Prior <ryanprior <at> hey.com>
Cc: Development of GNU Guix and the GNU System distribution
 <guix-devel <at> gnu.org>, 45919 <at> debbugs.gnu.org, zimoun <zimon.toutoune <at> gmail.com>
Subject: Re: bug#45919: [PATCH 0/8] Exporting a manifest and channels from a
 profile
Date: Mon, 01 Feb 2021 14:30:45 +0100
Hi,

Ryan Prior <ryanprior <at> hey.com> skribis:

> I don't think there's much drawback to having both the auto-generated
> files and a command that generates them. That seems more discoverable -
> you might happen across the files when you poke into a profile, or you
> might notice the command while reading the docs or the help output.

Note that the ‘manifest’ file starts with a comment.  This patch set
updates this comment so it mentions ‘--export-channels’.

> Glad to see this capability land any which way, this is something that
> comes up often!

Heh, good.  :-)

> While we're considering putting a manifest in the profile, is this a
> good time to also bring up the idea of renaming the "manifest" file? It
> confuses more people all the time. I'd be inclined to rename it
> "profile-metadata" or "lockfile". 

It’s the kind of thing that can’t really be changed, or at least not
without a looong transition period, because older ‘guix package’
commands wouldn’t recognize profiles that lack a ‘manifest’ file.

Thanks for your feedback,
Ludo’.




Information forwarded to guix-patches <at> gnu.org:
bug#45919; Package guix-patches. (Mon, 01 Feb 2021 15:33:02 GMT) Full text and rfc822 format available.

Message #82 received at 45919 <at> debbugs.gnu.org (full text, mbox):

From: Pierre Neidhardt <mail <at> ambrevar.xyz>
To: Ludovic Courtès <ludo <at> gnu.org>
Cc: guix-devel <guix-devel <at> gnu.org>, 45919 <at> debbugs.gnu.org
Subject: Re: bug#45919: [PATCH 0/8] Exporting a manifest and channels from a
 profile
Date: Mon, 01 Feb 2021 16:32:25 +0100
[Message part 1 (text/plain, inline)]
Ludovic Courtès <ludo <at> gnu.org> writes:

> Hi,
>
> Pierre Neidhardt <mail <at> ambrevar.xyz> skribis:
>
>> Ludovic Courtès <ludo <at> gnu.org> writes:
>
> [...]
>
>>>   • The generated files might use APIs that, in the meantime, got
>>>     deprecated or changed somehow.  This is in contrast with
>>>     ‘--export-profile’, which interprets ‘manifest’ (a versioned file
>>>     format) and produces code that can use the API du jour.
>>
>> /run/current-system/configuration.scm suffers from the same problem.
>
> Not really because it’s precisely the file that you gave to build the
> system.  So you know you can run:
>
>   cd /run/current-system
>   guix time-machine -C channels.scm -- system reconfigure configuration.scm
>
> and it’ll work (modulo the documented caveats).

Ha, actually no, it won't always work! :)
Configuration.scm is only the file passed to `guix system reconfigure`,
but is this file inherits from other user Guile modules, then the
configuration.scm won't be sufficient to regenerate the system.

You could argue that it's a user problem, but still, there is an
"impurity" here! :p

> But again, that’s not really the goal here.  The goal is to help users
> willing to migrate from the “imperative” mode to the declarative mode.

Sure, but my thinking is that we could hit two birds we one stone here.
If we only think one half of the problem, we might end up with too many
commands or an interface that's not flexible enough.

> Once you’re using a manifest, probably you’ll want to put that under
> version control, but that’s already the case.

The channels.scm files are missing though.

My two cents! :)

Cheers!

-- 
Pierre Neidhardt
https://ambrevar.xyz/
[signature.asc (application/pgp-signature, inline)]

Reply sent to Ludovic Courtès <ludo <at> gnu.org>:
You have taken responsibility. (Mon, 01 Feb 2021 17:05:01 GMT) Full text and rfc822 format available.

Notification sent to Ludovic Courtès <ludo <at> gnu.org>:
bug acknowledged by developer. (Mon, 01 Feb 2021 17:05:01 GMT) Full text and rfc822 format available.

Message #87 received at 45919-done <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: Pierre Neidhardt <mail <at> ambrevar.xyz>, zimoun <zimon.toutoune <at> gmail.com>
Cc: guix-devel <guix-devel <at> gnu.org>, 45919-done <at> debbugs.gnu.org
Subject: Re: bug#45919: [PATCH 0/8] Exporting a manifest and channels from a
 profile
Date: Mon, 01 Feb 2021 18:04:05 +0100
Hi!

So I went ahead and pushed this patch series as
15078567c17851ef0f2b017119f305e0d5e8a140.

We can always improve from here, and hopefully getting actual user
feedback will help us see the pros and cons of this option.

Thanks!

Ludo’.




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Tue, 02 Mar 2021 12:24:05 GMT) Full text and rfc822 format available.

This bug report was last modified 3 years and 54 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.