mirror of
https://git.in.rschanz.org/ryan77627/guix.git
synced 2024-11-07 07:26:13 -05:00
Add 'guix time-machine'.
* guix/scripts/time-machine.scm: New file. * Makefile.am: (MODULES): Add it. * guix/scripts/pull.scm (channel-list): Export. * guix/inferior.scm (cached-channel-instance): New procedure. (inferior-for-channels): Use it. * doc/guix.texi (Invoking guix time-machine): New section. (Channels): Cross-reference it. Signed-off-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
parent
1edcfda81b
commit
f675f8dec7
5 changed files with 187 additions and 14 deletions
|
@ -278,6 +278,7 @@ MODULES = \
|
|||
guix/scripts/container.scm \
|
||||
guix/scripts/container/exec.scm \
|
||||
guix/scripts/deploy.scm \
|
||||
guix/scripts/time-machine.scm \
|
||||
guix.scm \
|
||||
$(GNU_SYSTEM_MODULES)
|
||||
|
||||
|
|
|
@ -198,6 +198,7 @@ Package Management
|
|||
* Invoking guix gc:: Running the garbage collector.
|
||||
* Invoking guix pull:: Fetching the latest Guix and distribution.
|
||||
* Channels:: Customizing the package collection.
|
||||
* Invoking guix time-machine:: Running an older revision of Guix.
|
||||
* Inferiors:: Interacting with another revision of Guix.
|
||||
* Invoking guix describe:: Display information about your Guix revision.
|
||||
* Invoking guix archive:: Exporting and importing store files.
|
||||
|
@ -2550,6 +2551,7 @@ guix install emacs-guix
|
|||
* Invoking guix gc:: Running the garbage collector.
|
||||
* Invoking guix pull:: Fetching the latest Guix and distribution.
|
||||
* Channels:: Customizing the package collection.
|
||||
* Invoking guix time-machine:: Running an older revision of Guix.
|
||||
* Inferiors:: Interacting with another revision of Guix.
|
||||
* Invoking guix describe:: Display information about your Guix revision.
|
||||
* Invoking guix archive:: Exporting and importing store files.
|
||||
|
@ -4152,7 +4154,10 @@ say, on another machine, by providing a channel specification in
|
|||
@end lisp
|
||||
|
||||
The @command{guix describe --format=channels} command can even generate this
|
||||
list of channels directly (@pxref{Invoking guix describe}).
|
||||
list of channels directly (@pxref{Invoking guix describe}). The resulting
|
||||
file can be used with the -C options of @command{guix pull}
|
||||
(@pxref{Invoking guix pull}) or @command{guix time-machine}
|
||||
(@pxref{Invoking guix time-machine}).
|
||||
|
||||
At this point the two machines run the @emph{exact same Guix}, with access to
|
||||
the @emph{exact same packages}. The output of @command{guix build gimp} on
|
||||
|
@ -4166,6 +4171,57 @@ artifacts with very fine grain, and to reproduce software environments at
|
|||
will---some sort of ``meta reproducibility'' capabilities, if you will.
|
||||
@xref{Inferiors}, for another way to take advantage of these super powers.
|
||||
|
||||
@node Invoking guix time-machine
|
||||
@section Invoking @command{guix time-machine}
|
||||
|
||||
@cindex @command{guix time-machine}
|
||||
@cindex pinning, channels
|
||||
@cindex replicating Guix
|
||||
@cindex reproducibility, of Guix
|
||||
|
||||
The @command{guix time-machine} command provides access to other
|
||||
revisions of Guix, for example to install older versions of packages,
|
||||
or to reproduce a computation in an identical environment. The revision
|
||||
of Guix to be used is defined by a commit or by a channel
|
||||
description file created by @command{guix describe}
|
||||
(@pxref{Invoking guix describe}).
|
||||
|
||||
The general syntax is:
|
||||
|
||||
@example
|
||||
guix time-machine @var{options}@dots{} -- @var{command} @var {arg}@dots{}
|
||||
@end example
|
||||
|
||||
where @var{command} and @var{arg}@dots{} are passed unmodified to the
|
||||
@command{guix} command if the specified revision. The @var{options} that define
|
||||
this revision are the same as for @command{guix pull} (@pxref{Invoking guix pull}):
|
||||
|
||||
@table @code
|
||||
@item --url=@var{url}
|
||||
@itemx --commit=@var{commit}
|
||||
@itemx --branch=@var{branch}
|
||||
Use the @code{guix} channel from the specified @var{url}, at the
|
||||
given @var{commit} (a valid Git commit ID represented as a hexadecimal
|
||||
string), or @var{branch}.
|
||||
|
||||
@item --channels=@var{file}
|
||||
@itemx -C @var{file}
|
||||
Read the list of channels from @var{file}. @var{file} must contain
|
||||
Scheme code that evaluates to a list of channel objects.
|
||||
@xref{Channels} for more information.
|
||||
@end table
|
||||
|
||||
As for @command{guix pull}, the absence of any options means that the
|
||||
the latest commit on the master branch will be used. The command
|
||||
|
||||
@example
|
||||
guix time-machine -- build hello
|
||||
@end example
|
||||
|
||||
will thus build the package @code{hello} as defined in the master branch,
|
||||
which is in general a newer revison of Guix than you have installed.
|
||||
Time travel works in both directions!
|
||||
|
||||
@node Inferiors
|
||||
@section Inferiors
|
||||
|
||||
|
@ -10589,7 +10645,6 @@ ClientPID: 19419
|
|||
ClientCommand: cuirass --cache-directory /var/cache/cuirass @dots{}
|
||||
@end example
|
||||
|
||||
|
||||
@node System Configuration
|
||||
@chapter System Configuration
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ (define-module (guix inferior)
|
|||
gexp->derivation-in-inferior
|
||||
|
||||
%inferior-cache-directory
|
||||
cached-channel-instance
|
||||
inferior-for-channels))
|
||||
|
||||
;;; Commentary:
|
||||
|
@ -635,16 +636,13 @@ (define %inferior-cache-directory
|
|||
(make-parameter (string-append (cache-directory #:ensure? #f)
|
||||
"/inferiors")))
|
||||
|
||||
(define* (inferior-for-channels channels
|
||||
#:key
|
||||
(cache-directory (%inferior-cache-directory))
|
||||
(ttl (* 3600 24 30)))
|
||||
"Return an inferior for CHANNELS, a list of channels. Use the cache at
|
||||
CACHE-DIRECTORY, where entries can be reclaimed after TTL seconds. This
|
||||
procedure opens a new connection to the build daemon.
|
||||
|
||||
This is a convenience procedure that people may use in manifests passed to
|
||||
'guix package -m', for instance."
|
||||
(define* (cached-channel-instance channels
|
||||
#:key
|
||||
(cache-directory (%inferior-cache-directory))
|
||||
(ttl (* 3600 24 30)))
|
||||
"Return a directory containing a guix filetree defined by CHANNELS, a list of channels.
|
||||
The directory is a subdirectory of CACHE-DIRECTORY, where entries can be reclaimed after TTL seconds.
|
||||
This procedure opens a new connection to the build daemon."
|
||||
(with-store store
|
||||
(let ()
|
||||
(define instances
|
||||
|
@ -680,7 +678,7 @@ (define add-indirect-root*
|
|||
(file-expiration-time ttl))
|
||||
|
||||
(if (file-exists? cached)
|
||||
(open-inferior cached)
|
||||
cached
|
||||
(run-with-store store
|
||||
(mlet %store-monad ((profile
|
||||
(channel-instances->derivation instances)))
|
||||
|
@ -689,4 +687,20 @@ (define add-indirect-root*
|
|||
(built-derivations (list profile))
|
||||
(symlink* (derivation->output-path profile) cached)
|
||||
(add-indirect-root* cached)
|
||||
(return (open-inferior cached)))))))))
|
||||
(return cached))))))))
|
||||
|
||||
(define* (inferior-for-channels channels
|
||||
#:key
|
||||
(cache-directory (%inferior-cache-directory))
|
||||
(ttl (* 3600 24 30)))
|
||||
"Return an inferior for CHANNELS, a list of channels. Use the cache at
|
||||
CACHE-DIRECTORY, where entries can be reclaimed after TTL seconds. This
|
||||
procedure opens a new connection to the build daemon.
|
||||
|
||||
This is a convenience procedure that people may use in manifests passed to
|
||||
'guix package -m', for instance."
|
||||
(define cached
|
||||
(cached-channel-instance channels
|
||||
#:cache-directory cache-directory
|
||||
#:ttl ttl))
|
||||
(open-inferior cached))
|
||||
|
|
|
@ -56,6 +56,7 @@ (define-module (guix scripts pull)
|
|||
#:use-module (ice-9 vlist)
|
||||
#:use-module (ice-9 format)
|
||||
#:export (display-profile-content
|
||||
channel-list
|
||||
guix-pull))
|
||||
|
||||
|
||||
|
|
102
guix/scripts/time-machine.scm
Normal file
102
guix/scripts/time-machine.scm
Normal file
|
@ -0,0 +1,102 @@
|
|||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2019 Konrad Hinsen <konrad.hinsen@fastmail.net>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
;;; GNU Guix is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (guix scripts time-machine)
|
||||
#:use-module (guix ui)
|
||||
#:use-module (guix scripts)
|
||||
#:use-module (guix inferior)
|
||||
#:use-module (guix channels)
|
||||
#:use-module ((guix scripts pull) #:select (channel-list))
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-11)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:use-module (srfi srfi-37)
|
||||
#:export (guix-time-machine))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Command-line options.
|
||||
;;;
|
||||
|
||||
(define (show-help)
|
||||
(display (G_ "Usage: guix time-machine [OPTION] -- COMMAND ARGS...
|
||||
Execute COMMAND ARGS... in an older version of Guix.\n"))
|
||||
(display (G_ "
|
||||
-C, --channels=FILE deploy the channels defined in FILE"))
|
||||
(display (G_ "
|
||||
--url=URL use the Git repository at URL"))
|
||||
(display (G_ "
|
||||
--commit=COMMIT use the specified COMMIT"))
|
||||
(display (G_ "
|
||||
--branch=BRANCH use the tip of the specified BRANCH"))
|
||||
(display (G_ "
|
||||
-h, --help display this help and exit"))
|
||||
(display (G_ "
|
||||
-V, --version display version information and exit"))
|
||||
(newline)
|
||||
(show-bug-report-information))
|
||||
|
||||
(define %options
|
||||
;; Specifications of the command-line options.
|
||||
(list (option '(#\C "channels") #t #f
|
||||
(lambda (opt name arg result)
|
||||
(alist-cons 'channel-file arg result)))
|
||||
(option '("url") #t #f
|
||||
(lambda (opt name arg result)
|
||||
(alist-cons 'repository-url arg
|
||||
(alist-delete 'repository-url result))))
|
||||
(option '("commit") #t #f
|
||||
(lambda (opt name arg result)
|
||||
(alist-cons 'ref `(commit . ,arg) result)))
|
||||
(option '("branch") #t #f
|
||||
(lambda (opt name arg result)
|
||||
(alist-cons 'ref `(branch . ,arg) result)))
|
||||
(option '(#\h "help") #f #f
|
||||
(lambda args
|
||||
(show-help)
|
||||
(exit 0)))
|
||||
(option '(#\V "version") #f #f
|
||||
(lambda args
|
||||
(show-version-and-exit "guix time-machine")))))
|
||||
|
||||
(define (parse-args args)
|
||||
"Parse the list of command line arguments ARGS."
|
||||
;; The '--' token is used to separate the command to run from the rest of
|
||||
;; the operands.
|
||||
(let-values (((args command) (break (cut string=? "--" <>) args)))
|
||||
(let ((opts (parse-command-line args %options '(()) #:build-options? #f)))
|
||||
(match command
|
||||
(() opts)
|
||||
(("--") opts)
|
||||
(("--" command ...) (alist-cons 'exec command opts))))))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Entry point.
|
||||
;;;
|
||||
|
||||
(define (guix-time-machine . args)
|
||||
(with-error-handling
|
||||
(let* ((opts (parse-args args))
|
||||
(channels (channel-list opts))
|
||||
(command-line (assoc-ref opts 'exec)))
|
||||
(when command-line
|
||||
(let* ((directory (cached-channel-instance channels))
|
||||
(executable (string-append directory "/bin/guix")))
|
||||
(apply execl (cons* executable executable command-line)))))))
|
Loading…
Reference in a new issue