summaryrefslogtreecommitdiff
path: root/guix/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'guix/scripts')
-rw-r--r--guix/scripts/archive.scm5
-rw-r--r--guix/scripts/authenticate.scm224
-rw-r--r--guix/scripts/build.scm5
-rw-r--r--guix/scripts/challenge.scm5
-rw-r--r--guix/scripts/container.scm6
-rw-r--r--guix/scripts/copy.scm13
-rw-r--r--guix/scripts/deploy.scm3
-rw-r--r--guix/scripts/describe.scm3
-rw-r--r--guix/scripts/download.scm5
-rw-r--r--guix/scripts/edit.scm7
-rw-r--r--guix/scripts/environment.scm10
-rw-r--r--guix/scripts/gc.scm4
-rw-r--r--guix/scripts/git.scm6
-rw-r--r--guix/scripts/graph.scm5
-rw-r--r--guix/scripts/hash.scm5
-rw-r--r--guix/scripts/import.scm8
-rw-r--r--guix/scripts/install.scm6
-rw-r--r--guix/scripts/lint.scm5
-rw-r--r--guix/scripts/offload.scm8
-rw-r--r--guix/scripts/pack.scm5
-rw-r--r--guix/scripts/package.scm4
-rw-r--r--guix/scripts/perform-download.scm18
-rw-r--r--guix/scripts/processes.scm4
-rw-r--r--guix/scripts/publish.scm5
-rw-r--r--guix/scripts/pull.scm5
-rw-r--r--guix/scripts/refresh.scm7
-rw-r--r--guix/scripts/remove.scm6
-rw-r--r--guix/scripts/repl.scm5
-rw-r--r--guix/scripts/search.scm6
-rw-r--r--guix/scripts/show.scm4
-rw-r--r--guix/scripts/size.scm7
-rwxr-xr-xguix/scripts/substitute.scm14
-rw-r--r--guix/scripts/system.scm80
-rw-r--r--guix/scripts/time-machine.scm4
-rw-r--r--guix/scripts/upgrade.scm6
-rw-r--r--guix/scripts/weather.scm4
36 files changed, 368 insertions, 149 deletions
diff --git a/guix/scripts/archive.scm b/guix/scripts/archive.scm
index f3b86fba14..02557ce454 100644
--- a/guix/scripts/archive.scm
+++ b/guix/scripts/archive.scm
@@ -355,7 +355,10 @@ output port."
;;; Entry point.
;;;
-(define (guix-archive . args)
+(define-command (guix-archive . args)
+ (category plumbing)
+ (synopsis "manipulate, export, and import normalized archives (nars)")
+
(define (lines port)
;; Return lines read from PORT.
(let loop ((line (read-line port))
diff --git a/guix/scripts/authenticate.scm b/guix/scripts/authenticate.scm
index f1fd8ee895..0bac13edee 100644
--- a/guix/scripts/authenticate.scm
+++ b/guix/scripts/authenticate.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2020 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -17,14 +17,20 @@
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (guix scripts authenticate)
- #:use-module (guix config)
+ #:use-module (guix scripts)
#:use-module (guix base16)
#:use-module (gcrypt pk-crypto)
#:use-module (guix pki)
#:use-module (guix ui)
+ #:use-module (guix diagnostics)
+ #:use-module (srfi srfi-34)
+ #:use-module (srfi srfi-35)
+ #:use-module (srfi srfi-71)
+ #:use-module (rnrs bytevectors)
#:use-module (ice-9 binary-ports)
#:use-module (ice-9 rdelim)
#:use-module (ice-9 match)
+ #:use-module (ice-9 vlist)
#:export (guix-authenticate))
;;; Commentary:
@@ -39,58 +45,129 @@
;; Read a gcrypt sexp from a port and return it.
(compose string->canonical-sexp read-string))
-(define (read-hash-data port key-type)
- "Read sha256 hash data from PORT and return it as a gcrypt sexp. KEY-TYPE
-is a symbol representing the type of public key algo being used."
- (let* ((hex (read-string port))
- (bv (base16-string->bytevector (string-trim-both hex))))
- (bytevector->hash-data bv #:key-type key-type)))
-
-(define (sign-with-key key-file port)
- "Sign the hash read from PORT with KEY-FILE, and write an sexp that includes
-both the hash and the actual signature."
- (let* ((secret-key (call-with-input-file key-file read-canonical-sexp))
- (public-key (if (string-suffix? ".sec" key-file)
- (call-with-input-file
+(define (load-key-pair key-file)
+ "Load the key pair whose secret key lives at KEY-FILE. Return a pair of
+canonical sexps representing those keys."
+ (catch 'system-error
+ (lambda ()
+ (let* ((secret-key (call-with-input-file key-file read-canonical-sexp))
+ (public-key (call-with-input-file
(string-append (string-drop-right key-file 4)
".pub")
- read-canonical-sexp)
- (leave
- (G_ "cannot find public key for secret key '~a'~%")
- key-file)))
- (data (read-hash-data port (key-type public-key)))
- (signature (signature-sexp data secret-key public-key)))
- (display (canonical-sexp->string signature))
- #t))
-
-(define (validate-signature port)
- "Read the signature from PORT (which is as produced above), check whether
-its public key is authorized, verify the signature, and print the signed data
-to stdout upon success."
- (let* ((signature (read-canonical-sexp port))
- (subject (signature-subject signature))
- (data (signature-signed-data signature)))
+ read-canonical-sexp)))
+ (cons public-key secret-key)))
+ (lambda args
+ (let ((errno (system-error-errno args)))
+ (raise
+ (formatted-message
+ (G_ "failed to load key pair at '~a': ~a~%")
+ key-file (strerror errno)))))))
+
+(define (sign-with-key public-key secret-key sha256)
+ "Sign the hash SHA256 (a bytevector) with SECRET-KEY (a canonical sexp), and
+return the signature as a canonical sexp that includes SHA256, PUBLIC-KEY, and
+the actual signature."
+ (let ((data (bytevector->hash-data sha256
+ #:key-type (key-type public-key))))
+ (signature-sexp data secret-key public-key)))
+
+(define (validate-signature signature acl)
+ "Validate SIGNATURE, a canonical sexp. Check whether its public key is
+authorized in ACL, verify the signature, and return the signed data (a
+bytevector) upon success."
+ (let* ((subject (signature-subject signature))
+ (data (signature-signed-data signature)))
(if (and data subject)
- (if (authorized-key? subject)
+ (if (authorized-key? subject acl)
(if (valid-signature? signature)
- (let ((hash (hash-data->bytevector data)))
- (display (bytevector->base16-string hash))
- #t) ; success
- (leave (G_ "error: invalid signature: ~a~%")
- (canonical-sexp->string signature)))
- (leave (G_ "error: unauthorized public key: ~a~%")
- (canonical-sexp->string subject)))
- (leave (G_ "error: corrupt signature data: ~a~%")
- (canonical-sexp->string signature)))))
+ (hash-data->bytevector data) ; success
+ (raise
+ (formatted-message (G_ "invalid signature: ~a")
+ (canonical-sexp->string signature))))
+ (raise
+ (formatted-message (G_ "unauthorized public key: ~a")
+ (canonical-sexp->string subject))))
+ (raise
+ (formatted-message (G_ "corrupt signature data: ~a")
+ (canonical-sexp->string signature))))))
+
+(define (read-command port)
+ "Read a command from PORT and return the command and arguments as a list of
+strings. Return the empty list when the end-of-file is reached.
+
+Commands are newline-terminated and must look something like this:
+
+ COMMAND 3:abc 5:abcde 1:x
+
+where COMMAND is an alphanumeric sequence and the remainder is the command
+arguments. Each argument is written as its length (in characters), followed
+by colon, followed by the given number of characters."
+ (define (consume-whitespace port)
+ (let ((chr (lookahead-u8 port)))
+ (when (eqv? chr (char->integer #\space))
+ (get-u8 port)
+ (consume-whitespace port))))
+
+ (match (read-delimited " \t\n\r" port)
+ ((? eof-object?)
+ '())
+ (command
+ (let loop ((result (list command)))
+ (consume-whitespace port)
+ (let ((next (lookahead-u8 port)))
+ (cond ((eqv? next (char->integer #\newline))
+ (get-u8 port)
+ (reverse result))
+ ((eof-object? next)
+ (reverse result))
+ (else
+ (let* ((len (string->number (read-delimited ":" port)))
+ (str (utf8->string
+ (get-bytevector-n port len))))
+ (loop (cons str result))))))))))
+
+(define-syntax define-enumerate-type ;TODO: factorize
+ (syntax-rules ()
+ ((_ name->int (name id) ...)
+ (define-syntax name->int
+ (syntax-rules (name ...)
+ ((_ name) id) ...)))))
+
+;; Codes used when reply to requests.
+(define-enumerate-type reply-code
+ (success 0)
+ (command-not-found 404)
+ (command-failed 500))
;;;
-;;; Entry point with 'openssl'-compatible interface. We support this
-;;; interface because that's what the daemon expects, and we want to leave it
-;;; unmodified currently.
+;;; Entry point.
;;;
-(define (guix-authenticate . args)
+(define-command (guix-authenticate . args)
+ (category internal)
+ (synopsis "sign or verify signatures on normalized archives (nars)")
+
+ (define (send-reply code str)
+ ;; Send CODE and STR as a reply to our client.
+ (let ((bv (string->utf8 str)))
+ (format #t "~a ~a:" code (bytevector-length bv))
+ (put-bytevector (current-output-port) bv)
+ (force-output (current-output-port))))
+
+ (define (call-with-reply thunk)
+ ;; Send a reply for the result of THUNK or for any exception raised during
+ ;; its execution.
+ (guard (c ((formatted-message? c)
+ (send-reply (reply-code command-failed)
+ (apply format #f
+ (G_ (formatted-message-string c))
+ (formatted-message-arguments c)))))
+ (send-reply (reply-code success) (thunk))))
+
+ (define-syntax-rule (with-reply exp ...)
+ (call-with-reply (lambda () exp ...)))
+
;; Signature sexps written to stdout may contain binary data, so force
;; ISO-8859-1 encoding so that things are not mangled. See
;; <http://bugs.gnu.org/17312> for details.
@@ -101,29 +178,46 @@ to stdout upon success."
(with-fluids ((%default-port-encoding "ISO-8859-1")
(%default-port-conversion-strategy 'error))
(match args
- ;; As invoked by guix-daemon.
- (("rsautl" "-sign" "-inkey" key "-in" hash-file)
- (call-with-input-file hash-file
- (lambda (port)
- (sign-with-key key port))))
- ;; As invoked by Nix/Crypto.pm (used by Hydra.)
- (("rsautl" "-sign" "-inkey" key)
- (sign-with-key key (current-input-port)))
- ;; As invoked by guix-daemon.
- (("rsautl" "-verify" "-inkey" _ "-pubin" "-in" signature-file)
- (call-with-input-file signature-file
- (lambda (port)
- (validate-signature port))))
- ;; As invoked by Nix/Crypto.pm (used by Hydra.)
- (("rsautl" "-verify" "-inkey" _ "-pubin")
- (validate-signature (current-input-port)))
(("--help")
(display (G_ "Usage: guix authenticate OPTION...
-Sign or verify the signature on the given file. This tool is meant to
-be used internally by 'guix-daemon'.\n")))
+Sign data or verify signatures. This tool is meant to be used internally by
+'guix-daemon'.\n")))
(("--version")
(show-version-and-exit "guix authenticate"))
- (else
- (leave (G_ "wrong arguments"))))))
+ (()
+ (let ((acl (current-acl)))
+ (let loop ((key-pairs vlist-null))
+ ;; Read a request on standard input and reply.
+ (match (read-command (current-input-port))
+ (("sign" signing-key (= base16-string->bytevector hash))
+ (let* ((key-pairs keys
+ (match (vhash-assoc signing-key key-pairs)
+ ((_ . keys)
+ (values key-pairs keys))
+ (#f
+ (let ((keys (load-key-pair signing-key)))
+ (values (vhash-cons signing-key keys
+ key-pairs)
+ keys))))))
+ (with-reply (canonical-sexp->string
+ (match keys
+ ((public . secret)
+ (sign-with-key public secret hash)))))
+ (loop key-pairs)))
+ (("verify" signature)
+ (with-reply (bytevector->base16-string
+ (validate-signature
+ (string->canonical-sexp signature)
+ acl)))
+ (loop key-pairs))
+ (()
+ (exit 0))
+ (commands
+ (warning (G_ "~s: invalid command; ignoring~%") commands)
+ (send-reply (reply-code command-not-found)
+ "invalid command")
+ (loop key-pairs))))))
+ (_
+ (leave (G_ "wrong arguments~%"))))))
;;; authenticate.scm ends here
diff --git a/guix/scripts/build.scm b/guix/scripts/build.scm
index 6286a43c02..25418661b9 100644
--- a/guix/scripts/build.scm
+++ b/guix/scripts/build.scm
@@ -945,7 +945,10 @@ needed."
;;; Entry point.
;;;
-(define (guix-build . args)
+(define-command (guix-build . args)
+ (category packaging)
+ (synopsis "build packages or derivations without installing them")
+
(define opts
(parse-command-line args %options
(list %default-options)))
diff --git a/guix/scripts/challenge.scm b/guix/scripts/challenge.scm
index 624f51b200..39bd2c1c0f 100644
--- a/guix/scripts/challenge.scm
+++ b/guix/scripts/challenge.scm
@@ -475,7 +475,10 @@ Challenge the substitutes for PACKAGE... provided by one or more servers.\n"))
;;; Entry point.
;;;
-(define (guix-challenge . args)
+(define-command (guix-challenge . args)
+ (category packaging)
+ (synopsis "challenge substitute servers, comparing their binaries")
+
(with-error-handling
(let* ((opts (parse-command-line args %options (list %default-options)
#:build-options? #f))
diff --git a/guix/scripts/container.scm b/guix/scripts/container.scm
index 8041d64b6b..2369437043 100644
--- a/guix/scripts/container.scm
+++ b/guix/scripts/container.scm
@@ -20,6 +20,7 @@
(define-module (guix scripts container)
#:use-module (ice-9 match)
#:use-module (guix ui)
+ #:use-module (guix scripts)
#:export (guix-container))
(define (show-help)
@@ -46,7 +47,10 @@ Build and manipulate Linux containers.\n"))
(proc (string->symbol (string-append "guix-container-" name))))
(module-ref module proc)))
-(define (guix-container . args)
+(define-command (guix-container . args)
+ (category development)
+ (synopsis "run code in containers created by 'guix environment -C'")
+
(with-error-handling
(match args
(()
diff --git a/guix/scripts/copy.scm b/guix/scripts/copy.scm
index 16d2de30f7..2780d4fbe9 100644
--- a/guix/scripts/copy.scm
+++ b/guix/scripts/copy.scm
@@ -20,6 +20,7 @@
#:use-module (guix ui)
#:use-module (guix scripts)
#:use-module (guix ssh)
+ #:use-module ((ssh session) #:select (disconnect!))
#:use-module (guix store)
#:use-module ((guix status) #:select (with-status-verbosity))
#:use-module (guix utils)
@@ -71,9 +72,10 @@ package names, build the underlying packages before sending them."
(and (build-derivations local drv)
(let* ((session (open-ssh-session host #:user user
#:port (or port 22)))
- (sent (send-files local items
- (connect-to-remote-daemon session)
+ (remote (connect-to-remote-daemon session))
+ (sent (send-files local items remote
#:recursive? #t)))
+ (close-connection remote)
(format #t "~{~a~%~}" sent)
sent))))
@@ -93,6 +95,8 @@ package names, build the underlying packages before sending them."
(options->derivations+files local opts))
((retrieved)
(retrieve-files local items remote #:recursive? #t)))
+ (close-connection remote)
+ (disconnect! session)
(format #t "~{~a~%~}" retrieved)
retrieved)))
@@ -166,7 +170,10 @@ Copy ITEMS to or from the specified host over SSH.\n"))
;;; Entry point.
;;;
-(define (guix-copy . args)
+(define-command (guix-copy . args)
+ (category plumbing)
+ (synopsis "copy store items remotely over SSH")
+
(with-error-handling
(let* ((opts (parse-command-line args %options (list %default-options)))
(source (assoc-ref opts 'source))
diff --git a/guix/scripts/deploy.scm b/guix/scripts/deploy.scm
index 4a68197620..1b5be307be 100644
--- a/guix/scripts/deploy.scm
+++ b/guix/scripts/deploy.scm
@@ -136,7 +136,8 @@ Perform the deployment specified by FILE.\n"))
(machine-display-name machine))))
-(define (guix-deploy . args)
+(define-command (guix-deploy . args)
+ (synopsis "deploy operating systems on a set of machines")
(define (handle-argument arg result)
(alist-cons 'file arg result))
diff --git a/guix/scripts/describe.scm b/guix/scripts/describe.scm
index bc868ffbbf..c3667516eb 100644
--- a/guix/scripts/describe.scm
+++ b/guix/scripts/describe.scm
@@ -304,7 +304,8 @@ text. The hyperlink links to a web view of COMMIT, when available."
;;; Entry point.
;;;
-(define (guix-describe . args)
+(define-command (guix-describe . args)
+ (synopsis "describe the channel revisions currently used")
(let* ((opts (args-fold* args %options
(lambda (opt name arg result)
(leave (G_ "~A: unrecognized option~%")
diff --git a/guix/scripts/download.scm b/guix/scripts/download.scm
index 589f62da9d..ce8dd8b02c 100644
--- a/guix/scripts/download.scm
+++ b/guix/scripts/download.scm
@@ -156,7 +156,10 @@ and 'base16' ('hex' and 'hexadecimal' can be used as well).\n"))
;;; Entry point.
;;;
-(define (guix-download . args)
+(define-command (guix-download . args)
+ (category packaging)
+ (synopsis "download a file to the store and print its hash")
+
(define (parse-options)
;; Return the alist of option values.
(args-fold* args %options
diff --git a/guix/scripts/edit.scm b/guix/scripts/edit.scm
index 43f3011869..49c9d945b6 100644
--- a/guix/scripts/edit.scm
+++ b/guix/scripts/edit.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2015, 2016, 2019 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2015, 2016, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2015 Mathieu Lirzin <mthl@gnu.org>
;;; Copyright © 2020 Simon Tournier <zimon.toutoune@gmail.com>
;;;
@@ -78,7 +78,10 @@ line."
(search-path* %load-path (location-file location))))
-(define (guix-edit . args)
+(define-command (guix-edit . args)
+ (category packaging)
+ (synopsis "view and edit package definitions")
+
(define (parse-arguments)
;; Return the list of package names.
(args-fold* args %options
diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm
index b8979cac19..ad50281eb2 100644
--- a/guix/scripts/environment.scm
+++ b/guix/scripts/environment.scm
@@ -477,6 +477,7 @@ WHILE-LIST."
(group-entry (gid 65534) ;the overflow GID
(name "overflow"))))
(home-dir (password-entry-directory passwd))
+ (logname (password-entry-name passwd))
(environ (filter (match-lambda
((variable . value)
(find (cut regexp-exec <> variable)
@@ -528,6 +529,10 @@ WHILE-LIST."
;; The same variables as in Nix's 'build.cc'.
'("TMPDIR" "TEMPDIR" "TMP" "TEMP"))
+ ;; Some programs expect USER and/or LOGNAME to be set.
+ (setenv "LOGNAME" logname)
+ (setenv "USER" logname)
+
;; Create a dummy home directory.
(mkdir-p home-dir)
(setenv "HOME" home-dir)
@@ -673,7 +678,10 @@ message if any test fails."
;;; Entry point.
;;;
-(define (guix-environment . args)
+(define-command (guix-environment . args)
+ (category development)
+ (synopsis "spawn one-off software environments")
+
(with-error-handling
(let* ((opts (parse-args args))
(pure? (assoc-ref opts 'pure))
diff --git a/guix/scripts/gc.scm b/guix/scripts/gc.scm
index ab7c13315f..043273f491 100644
--- a/guix/scripts/gc.scm
+++ b/guix/scripts/gc.scm
@@ -220,7 +220,9 @@ is deprecated; use '-D'~%"))
;;; Entry point.
;;;
-(define (guix-gc . args)
+(define-command (guix-gc . args)
+ (synopsis "invoke the garbage collector")
+
(define (parse-options)
;; Return the alist of option values.
(parse-command-line args %options (list %default-options)
diff --git a/guix/scripts/git.scm b/guix/scripts/git.scm
index bc829cbe99..4436d8a6e0 100644
--- a/guix/scripts/git.scm
+++ b/guix/scripts/git.scm
@@ -19,6 +19,7 @@
(define-module (guix scripts git)
#:use-module (ice-9 match)
#:use-module (guix ui)
+ #:use-module (guix scripts)
#:export (guix-git))
(define (show-help)
@@ -45,7 +46,10 @@ Operate on Git repositories.\n"))
(proc (string->symbol (string-append "guix-git-" name))))
(module-ref module proc)))
-(define (guix-git . args)
+(define-command (guix-git . args)
+ (category plumbing)
+ (synopsis "operate on Git repositories")
+
(with-error-handling
(match args
(()
diff --git a/guix/scripts/graph.scm b/guix/scripts/graph.scm
index 73d9269de2..d7a08a4fe1 100644
--- a/guix/scripts/graph.scm
+++ b/guix/scripts/graph.scm
@@ -565,7 +565,10 @@ Emit a representation of the dependency graph of PACKAGE...\n"))
;;; Entry point.
;;;
-(define (guix-graph . args)
+(define-command (guix-graph . args)
+ (category packaging)
+ (synopsis "view and query package dependency graphs")
+
(with-error-handling
(define opts
(parse-command-line args %options
diff --git a/guix/scripts/hash.scm b/guix/scripts/hash.scm
index 9b4f419a24..797b99f053 100644
--- a/guix/scripts/hash.scm
+++ b/guix/scripts/hash.scm
@@ -116,7 +116,10 @@ and 'base16' ('hex' and 'hexadecimal' can be used as well).\n"))
;;; Entry point.
;;;
-(define (guix-hash . args)
+(define-command (guix-hash . args)
+ (category packaging)
+ (synopsis "compute the cryptographic hash of a file")
+
(define (parse-options)
;; Return the alist of option values.
(parse-command-line args %options (list %default-options)
diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm
index c6cc93fad8..0a3863f965 100644
--- a/guix/scripts/import.scm
+++ b/guix/scripts/import.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2012, 2013, 2014 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2012, 2013, 2014, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2014 David Thompson <davet@gnu.org>
;;; Copyright © 2018 Kyle Meyer <kyle@kyleam.com>
;;; Copyright © 2019 Ricardo Wurmus <rekado@elephly.net>
@@ -21,6 +21,7 @@
(define-module (guix scripts import)
#:use-module (guix ui)
+ #:use-module (guix scripts)
#:use-module (guix utils)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-11)
@@ -98,7 +99,10 @@ Run IMPORTER with ARGS.\n"))
(newline)
(show-bug-report-information))
-(define (guix-import . args)
+(define-command (guix-import . args)
+ (category packaging)
+ (synopsis "import a package definition from an external repository")
+
(match args
(()
(format (current-error-port)
diff --git a/guix/scripts/install.scm b/guix/scripts/install.scm
index d88e86e77a..894e60f9da 100644
--- a/guix/scripts/install.scm
+++ b/guix/scripts/install.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -66,7 +66,9 @@ This is an alias for 'guix package -i'.\n"))
%transformation-options
%standard-build-options)))
-(define (guix-install . args)
+(define-command (guix-install . args)
+ (synopsis "install packages")
+
(define (handle-argument arg result arg-handler)
;; Treat all non-option arguments as package specs.
(values (alist-cons 'install arg result)
diff --git a/guix/scripts/lint.scm b/guix/scripts/lint.scm
index 5168a1ca17..979d4f8363 100644
--- a/guix/scripts/lint.scm
+++ b/guix/scripts/lint.scm
@@ -157,7 +157,10 @@ run the checkers on all packages.\n"))
;;; Entry Point
;;;
-(define (guix-lint . args)
+(define-command (guix-lint . args)
+ (category packaging)
+ (synopsis "validate package definitions")
+
(define (parse-options)
;; Return the alist of option values.
(parse-command-line args %options (list %default-options)
diff --git a/guix/scripts/offload.scm b/guix/scripts/offload.scm
index a56701f07a..3dc8ccefcb 100644
--- a/guix/scripts/offload.scm
+++ b/guix/scripts/offload.scm
@@ -39,6 +39,7 @@
#:select (fcntl-flock set-thread-name))
#:use-module ((guix build utils) #:select (which mkdir-p))
#:use-module (guix ui)
+ #:use-module (guix scripts)
#:use-module (guix diagnostics)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-11)
@@ -365,6 +366,8 @@ of free disk space on '~a'~%")
#:log-port (current-error-port)
#:lock? #f)))
+ (close-connection store)
+ (disconnect! session)
(format (current-error-port) "done with offloaded '~a'~%"
(derivation-file-name drv)))
@@ -723,7 +726,10 @@ machine."
;;; Entry point.
;;;
-(define (guix-offload . args)
+(define-command (guix-offload . args)
+ (category plumbing)
+ (synopsis "set up and operate build offloading")
+
(define request-line-rx
;; The request format. See 'tryBuildHook' method in build.cc.
(make-regexp "([01]) ([a-z0-9_-]+) (/[[:graph:]]+.drv) ([[:graph:]]*)"))
diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm
index 9d6881fdaf..379e6a3ac6 100644
--- a/guix/scripts/pack.scm
+++ b/guix/scripts/pack.scm
@@ -1089,7 +1089,10 @@ Create a bundle of PACKAGE.\n"))
;;; Entry point.
;;;
-(define (guix-pack . args)
+(define-command (guix-pack . args)
+ (category development)
+ (synopsis "create application bundles")
+
(define opts
(parse-command-line args %options (list %default-options)))
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index ac8dedb5f3..4eb968a49b 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -941,7 +941,9 @@ processed, #f otherwise."
;;; Entry point.
;;;
-(define (guix-package . args)
+(define-command (guix-package . args)
+ (synopsis "manage packages and profiles")
+
(define (handle-argument arg result arg-handler)
;; Process non-option argument ARG by calling back ARG-HANDLER.
(if arg-handler
diff --git a/guix/scripts/perform-download.scm b/guix/scripts/perform-download.scm
index df787a9940..8d409092ba 100644
--- a/guix/scripts/perform-download.scm
+++ b/guix/scripts/perform-download.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016, 2017, 2018, 2020 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -18,6 +18,7 @@
(define-module (guix scripts perform-download)
#:use-module (guix ui)
+ #:use-module (guix scripts)
#:use-module (guix derivations)
#:use-module ((guix store) #:select (derivation-path? store-path?))
#:use-module (guix build download)
@@ -91,14 +92,15 @@ actual output is different from that when we're doing a 'bmCheck' or
(leave (G_ "refusing to run with elevated privileges (UID ~a)~%")
(getuid))))
-(define (guix-perform-download . args)
- "Perform the download described by the given fixed-output derivation.
+(define-command (guix-perform-download . args)
+ (category internal)
+ (synopsis "perform download described by fixed-output derivations")
-This is an \"out-of-band\" download in that this code is executed directly by
-the daemon and not explicitly described as an input of the derivation. This
-allows us to sidestep bootstrapping problems, such downloading the source code
-of GnuTLS over HTTPS, before we have built GnuTLS. See
-<http://bugs.gnu.org/22774>."
+ ;; This is an "out-of-band" download in that this code is executed directly
+ ;; by the daemon and not explicitly described as an input of the derivation.
+ ;; This allows us to sidestep bootstrapping problems, such as downloading
+ ;; the source code of GnuTLS over HTTPS before we have built GnuTLS. See
+ ;; <https://bugs.gnu.org/22774>.
(define print-build-trace?
(match (getenv "_NIX_OPTIONS")
diff --git a/guix/scripts/processes.scm b/guix/scripts/processes.scm
index 35698a0216..b4ca7b1687 100644
--- a/guix/scripts/processes.scm
+++ b/guix/scripts/processes.scm
@@ -223,7 +223,9 @@ List the current Guix sessions and their processes."))
;;; Entry point.
;;;
-(define (guix-processes . args)
+(define-command (guix-processes . args)
+ (category plumbing)
+ (synopsis "list currently running sessions")
(define options
(args-fold* args %options
(lambda (opt name arg result)
diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm
index 61542f83a0..4eaf961ab2 100644
--- a/guix/scripts/publish.scm
+++ b/guix/scripts/publish.scm
@@ -1013,7 +1013,10 @@ methods, return the applicable compression."
;;; Entry point.
;;;
-(define (guix-publish . args)
+(define-command (guix-publish . args)
+ (category packaging)
+ (synopsis "publish build results over HTTP")
+
(with-error-handling
(let* ((opts (args-fold* args %options
(lambda (opt name arg result)
diff --git a/guix/scripts/pull.scm b/guix/scripts/pull.scm
index 5b4ccf13fe..bb1b560a22 100644
--- a/guix/scripts/pull.scm
+++ b/guix/scripts/pull.scm
@@ -507,6 +507,7 @@ true, display what would be built without actually building it."
;; workaround, skip this code when $SUDO_USER is set. See
;; <https://bugs.gnu.org/36785>.
(unless (or (getenv "SUDO_USER")
+ (not (file-exists? %user-profile-directory))
(string=? %profile-directory
(dirname
(canonicalize-profile %user-profile-directory))))
@@ -750,7 +751,9 @@ Use '~/.config/guix/channels.scm' instead."))
channels)))
-(define (guix-pull . args)
+(define-command (guix-pull . args)
+ (synopsis "pull the latest revision of Guix")
+
(with-error-handling
(with-git-error-handling
(let* ((opts (parse-command-line args %options
diff --git a/guix/scripts/refresh.scm b/guix/scripts/refresh.scm
index efada1df5a..4a71df28d1 100644
--- a/guix/scripts/refresh.scm
+++ b/guix/scripts/refresh.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
;;; Copyright © 2015 Alex Kost <alezost@gmail.com>
@@ -496,7 +496,10 @@ all are dependent packages: ~{~a~^ ~}~%")
;;; Entry point.
;;;
-(define (guix-refresh . args)
+(define-command (guix-refresh . args)
+ (category packaging)
+ (synopsis "update existing package definitions")
+
(define (parse-options)
;; Return the alist of option values.
(parse-command-line args %options (list %default-options)
diff --git a/guix/scripts/remove.scm b/guix/scripts/remove.scm
index 2f06ea4f37..a46ad04d56 100644
--- a/guix/scripts/remove.scm
+++ b/guix/scripts/remove.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -63,7 +63,9 @@ This is an alias for 'guix package -r'.\n"))
%standard-build-options)))
-(define (guix-remove . args)
+(define-command (guix-remove . args)
+ (synopsis "remove installed packages")
+
(define (handle-argument arg result arg-handler)
;; Treat all non-option arguments as package specs.
(values (alist-cons 'remove arg result)
diff --git a/guix/scripts/repl.scm b/guix/scripts/repl.scm
index 0ea9c3655c..3c79e89f8d 100644
--- a/guix/scripts/repl.scm
+++ b/guix/scripts/repl.scm
@@ -137,7 +137,10 @@ call THUNK."
(loop)))))))
-(define (guix-repl . args)
+(define-command (guix-repl . args)
+ (category plumbing)
+ (synopsis "read-eval-print loop (REPL) for interactive programming")
+
(define opts
(args-fold* args %options
(lambda (opt name arg result)
diff --git a/guix/scripts/search.scm b/guix/scripts/search.scm
index 827b2eb7a9..0c9e6af07b 100644
--- a/guix/scripts/search.scm
+++ b/guix/scripts/search.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -57,7 +57,9 @@ This is an alias for 'guix package -s'.\n"))
(member "load-path" (option-names option)))
%standard-build-options)))
-(define (guix-search . args)
+(define-command (guix-search . args)
+ (synopsis "search for packages")
+
(define (handle-argument arg result)
;; Treat all non-option arguments as regexps.
(cons `(query search ,(or arg ""))
diff --git a/guix/scripts/show.scm b/guix/scripts/show.scm
index a2b0030a63..535d03c1a6 100644
--- a/guix/scripts/show.scm
+++ b/guix/scripts/show.scm
@@ -57,7 +57,9 @@ This is an alias for 'guix package --show='.\n"))
(member "load-path" (option-names option)))
%standard-build-options)))
-(define (guix-show . args)
+(define-command (guix-show . args)
+ (synopsis "show information about packages")
+
(define (handle-argument arg result)
;; Treat all non-option arguments as regexps.
(cons `(query show ,arg)
diff --git a/guix/scripts/size.scm b/guix/scripts/size.scm
index c42f4f7782..e46983382a 100644
--- a/guix/scripts/size.scm
+++ b/guix/scripts/size.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2019 Simon Tournier <zimon.toutoune@gmail.com>
;;;
;;; This file is part of GNU Guix.
@@ -298,7 +298,10 @@ Report the size of the PACKAGE or STORE-ITEM, with its dependencies.\n"))
;;; Entry point.
;;;
-(define (guix-size . args)
+(define-command (guix-size . args)
+ (category packaging)
+ (synopsis "profile the on-disk size of packages")
+
(with-error-handling
(let* ((opts (parse-command-line args %options (list %default-options)
#:build-options? #f))
diff --git a/guix/scripts/substitute.scm b/guix/scripts/substitute.scm
index f9d19fd735..26613df68f 100755
--- a/guix/scripts/substitute.scm
+++ b/guix/scripts/substitute.scm
@@ -20,6 +20,7 @@
(define-module (guix scripts substitute)
#:use-module (guix ui)
+ #:use-module (guix scripts)
#:use-module (guix store)
#:use-module (guix utils)
#:use-module (guix combinators)
@@ -1095,8 +1096,10 @@ default value."
(unless (string->uri uri)
(leave (G_ "~a: invalid URI~%") uri)))
-(define (guix-substitute . args)
- "Implement the build daemon's substituter protocol."
+(define-command (guix-substitute . args)
+ (category internal)
+ (synopsis "implement the build daemon's substituter protocol")
+
(define print-build-trace?
(match (or (find-daemon-option "untrusted-print-extended-build-trace")
(find-daemon-option "print-extended-build-trace"))
@@ -1126,12 +1129,13 @@ default value."
;; Sanity-check SUBSTITUTE-URLS so we can provide a meaningful error message.
(for-each validate-uri (substitute-urls))
- ;; Attempt to install the client's locale, mostly so that messages are
- ;; suitably translated.
+ ;; Attempt to install the client's locale so that messages are suitably
+ ;; translated. LC_CTYPE must be a UTF-8 locale; it's the case by default so
+ ;; don't change it.
(match (or (find-daemon-option "untrusted-locale")
(find-daemon-option "locale"))
(#f #f)
- (locale (false-if-exception (setlocale LC_ALL locale))))
+ (locale (false-if-exception (setlocale LC_MESSAGES locale))))
(catch 'system-error
(lambda ()
diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm
index f6d20382b6..bd5f84fc5b 100644
--- a/guix/scripts/system.scm
+++ b/guix/scripts/system.scm
@@ -6,6 +6,8 @@
;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2019 Christopher Baines <mail@cbaines.net>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+;;; Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
+;;; Copyright © 2020 Efraim Flashner <efraim@flashner.co.il>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -271,28 +273,33 @@ expression in %STORE-MONAD."
(define (report-shepherd-error error)
"Report ERROR, a '&shepherd-error' error condition object."
- (cond ((service-not-found-error? error)
- (report-error (G_ "service '~a' could not be found~%")
- (service-not-found-error-service error)))
- ((action-not-found-error? error)
- (report-error (G_ "service '~a' does not have an action '~a'~%")
- (action-not-found-error-service error)
- (action-not-found-error-action error)))
- ((action-exception-error? error)
- (report-error (G_ "exception caught while executing '~a' \
+ (when error
+ (cond ((service-not-found-error? error)
+ (warning (G_ "service '~a' could not be found~%")
+ (service-not-found-error-service error)))
+ ((action-not-found-error? error)
+ (warning (G_ "service '~a' does not have an action '~a'~%")
+ (action-not-found-error-service error)
+ (action-not-found-error-action error)))
+ ((action-exception-error? error)
+ (warning (G_ "exception caught while executing '~a' \
on service '~a':~%")
- (action-exception-error-action error)
- (action-exception-error-service error))
- (print-exception (current-error-port) #f
- (action-exception-error-key error)
- (action-exception-error-arguments error)))
- ((unknown-shepherd-error? error)
- (report-error (G_ "something went wrong: ~s~%")
- (unknown-shepherd-error-sexp error)))
- ((shepherd-error? error)
- (report-error (G_ "shepherd error~%")))
- ((not error) ;not an error
- #t)))
+ (action-exception-error-action error)
+ (action-exception-error-service error))
+ (print-exception (current-error-port) #f
+ (action-exception-error-key error)
+ (action-exception-error-arguments error)))
+ ((unknown-shepherd-error? error)
+ (warning (G_ "something went wrong: ~s~%")
+ (unknown-shepherd-error-sexp error)))
+ ((shepherd-error? error)
+ (warning (G_ "shepherd error~%"))))
+
+ ;; Don't leave users out in the cold and explain what that means and what
+ ;; they can do.
+ (warning (G_ "some services could not be upgraded~%"))
+ (display-hint (G_ "To allow changes to all the system services to take
+effect, you will need to reboot."))))
(define-syntax-rule (unless-file-not-found exp)
(catch 'system-error
@@ -662,7 +669,7 @@ checking this by themselves in their 'check' procedure."
(define* (system-derivation-for-action os base-image action
#:key image-size file-system-type
full-boot? container-shared-network?
- mappings)
+ mappings label)
"Return as a monadic value the derivation for OS according to ACTION."
(case action
((build init reconfigure)
@@ -686,7 +693,7 @@ checking this by themselves in their 'check' procedure."
(lower-object
(system-image
(image
- (inherit base-image)
+ (inherit (if label (image-with-label base-image label) base-image))
(size image-size)
(operating-system os)))))
((docker-image)
@@ -741,7 +748,7 @@ and TARGET arguments."
install-bootloader?
dry-run? derivations-only?
use-substitutes? bootloader-target target
- image-size file-system-type full-boot?
+ image-size file-system-type full-boot? label
container-shared-network?
(mappings '())
(gc-root #f))
@@ -795,6 +802,7 @@ static checks."
((target* (current-target-system))
(image -> (find-image file-system-type target*))
(sys (system-derivation-for-action os image action
+ #:label label
#:file-system-type file-system-type
#:image-size image-size
#:full-boot? full-boot?
@@ -835,7 +843,9 @@ static checks."
(upgrade-shepherd-services local-eval os)
(return (format #t (G_ "\
To complete the upgrade, run 'herd restart SERVICE' to stop,
-upgrade, and restart each service that was not automatically restarted.\n"))))))
+upgrade, and restart each service that was not automatically restarted.\n")))
+ (return (format #t (G_ "\
+Run 'herd status' to view the list of services on your system.\n"))))))
((init)
(newline)
(format #t (G_ "initializing operating system under '~a'...~%")
@@ -943,11 +953,15 @@ Some ACTIONS support additional ARGS.\n"))
(display (G_ "
--no-bootloader for 'init', do not install a bootloader"))
(display (G_ "
+ --label=LABEL for 'disk-image', label disk image with LABEL"))
+ (display (G_ "
--save-provenance save provenance information"))
(display (G_ "
- --share=SPEC for 'vm', share host file system according to SPEC"))
+ --share=SPEC for 'vm' and 'container', share host file system with
+ read/write access according to SPEC"))
(display (G_ "
- --expose=SPEC for 'vm', expose host file system according to SPEC"))
+ --expose=SPEC for 'vm' and 'container', expose host file system
+ directory as read-only according to SPEC"))
(display (G_ "
-N, --network for 'container', allow containers to access the network"))
(display (G_ "
@@ -1008,6 +1022,9 @@ Some ACTIONS support additional ARGS.\n"))
(option '("no-bootloader" "no-grub") #f #f
(lambda (opt name arg result)
(alist-cons 'install-bootloader? #f result)))
+ (option '("label") #t #f
+ (lambda (opt name arg result)
+ (alist-cons 'label arg result)))
(option '("full-boot") #f #f
(lambda (opt name arg result)
(alist-cons 'full-boot? #t result)))
@@ -1065,7 +1082,8 @@ Some ACTIONS support additional ARGS.\n"))
(validate-reconfigure . ,ensure-forward-reconfigure)
(file-system-type . "ext4")
(image-size . guess)
- (install-bootloader? . #t)))
+ (install-bootloader? . #t)
+ (label . #f)))
(define (verbosity-level opts)
"Return the verbosity level based on OPTS, the alist of parsed options."
@@ -1119,6 +1137,7 @@ resulting from command-line parsing."
(dry? (assoc-ref opts 'dry-run?))
(bootloader? (assoc-ref opts 'install-bootloader?))
+ (label (assoc-ref opts 'label))
(target-file (match args
((first second) second)
(_ #f)))
@@ -1169,6 +1188,7 @@ resulting from command-line parsing."
(_ #f))
opts)
#:install-bootloader? bootloader?
+ #:label label
#:target target-file
#:bootloader-target bootloader-target
#:gc-root (assoc-ref opts 'gc-root)))))
@@ -1233,7 +1253,9 @@ argument list and OPTS is the option alist."
;; need an operating system configuration file.
(else (process-action command args opts))))
-(define (guix-system . args)
+(define-command (guix-system . args)
+ (synopsis "build and deploy full operating systems")
+
(define (parse-sub-command arg result)
;; Parse sub-command ARG and augment RESULT accordingly.
(if (assoc-ref result 'action)
diff --git a/guix/scripts/time-machine.scm b/guix/scripts/time-machine.scm
index 441673b780..0d27414702 100644
--- a/guix/scripts/time-machine.scm
+++ b/guix/scripts/time-machine.scm
@@ -128,7 +128,9 @@ Execute COMMAND ARGS... in an older version of Guix.\n"))
;;; Entry point.
;;;
-(define (guix-time-machine . args)
+(define-command (guix-time-machine . args)
+ (synopsis "run commands from a different revision")
+
(with-error-handling
(with-git-error-handling
(let* ((opts (parse-args args))
diff --git a/guix/scripts/upgrade.scm b/guix/scripts/upgrade.scm
index d2784669be..8c7abd133a 100644
--- a/guix/scripts/upgrade.scm
+++ b/guix/scripts/upgrade.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020 Jakub Kądziołka <kuba@kadziolka.net>
;;;
;;; This file is part of GNU Guix.
@@ -67,7 +67,9 @@ This is an alias for 'guix package -u'.\n"))
%transformation-options
%standard-build-options)))
-(define (guix-upgrade . args)
+(define-command (guix-upgrade . args)
+ (synopsis "upgrade packages to their latest version")
+
(define (handle-argument arg result arg-handler)
;; Accept at most one non-option argument, and treat it as an upgrade
;; regexp.
diff --git a/guix/scripts/weather.scm b/guix/scripts/weather.scm
index 3035ff6ca8..6a2582c997 100644
--- a/guix/scripts/weather.scm
+++ b/guix/scripts/weather.scm
@@ -495,7 +495,9 @@ SERVER. Display information for packages with at least THRESHOLD dependents."
;;; Entry point.
;;;
-(define (guix-weather . args)
+(define-command (guix-weather . args)
+ (synopsis "report on the availability of pre-built package binaries")
+
(define (package-list opts)
;; Return the package list specified by OPTS.
(let ((files (filter-map (match-lambda