summaryrefslogtreecommitdiff
path: root/guix/scripts
diff options
context:
space:
mode:
authorMarius Bakke <mbakke@fastmail.com>2019-05-01 23:11:41 +0200
committerMarius Bakke <mbakke@fastmail.com>2019-05-01 23:11:41 +0200
commit3b458d5462e6bbd852c2dc5c6670d5655abf53f5 (patch)
tree4f3ccec0de1c355134369333c17e948e3258d546 /guix/scripts
parent2ca3fdc2db1aef96fbf702a2f26f5e18ce832038 (diff)
parent14da3daafc8dd92fdabd3367694c930440fd72cb (diff)
Merge branch 'master' into core-updates
Diffstat (limited to 'guix/scripts')
-rw-r--r--guix/scripts/build.scm109
-rw-r--r--guix/scripts/describe.scm8
-rw-r--r--guix/scripts/environment.scm64
-rw-r--r--guix/scripts/gc.scm71
-rw-r--r--guix/scripts/install.scm80
-rw-r--r--guix/scripts/lint.scm10
-rw-r--r--guix/scripts/pack.scm8
-rw-r--r--guix/scripts/package.scm21
-rw-r--r--guix/scripts/pull.scm138
-rw-r--r--guix/scripts/refresh.scm6
-rw-r--r--guix/scripts/remove.scm77
-rw-r--r--guix/scripts/search.scm67
-rw-r--r--guix/scripts/size.scm14
-rw-r--r--guix/scripts/system.scm5
-rw-r--r--guix/scripts/upgrade.scm88
15 files changed, 606 insertions, 160 deletions
diff --git a/guix/scripts/build.scm b/guix/scripts/build.scm
index 28864435df..ba143ad16b 100644
--- a/guix/scripts/build.scm
+++ b/guix/scripts/build.scm
@@ -119,7 +119,7 @@ found. Return #f if no build log was found."
(let* ((root (if (string-prefix? "/" root)
root
(string-append (canonicalize-path (dirname root))
- "/" root))))
+ "/" (basename root)))))
(catch 'system-error
(lambda ()
(match paths
@@ -635,8 +635,7 @@ options handled by 'set-build-options-from-command-line', and listed in
(define %default-options
;; Alist of default option values.
- `((system . ,(%current-system))
- (build-mode . ,(build-mode normal))
+ `((build-mode . ,(build-mode normal))
(graft? . #t)
(substitutes? . #t)
(build-hook? . #t)
@@ -729,8 +728,7 @@ must be one of 'package', 'all', or 'transitive'~%")
rest)))
(option '(#\s "system") #t #f
(lambda (opt name arg result)
- (alist-cons 'system arg
- (alist-delete 'system result eq?))))
+ (alist-cons 'system arg result)))
(option '("target") #t #f
(lambda (opt name arg result)
(alist-cons 'target arg
@@ -811,56 +809,71 @@ build."
(cut package-cross-derivation <> <> triplet <>))))
(define src (assoc-ref opts 'source))
- (define system (assoc-ref opts 'system))
(define graft? (assoc-ref opts 'graft?))
+ (define systems
+ (match (filter-map (match-lambda
+ (('system . system) system)
+ (_ #f))
+ opts)
+ (() (list (%current-system)))
+ (systems systems)))
+
+ (define things-to-build
+ (map (cut transform store <>)
+ (options->things-to-build opts)))
+
+ (define (compute-derivation obj system)
+ ;; Compute the derivation of OBJ for SYSTEM.
+ (match obj
+ ((? package? p)
+ (let ((p (or (and graft? (package-replacement p)) p)))
+ (match src
+ (#f
+ (list (package->derivation store p system)))
+ (#t
+ (match (package-source p)
+ (#f
+ (format (current-error-port)
+ (G_ "~a: warning: \
+package '~a' has no source~%")
+ (location->string (package-location p))
+ (package-name p))
+ '())
+ (s
+ (list (package-source-derivation store s)))))
+ (proc
+ (map (cut package-source-derivation store <>)
+ (proc p))))))
+ ((? derivation? drv)
+ (list drv))
+ ((? procedure? proc)
+ (list (run-with-store store
+ (mbegin %store-monad
+ (set-guile-for-build (default-guile))
+ (proc))
+ #:system system)))
+ ((? file-like? obj)
+ (list (run-with-store store
+ (lower-object obj system
+ #:target (assoc-ref opts 'target))
+ #:system system)))
+ ((? gexp? gexp)
+ (list (run-with-store store
+ (mbegin %store-monad
+ (set-guile-for-build (default-guile))
+ (gexp->derivation "gexp" gexp
+ #:system system))
+ #:system system)))))
;; We may get 'unbound-variable' errors while evaluating the 'inputs' fields
;; of user packages. Since 'guix build' is the primary tool for people
;; testing new packages, report such errors gracefully.
(with-unbound-variable-handling
(parameterize ((%graft? graft?))
- (append-map (match-lambda
- ((? package? p)
- (let ((p (or (and graft? (package-replacement p)) p)))
- (match src
- (#f
- (list (package->derivation store p system)))
- (#t
- (match (package-source p)
- (#f
- (format (current-error-port)
- (G_ "~a: warning: \
-package '~a' has no source~%")
- (location->string (package-location p))
- (package-name p))
- '())
- (s
- (list (package-source-derivation store s)))))
- (proc
- (map (cut package-source-derivation store <>)
- (proc p))))))
- ((? derivation? drv)
- (list drv))
- ((? procedure? proc)
- (list (run-with-store store
- (mbegin %store-monad
- (set-guile-for-build (default-guile))
- (proc))
- #:system system)))
- ((? file-like? obj)
- (list (run-with-store store
- (lower-object obj system
- #:target (assoc-ref opts 'target))
- #:system system)))
- ((? gexp? gexp)
- (list (run-with-store store
- (mbegin %store-monad
- (set-guile-for-build (default-guile))
- (gexp->derivation "gexp" gexp
- #:system system))
- #:system system))))
- (map (cut transform store <>)
- (options->things-to-build opts))))))
+ (append-map (lambda (system)
+ (append-map (cut compute-derivation <> system)
+ things-to-build))
+ systems))))
(define (show-build-log store file urls)
"Show the build log for FILE, falling back to remote logs from URLS if
diff --git a/guix/scripts/describe.scm b/guix/scripts/describe.scm
index b6287d3a4c..fa6b6cae37 100644
--- a/guix/scripts/describe.scm
+++ b/guix/scripts/describe.scm
@@ -18,6 +18,7 @@
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (guix scripts describe)
+ #:use-module ((guix config) #:select (%guix-version))
#:use-module ((guix ui) #:hide (display-profile-content))
#:use-module (guix channels)
#:use-module (guix scripts)
@@ -114,7 +115,12 @@ within a Git checkout."
(lambda ()
(repository-discover (dirname program)))
(lambda (key err)
- (leave (G_ "failed to determine origin~%")))))
+ (report-error (G_ "failed to determine origin~%"))
+ (display-hint (format #f (G_ "Perhaps this
+@command{guix} command was not obtained with @command{guix pull}? Its version
+string is ~a.~%")
+ %guix-version))
+ (exit 1))))
(repository (repository-open directory))
(head (repository-head repository))
(commit (oid->string (reference-target head))))
diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm
index 63f6129279..99c351ae43 100644
--- a/guix/scripts/environment.scm
+++ b/guix/scripts/environment.scm
@@ -33,6 +33,7 @@
#:use-module (guix scripts)
#:use-module (guix scripts build)
#:use-module (gnu build linux-container)
+ #:use-module (gnu build accounts)
#:use-module (gnu system linux-container)
#:use-module (gnu system file-systems)
#:use-module (gnu packages)
@@ -191,7 +192,7 @@ COMMAND or an interactive shell in that environment.\n"))
(print-extended-build-trace? . #t)
(multiplexed-build-output? . #t)
(debug . 0)
- (verbosity . 2)))
+ (verbosity . 1)))
(define (tag-package-arg opts arg)
"Return a two-element list with the form (TAG ARG) that tags ARG with either
@@ -458,10 +459,22 @@ will be used for the passwd entry. LINK-PROFILE? creates a symbolic link from
(return
(let* ((cwd (getcwd))
(home (getenv "HOME"))
- (passwd (mock-passwd (getpwuid (getuid))
- user
- bash))
- (home-dir (passwd:dir passwd))
+ (uid (if user 1000 (getuid)))
+ (gid (if user 1000 (getgid)))
+ (passwd (let ((pwd (getpwuid (getuid))))
+ (password-entry
+ (name (or user (passwd:name pwd)))
+ (real-name (if user
+ ""
+ (passwd:gecos pwd)))
+ (uid uid) (gid gid) (shell bash)
+ (directory (if user
+ (string-append "/home/" user)
+ (passwd:dir pwd))))))
+ (groups (list (group-entry (name "users") (gid gid))
+ (group-entry (gid 65534) ;the overflow GID
+ (name "overflow"))))
+ (home-dir (password-entry-directory passwd))
;; Bind-mount all requisite store items, user-specified mappings,
;; /bin/sh, the current working directory, and possibly networking
;; configuration files within the container.
@@ -519,17 +532,8 @@ will be used for the passwd entry. LINK-PROFILE? creates a symbolic link from
;; to read it, such as 'git clone' over SSH, a valid use-case when
;; sharing the host's network namespace.
(mkdir-p "/etc")
- (call-with-output-file "/etc/passwd"
- (lambda (port)
- (display (string-join (list (passwd:name passwd)
- "x" ; but there is no shadow
- "0" "0" ; user is now root
- (passwd:gecos passwd)
- (passwd:dir passwd)
- bash)
- ":")
- port)
- (newline port)))
+ (write-passwd (list passwd))
+ (write-group groups)
;; For convenience, start in the user's current working
;; directory rather than the root directory.
@@ -539,36 +543,12 @@ will be used for the passwd entry. LINK-PROFILE? creates a symbolic link from
;; A container's environment is already purified, so no need to
;; request it be purified again.
(launch-environment command profile manifest #:pure? #f)))
+ #:guest-uid uid
+ #:guest-gid gid
#:namespaces (if network?
(delq 'net %namespaces) ; share host network
%namespaces)))))))
-(define (mock-passwd passwd user-override shell)
- "Generate mock information for '/etc/passwd'. If USER-OVERRIDE is not '#f',
-it is expected to be a string representing the mock username; it will produce
-a user of that name, with a home directory of '/home/USER-OVERRIDE', and no
-GECOS field. If USER-OVERRIDE is '#f', data will be inherited from PASSWD.
-In either case, the shadow password and UID/GID are cleared, since the user
-runs as root within the container. SHELL will always be used in place of the
-shell in PASSWD.
-
-The resulting vector is suitable for use with Guile's POSIX user procedures.
-
-See passwd(5) for more information each of the fields."
- (if user-override
- (vector
- user-override
- "x" "0" "0" ;; no shadow, user is now root
- "" ;; no personal information
- (user-override-home user-override)
- shell)
- (vector
- (passwd:name passwd)
- "x" "0" "0" ;; no shadow, user is now root
- (passwd:gecos passwd)
- (passwd:dir passwd)
- shell)))
-
(define (user-override-home user)
"Return home directory for override user USER."
(string-append "/home/" user))
diff --git a/guix/scripts/gc.scm b/guix/scripts/gc.scm
index 6f37b767ff..9a57e5fd1e 100644
--- a/guix/scripts/gc.scm
+++ b/guix/scripts/gc.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2012, 2013, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2012, 2013, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -20,7 +20,10 @@
#:use-module (guix ui)
#:use-module (guix scripts)
#:use-module (guix store)
+ #:use-module (guix store roots)
#:autoload (guix build syscalls) (free-disk-space)
+ #:autoload (guix profiles) (generation-profile)
+ #:autoload (guix scripts package) (delete-generations)
#:use-module (ice-9 match)
#:use-module (ice-9 regex)
#:use-module (srfi srfi-1)
@@ -47,7 +50,12 @@ Invoke the garbage collector.\n"))
(display (G_ "
-F, --free-space=FREE attempt to reach FREE available space in the store"))
(display (G_ "
- -d, --delete attempt to delete PATHS"))
+ -d, --delete-generations[=PATTERN]
+ delete profile generations matching PATTERN"))
+ (display (G_ "
+ -D, --delete attempt to delete PATHS"))
+ (display (G_ "
+ --list-roots list the user's garbage collector roots"))
(display (G_ "
--optimize optimize the store by deduplicating identical files"))
(display (G_ "
@@ -95,6 +103,16 @@ Invoke the garbage collector.\n"))
lst)
'()))))
+(define (delete-old-generations store profile pattern)
+ "Remove the generations of PROFILE that match PATTERN, a duration pattern.
+Do nothing if none matches."
+ (let* ((current (generation-number profile))
+ (numbers (matching-generations pattern profile
+ #:duration-relation >)))
+
+ ;; Make sure we don't inadvertently remove the current generation.
+ (delete-generations store profile (delv current numbers))))
+
(define %options
;; Specification of the command-line options.
(list (option '(#\h "help") #f #f
@@ -120,10 +138,25 @@ Invoke the garbage collector.\n"))
(option '(#\F "free-space") #t #f
(lambda (opt name arg result)
(alist-cons 'free-space (size->number arg) result)))
- (option '(#\d "delete") #f #f
+ (option '(#\D "delete") #f #f ;used to be '-d' (lower case)
(lambda (opt name arg result)
(alist-cons 'action 'delete
(alist-delete 'action result))))
+ (option '(#\d "delete-generations") #f #t
+ (lambda (opt name arg result)
+ (if (and arg (store-path? arg))
+ (begin
+ (warning (G_ "'-d' as an alias for '--delete' \
+is deprecated; use '-D'~%"))
+ `((action . delete)
+ (argument . ,arg)
+ (alist-delete 'action result)))
+ (begin
+ (when (and arg (not (string->duration arg)))
+ (leave (G_ "~s does not denote a duration~%")
+ arg))
+ (alist-cons 'delete-generations (or arg "")
+ result)))))
(option '("optimize") #f #f
(lambda (opt name arg result)
(alist-cons 'action 'optimize
@@ -135,6 +168,10 @@ Invoke the garbage collector.\n"))
(alist-cons 'verify-options options
(alist-delete 'action
result))))))
+ (option '("list-roots") #f #f
+ (lambda (opt name arg result)
+ (alist-cons 'action 'list-roots
+ (alist-delete 'action result))))
(option '("list-dead") #f #f
(lambda (opt name arg result)
(alist-cons 'action 'list-dead
@@ -205,6 +242,27 @@ Invoke the garbage collector.\n"))
(info (G_ "freeing ~h MiBs~%") (/ to-free 1024. 1024.))
(collect-garbage store to-free)))))
+ (define (delete-generations store pattern)
+ ;; Delete the generations matching PATTERN of all the user's profiles.
+ (let ((profiles (delete-duplicates
+ (filter-map (lambda (root)
+ (and (or (zero? (getuid))
+ (user-owned? root))
+ (generation-profile root)))
+ (gc-roots)))))
+ (for-each (lambda (profile)
+ (delete-old-generations store profile pattern))
+ profiles)))
+
+ (define (list-roots)
+ ;; List all the user-owned GC roots.
+ (let ((roots (filter (if (zero? (getuid)) (const #t) user-owned?)
+ (gc-roots))))
+ (for-each (lambda (root)
+ (display root)
+ (newline))
+ roots)))
+
(with-error-handling
(let* ((opts (parse-options))
(store (open-connection))
@@ -229,6 +287,10 @@ Invoke the garbage collector.\n"))
(assert-no-extra-arguments)
(let ((min-freed (assoc-ref opts 'min-freed))
(free-space (assoc-ref opts 'free-space)))
+ (match (assoc-ref opts 'delete-generations)
+ (#f #t)
+ ((? string? pattern)
+ (delete-generations store pattern)))
(cond
(free-space
(ensure-free-space store free-space))
@@ -238,6 +300,9 @@ Invoke the garbage collector.\n"))
(else
(let-values (((paths freed) (collect-garbage store)))
(info (G_ "freed ~h MiBs~%") (/ freed 1024. 1024.)))))))
+ ((list-roots)
+ (assert-no-extra-arguments)
+ (list-roots))
((delete)
(delete-paths store (map direct-store-path paths)))
((list-references)
diff --git a/guix/scripts/install.scm b/guix/scripts/install.scm
new file mode 100644
index 0000000000..d88e86e77a
--- /dev/null
+++ b/guix/scripts/install.scm
@@ -0,0 +1,80 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 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 install)
+ #:use-module (guix ui)
+ #:use-module (guix scripts package)
+ #:use-module (guix scripts build)
+ #:use-module (guix scripts)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (srfi srfi-37)
+ #:export (guix-install))
+
+(define (show-help)
+ (display (G_ "Usage: guix install [OPTION] PACKAGES...
+Install the given PACKAGES.
+This is an alias for 'guix package -i'.\n"))
+ (display (G_ "
+ -p, --profile=PROFILE use PROFILE instead of the user's default profile"))
+ ;; '--bootstrap' not shown here.
+ (display (G_ "
+ -v, --verbosity=LEVEL use the given verbosity LEVEL"))
+ (newline)
+ (show-build-options-help)
+ (newline)
+ (show-transformation-options-help)
+ (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 %options
+ ;; Specification of the command-line options.
+ (cons* (option '(#\h "help") #f #f
+ (lambda args
+ (show-help)
+ (exit 0)))
+ (option '(#\V "version") #f #f
+ (lambda args
+ (show-version-and-exit "guix install")))
+
+ ;; Preserve some of the 'guix package' options.
+ (append (filter (lambda (option)
+ (any (cut member <> (option-names option))
+ '("profile" "dry-run" "verbosity" "bootstrap")))
+ %package-options)
+
+ %transformation-options
+ %standard-build-options)))
+
+(define (guix-install . args)
+ (define (handle-argument arg result arg-handler)
+ ;; Treat all non-option arguments as package specs.
+ (values (alist-cons 'install arg result)
+ arg-handler))
+
+ (define opts
+ (parse-command-line args %options
+ (list %package-default-options #f)
+ #:argument-handler handle-argument))
+
+ (guix-package* opts))
diff --git a/guix/scripts/lint.scm b/guix/scripts/lint.scm
index ddad5b7fd0..dc338a1d7b 100644
--- a/guix/scripts/lint.scm
+++ b/guix/scripts/lint.scm
@@ -45,7 +45,6 @@
#:use-module (guix cve)
#:use-module (gnu packages)
#:use-module (ice-9 match)
- #:use-module (ice-9 receive)
#:use-module (ice-9 regex)
#:use-module (ice-9 format)
#:use-module (web client)
@@ -796,10 +795,13 @@ descriptions maintained upstream."
(let ((uris (origin-uris origin)))
(for-each check-mirror-uri uris)))))
-(define (check-github-url package)
+(define* (check-github-url package #:key (timeout 3))
"Check whether PACKAGE uses source URLs that redirect to GitHub."
- (define (follow-redirect uri)
- (receive (response body) (http-head uri)
+ (define (follow-redirect url)
+ (let* ((uri (string->uri url))
+ (port (guix:open-connection-for-uri uri #:timeout timeout))
+ (response (http-head uri #:port port)))
+ (close-port port)
(case (response-code response)
((301 302)
(uri->string (assoc-ref (response-headers response) 'location)))
diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm
index d237ae6e94..2a7b84b847 100644
--- a/guix/scripts/pack.scm
+++ b/guix/scripts/pack.scm
@@ -126,13 +126,9 @@ dependencies are registered."
(define build
(with-extensions gcrypt-sqlite3&co
- ;; XXX: Adding (gnu build install) just to work around
- ;; <https://bugs.gnu.org/15602>: that way, (guix build store-copy) is
- ;; copied last and the 'store-info-XXX' macros are correctly expanded.
(with-imported-modules (source-module-closure
'((guix build store-copy)
- (guix store database)
- (gnu build install)))
+ (guix store database)))
#~(begin
(use-modules (guix store database)
(guix build store-copy)
@@ -633,7 +629,7 @@ please email '~a'~%")
(print-extended-build-trace? . #t)
(multiplexed-build-output? . #t)
(debug . 0)
- (verbosity . 2)
+ (verbosity . 1)
(symlinks . ())
(compressor . ,(first %compressors))))
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index b0c6a7ced7..aa27984ea2 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -58,7 +58,11 @@
delete-generations
delete-matching-generations
display-search-paths
- guix-package))
+ guix-package
+
+ (%options . %package-options)
+ (%default-options . %package-default-options)
+ guix-package*))
(define %store
(make-parameter #f))
@@ -278,11 +282,19 @@ path definition to be returned."
(evaluate-search-paths search-paths profiles
getenv))))
+(define (absolutize file)
+ "Return an absolute file name equivalent to FILE, but without resolving
+symlinks like 'canonicalize-path' would do."
+ (if (string-prefix? "/" file)
+ file
+ (string-append (getcwd) "/" file)))
+
(define* (display-search-paths entries profiles
#:key (kind 'exact))
"Display the search path environment variables that may need to be set for
ENTRIES, a list of manifest entries, in the context of PROFILE."
- (let* ((profiles (map user-friendly-profile profiles))
+ (let* ((profiles (map (compose user-friendly-profile absolutize)
+ profiles))
(settings (search-path-environment-variables entries profiles
#:kind kind)))
(unless (null? settings)
@@ -891,6 +903,11 @@ processed, #f otherwise."
(parse-command-line args %options (list %default-options #f)
#:argument-handler handle-argument))
+ (guix-package* opts))
+
+(define (guix-package* opts)
+ "Run the 'guix package' command on OPTS, an alist resulting for command-line
+option processing with 'parse-command-line'."
(with-error-handling
(or (process-query opts)
(parameterize ((%store (open-connection))
diff --git a/guix/scripts/pull.scm b/guix/scripts/pull.scm
index 730b6a0bf2..3929cd402e 100644
--- a/guix/scripts/pull.scm
+++ b/guix/scripts/pull.scm
@@ -86,13 +86,13 @@ Download and deploy the latest version of Guix.\n"))
(display (G_ "
--branch=BRANCH download the tip of the specified BRANCH"))
(display (G_ "
+ -N, --news display news compared to the previous generation"))
+ (display (G_ "
-l, --list-generations[=PATTERN]
list generations matching PATTERN"))
(display (G_ "
-p, --profile=PROFILE use PROFILE instead of ~/.config/guix/current"))
(display (G_ "
- -n, --dry-run show what would be pulled and built"))
- (display (G_ "
-v, --verbosity=LEVEL use the given verbosity LEVEL"))
(display (G_ "
-s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\""))
@@ -119,6 +119,9 @@ Download and deploy the latest version of Guix.\n"))
(lambda (opt name arg result)
(cons `(query list-generations ,(or arg ""))
result)))
+ (option '(#\N "news") #f #f
+ (lambda (opt name arg result)
+ (cons '(query display-news) result)))
(option '("url") #t #f
(lambda (opt name arg result)
(alist-cons 'repository-url arg
@@ -164,24 +167,33 @@ Download and deploy the latest version of Guix.\n"))
(define indirect-root-added
(store-lift add-indirect-root))
-(define (display-profile-news profile)
- "Display what's up in PROFILE--new packages, and all that."
+(define* (display-profile-news profile #:key concise?
+ current-is-newer?)
+ "Display what's up in PROFILE--new packages, and all that. If
+CURRENT-IS-NEWER? is true, assume that the current process represents the
+newest generation of PROFILE.x"
(match (memv (generation-number profile)
(reverse (profile-generations profile)))
((current previous _ ...)
- (newline)
- (let ((old (fold-available-packages
- (lambda* (name version result
- #:key supported? deprecated?
- #:allow-other-keys)
- (if (and supported? (not deprecated?))
- (alist-cons name version result)
- result))
- '()))
- (new (profile-package-alist
- (generation-file-name profile current))))
- (display-new/upgraded-packages old new
- #:heading (G_ "New in this revision:\n"))))
+ (let ((these (fold-available-packages
+ (lambda* (name version result
+ #:key supported? deprecated?
+ #:allow-other-keys)
+ (if (and supported? (not deprecated?))
+ (alist-cons name version result)
+ result))
+ '()))
+ (those (profile-package-alist
+ (generation-file-name profile
+ (if current-is-newer?
+ previous
+ current)))))
+ (let ((old (if current-is-newer? those these))
+ (new (if current-is-newer? these those)))
+ (display-new/upgraded-packages old new
+ #:concise? concise?
+ #:heading
+ (G_ "New in this revision:\n")))))
(_ #t)))
(define* (build-and-install instances profile
@@ -197,7 +209,8 @@ true, display what would be built without actually building it."
#:hooks %channel-profile-hooks
#:dry-run? dry-run?)
(munless dry-run?
- (return (display-profile-news profile))
+ (return (newline))
+ (return (display-profile-news profile #:concise? #t))
(match (which "guix")
(#f (return #f))
(str
@@ -377,36 +390,66 @@ of packages upgraded in ALIST2."
alist2)))
(values new upgraded)))
+(define* (ellipsis #:optional (port (current-output-port)))
+ "Return HORIZONTAL ELLIPSIS three dots if PORT's encoding cannot represent
+it."
+ (match (port-encoding port)
+ ("UTF-8" "…")
+ (_ "...")))
+
(define* (display-new/upgraded-packages alist1 alist2
- #:key (heading ""))
+ #:key (heading "") concise?)
"Given the two package name/version alists ALIST1 and ALIST2, display the
list of new and upgraded packages going from ALIST1 to ALIST2. When ALIST1
-and ALIST2 differ, display HEADING upfront."
+and ALIST2 differ, display HEADING upfront. When CONCISE? is true, do not
+display long package lists that would fill the user's screen."
+ (define (pretty str column)
+ (indented-string (fill-paragraph str (- (%text-width) 4)
+ column)
+ 4))
+
+ (define concise/max-item-count
+ ;; Maximum number of items to display when CONCISE? is true.
+ 12)
+
+ (define list->enumeration
+ (if concise?
+ (lambda* (lst #:optional (max concise/max-item-count))
+ (if (> (length lst) max)
+ (string-append (string-join (take lst max) ", ")
+ ", " (ellipsis))
+ (string-join lst ", ")))
+ (cut string-join <> ", ")))
+
(let-values (((new upgraded) (new/upgraded-packages alist1 alist2)))
+ (define new-count (length new))
+ (define upgraded-count (length upgraded))
+
(unless (and (null? new) (null? upgraded))
(display heading))
- (match (length new)
+ (match new-count
(0 #t)
(count
(format #t (N_ " ~h new package: ~a~%"
" ~h new packages: ~a~%" count)
count
- (indented-string
- (fill-paragraph (string-join (sort (map first new) string<?)
- ", ")
- (- (%text-width) 4) 30)
- 4))))
- (match (length upgraded)
+ (pretty (list->enumeration (sort (map first new) string<?))
+ 30))))
+ (match upgraded-count
(0 #t)
(count
(format #t (N_ " ~h package upgraded: ~a~%"
" ~h packages upgraded: ~a~%" count)
count
- (indented-string
- (fill-paragraph (string-join (sort upgraded string<?) ", ")
- (- (%text-width) 4) 35)
- 4))))))
+ (pretty (list->enumeration (sort upgraded string<?))
+ 35))))
+
+ (when (and concise?
+ (or (> new-count concise/max-item-count)
+ (> upgraded-count concise/max-item-count)))
+ (display-hint (G_ "Run @command{guix pull --news} to view the complete
+list of package changes.")))))
(define (display-profile-content-diff profile gen1 gen2)
"Display the changes in PROFILE GEN2 compared to generation GEN1."
@@ -446,7 +489,12 @@ and ALIST2 differ, display HEADING upfront."
(()
(exit 1))
((numbers ...)
- (list-generations profile numbers)))))))))
+ (list-generations profile numbers)))))))
+ (('display-news)
+ ;; Display profile news, with the understanding that this process
+ ;; represents the newest generation.
+ (display-profile-news profile
+ #:current-is-newer? #t))))
(define (channel-list opts)
"Return the list of channels to use. If OPTS specify a channel file,
@@ -486,24 +534,22 @@ Use '~/.config/guix/channels.scm' instead."))
(url (or (assoc-ref opts 'repository-url)
(environment-variable))))
(if (or ref url)
- (match channels
- ((one)
- ;; When there's only one channel, apply '--url', '--commit', and
- ;; '--branch' to this specific channel.
- (let ((url (or url (channel-url one))))
- (list (match ref
+ (match (find guix-channel? channels)
+ ((? channel? guix)
+ ;; Apply '--url', '--commit', and '--branch' to the 'guix' channel.
+ (let ((url (or url (channel-url guix))))
+ (cons (match ref
(('commit . commit)
- (channel (inherit one)
+ (channel (inherit guix)
(url url) (commit commit) (branch #f)))
(('branch . branch)
- (channel (inherit one)
+ (channel (inherit guix)
(url url) (commit #f) (branch branch)))
(#f
- (channel (inherit one) (url url)))))))
- (_
- ;; Otherwise bail out.
- (leave
- (G_ "'--url', '--commit', and '--branch' are not applicable~%"))))
+ (channel (inherit guix) (url url))))
+ (remove guix-channel? channels))))
+ (#f ;no 'guix' channel, failure will ensue
+ channels))
channels)))
@@ -515,11 +561,11 @@ Use '~/.config/guix/channels.scm' instead."))
(cache (string-append (cache-directory) "/pull"))
(channels (channel-list opts))
(profile (or (assoc-ref opts 'profile) %current-profile)))
- (ensure-default-profile)
(cond ((assoc-ref opts 'query)
(process-query opts profile))
(else
(with-store store
+ (ensure-default-profile)
(with-status-verbosity (assoc-ref opts 'verbosity)
(parameterize ((%current-system (assoc-ref opts 'system))
(%graft? (assoc-ref opts 'graft?))
diff --git a/guix/scripts/refresh.scm b/guix/scripts/refresh.scm
index 5b0f345cde..dd7026a6a4 100644
--- a/guix/scripts/refresh.scm
+++ b/guix/scripts/refresh.scm
@@ -297,7 +297,7 @@ KEY-DOWNLOAD specifies a download policy for missing OpenPGP keys; allowed
values: 'interactive' (default), 'always', and 'never'. When WARN? is true,
warn about packages that have no matching updater."
(if (lookup-updater package updaters)
- (let-values (((version tarball changes)
+ (let-values (((version tarball source)
(package-update store package updaters
#:key-download key-download))
((loc)
@@ -330,10 +330,10 @@ warn about packages that have no matching updater."
(G_ "~a: consider removing this propagated input: ~a~%")))
(package-name package)
(upstream-input-change-name change)))
- (changes))
+ (upstream-source-input-changes source))
(let ((hash (call-with-input-file tarball
port-sha256)))
- (update-package-source package version hash)))
+ (update-package-source package source hash)))
(warning (G_ "~a: version ~a could not be \
downloaded and authenticated; not updating~%")
(package-name package) version))))
diff --git a/guix/scripts/remove.scm b/guix/scripts/remove.scm
new file mode 100644
index 0000000000..2f06ea4f37
--- /dev/null
+++ b/guix/scripts/remove.scm
@@ -0,0 +1,77 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 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 remove)
+ #:use-module (guix ui)
+ #:use-module (guix scripts package)
+ #:use-module (guix scripts build)
+ #:use-module (guix scripts)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (srfi srfi-37)
+ #:export (guix-remove))
+
+(define (show-help)
+ (display (G_ "Usage: guix remove [OPTION] PACKAGES...
+Remove the given PACKAGES.
+This is an alias for 'guix package -r'.\n"))
+ (display (G_ "
+ -p, --profile=PROFILE use PROFILE instead of the user's default profile"))
+ ;; '--bootstrap' not shown here.
+ (display (G_ "
+ -v, --verbosity=LEVEL use the given verbosity LEVEL"))
+ (newline)
+ (show-build-options-help)
+ (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 %options
+ ;; Specification of the command-line options.
+ (cons* (option '(#\h "help") #f #f
+ (lambda args
+ (show-help)
+ (exit 0)))
+ (option '(#\V "version") #f #f
+ (lambda args
+ (show-version-and-exit "guix remove")))
+
+ ;; Preserve some of the 'guix package' options.
+ (append (filter (lambda (option)
+ (any (cut member <> (option-names option))
+ '("profile" "dry-run" "verbosity" "bootstrap")))
+ %package-options)
+
+ %standard-build-options)))
+
+(define (guix-remove . args)
+ (define (handle-argument arg result arg-handler)
+ ;; Treat all non-option arguments as package specs.
+ (values (alist-cons 'remove arg result)
+ arg-handler))
+
+ (define opts
+ (parse-command-line args %options
+ (list %package-default-options #f)
+ #:argument-handler handle-argument))
+
+ (guix-package* opts))
diff --git a/guix/scripts/search.scm b/guix/scripts/search.scm
new file mode 100644
index 0000000000..8fceb83668
--- /dev/null
+++ b/guix/scripts/search.scm
@@ -0,0 +1,67 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 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 search)
+ #:use-module (guix ui)
+ #:use-module (guix scripts package)
+ #:use-module (guix scripts)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (srfi srfi-37)
+ #:export (guix-search))
+
+(define (show-help)
+ (display (G_ "Usage: guix search [OPTION] REGEXPS...
+Search for packages matching REGEXPS."))
+ (display (G_"
+This is an alias for 'guix package -s'.\n"))
+ (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 %options
+ ;; Specification of the command-line options.
+ (list (option '(#\h "help") #f #f
+ (lambda args
+ (show-help)
+ (exit 0)))
+ (option '(#\V "version") #f #f
+ (lambda args
+ (show-version-and-exit "guix search")))))
+
+(define (guix-search . args)
+ (define (handle-argument arg result)
+ ;; Treat all non-option arguments as regexps.
+ (cons `(query search ,(or arg ""))
+ result))
+
+ (define opts
+ (args-fold* args %options
+ (lambda (opt name arg . rest)
+ (leave (G_ "~A: unrecognized option~%") name))
+ handle-argument
+ '()))
+
+ (unless (assoc-ref opts 'query)
+ (leave (G_ "missing arguments: no regular expressions to search for~%")))
+
+ (guix-package* opts))
diff --git a/guix/scripts/size.scm b/guix/scripts/size.scm
index 25218a2945..f549ce05b8 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 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -34,6 +34,7 @@
#:use-module (srfi srfi-37)
#:use-module (ice-9 match)
#:use-module (ice-9 format)
+ #:use-module (ice-9 vlist)
#:export (profile?
profile-file
profile-self-size
@@ -142,11 +143,20 @@ profile of ITEMS and their requisites."
(lambda (size)
(return (cons item size)))))
refs)))
+ (define size-table
+ (fold (lambda (pair result)
+ (match pair
+ ((item . size)
+ (vhash-cons item size result))))
+ vlist-null sizes))
+
(define (dependency-size item)
(mlet %store-monad ((deps (requisites* (list item))))
(foldm %store-monad
(lambda (item total)
- (return (+ (assoc-ref sizes item) total)))
+ (return (+ (match (vhash-assoc item size-table)
+ ((_ . size) size))
+ total)))
0
(delete-duplicates (cons item deps)))))
diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm
index 97508f4bd6..3c3d6cbd5f 100644
--- a/guix/scripts/system.scm
+++ b/guix/scripts/system.scm
@@ -855,7 +855,7 @@ static checks."
(bootloader-configuration-bootloader (operating-system-bootloader os)))
(define bootcfg
- (and (not (eq? 'container action))
+ (and (memq action '(init reconfigure))
(operating-system-bootcfg os menu-entries)))
(define bootloader-script
@@ -1299,8 +1299,7 @@ argument list and OPTS is the option alist."
(command (assoc-ref opts 'action)))
(parameterize ((%graft? (assoc-ref opts 'graft?)))
(with-status-verbosity (or (assoc-ref opts 'verbosity)
- (if (memq command '(init reconfigure))
- 1 2))
+ (if (eq? command 'build) 2 1))
(process-command command args opts))))))
;;; Local Variables:
diff --git a/guix/scripts/upgrade.scm b/guix/scripts/upgrade.scm
new file mode 100644
index 0000000000..7f14a2fdbe
--- /dev/null
+++ b/guix/scripts/upgrade.scm
@@ -0,0 +1,88 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 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 upgrade)
+ #:use-module (guix ui)
+ #:use-module (guix scripts package)
+ #:use-module (guix scripts build)
+ #:use-module (guix scripts)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (srfi srfi-37)
+ #:use-module (ice-9 match)
+ #:export (guix-upgrade))
+
+(define (show-help)
+ (display (G_ "Usage: guix upgrade [OPTION] [REGEXP]
+Upgrade packages that match REGEXP.
+This is an alias for 'guix package -u'.\n"))
+ (display (G_ "
+ -p, --profile=PROFILE use PROFILE instead of the user's default profile"))
+ (display (G_ "
+ -v, --verbosity=LEVEL use the given verbosity LEVEL"))
+ (newline)
+ (show-build-options-help)
+ (newline)
+ (show-transformation-options-help)
+ (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 %options
+ ;; Specification of the command-line options.
+ (cons* (option '(#\h "help") #f #f
+ (lambda args
+ (show-help)
+ (exit 0)))
+ (option '(#\V "version") #f #f
+ (lambda args
+ (show-version-and-exit "guix upgrade")))
+
+ ;; Preserve some of the 'guix package' options.
+ (append (filter (lambda (option)
+ (any (cut member <> (option-names option))
+ '("profile" "dry-run" "verbosity")))
+ %package-options)
+
+ %transformation-options
+ %standard-build-options)))
+
+(define (guix-upgrade . args)
+ (define (handle-argument arg result arg-handler)
+ ;; Accept at most one non-option argument, and treat it as an upgrade
+ ;; regexp.
+ (match (assq-ref result 'upgrade)
+ (#f
+ (values (alist-cons 'upgrade arg
+ (alist-delete 'upgrade result))
+ arg-handler))
+ (_
+ (leave (G_ "~A: extraneous argument~%") arg))))
+
+ (define opts
+ (parse-command-line args %options
+ (list `((upgrade . #f)
+ ,@%package-default-options)
+ #f)
+ #:argument-handler handle-argument))
+
+ (guix-package* opts))