diff options
| -rw-r--r-- | Makefile.am | 1 | ||||
| -rw-r--r-- | doc/guix.texi | 33 | ||||
| -rw-r--r-- | guix/scripts/pull.scm | 222 | ||||
| -rw-r--r-- | guix/ui.scm | 21 | ||||
| -rw-r--r-- | po/POTFILES.in | 1 | ||||
| -rw-r--r-- | scripts/guix.in | 12 |
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} |
| 522 | Upgrade all the installed packages matching @var{regexp}. | 523 | Upgrade all the installed packages matching @var{regexp}. |
| 523 | 524 | ||
| 525 | Note that this upgrades package to the latest version of packages found | ||
| 526 | in the distribution currently installed. To update your distribution, | ||
| 527 | you should regularly run @command{guix pull} (@pxref{Invoking guix | ||
| 528 | pull}). | ||
| 529 | |||
| 524 | @item --roll-back | 530 | @item --roll-back |
| 525 | Roll back to the previous @dfn{generation} of the profile---i.e., undo | 531 | Roll back to the previous @dfn{generation} of the profile---i.e., undo |
| 526 | the last transaction. | 532 | the 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 | |||
| 666 | Packages are installed or upgraded to the latest version available in | ||
| 667 | the distribution currently available on your local machine. To update | ||
| 668 | that distribution, along with the Guix tools, you must run @command{guix | ||
| 669 | pull}: the command downloads the latest Guix source code and package | ||
| 670 | descriptions, and deploys it. | ||
| 671 | |||
| 672 | On completion, @command{guix package} will use packages and package | ||
| 673 | versions from this just-retrieved copy of Guix. Not only that, but all | ||
| 674 | the Guix commands and Scheme modules will also be taken from that latest | ||
| 675 | version. New @command{guix} sub-commands added by the update also | ||
| 676 | become available. | ||
| 677 | |||
| 678 | The @command{guix pull} command is usually invoked with no arguments, | ||
| 679 | but it supports the following options: | ||
| 680 | |||
| 681 | @table @code | ||
| 682 | @item --verbose | ||
| 683 | Produce verbose output, writing build logs to the standard error output. | ||
| 684 | |||
| 685 | @item --bootstrap | ||
| 686 | Use the bootstrap Guile to build the latest Guix. This option is only | ||
| 687 | useful 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 | ||
| 43 | path." | ||
| 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 | ||
| 57 | files." | ||
| 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]... | ||
| 152 | Download 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 | ||
| 184 | exists. 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 |
| 183 | that the first character is at COLUMN. | 204 | that 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 | |||
| 8 | guix/scripts/download.scm | 8 | guix/scripts/download.scm |
| 9 | guix/scripts/package.scm | 9 | guix/scripts/package.scm |
| 10 | guix/scripts/gc.scm | 10 | guix/scripts/gc.scm |
| 11 | guix/scripts/pull.scm | ||
| 11 | guix/ui.scm | 12 | guix/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)) |
