unofficial mirror of guix-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Nikita Karetnikov <nikita@karetnikov.org>
To: "Ludovic Courtès" <ludo@gnu.org>
Cc: guix-devel@gnu.org
Subject: [PATCH] guix package: Add '--delete-generations'.
Date: Sun, 22 Sep 2013 23:19:14 +0400	[thread overview]
Message-ID: <87li2oslzh.fsf_-_@karetnikov.org> (raw)
In-Reply-To: <87hae81uvo.fsf@gnu.org> ("Ludovic Courtès"'s message of "Thu, 29 Aug 2013 15:36:43 +0200")


[-- Attachment #1.1: Type: text/plain, Size: 266 bytes --]

Can I push this patch to ‘master’?  Do you see any problems?

I had noticed that ‘--roll-back’ doesn’t output anything with
‘--dry-run’, so I implemented ‘--delete-generations’ similarly.  Maybe
it would be better to print something.  WDYT?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-guix-package-Add-delete-generations.patch --]
[-- Type: text/x-diff, Size: 20291 bytes --]

From ede983c90bd4cdece708820e1d52a2d1894a51c8 Mon Sep 17 00:00:00 2001
From: Nikita Karetnikov <nikita@karetnikov.org>
Date: Sun, 22 Sep 2013 18:50:06 +0000
Subject: [PATCH] guix package: Add '--delete-generations'.

* guix/scripts/package.scm (link-to-empty-environment)
  (switch-to-previous-generation): New functions.
  (roll-back): Replace internal functions with the new ones.
  (show-help): Add '--delete-generations'.
  (%options): Likewise.
  (guix-package): Add 'apply-to-generations'.
  (guix-package)[process-actions]: Add support for '--delete-generations'.
  (guix-package)[process-query]: Replace 'cond' with 'apply-to-generations'.
* tests/guix-package.sh: Test '--delete-generations'.
* doc/guix.texi (Invoking guix-package): Document '--delete-generations'.
---
 doc/guix.texi            |    7 ++
 guix/scripts/package.scm |  271 ++++++++++++++++++++++++++++------------------
 tests/guix-package.sh    |    7 ++
 3 files changed, 178 insertions(+), 107 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index fdddcc5..3d61630 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -639,6 +639,13 @@ or months by passing an integer along with the first letter of the
 duration, e.g., @code{--list-generations=20d}.
 @end itemize
 
+@item --delete-generations[=@var{pattern}]
+@itemx -d [@var{pattern}]
+Delete generations.
+
+When @var{pattern} is specified, delete only the matching generations.
+This command accepts the same patterns as @option{--list-generations}.
+
 @item --profile=@var{profile}
 @itemx -p @var{profile}
 Use @var{profile} instead of the user's default profile.
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index c0cedcd..c72b56e 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -214,6 +214,25 @@ all of PACKAGES, a list of name/version/output/path/deps tuples."
              (compose string->number (cut match:substring <> 1)))
       0))
 
+(define (link-to-empty-environment generation)
+  "Link GENERATION, a string, to the empty environment."
+  (let* ((drv  (profile-derivation (%store) '()))
+         (prof (derivation->output-path drv "out")))
+    (when (not (build-derivations (%store) (list drv)))
+          (leave (_ "failed to build the empty profile~%")))
+
+    (switch-symlinks generation prof)))
+
+(define (switch-to-previous-generation profile)
+  "Atomically switch PROFILE to the previous generation."
+  (let* ((number              (generation-number profile))
+         (previous-number     (previous-generation-number profile number))
+         (previous-generation (format #f "~a-~a-link"
+                                      profile previous-number)))
+    (format #t (_ "switching from generation ~a to ~a~%")
+            number previous-number)
+    (switch-symlinks profile previous-generation)))
+
 (define (roll-back profile)
   "Roll back to the previous generation of PROFILE."
   (let* ((number              (generation-number profile))
@@ -222,28 +241,18 @@ all of PACKAGES, a list of name/version/output/path/deps tuples."
                                       profile previous-number))
          (manifest            (string-append previous-generation "/manifest")))
 
-    (define (switch-link)
-      ;; Atomically switch PROFILE to the previous generation.
-      (format #t (_ "switching from generation ~a to ~a~%")
-              number previous-number)
-      (switch-symlinks profile previous-generation))
-
-    (cond ((not (file-exists? profile))           ; invalid profile
+    (cond ((not (file-exists? profile))                 ; invalid profile
            (leave (_ "profile `~a' does not exist~%")
                   profile))
-          ((zero? number)                         ; empty profile
+          ((zero? number)                               ; empty profile
            (format (current-error-port)
                    (_ "nothing to do: already at the empty profile~%")))
-          ((or (zero? previous-number)            ; going to emptiness
+          ((or (zero? previous-number)                  ; going to emptiness
                (not (file-exists? previous-generation)))
-           (let* ((drv  (profile-derivation (%store) '()))
-                  (prof (derivation->output-path drv "out")))
-             (when (not (build-derivations (%store) (list drv)))
-               (leave (_ "failed to build the empty profile~%")))
-
-             (switch-symlinks previous-generation prof)
-             (switch-link)))
-          (else (switch-link)))))                 ; anything else
+           (begin (link-to-empty-environment previous-generation)
+                  (switch-to-previous-generation profile)))
+          (else
+           (switch-to-previous-generation profile)))))  ; anything else
 
 (define (generation-time profile number)
   "Return the creation time of a generation in the UTC format."
@@ -511,6 +520,9 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))
   (display (_ "
   -l, --list-generations[=PATTERN]
                          list generations matching PATTERN"))
+  (display (_ "
+  -d, --delete-generations[=PATTERN]
+                         delete generations matching PATTERN"))
   (newline)
   (display (_ "
   -p, --profile=PROFILE  use PROFILE instead of the user's default profile"))
@@ -574,6 +586,10 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))
                 (lambda (opt name arg result)
                   (cons `(query list-generations ,(or arg ""))
                         result)))
+        (option '(#\d "delete-generations") #f #t
+                (lambda (opt name arg result)
+                  (alist-cons 'delete-generations (or arg "")
+                              result)))
         (option '("search-paths") #f #f
                 (lambda (opt name arg result)
                   (cons `(query search-paths) result)))
@@ -742,6 +758,20 @@ more information.~%"))
                 %profile-directory (or (getenv "USER") (getuid)))
         (rtfm))))
 
+  (define (apply-to-generations function profile pattern)
+    (cond ((not (file-exists? profile)) ; XXX: race condition
+           (leave (_ "profile '~a' does not exist~%")
+                  profile))
+          ((string-null? pattern)
+           (for-each function
+                     (generation-numbers profile)))
+          ((matching-generations pattern profile)
+           =>
+           (cut for-each function <>))
+          (else
+           (leave (_ "invalid syntax: ~a~%")
+                  pattern))))
+
   (define (process-actions opts)
     ;; Process any install/remove/upgrade action from OPTS.
 
@@ -824,85 +854,123 @@ more information.~%"))
                        install))))
         (_ #f)))
 
+    (define (delete-generation number)
+      (define (display-and-delete generation)
+        (begin (format #t "deleting ~a~%" generation)
+               (delete-file generation)))
+
+      (define (current-generation? profile generation)
+        (string=? (readlink profile) generation))
+
+      (let* ((generation      (format #f "~a-~a-link" profile number))
+             (previous-number (previous-generation-number profile number))
+             (previous-generation (format #f "~a-~a-link"
+                                          profile previous-number)))
+        (cond ((zero? number))  ; do not delete generation 0
+              ((and (current-generation? profile generation)
+                    (not (file-exists? previous-generation)))
+               (begin (link-to-empty-environment previous-generation)
+                      (switch-to-previous-generation profile)
+                      (display-and-delete generation)))
+              ((current-generation? profile generation)
+               (begin (roll-back profile)
+                      (display-and-delete generation)))
+              (else
+               (display-and-delete generation)))))
+
     ;; First roll back if asked to.
-    (if (and (assoc-ref opts 'roll-back?) (not dry-run?))
-        (begin
-          (roll-back profile)
-          (process-actions (alist-delete 'roll-back? opts)))
-        (let* ((installed (manifest-packages (profile-manifest profile)))
-               (upgrade-regexps (filter-map (match-lambda
-                                             (('upgrade . regexp)
-                                              (make-regexp (or regexp "")))
-                                             (_ #f))
-                                            opts))
-               (upgrade  (if (null? upgrade-regexps)
-                             '()
-                             (let ((newest (find-newest-available-packages)))
-                               (filter-map (match-lambda
-                                            ((name version output path _)
-                                             (and (any (cut regexp-exec <> name)
-                                                       upgrade-regexps)
-                                                  (upgradeable? name version path)
-                                                  (find-package name
-                                                                (or output "out"))))
-                                            (_ #f))
-                                           installed))))
-               (install  (append
-                          upgrade
-                          (filter-map (match-lambda
-                                       (('install . (? package? p))
-                                        (package->tuple p))
-                                       (('install . (? store-path?))
-                                        #f)
-                                       (('install . package)
-                                        (find-package package))
-                                       (_ #f))
-                                      opts)))
-               (drv      (filter-map (match-lambda
-                                      ((name version sub-drv
-                                             (? package? package)
-                                             (deps ...))
-                                       (check-package-freshness package)
-                                       (package-derivation (%store) package))
-                                      (_ #f))
-                                     install))
-               (install* (append
-                          (filter-map (match-lambda
-                                       (('install . (? package? p))
-                                        #f)
-                                       (('install . (? store-path? path))
-                                        (let-values (((name version)
-                                                      (package-name->name+version
-                                                       (store-path-package-name
-                                                        path))))
-                                          `(,name ,version #f ,path ())))
+    (cond ((and (assoc-ref opts 'roll-back?) (not dry-run?))
+           (begin
+             (roll-back profile)
+             (process-actions (alist-delete 'roll-back? opts))))
+          ((and (assoc-ref opts 'delete-generations)
+                (not dry-run?))
+           (filter-map (match-lambda
+                        (('delete-generations . pattern)
+                         (begin (apply-to-generations delete-generation
+                                                      profile pattern)
+                                (process-actions
+                                 (alist-delete 'delete-generations opts))))
+                        (_ #f))
+                       opts))
+          (else
+           (let* ((installed (manifest-packages (profile-manifest profile)))
+                  (upgrade-regexps (filter-map (match-lambda
+                                                (('upgrade . regexp)
+                                                 (make-regexp (or regexp "")))
+                                                (_ #f))
+                                               opts))
+                  (upgrade (if (null? upgrade-regexps)
+                               '()
+                               (let ((newest (find-newest-available-packages)))
+                                 (filter-map
+                                  (match-lambda
+                                   ((name version output path _)
+                                    (and (any (cut regexp-exec <> name)
+                                              upgrade-regexps)
+                                         (upgradeable? name version path)
+                                         (find-package name
+                                                       (or output "out"))))
+                                   (_ #f))
+                                  installed))))
+                  (install (append
+                            upgrade
+                            (filter-map (match-lambda
+                                         (('install . (? package? p))
+                                          (package->tuple p))
+                                         (('install . (? store-path?))
+                                          #f)
+                                         (('install . package)
+                                          (find-package package))
+                                         (_ #f))
+                                        opts)))
+                  (drv (filter-map (match-lambda
+                                    ((name version sub-drv
+                                           (? package? package)
+                                           (deps ...))
+                                     (check-package-freshness package)
+                                     (package-derivation (%store) package))
+                                    (_ #f))
+                                   install))
+                  (install*
+                   (append
+                    (filter-map (match-lambda
+                                 (('install . (? package? p))
+                                  #f)
+                                 (('install . (? store-path? path))
+                                  (let-values (((name version)
+                                                (package-name->name+version
+                                                 (store-path-package-name
+                                                  path))))
+                                    `(,name ,version #f ,path ())))
+                                 (_ #f))
+                                opts)
+                    (map (lambda (tuple drv)
+                           (match tuple
+                                  ((name version sub-drv _ (deps ...))
+                                   (let ((output-path
+                                          (derivation->output-path
+                                           drv sub-drv)))
+                                     `(,name ,version ,sub-drv ,output-path
+                                             ,(canonicalize-deps deps))))))
+                         install drv)))
+                  (remove (filter-map (match-lambda
+                                       (('remove . package)
+                                        package)
                                        (_ #f))
-                                      opts)
-                          (map (lambda (tuple drv)
-                                 (match tuple
-                                   ((name version sub-drv _ (deps ...))
-                                    (let ((output-path
-                                           (derivation->output-path
-                                            drv sub-drv)))
-                                      `(,name ,version ,sub-drv ,output-path
-                                              ,(canonicalize-deps deps))))))
-                               install drv)))
-               (remove   (filter-map (match-lambda
-                                      (('remove . package)
-                                       package)
-                                      (_ #f))
-                                     opts))
-               (remove*  (filter-map (cut assoc <> installed) remove))
-               (packages (append install*
-                                 (fold (lambda (package result)
-                                         (match package
-                                           ((name _ out _ ...)
-                                            (filter (negate
-                                                     (cut same-package? <>
-                                                          name out))
-                                                    result))))
-                                       (fold alist-delete installed remove)
-                                       install*))))
+                                      opts))
+                  (remove* (filter-map (cut assoc <> installed) remove))
+                  (packages
+                   (append install*
+                           (fold (lambda (package result)
+                                   (match package
+                                          ((name _ out _ ...)
+                                           (filter (negate
+                                                    (cut same-package? <>
+                                                         name out))
+                                                   result))))
+                                 (fold alist-delete installed remove)
+                                 install*))))
 
           (when (equal? profile %current-profile)
             (ensure-default-profile))
@@ -946,7 +1014,7 @@ more information.~%"))
                                                count)
                                         count)
                                 (display-search-paths packages
-                                                      profile))))))))))
+                                                      profile)))))))))))
 
   (define (process-query opts)
     ;; Process any query specified by OPTS.  Return #t when a query was
@@ -970,18 +1038,7 @@ more information.~%"))
                          (format #f "~a-~a-link" profile number))))
              (newline)))
 
-         (cond ((not (file-exists? profile)) ; XXX: race condition
-                (leave (_ "profile '~a' does not exist~%")
-                       profile))
-               ((string-null? pattern)
-                (for-each list-generation
-                          (generation-numbers profile)))
-               ((matching-generations pattern profile)
-                =>
-                (cut for-each list-generation <>))
-               (else
-                (leave (_ "invalid syntax: ~a~%")
-                       pattern)))
+         (apply-to-generations list-generation profile pattern)
          #t)
 
         (('list-installed regexp)
diff --git a/tests/guix-package.sh b/tests/guix-package.sh
index b09a9c0..65bc94c 100644
--- a/tests/guix-package.sh
+++ b/tests/guix-package.sh
@@ -132,6 +132,13 @@ then
     # Make sure LIBRARY_PATH gets listed by `--search-paths'.
     guix package --bootstrap -p "$profile" -i guile-bootstrap -i gcc-bootstrap
     guix package --search-paths -p "$profile" | grep LIBRARY_PATH
+
+    # Delete the third generation and check that it was actually deleted.
+    guix package -p "$profile" --delete-generations=3
+    test -z "`guix package -p "$profile" -l 3`"
+
+    # Do not output anything when such a generation does not exist.
+    test -z "`guix package -p "$profile" --delete-generations=42`"
 fi
 
 # Make sure the `:' syntax works.
-- 
1.7.9.5


[-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --]

  parent reply	other threads:[~2013-09-22 19:14 UTC|newest]

Thread overview: 132+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-29 12:34 Goals for 0.4 Ludovic Courtès
2013-08-29 13:16 ` Nikita Karetnikov
2013-08-29 13:36   ` Ludovic Courtès
2013-08-30 17:55     ` Nikita Karetnikov
2013-08-30 18:31       ` Ludovic Courtès
2013-08-31 16:40         ` Nikita Karetnikov
2013-08-31 18:05           ` Ludovic Courtès
2013-08-31 20:34             ` Jose E. Marchesi
2013-08-31 21:07               ` Ludovic Courtès
2013-09-01 23:16                 ` New ‘--list-generations’ and ‘--delete-generations’ options (was: Goals for 0.4) Nikita Karetnikov
2013-09-02  9:08                   ` New ‘--list-generations’ and ‘--delete-generations’ options Ludovic Courtès
2013-09-05  1:30                     ` Nikita Karetnikov
2013-09-05 20:00                       ` Ludovic Courtès
2013-09-05 21:14                         ` Nikita Karetnikov
2013-09-07 19:34                           ` Ludovic Courtès
2013-09-08 10:59                             ` Nikita Karetnikov
2013-09-08 20:22                               ` Ludovic Courtès
2013-09-09  9:17                                 ` Nikita Karetnikov
2013-09-09 16:55                                   ` Ludovic Courtès
2013-09-11  5:16                                     ` Nikita Karetnikov
2013-09-11 21:25                                       ` Ludovic Courtès
2013-09-12  9:17                                         ` Nikita Karetnikov
2013-09-12 12:26                                           ` Ludovic Courtès
2013-09-13 14:44                                             ` Nikita Karetnikov
2013-09-13 21:29                                               ` Ludovic Courtès
2013-09-16 11:12                                                 ` Nikita Karetnikov
2013-09-16 12:16                                                   ` Ludovic Courtès
2013-09-18  0:43                                                     ` PRELIMINARY: [PATCH] guix package: Add '--list-generations' Nikita Karetnikov
2013-09-18 17:35                                                       ` Nikita Karetnikov
2013-09-18 21:32                                                       ` Ludovic Courtès
2013-09-19  0:49                                                         ` Nikita Karetnikov
2013-09-19  9:39                                                           ` Ludovic Courtès
2013-09-19 11:48                                                             ` Nikita Karetnikov
2013-09-19 12:13                                                               ` Ludovic Courtès
2013-09-21 20:39                                                                 ` Ludovic Courtès
2013-09-18 21:35                                                       ` PRELIMINARY: " Ludovic Courtès
2013-09-22 19:19     ` Nikita Karetnikov [this message]
2013-09-22 20:15       ` Generation 0 (was: [PATCH] guix package: Add '--delete-generations'.) Nikita Karetnikov
2013-09-22 21:15         ` Generation 0 Ludovic Courtès
2013-09-23 10:14           ` Nikita Karetnikov
2013-09-23 15:42             ` Ludovic Courtès
2013-09-24  0:54           ` Nikita Karetnikov
2013-09-24  5:56             ` [PATCH] guix package: Show which generation is the current one. (was: Generation 0) Nikita Karetnikov
2013-09-24 12:45               ` [PATCH] guix package: Show which generation is the current one Ludovic Courtès
2013-09-24 13:55                 ` Nikita Karetnikov
2013-09-24 14:16                   ` Ludovic Courtès
2013-09-25  2:10                     ` Nikita Karetnikov
2013-09-25 12:51                       ` Ludovic Courtès
2013-09-24 12:43             ` Generation 0 Ludovic Courtès
2013-09-24 22:29               ` Nikita Karetnikov
2013-09-25 12:50                 ` Ludovic Courtès
2013-09-25 18:07                   ` Nikita Karetnikov
2013-09-25 19:24                     ` Ludovic Courtès
2013-09-26  2:18                       ` Nikita Karetnikov
2013-09-26  9:44                         ` Ludovic Courtès
2013-09-22 20:55       ` [PATCH] guix package: Add '--delete-generations' Ludovic Courtès
2013-09-23 10:11         ` Nikita Karetnikov
2013-09-23 15:41           ` Ludovic Courtès
2013-09-24  7:21             ` Nikita Karetnikov
2013-09-24 12:50               ` Ludovic Courtès
2013-09-24 13:57                 ` Nikita Karetnikov
2013-09-25  4:21             ` Nikita Karetnikov
2013-09-25 13:05               ` Ludovic Courtès
2013-09-26  2:47                 ` Nikita Karetnikov
2013-09-26  9:49                   ` Ludovic Courtès
2013-09-27 19:04                     ` Ludovic Courtès
2013-09-03 19:21   ` MIPS64/N64 support (was: Goals for 0.4) Nikita Karetnikov
2013-09-03 20:45     ` MIPS64/N64 support Ludovic Courtès
2013-09-04  0:35       ` Nikita Karetnikov
2013-09-04 12:18         ` Ludovic Courtès
2013-09-06  8:35           ` Nikita Karetnikov
2013-09-06  9:46             ` Ludovic Courtès
2013-09-07  2:45               ` Nikita Karetnikov
2013-09-07 12:57                 ` Ludovic Courtès
2013-09-08 14:21                   ` Nikita Karetnikov
2013-09-08 19:54                     ` Ludovic Courtès
2013-09-09  5:38                       ` Nikita Karetnikov
2013-09-09 16:47                         ` Ludovic Courtès
2013-09-27  2:16                           ` Nikita Karetnikov
2013-09-27 19:00                             ` Ludovic Courtès
2013-09-29 13:27                               ` Nikita Karetnikov
2013-09-29 13:31                                 ` Ludovic Courtès
2013-09-29 23:18                                   ` Nikita Karetnikov
2013-09-30 11:32                                     ` Nikita Karetnikov
2013-09-30 16:26                                       ` Ludovic Courtès
2013-09-30 21:51                                         ` Nikita Karetnikov
2013-10-01  7:09                                           ` Lluís Batlle i Rossell
2013-10-01  7:48                                             ` Nikita Karetnikov
2013-10-01  8:03                                               ` Lluís Batlle i Rossell
2013-10-01  8:55                                                 ` Nikita Karetnikov
2013-10-01  8:59                                                   ` Nikita Karetnikov
2013-10-01  9:30                                                   ` Lluís Batlle i Rossell
2013-10-01 10:06                                                     ` Nikita Karetnikov
2013-10-01 10:04                                                       ` Lluís Batlle i Rossell
2013-10-01 11:25                                                         ` Ludovic Courtès
2013-10-01 11:56                                                           ` Lluís Batlle i Rossell
2013-10-07 18:47                                       ` Mark H Weaver
2013-10-07 19:39                                         ` Ludovic Courtès
2013-10-08 23:03                                           ` Mark H Weaver
2013-10-09  6:53                                             ` Mark H Weaver
2013-10-09 10:42                                               ` Ludovic Courtès
2013-10-09 10:39                                             ` Ludovic Courtès
2013-10-10  4:08                                       ` Mark H Weaver
2013-09-30 16:09                                     ` Ludovic Courtès
2013-08-29 15:49 ` Goals for 0.4 Amirouche Boubekki
2013-08-29 20:04   ` Ludovic Courtès
2013-08-30 16:09     ` Cyprien Nicolas
2013-08-30 17:40       ` Amirouche Boubekki
2013-08-30 19:31       ` Overlays Ludovic Courtès
2013-08-30 20:42         ` Overlays Nikita Karetnikov
2013-08-30 21:21           ` Overlays Ludovic Courtès
2013-08-31 10:56             ` Overlays Amirouche Boubekki
2013-08-31 15:57               ` Overlays Ludovic Courtès
2013-08-29 20:42 ` Goals for 0.4 Andreas Enge
2013-08-29 21:32   ` Ludovic Courtès
2013-09-25  8:43   ` Andreas Enge
2013-09-25 13:13     ` Ludovic Courtès
2013-09-26 11:35       ` Andreas Enge
2013-09-28 13:25         ` Ludovic Courtès
2013-09-29 21:29           ` Alex Sassmannshausen
2013-09-02 17:33 ` Cyril Roelandt
2013-09-02 19:38   ` Ludovic Courtès
2013-09-02 19:40     ` Cyril Roelandt
2013-09-02 21:35       ` Ludovic Courtès
2013-09-06  9:19 ` ‘--no-substitutes’ is ignored on i686 (was: Goals for 0.4) Nikita Karetnikov
2013-09-06  9:59   ` ‘--no-substitutes’ is ignored on i686 Ludovic Courtès
2013-09-07  8:43     ` Nikita Karetnikov
2013-09-07 13:00       ` Ludovic Courtès
2013-09-08 11:53         ` Nikita Karetnikov
2013-09-08 11:51           ` Cyril Roelandt
2013-09-08 13:22             ` Nikita Karetnikov
2013-09-24 21:59 ` Goals for 0.4 Ludovic Courtès

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://guix.gnu.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87li2oslzh.fsf_-_@karetnikov.org \
    --to=nikita@karetnikov.org \
    --cc=guix-devel@gnu.org \
    --cc=ludo@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).