summaryrefslogtreecommitdiff
path: root/guix/profiles.scm
diff options
context:
space:
mode:
Diffstat (limited to 'guix/profiles.scm')
-rw-r--r--guix/profiles.scm100
1 files changed, 78 insertions, 22 deletions
diff --git a/guix/profiles.scm b/guix/profiles.scm
index 55c3b6e768..9dc9ab43b9 100644
--- a/guix/profiles.scm
+++ b/guix/profiles.scm
@@ -32,6 +32,7 @@
#:use-module (ice-9 format)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9)
+ #:use-module (srfi srfi-11)
#:use-module (srfi srfi-19)
#:use-module (srfi srfi-26)
#:export (manifest make-manifest
@@ -52,6 +53,7 @@
manifest-remove
manifest-add
+ manifest-lookup
manifest-installed?
manifest-matching-entries
@@ -60,6 +62,7 @@
manifest-transaction-install
manifest-transaction-remove
manifest-perform-transaction
+ manifest-transaction-effects
manifest-show-transaction
profile-manifest
@@ -235,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."
@@ -266,6 +274,39 @@ Remove MANIFEST entries that have the same name and output as ENTRIES."
(remove manifest-transaction-remove ; list of <manifest-pattern>
(default '())))
+(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. 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))
+ (output (manifest-entry-output entry))))
+
+ (let loop ((input (manifest-transaction-install transaction))
+ (install '())
+ (upgrade '()))
+ (match input
+ (()
+ (let ((remove (manifest-transaction-remove transaction)))
+ (values (manifest-matching-entries manifest remove)
+ (reverse install) (reverse upgrade))))
+ ((entry rest ...)
+ ;; Check whether installing ENTRY corresponds to the installation of a
+ ;; new package or to an upgrade.
+
+ ;; 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))
+ (previous (manifest-lookup manifest pattern)))
+ (loop rest
+ (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."
(let ((install (manifest-transaction-install transaction))
@@ -273,35 +314,48 @@ Remove MANIFEST entries that have the same name and output as ENTRIES."
(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."
(define (package-strings name version output item)
(map (lambda (name version output item)
- (format #f " ~a-~a\t~a\t~a" name version output
+ (format #f " ~a~:[:~a~;~*~]\t~a\t~a"
+ name
+ (equal? output "out") output version
(if (package? item)
(package-output store item output)
item)))
name version output item))
- (let* ((remove (manifest-matching-entries
- manifest (manifest-transaction-remove transaction)))
- (install/upgrade (manifest-transaction-install transaction))
- (install '())
- (upgrade (append-map
- (lambda (entry)
- (let ((matching
- (manifest-matching-entries
- manifest
- (list (manifest-pattern
- (name (manifest-entry-name entry))
- (output (manifest-entry-output entry)))))))
- (when (null? matching)
- (set! install (cons entry install)))
- matching))
- install/upgrade)))
+ (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~:[:~a~;~*~]\t~a ~a ~a\t~a"
+ name (equal? output "out") output
+ old-version → new-version
+ (if (package? item)
+ (package-output store item output)
+ item)))
+
+ (let-values (((remove install upgrade)
+ (manifest-transaction-effects manifest transaction)))
(match remove
- ((($ <manifest-entry> name version output item _) ..1)
+ ((($ <manifest-entry> name version output item) ..1)
(let ((len (length name))
(remove (package-strings name version output item)))
(if dry-run?
@@ -317,9 +371,11 @@ Remove MANIFEST entries that have the same name and output as ENTRIES."
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~%~}~%"