summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2013-02-20 23:46:38 +0100
committerLudovic Courtès <ludo@gnu.org>2013-02-20 23:47:16 +0100
commitf651b477b701d086402c18665eca68b26c3bec6b (patch)
treee0d9d10df8488ddd63eff3be5c3f9d3c1d66b290
parent9bb2b96aabdbb245c4a409e96b25df2954cfe385 (diff)
Add "guix pull".
* guix/scripts/pull.scm: New file. * Makefile.am (MODULES): Add it. * doc/guix.texi (Invoking guix pull): New node. (Invoking guix package): Add cross-ref to it. * guix/ui.scm (config-directory): New procedure. * scripts/guix.in: When `GUIX_UNINSTALLED' is undefined, add $XDG_CONFIG_HOME/guix/latest to the search path. * po/POTFILES.in: Add guix/scripts/pull.scm.
-rw-r--r--Makefile.am1
-rw-r--r--doc/guix.texi33
-rw-r--r--guix/scripts/pull.scm222
-rw-r--r--guix/ui.scm21
-rw-r--r--po/POTFILES.in1
-rw-r--r--scripts/guix.in12
6 files changed, 288 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am
index cabbe21cdd7..bed4d06ec0a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -30,6 +30,7 @@ MODULES = \
30 guix/scripts/import.scm \ 30 guix/scripts/import.scm \
31 guix/scripts/package.scm \ 31 guix/scripts/package.scm \
32 guix/scripts/gc.scm \ 32 guix/scripts/gc.scm \
33 guix/scripts/pull.scm \
33 guix/base32.scm \ 34 guix/base32.scm \
34 guix/utils.scm \ 35 guix/utils.scm \
35 guix/derivations.scm \ 36 guix/derivations.scm \
diff --git a/doc/guix.texi b/doc/guix.texi
index 9245bd00f52..6a9ebab1f67 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -393,6 +393,7 @@ management tools it provides.
393* Features:: How Guix will make your life brighter. 393* Features:: How Guix will make your life brighter.
394* Invoking guix package:: Package installation, removal, etc. 394* Invoking guix package:: Package installation, removal, etc.
395* Invoking guix gc:: Running the garbage collector. 395* Invoking guix gc:: Running the garbage collector.
396* Invoking guix pull:: Fetching the latest Guix and distribution.
396@end menu 397@end menu
397 398
398@node Features 399@node Features
@@ -521,6 +522,11 @@ Remove @var{package}.
521@itemx -u @var{regexp} 522@itemx -u @var{regexp}
522Upgrade all the installed packages matching @var{regexp}. 523Upgrade all the installed packages matching @var{regexp}.
523 524
525Note that this upgrades package to the latest version of packages found
526in the distribution currently installed. To update your distribution,
527you should regularly run @command{guix pull} (@pxref{Invoking guix
528pull}).
529
524@item --roll-back 530@item --roll-back
525Roll back to the previous @dfn{generation} of the profile---i.e., undo 531Roll back to the previous @dfn{generation} of the profile---i.e., undo
526the last transaction. 532the last transaction.
@@ -654,6 +660,33 @@ Show the list of live store files and directories.
654@end table 660@end table
655 661
656 662
663@node Invoking guix pull
664@section Invoking @command{guix pull}
665
666Packages are installed or upgraded to the latest version available in
667the distribution currently available on your local machine. To update
668that distribution, along with the Guix tools, you must run @command{guix
669pull}: the command downloads the latest Guix source code and package
670descriptions, and deploys it.
671
672On completion, @command{guix package} will use packages and package
673versions from this just-retrieved copy of Guix. Not only that, but all
674the Guix commands and Scheme modules will also be taken from that latest
675version. New @command{guix} sub-commands added by the update also
676become available.
677
678The @command{guix pull} command is usually invoked with no arguments,
679but it supports the following options:
680
681@table @code
682@item --verbose
683Produce verbose output, writing build logs to the standard error output.
684
685@item --bootstrap
686Use the bootstrap Guile to build the latest Guix. This option is only
687useful to Guix developers.
688@end table
689
657@c ********************************************************************* 690@c *********************************************************************
658@node Programming Interface 691@node Programming Interface
659@chapter Programming Interface 692@chapter Programming Interface
diff --git a/guix/scripts/pull.scm b/guix/scripts/pull.scm
new file mode 100644
index 00000000000..f12133fff7d
--- /dev/null
+++ b/guix/scripts/pull.scm
@@ -0,0 +1,222 @@
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 pull)
20 #:use-module (guix ui)
21 #:use-module (guix store)
22 #:use-module (guix config)
23 #:use-module (guix packages)
24 #:use-module (guix derivations)
25 #:use-module (guix build download)
26 #:use-module (gnu packages base)
27 #:use-module ((gnu packages bootstrap)
28 #:select (%bootstrap-guile))
29 #:use-module (gnu packages compression)
30 #:use-module (gnu packages gnupg)
31 #:use-module (srfi srfi-1)
32 #:use-module (srfi srfi-11)
33 #:use-module (srfi srfi-37)
34 #:export (guix-pull))
35
36(define %snapshot-url
37 "http://hydra.gnu.org/job/guix/master/tarball/latest/download"
38 ;;"http://git.savannah.gnu.org/cgit/guix.git/snapshot/guix-master.tar.gz"
39 )
40
41(define (download-and-store store)
42 "Download the latest Guix tarball, add it to STORE, and return its store
43path."
44 ;; FIXME: Authenticate the downloaded file!
45 ;; FIXME: Optimize data transfers using rsync, Git, bsdiff, or GNUnet's DHT.
46 (call-with-temporary-output-file
47 (lambda (temp port)
48 (let ((result
49 (parameterize ((current-output-port (current-error-port)))
50 (url-fetch %snapshot-url temp))))
51 (close port)
52 (and result
53 (add-to-store store "guix-latest.tar.gz" #f "sha256" temp))))))
54
55(define (unpack store tarball)
56 "Return a derivation that unpacks TARBALL into STORE and compiles Scheme
57files."
58 (define builder
59 `(begin
60 (use-modules (guix build utils)
61 (system base compile)
62 (ice-9 ftw)
63 (ice-9 match))
64
65 (let ((out (assoc-ref %outputs "out"))
66 (tar (assoc-ref %build-inputs "tar"))
67 (gzip (assoc-ref %build-inputs "gzip"))
68 (gcrypt (assoc-ref %build-inputs "gcrypt"))
69 (tarball (assoc-ref %build-inputs "tarball")))
70 (setenv "PATH" (string-append tar "/bin:" gzip "/bin"))
71
72 (system* "tar" "xvf" tarball)
73 (match (scandir "." (lambda (name)
74 (and (not (member name '("." "..")))
75 (file-is-directory? name))))
76 ((dir)
77 (chdir dir))
78 (x
79 (error "tarball did not produce a single source directory" x)))
80
81 (format #t "copying and compiling Guix to `~a'...~%" out)
82
83 ;; Copy everything under guix/ and gnu/ plus guix.scm.
84 (file-system-fold (lambda (dir stat result) ; enter?
85 (or (string-prefix? "./guix" dir)
86 (string-prefix? "./gnu" dir)
87 (string=? "." dir)))
88 (lambda (file stat result) ; leaf
89 (when (or (not (string=? (dirname file) "."))
90 (string=? (basename file) "guix.scm"))
91 (let ((target (string-drop file 1)))
92 (copy-file file
93 (string-append out target)))))
94 (lambda (dir stat result) ; down
95 (mkdir (string-append out
96 (string-drop dir 1))))
97 (const #t) ; up
98 (const #t) ; skip
99 (lambda (file stat errno result)
100 (error "cannot access file"
101 file (strerror errno)))
102 #f
103 "."
104 lstat)
105
106 ;; Add a fake (guix config) module to allow the other modules to be
107 ;; compiled. The user's (guix config) is the one that will be used.
108 (copy-file "guix/config.scm.in"
109 (string-append out "/guix/config.scm"))
110 (substitute* (string-append out "/guix/config.scm")
111 (("@LIBGCRYPT@")
112 (string-append gcrypt "/lib/libgcrypt")))
113
114 ;; Augment the search path so Scheme code can be compiled.
115 (set! %load-path (cons out %load-path))
116 (set! %load-compiled-path (cons out %load-compiled-path))
117
118 ;; Compile the .scm files.
119 (for-each (lambda (file)
120 (when (string-suffix? ".scm" file)
121 (let ((go (string-append (string-drop-right file 4)
122 ".go")))
123 (compile-file file
124 #:output-file go
125 #:opts %auto-compilation-options))))
126 (find-files out "\\.scm"))
127
128 ;; Remove the "fake" (guix config).
129 (delete-file (string-append out "/guix/config.scm"))
130 (delete-file (string-append out "/guix/config.go")))))
131
132 (build-expression->derivation store "guix-latest" (%current-system)
133 builder
134 `(("tar" ,(package-derivation store tar))
135 ("gzip" ,(package-derivation store gzip))
136 ("gcrypt" ,(package-derivation store
137 libgcrypt))
138 ("tarball" ,tarball))
139 #:modules '((guix build utils))))
140
141
142;;;
143;;; Command-line options.
144;;;
145
146(define %default-options
147 ;; Alist of default option values.
148 '())
149
150(define (show-help)
151 (display (_ "Usage: guix pull [OPTION]...
152Download and deploy the latest version of Guix.\n"))
153 (display (_ "
154 --verbose produce verbose output"))
155 (display (_ "
156 --bootstrap use the bootstrap Guile to build the new Guix"))
157 (newline)
158 (display (_ "
159 -h, --help display this help and exit"))
160 (display (_ "
161 -V, --version display version information and exit"))
162 (newline)
163 (show-bug-report-information))
164
165(define %options
166 ;; Specifications of the command-line options.
167 (list (option '("verbose") #f #f
168 (lambda (opt name arg result)
169 (alist-cons 'verbose? #t result)))
170 (option '("bootstrap") #f #f
171 (lambda (opt name arg result)
172 (alist-cons 'bootstrap? #t result)))
173
174 (option '(#\h "help") #f #f
175 (lambda args
176 (show-help)
177 (exit 0)))
178 (option '(#\V "version") #f #f
179 (lambda args
180 (show-version-and-exit "guix pull")))))
181
182(define (guix-pull . args)
183 (define (parse-options)
184 ;; Return the alist of option values.
185 (args-fold args %options
186 (lambda (opt name arg result)
187 (leave (_ "~A: unrecognized option~%") name))
188 (lambda (arg result)
189 (leave (_ "~A: unexpected argument~%") arg))
190 %default-options))
191
192 (let ((opts (parse-options))
193 (store (open-connection)))
194 (with-error-handling
195 (let ((tarball (download-and-store store)))
196 (unless tarball
197 (leave (_ "failed to download up-to-date source, exiting\n")))
198 (parameterize ((%guile-for-build
199 (package-derivation store
200 (if (assoc-ref opts 'bootstrap?)
201 %bootstrap-guile
202 guile-final)))
203 (current-build-output-port
204 (if (assoc-ref opts 'verbose?)
205 (current-error-port)
206 (%make-void-port "w"))))
207 (let*-values (((config-dir)
208 (config-directory))
209 ((source drv)
210 (unpack store tarball))
211 ((source-dir)
212 (derivation-output-path
213 (assoc-ref (derivation-outputs drv) "out"))))
214 (show-what-to-build store (list source))
215 (if (build-derivations store (list source))
216 (let ((latest (string-append config-dir "/latest")))
217 (add-indirect-root store latest)
218 (switch-symlinks latest source-dir)
219 (format #t
220 (_ "updated ~a successfully deployed under `~a'~%")
221 %guix-package-name latest)
222 #t))))))))
diff --git a/guix/ui.scm b/guix/ui.scm
index 2b755045737..7d1ea2bcbd6 100644
--- a/guix/ui.scm
+++ b/guix/ui.scm
@@ -41,6 +41,7 @@
41 location->string 41 location->string
42 call-with-temporary-output-file 42 call-with-temporary-output-file
43 switch-symlinks 43 switch-symlinks
44 config-directory
44 fill-paragraph 45 fill-paragraph
45 string->recutils 46 string->recutils
46 package->recutils 47 package->recutils
@@ -178,6 +179,26 @@ both when LINK already exists and when it does not."
178 (symlink target pivot) 179 (symlink target pivot)
179 (rename-file pivot link))) 180 (rename-file pivot link)))
180 181
182(define (config-directory)
183 "Return the name of the configuration directory, after making sure that it
184exists. Honor the XDG specs,
185<http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html>."
186 (let ((dir (and=> (or (getenv "XDG_CONFIG_HOME")
187 (and=> (getenv "HOME")
188 (cut string-append <> "/.config")))
189 (cut string-append <> "/guix"))))
190 (catch 'system-error
191 (lambda ()
192 (mkdir dir)
193 dir)
194 (lambda args
195 (match (system-error-errno args)
196 ((or EEXIST 0)
197 dir)
198 (err
199 (leave (_ "failed to create configuration directory `~a': ~a~%")
200 dir (strerror err))))))))
201
181(define* (fill-paragraph str width #:optional (column 0)) 202(define* (fill-paragraph str width #:optional (column 0))
182 "Fill STR such that each line contains at most WIDTH characters, assuming 203 "Fill STR such that each line contains at most WIDTH characters, assuming
183that the first character is at COLUMN. 204that the first character is at COLUMN.
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 5c0f131c065..bdb894db207 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -8,4 +8,5 @@ guix/scripts/build.scm
8guix/scripts/download.scm 8guix/scripts/download.scm
9guix/scripts/package.scm 9guix/scripts/package.scm
10guix/scripts/gc.scm 10guix/scripts/gc.scm
11guix/scripts/pull.scm
11guix/ui.scm 12guix/ui.scm
diff --git a/scripts/guix.in b/scripts/guix.in
index 2fdde7d13a8..1315789a9c9 100644
--- a/scripts/guix.in
+++ b/scripts/guix.in
@@ -22,7 +22,8 @@
22;; IMPORTANT: We must avoid loading any modules from Guix here, 22;; IMPORTANT: We must avoid loading any modules from Guix here,
23;; because we need to adjust the guile load paths first. 23;; because we need to adjust the guile load paths first.
24;; It's okay to import modules from core Guile though. 24;; It's okay to import modules from core Guile though.
25(use-modules (ice-9 regex)) 25(use-modules (ice-9 regex)
26 (srfi srfi-26))
26 27
27(let () 28(let ()
28 (define-syntax-rule (push! elt v) (set! v (cons elt v))) 29 (define-syntax-rule (push! elt v) (set! v (cons elt v)))
@@ -45,7 +46,14 @@
45 (unless (getenv "GUIX_UNINSTALLED") 46 (unless (getenv "GUIX_UNINSTALLED")
46 (let ((module-dir (config-lookup "guilemoduledir"))) 47 (let ((module-dir (config-lookup "guilemoduledir")))
47 (push! module-dir %load-path) 48 (push! module-dir %load-path)
48 (push! module-dir %load-compiled-path)))) 49 (push! module-dir %load-compiled-path))
50 (let ((updates-dir (and=> (or (getenv "XDG_CONFIG_HOME")
51 (and=> (getenv "HOME")
52 (cut string-append <> "/.config")))
53 (cut string-append <> "/guix/latest"))))
54 (when (file-exists? updates-dir)
55 (push! updates-dir %load-path)
56 (push! updates-dir %load-compiled-path)))))
49 57
50 (define (run-guix-main) 58 (define (run-guix-main)
51 (let ((guix-main (module-ref (resolve-interface '(guix ui)) 59 (let ((guix-main (module-ref (resolve-interface '(guix ui))