summary refs log tree commit diff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2014-01-06 22:25:29 +0100
committerLudovic Courtès <ludo@gnu.org>2014-01-06 22:25:29 +0100
commit87236aed77bd57ecd143d84acf864fb112842118 (patch)
tree77ebed23b8267ab621a69051ba60e58dfe715689
parentb84612605204d604da84b30e56966994cc03d0a3 (diff)
downloadguix-87236aed77bd57ecd143d84acf864fb112842118.tar.gz
archive: Add '--missing'.
* guix/scripts/archive.scm (show-help, %options): Add '--missing'.
  (guix-archive)[lines]: New procedure.
  Use it to honor '--missing'.
* tests/guix-archive.sh: Add tests.
* doc/guix.texi (Invoking guix archive): Document '--missing'.
-rw-r--r--doc/guix.texi11
-rw-r--r--guix/scripts/archive.scm21
-rw-r--r--tests/guix-archive.sh20
3 files changed, 51 insertions, 1 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index d5884008f4..93d1c2be3b 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -938,6 +938,12 @@ package to a machine connected over SSH, one would run:
 guix archive --export emacs | ssh the-machine guix archive --import
 @end example
 
+@noindent
+However, note that, in this example, all of @code{emacs} and its
+dependencies are transferred, regardless of what is already available in
+the target machine's store.  The @code{--missing} option can help figure
+out which items are missing from the target's store.
+
 Archives are stored in the ``Nix archive'' or ``Nar'' format, which is
 comparable in spirit to `tar'.  When exporting, the daemon digitally
 signs the contents of the archive, and that digital signature is
@@ -959,6 +965,11 @@ therein into the store.  Abort if the archive has an invalid digital
 signature, or if it is signed by a public key not among the authorized
 keys (see @code{--authorize} below.)
 
+@item --missing
+Read a list of store file names from the standard input, one per line,
+and write on the standard output the subset of these files missing from
+the store.
+
 @item --generate-key[=@var{parameters}]
 @cindex signing, archives
 Generate a new key pair for the daemons.  This is a prerequisite before
diff --git a/guix/scripts/archive.scm b/guix/scripts/archive.scm
index 3b778d8151..32690c6b45 100644
--- a/guix/scripts/archive.scm
+++ b/guix/scripts/archive.scm
@@ -27,6 +27,8 @@
   #:use-module (guix pki)
   #:use-module (guix pk-crypto)
   #:use-module (ice-9 match)
+  #:use-module (ice-9 format)
+  #:use-module (ice-9 rdelim)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-11)
   #:use-module (srfi srfi-26)
@@ -55,6 +57,8 @@ Export/import one or more packages from/to the store.\n"))
       --export           export the specified files/packages to stdout"))
   (display (_ "
       --import           import from the archive passed on stdin"))
+  (display (_ "
+      --missing          print the files from stdin that are missing"))
   (newline)
   (display (_ "
       --generate-key[=PARAMETERS]
@@ -102,6 +106,9 @@ Export/import one or more packages from/to the store.\n"))
         (option '("import") #f #f
                 (lambda (opt name arg result)
                   (alist-cons 'import #t result)))
+        (option '("missing") #f #f
+                (lambda (opt name arg result)
+                  (alist-cons 'missing #t result)))
         (option '("generate-key") #f #t
                 (lambda (opt name arg result)
                   (catch 'gcry-error
@@ -294,6 +301,15 @@ the input port."
                   (alist-cons 'argument arg result))
                 %default-options))
 
+  (define (lines port)
+    ;; Return lines read from PORT.
+    (let loop ((line   (read-line port))
+               (result '()))
+      (if (eof-object? line)
+          (reverse result)
+          (loop (read-line port)
+                (cons line result)))))
+
   (with-error-handling
     ;; Ask for absolute file names so that .drv file names passed from the
     ;; user to 'read-derivation' are absolute when it returns.
@@ -310,6 +326,11 @@ the input port."
                         (export-from-store store opts))
                        ((assoc-ref opts 'import)
                         (import-paths store (current-input-port)))
+                       ((assoc-ref opts 'missing)
+                        (let* ((files   (lines (current-input-port)))
+                               (missing (remove (cut valid-path? store <>)
+                                                files)))
+                          (format #t "~{~a~%~}" missing)))
                        (else
                         (leave
                          (_ "either '--export' or '--import' \
diff --git a/tests/guix-archive.sh b/tests/guix-archive.sh
index 3ac618ae33..0de7395145 100644
--- a/tests/guix-archive.sh
+++ b/tests/guix-archive.sh
@@ -1,5 +1,5 @@
 # GNU Guix --- Functional package management for GNU
-# Copyright © 2013 Ludovic Courtès <ludo@gnu.org>
+# Copyright © 2013, 2014 Ludovic Courtès <ludo@gnu.org>
 #
 # This file is part of GNU Guix.
 #
@@ -44,5 +44,23 @@ guix archive --import < "$archive" 2>&1 | grep "import.*guile-bootstrap"
 if guix archive something-that-does-not-exist
 then false; else true; fi
 
+# This one must not be listed as missing.
+guix build guile-bootstrap > "$archive"
+guix archive --missing < "$archive"
+test "`guix archive --missing < "$archive"`" = ""
+
+# Two out of three should be listed as missing.
+echo "$NIX_STORE_DIR/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-foo" >> "$archive"
+echo "$NIX_STORE_DIR/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-bar" >> "$archive"
+guix archive --missing < "$archive" > "$archive_alt"
+echo "$NIX_STORE_DIR/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-foo" > "$archive"
+echo "$NIX_STORE_DIR/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-bar" >> "$archive"
+cmp "$archive" "$archive_alt"
+
+# This is not a valid store file name, so an error.
+echo something invalid > "$archive"
+if guix archive --missing < "$archive"
+then false; else true; fi
+
 if echo foo | guix archive --authorize
 then false; else true; fi