Add 'guix describe'.
* guix/scripts/describe.scm: New file. * Makefile.am (MODULES): Add it. (SH_TESTS): Add tests/guix-describe.sh. * po/guix/POTFILES.in: Add it. * guix/scripts/pull.scm (display-profile-content): Export. * guix/describe.scm (current-profile, current-profile-entries): Export. * tests/guix-describe.sh: New file. * doc/guix.texi (Features): Mention 'guix pull' and provenance tracking. (Invoking guix pull): Link to 'guix describe'. (Channels): Likewise. (Invoking guix describe): New node.master
parent
ee94cfeb99
commit
bd7470185b
|
@ -204,6 +204,7 @@ MODULES = \
|
||||||
guix/scripts/authenticate.scm \
|
guix/scripts/authenticate.scm \
|
||||||
guix/scripts/refresh.scm \
|
guix/scripts/refresh.scm \
|
||||||
guix/scripts/repl.scm \
|
guix/scripts/repl.scm \
|
||||||
|
guix/scripts/describe.scm \
|
||||||
guix/scripts/system.scm \
|
guix/scripts/system.scm \
|
||||||
guix/scripts/system/search.scm \
|
guix/scripts/system/search.scm \
|
||||||
guix/scripts/lint.scm \
|
guix/scripts/lint.scm \
|
||||||
|
@ -409,6 +410,7 @@ SH_TESTS = \
|
||||||
tests/guix-environment.sh \
|
tests/guix-environment.sh \
|
||||||
tests/guix-environment-container.sh \
|
tests/guix-environment-container.sh \
|
||||||
tests/guix-graph.sh \
|
tests/guix-graph.sh \
|
||||||
|
tests/guix-describe.sh \
|
||||||
tests/guix-lint.sh
|
tests/guix-lint.sh
|
||||||
|
|
||||||
TESTS = $(SCM_TESTS) $(SH_TESTS)
|
TESTS = $(SCM_TESTS) $(SH_TESTS)
|
||||||
|
|
|
@ -147,6 +147,7 @@ Package Management
|
||||||
* Invoking guix gc:: Running the garbage collector.
|
* Invoking guix gc:: Running the garbage collector.
|
||||||
* Invoking guix pull:: Fetching the latest Guix and distribution.
|
* Invoking guix pull:: Fetching the latest Guix and distribution.
|
||||||
* Channels:: Customizing the package collection.
|
* Channels:: Customizing the package collection.
|
||||||
|
* Invoking guix describe:: Display information about your Guix revision.
|
||||||
* Invoking guix pack:: Creating software bundles.
|
* Invoking guix pack:: Creating software bundles.
|
||||||
* Invoking guix archive:: Exporting and importing store files.
|
* Invoking guix archive:: Exporting and importing store files.
|
||||||
|
|
||||||
|
@ -1698,6 +1699,7 @@ guix package -i emacs-guix
|
||||||
* Invoking guix gc:: Running the garbage collector.
|
* Invoking guix gc:: Running the garbage collector.
|
||||||
* Invoking guix pull:: Fetching the latest Guix and distribution.
|
* Invoking guix pull:: Fetching the latest Guix and distribution.
|
||||||
* Channels:: Customizing the package collection.
|
* Channels:: Customizing the package collection.
|
||||||
|
* Invoking guix describe:: Display information about your Guix revision.
|
||||||
* Invoking guix pack:: Creating software bundles.
|
* Invoking guix pack:: Creating software bundles.
|
||||||
* Invoking guix archive:: Exporting and importing store files.
|
* Invoking guix archive:: Exporting and importing store files.
|
||||||
@end menu
|
@end menu
|
||||||
|
@ -1751,7 +1753,7 @@ collected.
|
||||||
|
|
||||||
@cindex reproducibility
|
@cindex reproducibility
|
||||||
@cindex reproducible builds
|
@cindex reproducible builds
|
||||||
Finally, Guix takes a @dfn{purely functional} approach to package
|
Guix takes a @dfn{purely functional} approach to package
|
||||||
management, as described in the introduction (@pxref{Introduction}).
|
management, as described in the introduction (@pxref{Introduction}).
|
||||||
Each @file{/gnu/store} package directory name contains a hash of all the
|
Each @file{/gnu/store} package directory name contains a hash of all the
|
||||||
inputs that were used to build that package---compiler, libraries, build
|
inputs that were used to build that package---compiler, libraries, build
|
||||||
|
@ -1779,6 +1781,15 @@ a package to quickly set up the right development environment for their
|
||||||
package, without having to manually install the dependencies of the
|
package, without having to manually install the dependencies of the
|
||||||
package into their profile (@pxref{Invoking guix environment}).
|
package into their profile (@pxref{Invoking guix environment}).
|
||||||
|
|
||||||
|
@cindex replication, of software environments
|
||||||
|
@cindex provenance tracking, of software artifacts
|
||||||
|
All of Guix and its package definitions is version-controlled, and
|
||||||
|
@command{guix pull} allows you to ``travel in time'' on the history of Guix
|
||||||
|
itself (@pxref{Invoking guix pull}). This makes it possible to replicate a
|
||||||
|
Guix instance on a different machine or at a later point in time, which in
|
||||||
|
turn allows you to @emph{replicate complete software environments}, while
|
||||||
|
retaining precise @dfn{provenance tracking} of the software.
|
||||||
|
|
||||||
@node Invoking guix package
|
@node Invoking guix package
|
||||||
@section Invoking @command{guix package}
|
@section Invoking @command{guix package}
|
||||||
|
|
||||||
|
@ -2806,6 +2817,9 @@ Generation 3 Jun 13 2018 23:31:07 (current)
|
||||||
69 packages upgraded: borg@@1.1.6, cheese@@3.28.0, @dots{}
|
69 packages upgraded: borg@@1.1.6, cheese@@3.28.0, @dots{}
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
@ref{Invoking guix describe, @command{guix describe}}, for other ways to
|
||||||
|
describe the current status of Guix.
|
||||||
|
|
||||||
This @code{~/.config/guix/current} profile works like any other profile
|
This @code{~/.config/guix/current} profile works like any other profile
|
||||||
created by @command{guix package} (@pxref{Invoking guix package}). That
|
created by @command{guix package} (@pxref{Invoking guix package}). That
|
||||||
is, you can list generations, roll back to the previous
|
is, you can list generations, roll back to the previous
|
||||||
|
@ -2851,6 +2865,9 @@ is provided, the subset of generations that match @var{pattern}.
|
||||||
The syntax of @var{pattern} is the same as with @code{guix package
|
The syntax of @var{pattern} is the same as with @code{guix package
|
||||||
--list-generations} (@pxref{Invoking guix package}).
|
--list-generations} (@pxref{Invoking guix package}).
|
||||||
|
|
||||||
|
@ref{Invoking guix describe}, for a way to display information about the
|
||||||
|
current generation only.
|
||||||
|
|
||||||
@item --profile=@var{profile}
|
@item --profile=@var{profile}
|
||||||
@itemx -p @var{profile}
|
@itemx -p @var{profile}
|
||||||
Use @var{profile} instead of @file{~/.config/guix/current}.
|
Use @var{profile} instead of @file{~/.config/guix/current}.
|
||||||
|
@ -3023,6 +3040,9 @@ say, on another machine, by providing a channel specification in
|
||||||
(branch "dd3df5e2c8818760a8fc0bd699e55d3b69fef2bb")))
|
(branch "dd3df5e2c8818760a8fc0bd699e55d3b69fef2bb")))
|
||||||
@end lisp
|
@end lisp
|
||||||
|
|
||||||
|
The @command{guix describe --format=channels} command can even generate this
|
||||||
|
list of channels directly (@pxref{Invoking guix describe}).
|
||||||
|
|
||||||
At this point the two machines run the @emph{exact same Guix}, with access to
|
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
|
the @emph{exact same packages}. The output of @command{guix build gimp} on
|
||||||
one machine will be exactly the same, bit for bit, as the output of the same
|
one machine will be exactly the same, bit for bit, as the output of the same
|
||||||
|
@ -3034,6 +3054,78 @@ This gives you super powers, allowing you to track the provenance of binary
|
||||||
artifacts with very fine grain, and to reproduce software environments at
|
artifacts with very fine grain, and to reproduce software environments at
|
||||||
will---some sort of ``meta reproducibility'' capabilities, if you will.
|
will---some sort of ``meta reproducibility'' capabilities, if you will.
|
||||||
|
|
||||||
|
@node Invoking guix describe
|
||||||
|
@section Invoking @command{guix describe}
|
||||||
|
|
||||||
|
@cindex reproducibility
|
||||||
|
@cindex replicating Guix
|
||||||
|
Often you may want to answer questions like: ``Which revision of Guix am I
|
||||||
|
using?'' or ``Which channels am I using?'' This is useful information in many
|
||||||
|
situations: if you want to @emph{replicate} an environment on a different
|
||||||
|
machine or user account, if you want to report a bug or to determine what
|
||||||
|
change in the channels you are using caused it, or if you want to record your
|
||||||
|
system state for reproducibility purposes. The @command{guix describe}
|
||||||
|
command answers these questions.
|
||||||
|
|
||||||
|
When run from a @command{guix pull}ed @command{guix}, @command{guix describe}
|
||||||
|
displays the channel(s) that it was built from, including their repository URL
|
||||||
|
and commit IDs (@pxref{Channels}):
|
||||||
|
|
||||||
|
@example
|
||||||
|
$ guix describe
|
||||||
|
Generation 10 Sep 03 2018 17:32:44 (current)
|
||||||
|
guix e0fa68c
|
||||||
|
repository URL: https://git.savannah.gnu.org/git/guix.git
|
||||||
|
branch: master
|
||||||
|
commit: e0fa68c7718fffd33d81af415279d6ddb518f727
|
||||||
|
@end example
|
||||||
|
|
||||||
|
If you're familiar with the Git version control system, this is similar in
|
||||||
|
spirit to @command{git describe}; the output is also similar to that of
|
||||||
|
@command{guix pull --list-generations}, but limited to the current generation
|
||||||
|
(@pxref{Invoking guix pull, the @option{--list-generations} option}). Because
|
||||||
|
the Git commit ID shown above unambiguously refers to a snapshot of Guix, this
|
||||||
|
information is all it takes to describe the revision of Guix you're using, and
|
||||||
|
also to replicate it.
|
||||||
|
|
||||||
|
To make it easier to replicate Guix, @command{guix describe} can also be asked
|
||||||
|
to return a list of channels instead of the human-readable description above:
|
||||||
|
|
||||||
|
@example
|
||||||
|
$ guix describe -f channels
|
||||||
|
(list (channel
|
||||||
|
(name 'guix)
|
||||||
|
(url "https://git.savannah.gnu.org/git/guix.git")
|
||||||
|
(commit
|
||||||
|
"e0fa68c7718fffd33d81af415279d6ddb518f727")))
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
You can save this to a file and feed it to @command{guix pull -C} on some
|
||||||
|
other machine or at a later point in time, which will instantiate @emph{this
|
||||||
|
exact Guix revision} (@pxref{Invoking guix pull, the @option{-C} option}).
|
||||||
|
From there on, since you're able to deploy the same revision of Guix, you can
|
||||||
|
just as well @emph{replicate a complete software environment}. We humbly
|
||||||
|
think that this is @emph{awesome}, and we hope you'll like it too!
|
||||||
|
|
||||||
|
The details of the options supported by @command{guix describe} are as
|
||||||
|
follows:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item --format=@var{format}
|
||||||
|
@itemx -f @var{format}
|
||||||
|
Produce output in the specified @var{format}, one of:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item human
|
||||||
|
produce human-readable output;
|
||||||
|
@item channels
|
||||||
|
produce a list of channel specifications that can be passed to @command{guix
|
||||||
|
pull -C} or installed as @file{~/.config/guix/channels.scm} (@pxref{Invoking
|
||||||
|
guix pull}).
|
||||||
|
@end table
|
||||||
|
@end table
|
||||||
|
|
||||||
@node Invoking guix pack
|
@node Invoking guix pack
|
||||||
@section Invoking @command{guix pack}
|
@section Invoking @command{guix pack}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,9 @@
|
||||||
#:use-module (guix profiles)
|
#:use-module (guix profiles)
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:export (package-path-entries))
|
#:export (current-profile
|
||||||
|
current-profile-entries
|
||||||
|
package-path-entries))
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
;;;
|
;;;
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
;;; GNU Guix --- Functional package management for GNU
|
||||||
|
;;; Copyright © 2018 Ludovic Courtès <ludo@gnu.org>
|
||||||
|
;;;
|
||||||
|
;;; 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 describe)
|
||||||
|
#:use-module ((guix ui) #:hide (display-profile-content))
|
||||||
|
#:use-module (guix scripts)
|
||||||
|
#:use-module (guix describe)
|
||||||
|
#:use-module (guix profiles)
|
||||||
|
#:use-module ((guix scripts pull) #:select (display-profile-content))
|
||||||
|
#:use-module (git)
|
||||||
|
#:use-module (srfi srfi-1)
|
||||||
|
#:use-module (srfi srfi-37)
|
||||||
|
#:use-module (ice-9 match)
|
||||||
|
#:autoload (ice-9 pretty-print) (pretty-print)
|
||||||
|
#:export (guix-describe))
|
||||||
|
|
||||||
|
|
||||||
|
;;;
|
||||||
|
;;; Command-line options.
|
||||||
|
;;;
|
||||||
|
|
||||||
|
(define %options
|
||||||
|
;; Specifications of the command-line options.
|
||||||
|
(list (option '(#\f "format") #t #f
|
||||||
|
(lambda (opt name arg result)
|
||||||
|
(unless (member arg '("human" "channels"))
|
||||||
|
(leave (G_ "~a: unsupported output format~%") arg))
|
||||||
|
(alist-cons 'format 'channels result)))
|
||||||
|
(option '(#\h "help") #f #f
|
||||||
|
(lambda args
|
||||||
|
(show-help)
|
||||||
|
(exit 0)))
|
||||||
|
(option '(#\V "version") #f #f
|
||||||
|
(lambda args
|
||||||
|
(show-version-and-exit "guix describe")))))
|
||||||
|
|
||||||
|
(define %default-options
|
||||||
|
;; Alist of default option values.
|
||||||
|
'((format . human)))
|
||||||
|
|
||||||
|
(define (show-help)
|
||||||
|
(display (G_ "Usage: guix describe [OPTION]...
|
||||||
|
Display information about the channels currently in use.\n"))
|
||||||
|
(display (G_ "
|
||||||
|
-f, --format=FORMAT display information in the given FORMAT"))
|
||||||
|
(newline)
|
||||||
|
(display (G_ "
|
||||||
|
-h, --help display this help and exit"))
|
||||||
|
(display (G_ "
|
||||||
|
-V, --version display version information and exit"))
|
||||||
|
(newline)
|
||||||
|
(show-bug-report-information))
|
||||||
|
|
||||||
|
(define (display-package-search-path fmt)
|
||||||
|
"Display GUIX_PACKAGE_PATH, if it is set, according to FMT."
|
||||||
|
(match (getenv "GUIX_PACKAGE_PATH")
|
||||||
|
(#f #t)
|
||||||
|
(string
|
||||||
|
(match fmt
|
||||||
|
('human
|
||||||
|
(format #t "~%GUIX_PACKAGE_PATH=\"~a\"~%" string))
|
||||||
|
('channels
|
||||||
|
(format #t (G_ "~%;; warning: GUIX_PACKAGE_PATH=\"~a\"~%")
|
||||||
|
string))))))
|
||||||
|
|
||||||
|
(define (display-checkout-info fmt)
|
||||||
|
"Display information about the current checkout according to FMT, a symbol
|
||||||
|
denoting the requested format. Exit if the current directory does not lie
|
||||||
|
within a Git checkout."
|
||||||
|
(let* ((program (car (command-line)))
|
||||||
|
(directory (catch 'git-error
|
||||||
|
(lambda ()
|
||||||
|
(repository-discover (dirname program)))
|
||||||
|
(lambda (key err)
|
||||||
|
(leave (G_ "failed to determine origin~%")))))
|
||||||
|
(repository (repository-open directory))
|
||||||
|
(head (repository-head repository))
|
||||||
|
(commit (oid->string (reference-target head))))
|
||||||
|
(match fmt
|
||||||
|
('human
|
||||||
|
(format #t (G_ "Git checkout:~%"))
|
||||||
|
(format #t (G_ " repository: ~a~%") (dirname directory))
|
||||||
|
(format #t (G_ " branch: ~a~%") (reference-shorthand head))
|
||||||
|
(format #t (G_ " commit: ~a~%") commit))
|
||||||
|
('channels
|
||||||
|
(pretty-print `(list (channel
|
||||||
|
(name 'guix)
|
||||||
|
(url ,(dirname directory))
|
||||||
|
(commit ,commit))))))
|
||||||
|
(display-package-search-path fmt)))
|
||||||
|
|
||||||
|
(define (display-profile-info profile fmt)
|
||||||
|
"Display information about PROFILE, a profile as created by (guix channels),
|
||||||
|
in the format specified by FMT."
|
||||||
|
(define number
|
||||||
|
(match (profile-generations profile)
|
||||||
|
((_ ... last) last)))
|
||||||
|
|
||||||
|
(match fmt
|
||||||
|
('human
|
||||||
|
(display-profile-content profile number))
|
||||||
|
('channels
|
||||||
|
(pretty-print
|
||||||
|
`(list ,@(map (lambda (entry)
|
||||||
|
(match (assq 'source (manifest-entry-properties entry))
|
||||||
|
(('source ('repository ('version 0)
|
||||||
|
('url url)
|
||||||
|
('branch branch)
|
||||||
|
('commit commit)
|
||||||
|
_ ...))
|
||||||
|
`(channel (name ',(string->symbol
|
||||||
|
(manifest-entry-name entry)))
|
||||||
|
(url ,url)
|
||||||
|
(commit ,commit)))
|
||||||
|
|
||||||
|
;; Pre-0.15.0 Guix does not provide that information,
|
||||||
|
;; so there's not much we can do in that case.
|
||||||
|
(_ '???)))
|
||||||
|
|
||||||
|
;; Show most recently installed packages last.
|
||||||
|
(reverse
|
||||||
|
(manifest-entries
|
||||||
|
(profile-manifest (generation-file-name profile
|
||||||
|
number)))))))))
|
||||||
|
(display-package-search-path fmt))
|
||||||
|
|
||||||
|
|
||||||
|
;;;
|
||||||
|
;;; Entry point.
|
||||||
|
;;;
|
||||||
|
|
||||||
|
(define (guix-describe . args)
|
||||||
|
(let* ((opts (args-fold* args %options
|
||||||
|
(lambda (opt name arg result)
|
||||||
|
(leave (G_ "~A: unrecognized option~%")
|
||||||
|
name))
|
||||||
|
cons
|
||||||
|
%default-options))
|
||||||
|
(format (assq-ref opts 'format)))
|
||||||
|
(with-error-handling
|
||||||
|
(match (current-profile)
|
||||||
|
(#f
|
||||||
|
(display-checkout-info format))
|
||||||
|
(profile
|
||||||
|
(display-profile-info profile format))))))
|
|
@ -48,7 +48,8 @@
|
||||||
#:use-module (srfi srfi-37)
|
#:use-module (srfi srfi-37)
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:use-module (ice-9 vlist)
|
#:use-module (ice-9 vlist)
|
||||||
#:export (guix-pull))
|
#:export (display-profile-content
|
||||||
|
guix-pull))
|
||||||
|
|
||||||
|
|
||||||
;;;
|
;;;
|
||||||
|
|
|
@ -31,6 +31,7 @@ guix/scripts/challenge.scm
|
||||||
guix/scripts/copy.scm
|
guix/scripts/copy.scm
|
||||||
guix/scripts/pack.scm
|
guix/scripts/pack.scm
|
||||||
guix/scripts/weather.scm
|
guix/scripts/weather.scm
|
||||||
|
guix/scripts/describe.scm
|
||||||
guix/gnu-maintenance.scm
|
guix/gnu-maintenance.scm
|
||||||
guix/scripts/container.scm
|
guix/scripts/container.scm
|
||||||
guix/scripts/container/exec.scm
|
guix/scripts/container/exec.scm
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
# GNU Guix --- Functional package management for GNU
|
||||||
|
# Copyright © 2018 Ludovic Courtès <ludo@gnu.org>
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test 'guix describe'.
|
||||||
|
#
|
||||||
|
|
||||||
|
guix describe --version
|
||||||
|
|
||||||
|
tmpfile="t-guix-describe-$$"
|
||||||
|
trap "rm -f $tmpfile" EXIT
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
|
||||||
|
if [ -d "$abs_top_srcdir/.git" ]
|
||||||
|
then
|
||||||
|
# Since we're in a Git checkout, we can at least check that these things
|
||||||
|
# work.
|
||||||
|
guix describe | grep -i "checkout"
|
||||||
|
if git --version > /dev/null 2>&1
|
||||||
|
then
|
||||||
|
result="`guix describe | grep commit: | cut -d : -f 2-`"
|
||||||
|
commit="`git log | head -1 | cut -c 7-`"
|
||||||
|
test "x$result" = "x$commit"
|
||||||
|
fi
|
||||||
|
guix describe -f channels
|
||||||
|
case "`guix describe -f channels | grep url`" in
|
||||||
|
*"(url \"$abs_top_srcdir\")") true;;
|
||||||
|
*) false;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
exit 77
|
||||||
|
fi
|
Reference in New Issue