Browse Source

pull: Install the new Guix in a profile.

* guix/scripts/pull.scm (%pull-version): New variable.
(build-from-source): Pass #:pull-version to BUILD.
(whole-package-for-legacy, derivation->manifest-entry): New procedure.
(build-and-install): Rewrite in terms of 'build-and-use-profile'.
* guix/scripts/system.scm (maybe-suggest-running-guix-pull)[latest]:
Switch to "/current".
* scripts/ (augment-load-paths!): Remove use of
* build-aux/compile-as-derivation.scm: Replace "/guix/latest/" with
* guix/scripts.scm (warn-about-old-distro)[age]: Check "/current"
instead of "/latest".
* doc/guix.texi (Invoking guix pull): Document it.
* doc/contributing.texi (Running Guix Before It Is Installed): Remove
footnote about abusing ~/.config/guix/latest.
Ludovic Courtès 2 years ago
No known key found for this signature in database GPG Key ID: 90B11993D9AEBB5
7 changed files with 94 additions and 56 deletions
  1. +2
  2. +2
  3. +33
  4. +2
  5. +53
  6. +1
  7. +1

+ 2
- 1
build-aux/compile-as-derivation.scm View File

@@ -25,7 +25,8 @@
(and=> (or (getenv "XDG_CONFIG_HOME")
(and=> (getenv "HOME")
(cut string-append <> "/.config")))
(cut string-append <> "/guix/latest")))
(cute string-append <> "/guix/current/share/guile/site/"

(use-modules (guix) (guix ui)
(guix git-download)

+ 2
- 8
doc/contributing.texi View File

@@ -155,15 +155,9 @@ The @command{pre-inst-env} script sets up all the environment variables
necessary to support this, including @env{PATH} and @env{GUILE_LOAD_PATH}.

Note that @command{./pre-inst-env guix pull} does @emph{not} upgrade the
local source tree; it simply updates the @file{~/.config/guix/latest}
local source tree; it simply updates the @file{~/.config/guix/current}
symlink (@pxref{Invoking guix pull}). Run @command{git pull} instead if
you want to upgrade your local source tree.@footnote{If you would like
to set up @command{guix} to use your Git checkout, you can point the
@file{~/.config/guix/latest} symlink to your Git checkout directory.
If you are the sole user of your system, you may also consider pointing
the @file{/root/.config/guix/latest} symlink to point to
@file{~/.config/guix/latest}; this way it will always use the same
@command{guix} as your user does.}
you want to upgrade your local source tree.

@node The Perfect Setup

+ 33
- 5
doc/guix.texi View File

@@ -2743,11 +2743,39 @@ Any user can update their Guix copy using @command{guix pull}, and the
effect is limited to the user who run @command{guix pull}. For
instance, when user @code{root} runs @command{guix pull}, this has no
effect on the version of Guix that user @code{alice} sees, and vice
versa@footnote{Under the hood, @command{guix pull} updates the
@file{~/.config/guix/latest} symbolic link to point to the latest Guix,
and the @command{guix} command loads code from there. Currently, the
only way to roll back an invocation of @command{guix pull} is to
manually update this symlink to point to the previous Guix.}.

The result of running @command{guix pull} is a @dfn{profile} available
under @file{~/.config/guix/current} containing the latest Guix. Thus,
make sure to add it to the beginning of your search path so that you use
the latest version, and similarly for the Info manual

export PATH="$HOME/.config/guix/current/bin:$PATH"
export INFOPATH="$HOME/.config/guix/current/share/info:$INFOPATH"
@end example

This @code{~/.config/guix/current} profile works like any other profile
created by @command{guix package} (@pxref{Invoking guix package}). That
is, you can list generations, roll back to the previous
generation---i.e., the previous Guix---and so on:

$ guix package -p ~/.config/guix/current -l
Generation 1 May 25 2018 10:06:41
guix 221951a out /gnu/store/i4dfk7vw5k112s49jrhl6hwsfnh6wr7l-guix-221951af4

Generation 2 May 27 2018 19:07:47
+ guix 2fbae00 out /gnu/store/44cv9hyvxg34xf5kblf5dz57hc52y4bm-guix-2fbae006f
- guix 221951a out /gnu/store/i4dfk7vw5k112s49jrhl6hwsfnh6wr7l-guix-221951af4

Generation 3 May 30 2018 16:11:39 (current)
+ guix a076f19 out /gnu/store/332czkicwwg6lc3x4aqbw5q2mq12s7fj-guix-a076f1990
- guix 2fbae00 out /gnu/store/44cv9hyvxg34xf5kblf5dz57hc52y4bm-guix-2fbae006f
$ guix package -p ~/.config/guix/current --roll-back
switched from generation 3 to 2
@end example

The @command{guix pull} command is usually invoked with no arguments,
but it supports the following options:

+ 2
- 2
guix/scripts.scm View File

@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015, 2017 Ludovic Courtès <>
;;; Copyright © 2013, 2014, 2015, 2017, 2018 Ludovic Courtès <>
;;; Copyright © 2014 Deck Pickard <>
;;; Copyright © 2015, 2016 Alex Kost <>
@@ -170,7 +170,7 @@ Show what and how will/would be built."
(define age
(match (false-if-not-found
(lstat (string-append (config-directory #:ensure? #f)
(#f #f)
(stat (- (time-second (current-time time-utc))
(stat:mtime stat)))))

+ 53
- 26
guix/scripts/pull.scm View File

@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015, 2017 Ludovic Courtès <>
;;; Copyright © 2013, 2014, 2015, 2017, 2018 Ludovic Courtès <>
;;; Copyright © 2017 Marius Bakke <>
;;; This file is part of GNU Guix.
@@ -25,10 +25,15 @@
#:use-module (guix config)
#:use-module (guix packages)
#:use-module (guix derivations)
#:use-module (guix profiles)
#:use-module (guix gexp)
#:use-module (guix grafts)
#:use-module (guix monads)
#:use-module (guix scripts build)
#:autoload (guix self) (whole-package)
#:autoload (gnu packages ssh) (guile-ssh)
#:autoload (gnu packages tls) (gnutls)
#:use-module ((guix scripts package) #:select (build-and-use-profile))
#:use-module ((guix build utils)
#:select (with-directory-excursion delete-file-recursively))
#:use-module ((guix build download)
@@ -158,6 +163,12 @@ Download and deploy the latest version of Guix.\n"))
;; a makefile, and, similarly, is intended to always keep this name.

(define %pull-version
;; This is the version of the 'guix pull' protocol. It specifies what's
;; expected from %SELF-BUILD-FILE. The initial version ("0") was when we'd
;; place a set of compiled Guile modules in ~/.config/guix/latest.

(define* (build-from-source source
#:key verbose? commit)
"Return a derivation to build Guix from SOURCE, using the self-build script
@@ -170,35 +181,51 @@ contained therein. Use COMMIT as the version string."
(build (primitive-load script)))
;; BUILD must be a monadic procedure of at least one argument: the source
;; tree.
(build source #:verbose? verbose? #:version commit)))
;; Note: BUILD can return #f if it does not support %PULL-VERSION. In the
;; future we'll fall back to a previous version of the protocol when that
;; happens.
(build source #:verbose? verbose? #:version commit
#:pull-version %pull-version)))

(define (whole-package-for-legacy name modules)
"Return a full-blown Guix package for MODULES, a derivation that builds Guix
modules in the old ~/.config/guix/latest style."
(whole-package name modules

;; In the "old style", %SELF-BUILD-FILE would simply return a
;; derivation that builds modules. We have to infer what the
;; dependencies of these modules were.
(list guile-json guile-git guile-bytestructures
guile-ssh gnutls)))

(define (derivation->manifest-entry drv commit)
"Return a manifest entry for DRV, which represents Guix at COMMIT."
(mbegin %store-monad
(what-to-build (list drv))
(built-derivations (list drv))
(let ((out (derivation->output-path drv)))
(return (manifest-entry
(name "guix")
(version (string-take commit 7))
(item (if (file-exists? (string-append out "/bin/guix"))
(whole-package-for-legacy (string-append name "-"

(define* (build-and-install source config-dir
#:key verbose? commit)
"Build the tool from SOURCE, and install it in CONFIG-DIR."
(mlet* %store-monad ((source (build-from-source source
#:commit commit
#:verbose? verbose?))
(source-dir -> (derivation->output-path source))
(to-do? (what-to-build (list source)))
(built? (built-derivations (list source))))
;; Always update the 'latest' symlink, regardless of whether SOURCE was
;; already built or not.
(if built?
(mlet* %store-monad
((latest -> (string-append config-dir "/latest"))
(done (indirect-root-added latest)))
(if (and (file-exists? latest)
(string=? (readlink latest) source-dir))
(display (G_ "Guix already up to date\n"))
(return #t))
(switch-symlinks latest source-dir)
(format #t
(G_ "updated ~a successfully deployed under `~a'~%")
%guix-package-name latest)
(return #t))))
(leave (G_ "failed to update Guix, check the build log~%")))))
(define update-profile
(store-lift build-and-use-profile))

(mlet* %store-monad ((drv (build-from-source source
#:commit commit
#:verbose? verbose?))
(entry (derivation->manifest-entry drv commit)))
(update-profile (string-append config-dir "/current")
(manifest (list entry)))))

(define (honor-lets-encrypt-certificates! store)
"Tell Guile-Git to use the Let's Encrypt certificates."

+ 1
- 1
guix/scripts/system.scm View File

@@ -740,7 +740,7 @@ checking this by themselves in their 'check' procedure."
;; <> for
;; a discussion.
(define latest
(string-append (config-directory) "/latest"))
(string-append (config-directory) "/current"))

(unless (file-exists? latest)
(warning (G_ "~a not found: 'guix pull' was never run~%") latest)

+ 1
- 13
scripts/ View File

@@ -23,25 +23,13 @@
;; IMPORTANT: We must avoid loading any modules from Guix here,
;; because we need to adjust the guile load paths first.
;; It's okay to import modules from core Guile though.
(use-modules (srfi srfi-26))

(define-syntax-rule (push! elt v) (set! v (cons elt v)))

(define (augment-load-paths!)
;; Add installed modules to load-path.
(push! "@guilemoduledir@" %load-path)
(push! "@guileobjectdir@" %load-compiled-path)

;; Add modules fetched by 'guix pull' to load-path.
(let ((updates-dir (and=> (or (getenv "XDG_CONFIG_HOME")
(and=> (getenv "HOME")
(cut string-append <> "/.config")))
(cut string-append <> "/guix/latest"))))
(when (and=> updates-dir file-exists?)
;; XXX: Currently 'guix pull' puts both .scm and .go files in
(push! updates-dir %load-path)
(push! updates-dir %load-compiled-path))))
(push! "@guileobjectdir@" %load-compiled-path))

(define* (main #:optional (args (command-line)))
(unless (getenv "GUIX_UNINSTALLED")