summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--guix/profiles.scm53
-rw-r--r--tests/profiles.scm20
2 files changed, 64 insertions, 9 deletions
diff --git a/guix/profiles.scm b/guix/profiles.scm
index 843040156c..52bd5bc332 100644
--- a/guix/profiles.scm
+++ b/guix/profiles.scm
@@ -53,6 +53,7 @@
 
             manifest-remove
             manifest-add
+            manifest-lookup
             manifest-installed?
             manifest-matching-entries
 
@@ -237,11 +238,16 @@ Remove MANIFEST entries that have the same name and output as ENTRIES."
                  (manifest-entries manifest)
                  entries))))
 
+(define (manifest-lookup manifest pattern)
+  "Return the first item of MANIFEST that matches PATTERN, or #f if there is
+no match.."
+  (find (entry-predicate pattern)
+        (manifest-entries manifest)))
+
 (define (manifest-installed? manifest pattern)
   "Return #t if MANIFEST has an entry matching PATTERN (a manifest-pattern),
 #f otherwise."
-  (->bool (find (entry-predicate pattern)
-                (manifest-entries manifest))))
+  (->bool (manifest-lookup manifest pattern)))
 
 (define (manifest-matching-entries manifest patterns)
   "Return all the entries of MANIFEST that match one of the PATTERNS."
@@ -271,7 +277,9 @@ Remove MANIFEST entries that have the same name and output as ENTRIES."
 (define (manifest-transaction-effects manifest transaction)
   "Compute the effect of applying TRANSACTION to MANIFEST.  Return 3 values:
 the list of packages that would be removed, installed, or upgraded when
-applying TRANSACTION to MANIFEST."
+applying TRANSACTION to MANIFEST.  Upgrades are represented as pairs where the
+head is the entry being upgraded and the tail is the entry that will replace
+it."
   (define (manifest-entry->pattern entry)
     (manifest-pattern
       (name   (manifest-entry-name entry))
@@ -292,10 +300,12 @@ applying TRANSACTION to MANIFEST."
        ;; XXX: When the exact same output directory is installed, we're not
        ;; really upgrading anything.  Add a check for that case.
        (let* ((pattern  (manifest-entry->pattern entry))
-              (upgrade? (manifest-installed? manifest pattern)))
+              (previous (manifest-lookup manifest pattern)))
          (loop rest
-               (if upgrade? install (cons entry install))
-               (if upgrade? (cons entry upgrade) upgrade)))))))
+               (if previous install (cons entry install))
+               (if previous
+                   (alist-cons previous entry upgrade)
+                   upgrade)))))))
 
 (define (manifest-perform-transaction manifest transaction)
   "Perform TRANSACTION on MANIFEST and return new manifest."
@@ -304,6 +314,20 @@ applying TRANSACTION to MANIFEST."
     (manifest-add (manifest-remove manifest remove)
                   install)))
 
+(define (right-arrow port)
+  "Return either a string containing the 'RIGHT ARROW' character, or an ASCII
+replacement if PORT is not Unicode-capable."
+  (with-fluids ((%default-port-encoding (port-encoding port)))
+    (let ((arrow "→"))
+      (catch 'encoding-error
+        (lambda ()
+          (with-fluids ((%default-port-conversion-strategy 'error))
+            (with-output-to-string
+              (lambda ()
+                (display arrow)))))
+        (lambda (key . args)
+          ">")))))
+
 (define* (manifest-show-transaction store manifest transaction
                                     #:key dry-run?)
   "Display what will/would be installed/removed from MANIFEST by TRANSACTION."
@@ -315,6 +339,17 @@ applying TRANSACTION to MANIFEST."
                        item)))
          name version output item))
 
+  (define →                        ;an arrow that can be represented on stderr
+    (right-arrow (current-error-port)))
+
+  (define (upgrade-string name old-version new-version output item)
+    (format #f "   ~a\t~a ~a ~a\t~a\t~a" name
+            old-version → new-version
+            output
+            (if (package? item)
+                (package-output store item output)
+                item)))
+
   (let-values (((remove install upgrade)
                 (manifest-transaction-effects manifest transaction)))
     (match remove
@@ -334,9 +369,11 @@ applying TRANSACTION to MANIFEST."
                      remove))))
       (_ #f))
     (match upgrade
-      ((($ <manifest-entry> name version output item _) ..1)
+      (((($ <manifest-entry> name old-version)
+         . ($ <manifest-entry> _ new-version output item)) ..1)
        (let ((len     (length name))
-             (upgrade (package-strings name version output item)))
+             (upgrade (map upgrade-string
+                           name old-version new-version output item)))
          (if dry-run?
              (format (current-error-port)
                      (N_ "The following package would be upgraded:~%~{~a~%~}~%"
diff --git a/tests/profiles.scm b/tests/profiles.scm
index d88def32fd..879f71073f 100644
--- a/tests/profiles.scm
+++ b/tests/profiles.scm
@@ -26,6 +26,7 @@
   #:use-module (guix derivations)
   #:use-module (gnu packages bootstrap)
   #:use-module (ice-9 match)
+  #:use-module (ice-9 regex)
   #:use-module (srfi srfi-11)
   #:use-module (srfi srfi-64))
 
@@ -153,7 +154,24 @@
                   (manifest-transaction-effects m0 t)))
       (and (null? remove)
            (equal? (list glibc) install)
-           (equal? (list guile-2.0.9) upgrade)))))
+           (equal? (list (cons guile-1.8.8 guile-2.0.9)) upgrade)))))
+
+(test-assert "manifest-show-transaction"
+  (let* ((m (manifest (list guile-1.8.8)))
+         (t (manifest-transaction (install (list guile-2.0.9)))))
+    (let-values (((remove install upgrade)
+                  (manifest-transaction-effects m t)))
+      (with-store store
+        (and (string-match "guile\t1.8.8 → 2.0.9"
+                           (with-fluids ((%default-port-encoding "UTF-8"))
+                             (with-error-to-string
+                              (lambda ()
+                                (manifest-show-transaction store m t)))))
+             (string-match "guile\t1.8.8 > 2.0.9"
+                           (with-fluids ((%default-port-encoding "ISO-8859-1"))
+                             (with-error-to-string
+                              (lambda ()
+                                (manifest-show-transaction store m t))))))))))
 
 (test-assert "profile-derivation"
   (run-with-store %store