summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2013-12-22 01:08:21 +0100
committerLudovic Courtès <ludo@gnu.org>2013-12-22 01:08:21 +0100
commit760c60d68491bd6803e86e405e765f3337663f17 (patch)
tree46745d190762aabea5dc16299c2b9f8780fb69eb
parent7edccf4d62c299d2c52f0c55d80e9189924562d3 (diff)
Add 'guix archive'.
* guix/scripts/archive.scm, tests/guix-archive.sh: New files. * Makefile.am (MODULES): Add 'archive.scm'. (SH_TESTS): Add 'guix-archive.sh'. * doc/guix.texi (Invoking guix archive): New section. * guix/scripts/build.scm: Export 'derivation-from-expression'. * guix/scripts/package.scm: Export 'specification->package+output'.
-rw-r--r--Makefile.am2
-rw-r--r--doc/guix.texi59
-rw-r--r--guix/scripts/archive.scm232
-rw-r--r--guix/scripts/build.scm3
-rw-r--r--guix/scripts/package.scm5
-rw-r--r--tests/guix-archive.sh45
6 files changed, 342 insertions, 4 deletions
diff --git a/Makefile.am b/Makefile.am
index 4815c55fba3..ba54f8c582e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -67,6 +67,7 @@ MODULES = \
67 guix/snix.scm \ 67 guix/snix.scm \
68 guix/scripts/download.scm \ 68 guix/scripts/download.scm \
69 guix/scripts/build.scm \ 69 guix/scripts/build.scm \
70 guix/scripts/archive.scm \
70 guix/scripts/import.scm \ 71 guix/scripts/import.scm \
71 guix/scripts/package.scm \ 72 guix/scripts/package.scm \
72 guix/scripts/gc.scm \ 73 guix/scripts/gc.scm \
@@ -130,6 +131,7 @@ SH_TESTS = \
130 tests/guix-gc.sh \ 131 tests/guix-gc.sh \
131 tests/guix-hash.sh \ 132 tests/guix-hash.sh \
132 tests/guix-package.sh \ 133 tests/guix-package.sh \
134 tests/guix-archive.sh \
133 tests/guix-authenticate.sh 135 tests/guix-authenticate.sh
134 136
135if BUILD_DAEMON 137if BUILD_DAEMON
diff --git a/doc/guix.texi b/doc/guix.texi
index fcffa5a22bc..c78e0d0d055 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -407,9 +407,10 @@ management tools it provides.
407@menu 407@menu
408* Features:: How Guix will make your life brighter. 408* Features:: How Guix will make your life brighter.
409* Invoking guix package:: Package installation, removal, etc. 409* Invoking guix package:: Package installation, removal, etc.
410* Packages with Multiple Outputs:: Single source package, multiple outputs. 410* Packages with Multiple Outputs:: Single source package, multiple outputs.
411* Invoking guix gc:: Running the garbage collector. 411* Invoking guix gc:: Running the garbage collector.
412* Invoking guix pull:: Fetching the latest Guix and distribution. 412* Invoking guix pull:: Fetching the latest Guix and distribution.
413* Invoking guix archive:: Exporting and importing store files.
413@end menu 414@end menu
414 415
415@node Features 416@node Features
@@ -914,6 +915,62 @@ Use the bootstrap Guile to build the latest Guix. This option is only
914useful to Guix developers. 915useful to Guix developers.
915@end table 916@end table
916 917
918
919@node Invoking guix archive
920@section Invoking @command{guix archive}
921
922The @command{guix archive} command allows users to @dfn{export} files
923from the store into a single archive, and to later @dfn{import} them.
924In particular, it allows store files to be transferred from one machine
925to another machine's store. For example, to transfer the @code{emacs}
926package to a machine connected over SSH, one would run:
927
928@example
929guix archive --export emacs | ssh the-machine guix archive --import
930@end example
931
932Archives are stored in the ``Nix archive'' or ``Nar'' format, which is
933comparable in spirit to `tar'. When exporting, the daemon digitally
934signs the contents of the archive, and that digital signature is
935appended. When importing, the daemon verifies the signature and rejects
936the import in case of an invalid signature.
937@c FIXME: Add xref to daemon doc about signatures.
938
939The main options are:
940
941@table @code
942@item --export
943Export the specified store files or packages (see below.) Write the
944resulting archive to the standard output.
945
946@item --import
947Read an archive from the standard input, and import the files listed
948therein into the store. Abort if the archive has an invalid digital
949signature.
950@end table
951
952To export store files as an archive to the standard output, run:
953
954@example
955guix archive --export @var{options} @var{specifications}...
956@end example
957
958@var{specifications} may be either store file names or package
959specifications, as for @command{guix package} (@pxref{Invoking guix
960package}). For instance, the following command creates an archive
961containing the @code{gui} output of the @code{git} package and the main
962output of @code{emacs}:
963
964@example
965guix archive --export git:gui /nix/store/...-emacs-24.3 > great.nar
966@end example
967
968If the specified packages are not built yet, @command{guix archive}
969automatically builds them. The build process may be controlled with the
970same options that can be passed to the @command{guix build} command
971(@pxref{Invoking guix build}).
972
973
917@c ********************************************************************* 974@c *********************************************************************
918@node Programming Interface 975@node Programming Interface
919@chapter Programming Interface 976@chapter Programming Interface
diff --git a/guix/scripts/archive.scm b/guix/scripts/archive.scm
new file mode 100644
index 00000000000..df538ed1b7d
--- /dev/null
+++ b/guix/scripts/archive.scm
@@ -0,0 +1,232 @@
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2013 Ludovic Courtès <ludo@gnu.org>
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (guix scripts archive)
20 #:use-module (guix config)
21 #:use-module (guix utils)
22 #:use-module (guix store)
23 #:use-module (guix packages)
24 #:use-module (guix derivations)
25 #:use-module (guix ui)
26 #:use-module (ice-9 match)
27 #:use-module (srfi srfi-1)
28 #:use-module (srfi srfi-11)
29 #:use-module (srfi srfi-26)
30 #:use-module (srfi srfi-37)
31 #:use-module (guix scripts build)
32 #:use-module (guix scripts package)
33 #:export (guix-archive))
34
35
36;;;
37;;; Command-line options.
38;;;
39
40(define %default-options
41 ;; Alist of default option values.
42 `((system . ,(%current-system))
43 (substitutes? . #t)
44 (max-silent-time . 3600)
45 (verbosity . 0)))
46
47(define (show-help)
48 (display (_ "Usage: guix archive [OPTION]... PACKAGE...
49Export/import one or more packages from/to the store.\n"))
50 (display (_ "
51 --export export the specified files/packages to stdout"))
52 (display (_ "
53 --import import from the archive passed on stdin"))
54 (newline)
55 (display (_ "
56 -e, --expression=EXPR build the package or derivation EXPR evaluates to"))
57 (display (_ "
58 -S, --source build the packages' source derivations"))
59 (display (_ "
60 -s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\""))
61 (display (_ "
62 --target=TRIPLET cross-build for TRIPLET--e.g., \"armel-linux-gnu\""))
63 (display (_ "
64 -n, --dry-run do not build the derivations"))
65 (display (_ "
66 --fallback fall back to building when the substituter fails"))
67 (display (_ "
68 --no-substitutes build instead of resorting to pre-built substitutes"))
69 (display (_ "
70 --max-silent-time=SECONDS
71 mark the build as failed after SECONDS of silence"))
72 (display (_ "
73 -c, --cores=N allow the use of up to N CPU cores for the build"))
74 (newline)
75 (display (_ "
76 -h, --help display this help and exit"))
77 (display (_ "
78 -V, --version display version information and exit"))
79 (newline)
80 (show-bug-report-information))
81
82(define %options
83 ;; Specifications of the command-line options.
84 (list (option '(#\h "help") #f #f
85 (lambda args
86 (show-help)
87 (exit 0)))
88 (option '(#\V "version") #f #f
89 (lambda args
90 (show-version-and-exit "guix build")))
91
92 (option '("export") #f #f
93 (lambda (opt name arg result)
94 (alist-cons 'export #t result)))
95 (option '("import") #f #f
96 (lambda (opt name arg result)
97 (alist-cons 'import #t result)))
98
99 (option '(#\S "source") #f #f
100 (lambda (opt name arg result)
101 (alist-cons 'source? #t result)))
102 (option '(#\s "system") #t #f
103 (lambda (opt name arg result)
104 (alist-cons 'system arg
105 (alist-delete 'system result eq?))))
106 (option '("target") #t #f
107 (lambda (opt name arg result)
108 (alist-cons 'target arg
109 (alist-delete 'target result eq?))))
110 (option '(#\e "expression") #t #f
111 (lambda (opt name arg result)
112 (alist-cons 'expression arg result)))
113 (option '(#\c "cores") #t #f
114 (lambda (opt name arg result)
115 (let ((c (false-if-exception (string->number arg))))
116 (if c
117 (alist-cons 'cores c result)
118 (leave (_ "~a: not a number~%") arg)))))
119 (option '(#\n "dry-run") #f #f
120 (lambda (opt name arg result)
121 (alist-cons 'dry-run? #t result)))
122 (option '("fallback") #f #f
123 (lambda (opt name arg result)
124 (alist-cons 'fallback? #t
125 (alist-delete 'fallback? result))))
126 (option '("no-substitutes") #f #f
127 (lambda (opt name arg result)
128 (alist-cons 'substitutes? #f
129 (alist-delete 'substitutes? result))))
130 (option '("max-silent-time") #t #f
131 (lambda (opt name arg result)
132 (alist-cons 'max-silent-time (string->number* arg)
133 result)))
134 (option '(#\r "root") #t #f
135 (lambda (opt name arg result)
136 (alist-cons 'gc-root arg result)))
137 (option '("verbosity") #t #f
138 (lambda (opt name arg result)
139 (let ((level (string->number arg)))
140 (alist-cons 'verbosity level
141 (alist-delete 'verbosity result)))))))
142
143(define (options->derivations+files store opts)
144 "Given OPTS, the result of 'args-fold', return a list of derivations to
145build and a list of store files to transfer."
146 (define package->derivation
147 (match (assoc-ref opts 'target)
148 (#f package-derivation)
149 (triplet
150 (cut package-cross-derivation <> <> triplet <>))))
151
152 (define src? (assoc-ref opts 'source?))
153 (define sys (assoc-ref opts 'system))
154
155 (fold2 (lambda (arg derivations files)
156 (match arg
157 (('expression . str)
158 (let ((drv (derivation-from-expression store str
159 package->derivation
160 sys src?)))
161 (values (cons drv derivations)
162 (cons (derivation->output-path drv) files))))
163 (('argument . (? store-path? file))
164 (values derivations (cons file files)))
165 (('argument . (? string? spec))
166 (let-values (((p output)
167 (specification->package+output spec)))
168 (if src?
169 (let* ((s (package-source p))
170 (drv (package-source-derivation store s)))
171 (values (cons drv derivations)
172 (cons (derivation->output-path drv)
173 files)))
174 (let ((drv (package->derivation store p sys)))
175 (values (cons drv derivations)
176 (cons (derivation->output-path drv output)
177 files))))))
178 (_
179 (values derivations files))))
180 '()
181 '()
182 opts))
183
184
185;;;
186;;; Entry point.
187;;;
188
189(define (export-from-store store opts)
190 "Export the packages or derivations specified in OPTS from STORE. Write the
191resulting archive to the standard output port."
192 (let-values (((drv files)
193 (options->derivations+files store opts)))
194 (show-what-to-build store drv
195 #:use-substitutes? (assoc-ref opts 'substitutes?)
196 #:dry-run? (assoc-ref opts 'dry-run?))
197
198 (set-build-options store
199 #:build-cores (or (assoc-ref opts 'cores) 0)
200 #:fallback? (assoc-ref opts 'fallback?)
201 #:use-substitutes? (assoc-ref opts 'substitutes?)
202 #:max-silent-time (assoc-ref opts 'max-silent-time))
203
204 (if (or (assoc-ref opts 'dry-run?)
205 (build-derivations store drv))
206 (export-paths store files (current-output-port))
207 (leave (_ "unable to export the given packages")))))
208
209(define (guix-archive . args)
210 (define (parse-options)
211 ;; Return the alist of option values.
212 (args-fold* args %options
213 (lambda (opt name arg result)
214 (leave (_ "~A: unrecognized option~%") name))
215 (lambda (arg result)
216 (alist-cons 'argument arg result))
217 %default-options))
218
219 (with-error-handling
220 ;; Ask for absolute file names so that .drv file names passed from the
221 ;; user to 'read-derivation' are absolute when it returns.
222 (with-fluids ((%file-port-name-canonicalization 'absolute))
223 (let* ((opts (parse-options))
224 (store (open-connection)))
225
226 (cond ((assoc-ref opts 'export)
227 (export-from-store store opts))
228 ((assoc-ref opts 'import)
229 (import-paths store (current-input-port)))
230 (else
231 (leave
232 (_ "either '--export' or '--import' must be specified"))))))))
diff --git a/guix/scripts/build.scm b/guix/scripts/build.scm
index b3d852e950d..90187094c1c 100644
--- a/guix/scripts/build.scm
+++ b/guix/scripts/build.scm
@@ -33,7 +33,8 @@
33 #:use-module (srfi srfi-34) 33 #:use-module (srfi srfi-34)
34 #:use-module (srfi srfi-37) 34 #:use-module (srfi srfi-37)
35 #:autoload (gnu packages) (find-best-packages-by-name) 35 #:autoload (gnu packages) (find-best-packages-by-name)
36 #:export (guix-build)) 36 #:export (derivation-from-expression
37 guix-build))
37 38
38(define (derivation-from-expression store str package-derivation 39(define (derivation-from-expression store str package-derivation
39 system source?) 40 system source?)
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index 8c197a741ed..7cebf6b4d40 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -41,7 +41,8 @@
41 #:use-module ((gnu packages base) #:select (guile-final)) 41 #:use-module ((gnu packages base) #:select (guile-final))
42 #:use-module ((gnu packages bootstrap) #:select (%bootstrap-guile)) 42 #:use-module ((gnu packages bootstrap) #:select (%bootstrap-guile))
43 #:use-module (guix gnu-maintenance) 43 #:use-module (guix gnu-maintenance)
44 #:export (guix-package)) 44 #:export (specification->package+output
45 guix-package))
45 46
46(define %store 47(define %store
47 (make-parameter #f)) 48 (make-parameter #f))
@@ -293,7 +294,7 @@ return its return value."
293 #f)))) 294 #f))))
294 295
295(define* (specification->package+output spec #:optional (output "out")) 296(define* (specification->package+output spec #:optional (output "out"))
296 "Find the package and output specified by SPEC, or #f and #f; SPEC may 297 "Return the package and output specified by SPEC, or #f and #f; SPEC may
297optionally contain a version number and an output name, as in these examples: 298optionally contain a version number and an output name, as in these examples:
298 299
299 guile 300 guile
diff --git a/tests/guix-archive.sh b/tests/guix-archive.sh
new file mode 100644
index 00000000000..ef048354690
--- /dev/null
+++ b/tests/guix-archive.sh
@@ -0,0 +1,45 @@
1# GNU Guix --- Functional package management for GNU
2# Copyright © 2013 Ludovic Courtès <ludo@gnu.org>
3#
4# This file is part of GNU Guix.
5#
6# GNU Guix is free software; you can redistribute it and/or modify it
7# under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 3 of the License, or (at
9# your option) any later version.
10#
11# GNU Guix is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19#
20# Test the 'guix archive' command-line utility.
21#
22
23guix archive --version
24
25archive="t-archive-$$"
26archive_alt="t-archive-alt-$$"
27rm -f "$archive" "$archive_alt"
28
29trap 'rm -f "$archive" "$archive_alt"' EXIT
30
31guix archive --export guile-bootstrap > "$archive"
32guix archive --export guile-bootstrap:out > "$archive_alt"
33cmp "$archive" "$archive_alt"
34
35guix archive --export \
36 -e '(@ (gnu packages bootstrap) %bootstrap-guile)' > "$archive_alt"
37cmp "$archive" "$archive_alt"
38
39guix archive --export `guix build guile-bootstrap` > "$archive_alt"
40cmp "$archive" "$archive_alt"
41
42guix archive --import < "$archive" 2>&1 | grep "import.*guile-bootstrap"
43
44if guix archive something-that-does-not-exist
45then false; else true; fi