Ludovic Courtès (2014-10-10 02:08 +0400) wrote:

> l...@gnu.org (Ludovic Courtès) skribis:
>
>> There’s:
>>
>>   (guix store) -> (guix nar) -> (guix ui) -> (guix store) ...
>
> Commit 0363991 fixes that.
>
> (Now we must make sure we don’t reintroduce cycles in these modules;
> probably we should integrate Mark’s cycle detection script somehow.)
>
> With that I was able to apply the patch you posted.
>
> Thanks, and sorry for the mess!

Thank you for fixing that and sorry that I didn't reply to you on #guix
yesterday (I was away).

Now there shouldn't be problems with adding new condition types to (guix
profiles).  The patch is attached and “make check” was successful on
that.  2 little questions:

1. As you suggested I made a hierarchy of conditions:

> This is bikeshedding, but I would make a hierarchy like this:
>
>                      &profile-error, with ‘profile’ field
>                             ^
>            .———————————————–+———————————————–.
>            |                                 |
>   &profile-not-found-error        &missing-generation-error, with 
> ‘generation’ field

Thank you for the idea btw, I like it.  So the question is: should the
parent &profile-error be handled as well?  If yes, what message to use?

2. And another question: the current error for generation would look
like this:

  generation 18 does not exist

Is it OK or should I use ‘generation-file-name’ there and make it:

  generation '/some/path/to/profile/generation-18-link' does not exist



The problem now is I can't add ‘switch-to-generation’ procedure to (guix
profiles) as it uses ‘_’ and ‘switch-symlinks’ from (guix ui) which is
not “#:use-module”-ed anymore.  This patch is also attached.  What to do
about it?  I think moving ‘switch-to-generation’ to (guix ui) is not
good or is it?  Perhaps it would be better to move ‘switch-symlinks’ and
all ‘_’, ‘N_’, … stuff to (guix utils)?  But what do I know, it's up to
you again (I feel guilty that I have to bother you again).

>From af9d9869f2430dd3e20885e685867c6843ba4279 Mon Sep 17 00:00:00 2001
From: Alex Kost <alez...@gmail.com>
Date: Wed, 8 Oct 2014 17:29:01 +0400
Subject: [PATCH 1/3] profiles: Add condition types for profiles and
 generations.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Suggested by Ludovic Courtès.

* guix/profiles.scm (&profile-error, &profile-not-found-error,
  &missing-generation-error): New condition types.
* guix/ui.scm (call-with-error-handling): Handle new types.
* guix/scripts/package.scm (roll-back, guix-package): Raise
  '&profile-not-found-error' where needed.
---
 guix/profiles.scm        | 29 ++++++++++++++++++++++++++++-
 guix/scripts/package.scm | 18 ++++++++++--------
 guix/ui.scm              |  7 +++++++
 3 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/guix/profiles.scm b/guix/profiles.scm
index f2eb754..793af24 100644
--- a/guix/profiles.scm
+++ b/guix/profiles.scm
@@ -34,7 +34,18 @@
   #:use-module (srfi srfi-11)
   #:use-module (srfi srfi-19)
   #:use-module (srfi srfi-26)
-  #:export (manifest make-manifest
+  #:use-module (srfi srfi-34)
+  #:use-module (srfi srfi-35)
+  #:export (&profile-error
+            profile-error?
+            profile-error-profile
+            &profile-not-found-error
+            profile-not-found-error?
+            &missing-generation-error
+            missing-generation-error?
+            missing-generation-error-generation
+
+            manifest make-manifest
             manifest?
             manifest-entries
 
@@ -82,6 +93,22 @@
 

 ;;;
+;;; Condition types.
+;;;
+
+(define-condition-type &profile-error &error
+  profile-error?
+  (profile profile-error-profile))
+
+(define-condition-type &profile-not-found-error &profile-error
+  profile-not-found-error?)
+
+(define-condition-type &missing-generation-error &profile-error
+  missing-generation-error?
+  (generation missing-generation-error-generation))
+
+
+;;;
 ;;; Manifests.
 ;;;
 
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index 031f71a..ab9d303 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -38,6 +38,8 @@
   #:use-module (srfi srfi-11)
   #:use-module (srfi srfi-19)
   #:use-module (srfi srfi-26)
+  #:use-module (srfi srfi-34)
+  #:use-module (srfi srfi-35)
   #:use-module (srfi srfi-37)
   #:use-module (gnu packages)
   #:use-module (gnu packages base)
@@ -109,8 +111,8 @@ return PROFILE unchanged.  The goal is to treat '-p ~/.guix-profile' as if
          (previous-number     (previous-generation-number profile number))
          (previous-generation (generation-file-name profile previous-number)))
     (cond ((not (file-exists? profile))                 ; invalid profile
-           (leave (_ "profile '~a' does not exist~%")
-                  profile))
+           (raise (condition (&profile-not-found-error
+                              (profile profile)))))
           ((zero? number)                               ; empty profile
            (format (current-error-port)
                    (_ "nothing to do: already at the empty profile~%")))
@@ -723,8 +725,8 @@ more information.~%"))
             (match-lambda
              (('delete-generations . pattern)
               (cond ((not (file-exists? profile)) ; XXX: race condition
-                     (leave (_ "profile '~a' does not exist~%")
-                            profile))
+                     (raise (condition (&profile-not-found-error
+                                        (profile profile)))))
                     ((string-null? pattern)
                      (delete-generations
                       (%store) profile
@@ -833,8 +835,8 @@ more information.~%"))
              (newline)))
 
          (cond ((not (file-exists? profile)) ; XXX: race condition
-                (leave (_ "profile '~a' does not exist~%")
-                       profile))
+                (raise (condition (&profile-not-found-error
+                                   (profile profile)))))
                ((string-null? pattern)
                 (for-each list-generation (profile-generations profile)))
                ((matching-generations pattern profile)
@@ -915,8 +917,8 @@ more information.~%"))
         (_ #f))))
 
   (let ((opts (parse-options)))
-    (or (process-query opts)
-        (with-error-handling
+    (with-error-handling
+      (or (process-query opts)
           (parameterize ((%store (open-connection)))
             (set-build-options-from-command-line (%store) opts)
 
diff --git a/guix/ui.scm b/guix/ui.scm
index 8c4a9d2..feeb10e 100644
--- a/guix/ui.scm
+++ b/guix/ui.scm
@@ -2,6 +2,7 @@
 ;;; Copyright © 2012, 2013, 2014 Ludovic Courtès <l...@gnu.org>
 ;;; Copyright © 2013 Mark H Weaver <m...@netris.org>
 ;;; Copyright © 2013 Nikita Karetnikov <nik...@karetnikov.org>
+;;; Copyright © 2014 Alex Kost <alez...@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -231,6 +232,12 @@ interpreted."
                       (location->string loc)
                       (package-full-name package)
                       (build-system-name system))))
+            ((profile-not-found-error? c)
+             (leave (_ "profile '~a' does not exist~%")
+                    (profile-error-profile c)))
+            ((missing-generation-error? c)
+             (leave (_ "generation ~a does not exist~%")
+                    (missing-generation-error-generation c)))
             ((nix-connection-error? c)
              (leave (_ "failed to connect to `~a': ~a~%")
                     (nix-connection-error-file c)
-- 
2.1.2

>From da49a2b7af5295c3c72b7e4590219cbac827877b Mon Sep 17 00:00:00 2001
From: Alex Kost <alez...@gmail.com>
Date: Wed, 8 Oct 2014 00:39:42 +0400
Subject: [PATCH 2/3] profiles: Add procedures for switching generations.

* guix/scripts/package.scm (switch-to-previous-generation): Move to...
* guix/profiles.scm: ... here. Use 'switch-to-generation'.
  (relative-generation): New procedure.
  (previous-generation-number): Use it.
  (switch-to-generation): New procedure.
---
 guix/profiles.scm        | 51 ++++++++++++++++++++++++++++++++++++++++--------
 guix/scripts/package.scm |  9 ---------
 2 files changed, 43 insertions(+), 17 deletions(-)

diff --git a/guix/profiles.scm b/guix/profiles.scm
index 793af24..f56e407 100644
--- a/guix/profiles.scm
+++ b/guix/profiles.scm
@@ -80,9 +80,12 @@
             generation-number
             generation-numbers
             profile-generations
+            relative-generation
             previous-generation-number
             generation-time
-            generation-file-name))
+            generation-file-name
+            switch-to-generation
+            switch-to-previous-generation))
 
 ;;; Commentary:
 ;;;
@@ -503,16 +506,28 @@ former profiles were found."
         '()
         generations)))
 
-(define (previous-generation-number profile number)
+(define* (relative-generation profile shift #:optional
+                              (current (generation-number profile)))
+  "Return PROFILE's generation shifted from the CURRENT generation by SHIFT.
+SHIFT is a positive or negative number.
+Return #f if there is no such generation."
+  (let* ((abs-shift (abs shift))
+         (numbers (profile-generations profile))
+         (from-current (memq current
+                             (if (negative? shift)
+                                 (reverse numbers)
+                                 numbers))))
+    (and from-current
+         (< abs-shift (length from-current))
+         (list-ref from-current abs-shift))))
+
+(define* (previous-generation-number profile #:optional
+                                     (number (generation-number profile)))
   "Return the number of the generation before generation NUMBER of
 PROFILE, or 0 if none exists.  It could be NUMBER - 1, but it's not the
 case when generations have been deleted (there are \"holes\")."
-  (fold (lambda (candidate highest)
-          (if (and (< candidate number) (> candidate highest))
-              candidate
-              highest))
-        0
-        (generation-numbers profile)))
+  (or (relative-generation profile -1 number)
+      0))
 
 (define (generation-file-name profile generation)
   "Return the file name for PROFILE's GENERATION."
@@ -523,4 +538,24 @@ case when generations have been deleted (there are \"holes\")."
   (make-time time-utc 0
              (stat:ctime (stat (generation-file-name profile number)))))
 
+(define (switch-to-generation profile number)
+  "Atomically switch PROFILE to the generation NUMBER."
+  (let ((current    (generation-number profile))
+        (generation (generation-file-name profile number)))
+    (cond ((not (file-exists? profile))
+           (raise (condition (&profile-not-found-error
+                              (profile profile)))))
+          ((not (file-exists? generation))
+           (raise (condition (&missing-generation-error
+                              (generation number)))))
+          (else
+           (format #t (_ "switching from generation ~a to ~a~%")
+                   current number)
+           (switch-symlinks profile generation)))))
+
+(define (switch-to-previous-generation profile)
+  "Atomically switch PROFILE to the previous generation."
+  (switch-to-generation profile
+                        (previous-generation-number profile)))
+
 ;;; profiles.scm ends here
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index ab9d303..460416f 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -96,15 +96,6 @@ return PROFILE unchanged.  The goal is to treat '-p ~/.guix-profile' as if
 
     (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 (generation-file-name profile previous-number)))
-    (format #t (_ "switching from generation ~a to ~a~%")
-            number previous-number)
-    (switch-symlinks profile previous-generation)))
-
 (define (roll-back store profile)
   "Roll back to the previous generation of PROFILE."
   (let* ((number              (generation-number profile))
-- 
2.1.2

Reply via email to