summaryrefslogtreecommitdiff
path: root/guix/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'guix/scripts')
-rw-r--r--guix/scripts/container/exec.scm2
-rw-r--r--guix/scripts/deploy.scm52
-rw-r--r--guix/scripts/describe.scm27
-rw-r--r--guix/scripts/download.scm15
-rw-r--r--guix/scripts/environment.scm42
-rw-r--r--guix/scripts/gc.scm15
-rw-r--r--guix/scripts/import.scm4
-rw-r--r--guix/scripts/import/cran.scm9
-rw-r--r--guix/scripts/import/crate.scm41
-rw-r--r--guix/scripts/lint.scm6
-rw-r--r--guix/scripts/offload.scm3
-rw-r--r--guix/scripts/pack.scm93
-rw-r--r--guix/scripts/package.scm30
-rw-r--r--guix/scripts/pull.scm242
-rw-r--r--guix/scripts/refresh.scm57
-rw-r--r--guix/scripts/search.scm11
-rw-r--r--guix/scripts/show.scm76
-rw-r--r--guix/scripts/system.scm6
18 files changed, 587 insertions, 144 deletions
diff --git a/guix/scripts/container/exec.scm b/guix/scripts/container/exec.scm
index d598f5cac4..51b616b384 100644
--- a/guix/scripts/container/exec.scm
+++ b/guix/scripts/container/exec.scm
@@ -38,7 +38,7 @@
(define (show-help)
(display (G_ "Usage: guix container exec PID COMMAND [ARGS...]
-Execute COMMMAND within the container process PID.\n"))
+Execute COMMAND within the container process PID.\n"))
(newline)
(display (G_ "
-h, --help display this help and exit"))
diff --git a/guix/scripts/deploy.scm b/guix/scripts/deploy.scm
index ebc99e52cc..f311587ec3 100644
--- a/guix/scripts/deploy.scm
+++ b/guix/scripts/deploy.scm
@@ -26,8 +26,11 @@
#:use-module (guix ui)
#:use-module (guix utils)
#:use-module (guix grafts)
+ #:use-module (guix status)
#:use-module (ice-9 format)
#:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-34)
+ #:use-module (srfi srfi-35)
#:use-module (srfi srfi-37)
#:export (guix-deploy))
@@ -43,8 +46,6 @@
(define (show-help)
(display (G_ "Usage: guix deploy [OPTION] FILE...
Perform the deployment specified by FILE.\n"))
- (display (G_ "
- -s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\""))
(show-build-options-help)
(newline)
(display (G_ "
@@ -52,6 +53,8 @@ Perform the deployment specified by FILE.\n"))
(display (G_ "
-V, --version display version information and exit"))
(newline)
+ (display (G_ "
+ -v, --verbosity=LEVEL use the given verbosity LEVEL"))
(show-bug-report-information))
(define %options
@@ -63,15 +66,24 @@ Perform the deployment specified by FILE.\n"))
(lambda (opt name arg result)
(alist-cons 'system arg
(alist-delete 'system result eq?))))
+ (option '(#\v "verbosity") #t #f
+ (lambda (opt name arg result)
+ (let ((level (string->number* arg)))
+ (alist-cons 'verbosity level
+ (alist-delete 'verbosity result)))))
+
%standard-build-options))
(define %default-options
- `((system . ,(%current-system))
+ ;; Alist of default option values.
+ `((verbosity . 1)
+ (debug . 0)
+ (graft? . #t)
(substitutes? . #t)
(build-hook? . #t)
- (graft? . #t)
- (debug . 0)
- (verbosity . 1)))
+ (print-build-trace? . #t)
+ (print-extended-build-trace? . #t)
+ (multiplexed-build-output? . #t)))
(define (load-source-file file)
"Load FILE as a user module."
@@ -84,15 +96,27 @@ Perform the deployment specified by FILE.\n"))
(define (guix-deploy . args)
(define (handle-argument arg result)
(alist-cons 'file arg result))
+
(let* ((opts (parse-command-line args %options (list %default-options)
#:argument-handler handle-argument))
(file (assq-ref opts 'file))
(machines (or (and file (load-source-file file)) '())))
- (with-store store
- (set-build-options-from-command-line store opts)
- (for-each (lambda (machine)
- (info (G_ "deploying to ~a...") (machine-display-name machine))
- (parameterize ((%current-system (assq-ref opts 'system))
- (%graft? (assq-ref opts 'graft?)))
- (run-with-store store (deploy-machine machine))))
- machines))))
+ (with-status-verbosity (assoc-ref opts 'verbosity)
+ (with-store store
+ (set-build-options-from-command-line store opts)
+ (for-each (lambda (machine)
+ (info (G_ "deploying to ~a...~%")
+ (machine-display-name machine))
+ (parameterize ((%graft? (assq-ref opts 'graft?)))
+ (guard (c ((message-condition? c)
+ (report-error (G_ "failed to deploy ~a: ~a~%")
+ (machine-display-name machine)
+ (condition-message c)))
+ ((deploy-error? c)
+ (when (deploy-error-should-roll-back c)
+ (info (G_ "rolling back ~a...~%")
+ (machine-display-name machine))
+ (run-with-store store (roll-back-machine machine)))
+ (apply throw (deploy-error-captured-args c))))
+ (run-with-store store (deploy-machine machine)))))
+ machines)))))
diff --git a/guix/scripts/describe.scm b/guix/scripts/describe.scm
index fa6b6cae37..99a88c50fa 100644
--- a/guix/scripts/describe.scm
+++ b/guix/scripts/describe.scm
@@ -153,30 +153,9 @@ in the format specified by FMT."
(generation-number profile))
(define channels
- (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.
- (_ (channel (name 'guix)
- (url "?")
- (commit "?")))))
-
- ;; Show most recently installed packages last.
- (reverse
- (manifest-entries
- (profile-manifest
- (if (zero? number)
- profile
- (generation-file-name profile number)))))))
+ (profile-channels (if (zero? number)
+ profile
+ (generation-file-name profile number))))
(match fmt
('human
diff --git a/guix/scripts/download.scm b/guix/scripts/download.scm
index d8fe71ce12..22cd75ea0b 100644
--- a/guix/scripts/download.scm
+++ b/guix/scripts/download.scm
@@ -33,6 +33,7 @@
#:use-module (web uri)
#:use-module (ice-9 match)
#:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-14)
#:use-module (srfi srfi-26)
#:use-module (srfi srfi-37)
#:use-module (rnrs bytevectors)
@@ -54,9 +55,23 @@
(url-fetch url file #:mirrors %mirrors)))
file))
+(define (ensure-valid-store-file-name name)
+ "Replace any character not allowed in a stror name by an underscore."
+
+ (define valid
+ ;; according to nix/libstore/store-api.cc
+ (string->char-set (string-append "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789" "+-._?=")))
+ (string-map (lambda (c)
+ (if (char-set-contains? valid c) c #\_))
+ name))
+
+
(define* (download-to-store* url #:key (verify-certificate? #t))
(with-store store
(download-to-store store url
+ (ensure-valid-store-file-name (basename url))
#:verify-certificate? verify-certificate?)))
(define %default-options
diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm
index cf58768300..d78ca0f303 100644
--- a/guix/scripts/environment.scm
+++ b/guix/scripts/environment.scm
@@ -29,7 +29,7 @@
#:use-module (guix search-paths)
#:use-module (guix build utils)
#:use-module (guix monads)
- #:use-module ((guix gexp) #:select (lower-inputs))
+ #:use-module ((guix gexp) #:select (lower-object))
#:use-module (guix scripts)
#:use-module (guix scripts build)
#:use-module (gnu build linux-container)
@@ -40,7 +40,8 @@
#:use-module (gnu packages bash)
#:use-module (gnu packages commencement)
#:use-module (gnu packages guile)
- #:use-module ((gnu packages bootstrap) #:select (%bootstrap-guile))
+ #:use-module ((gnu packages bootstrap)
+ #:select (bootstrap-executable %bootstrap-guile))
#:use-module (ice-9 format)
#:use-module (ice-9 match)
#:use-module (ice-9 rdelim)
@@ -452,7 +453,7 @@ regexps in WHITE-LIST."
(define* (launch-environment/container #:key command bash user user-mappings
profile manifest link-profile? network?
- map-cwd?)
+ map-cwd? (white-list '()))
"Run COMMAND within a container that features the software in PROFILE.
Environment variables are set according to the search paths of MANIFEST.
The global shell is BASH, a file name for a GNU Bash binary in the
@@ -461,7 +462,14 @@ USER-MAPPINGS, a list of file system mappings, contains the user-specified
host file systems to mount inside the container. If USER is not #f, each
target of USER-MAPPINGS will be re-written relative to '/home/USER', and USER
will be used for the passwd entry. LINK-PROFILE? creates a symbolic link from
-~/.guix-profile to the environment profile."
+~/.guix-profile to the environment profile.
+
+Preserve environment variables whose name matches the one of the regexps in
+WHILE-LIST."
+ (define (optional-mapping->fs mapping)
+ (and (file-exists? (file-system-mapping-source mapping))
+ (file-system-mapping->bind-mount mapping)))
+
(mlet %store-monad ((reqs (inputs->requisites
(list (direct-store-path bash) profile))))
(return
@@ -483,6 +491,11 @@ will be used for the passwd entry. LINK-PROFILE? creates a symbolic link from
(group-entry (gid 65534) ;the overflow GID
(name "overflow"))))
(home-dir (password-entry-directory passwd))
+ (environ (filter (match-lambda
+ ((variable . value)
+ (find (cut regexp-exec <> variable)
+ white-list)))
+ (get-environment-variables)))
;; Bind-mount all requisite store items, user-specified mappings,
;; /bin/sh, the current working directory, and possibly networking
;; configuration files within the container.
@@ -498,11 +511,6 @@ will be used for the passwd entry. LINK-PROFILE? creates a symbolic link from
(target cwd)
(writable? #t)))
'())))
- ;; When in Rome, do as Nix build.cc does: Automagically
- ;; map common network configuration files.
- (if network?
- %network-file-mappings
- '())
;; Mappings for the union closure of all inputs.
(map (lambda (dir)
(file-system-mapping
@@ -511,6 +519,10 @@ will be used for the passwd entry. LINK-PROFILE? creates a symbolic link from
(writable? #f)))
reqs)))
(file-systems (append %container-file-systems
+ (if network?
+ (filter-map optional-mapping->fs
+ %network-file-mappings)
+ '())
(map file-system-mapping->bind-mount
mappings))))
(exit/status
@@ -552,6 +564,12 @@ will be used for the passwd entry. LINK-PROFILE? creates a symbolic link from
(override-user-dir user home cwd)
home-dir))
+ ;; Set environment variables that match WHITE-LIST.
+ (for-each (match-lambda
+ ((variable . value)
+ (setenv variable value)))
+ environ)
+
(primitive-exit/status
;; A container's environment is already purified, so no need to
;; request it be purified again.
@@ -613,8 +631,7 @@ Otherwise, return the derivation for the Bash package."
(package->derivation bash))
;; Use the bootstrap Bash instead.
((and container? bootstrap?)
- (interned-file
- (search-bootstrap-binary "bash" system)))
+ (lower-object (bootstrap-executable "bash" system)))
(else
(return #f)))))
@@ -747,7 +764,7 @@ message if any test fails."
(container?
(let ((bash-binary
(if bootstrap?
- bash
+ (derivation->output-path bash)
(string-append (derivation->output-path bash)
"/bin/sh"))))
(launch-environment/container #:command command
@@ -756,6 +773,7 @@ message if any test fails."
#:user-mappings mappings
#:profile profile
#:manifest manifest
+ #:white-list white-list
#:link-profile? link-prof?
#:network? network?
#:map-cwd? (not no-cwd?))))
diff --git a/guix/scripts/gc.scm b/guix/scripts/gc.scm
index 31657326b6..3f20a2e192 100644
--- a/guix/scripts/gc.scm
+++ b/guix/scripts/gc.scm
@@ -57,6 +57,8 @@ Invoke the garbage collector.\n"))
(display (G_ "
--list-roots list the user's garbage collector roots"))
(display (G_ "
+ --list-busy list store items used by running processes"))
+ (display (G_ "
--optimize optimize the store by deduplicating identical files"))
(display (G_ "
--list-dead list dead paths"))
@@ -174,6 +176,10 @@ is deprecated; use '-D'~%"))
(lambda (opt name arg result)
(alist-cons 'action 'list-roots
(alist-delete 'action result))))
+ (option '("list-busy") #f #f
+ (lambda (opt name arg result)
+ (alist-cons 'action 'list-busy
+ (alist-delete 'action result))))
(option '("list-dead") #f #f
(lambda (opt name arg result)
(alist-cons 'action 'list-dead
@@ -265,6 +271,12 @@ is deprecated; use '-D'~%"))
(newline))
roots)))
+ (define (list-busy)
+ ;; List store items used by running processes.
+ (for-each (lambda (item)
+ (display item) (newline))
+ (busy-store-items)))
+
(with-error-handling
(let* ((opts (parse-options))
(store (open-connection))
@@ -305,6 +317,9 @@ is deprecated; use '-D'~%"))
((list-roots)
(assert-no-extra-arguments)
(list-roots))
+ ((list-busy)
+ (assert-no-extra-arguments)
+ (list-busy))
((delete)
(delete-paths store (map direct-store-path paths)))
((list-references)
diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm
index 0b326e1049..c6cc93fad8 100644
--- a/guix/scripts/import.scm
+++ b/guix/scripts/import.scm
@@ -2,6 +2,7 @@
;;; Copyright © 2012, 2013, 2014 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>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -113,7 +114,8 @@ Run IMPORTER with ARGS.\n"))
(pretty-print expr (newline-rewriting-port
(current-output-port))))))
(match (apply (resolve-importer importer) args)
- ((and expr ('package _ ...))
+ ((and expr (or ('package _ ...)
+ ('let _ ...)))
(print expr))
((? list? expressions)
(for-each (lambda (expr)
diff --git a/guix/scripts/import/cran.scm b/guix/scripts/import/cran.scm
index 794fb710cd..b6592f78a9 100644
--- a/guix/scripts/import/cran.scm
+++ b/guix/scripts/import/cran.scm
@@ -1,6 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
-;;; Copyright © 2015, 2017 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2015, 2017, 2019 Ricardo Wurmus <rekado@elephly.net>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -22,6 +22,7 @@
#:use-module (guix utils)
#:use-module (guix scripts)
#:use-module (guix import cran)
+ #:use-module (guix import utils)
#:use-module (guix scripts import)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-11)
@@ -96,11 +97,7 @@ Import and convert the CRAN package for PACKAGE-NAME.\n"))
((package-name)
(if (assoc-ref opts 'recursive)
;; Recursive import
- (map (match-lambda
- ((and ('package ('name name) . rest) pkg)
- `(define-public ,(string->symbol name)
- ,pkg))
- (_ #f))
+ (map package->definition
(reverse
(stream->list
(cran-recursive-import package-name
diff --git a/guix/scripts/import/crate.scm b/guix/scripts/import/crate.scm
index cab9a4397b..4690cceb4d 100644
--- a/guix/scripts/import/crate.scm
+++ b/guix/scripts/import/crate.scm
@@ -2,6 +2,7 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2014 David Thompson <davet@gnu.org>
;;; Copyright © 2016 David Craven <david@craven.ch>
+;;; Copyright © 2019 Martin Becze <mjbecze@riseup.net>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -27,6 +28,7 @@
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-11)
#:use-module (srfi srfi-37)
+ #:use-module (srfi srfi-41)
#:use-module (ice-9 match)
#:use-module (ice-9 format)
#:export (guix-import-crate))
@@ -43,6 +45,9 @@
(display (G_ "Usage: guix import crate PACKAGE-NAME
Import and convert the crate.io package for PACKAGE-NAME.\n"))
(display (G_ "
+ -r, --recursive import packages recursively"))
+ (newline)
+ (display (G_ "
-h, --help display this help and exit"))
(display (G_ "
-V, --version display version information and exit"))
@@ -58,6 +63,9 @@ Import and convert the crate.io package for PACKAGE-NAME.\n"))
(option '(#\V "version") #f #f
(lambda args
(show-version-and-exit "guix import crate")))
+ (option '(#\r "recursive") #f #f
+ (lambda (opt name arg result)
+ (alist-cons 'recursive #t result)))
%standard-import-options))
@@ -75,19 +83,34 @@ Import and convert the crate.io package for PACKAGE-NAME.\n"))
(alist-cons 'argument arg result))
%default-options))
+
(let* ((opts (parse-options))
(args (filter-map (match-lambda
- (('argument . value)
- value)
- (_ #f))
+ (('argument . value)
+ value)
+ (_ #f))
(reverse opts))))
(match args
- ((package-name)
- (let ((sexp (crate->guix-package package-name)))
- (unless sexp
- (leave (G_ "failed to download meta-data for package '~a'~%")
- package-name))
- sexp))
+ ((spec)
+ (define-values (name version)
+ (package-name->name+version spec))
+
+ (if (assoc-ref opts 'recursive)
+ (map (match-lambda
+ ((and ('package ('name name) . rest) pkg)
+ `(define-public ,(string->symbol name)
+ ,pkg))
+ (_ #f))
+ (reverse
+ (stream->list
+ (crate-recursive-import name))))
+ (let ((sexp (crate->guix-package name version)))
+ (unless sexp
+ (leave (G_ "failed to download meta-data for package '~a'~%")
+ (if version
+ (string-append name "@" version)
+ name)))
+ sexp)))
(()
(leave (G_ "too few arguments~%")))
((many ...)
diff --git a/guix/scripts/lint.scm b/guix/scripts/lint.scm
index ee1c826d2e..1668d02992 100644
--- a/guix/scripts/lint.scm
+++ b/guix/scripts/lint.scm
@@ -46,9 +46,9 @@
(lambda (lint-warning)
(let ((package (lint-warning-package lint-warning))
(loc (lint-warning-location lint-warning)))
- (warning loc (G_ "~a@~a: ~a~%")
- (package-name package) (package-version package)
- (lint-warning-message lint-warning))))
+ (info loc (G_ "~a@~a: ~a~%")
+ (package-name package) (package-version package)
+ (lint-warning-message lint-warning))))
warnings))
(define (run-checkers package checkers)
diff --git a/guix/scripts/offload.scm b/guix/scripts/offload.scm
index 0c0dd9d516..bb307cefd1 100644
--- a/guix/scripts/offload.scm
+++ b/guix/scripts/offload.scm
@@ -243,7 +243,8 @@ instead of '~a' of type '~a'~%")
;; of these; if we fail, that means all the build slots are already taken.
;; Inspired by Nix's build-remote.pl.
(string-append (string-append %state-directory "/offload/"
- (build-machine-name machine)
+ (build-machine-name machine) ":"
+ (number->string (build-machine-port machine))
"/" (number->string slot))))
(define (acquire-build-slot machine)
diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm
index fdb98983bf..920d6c01fe 100644
--- a/guix/scripts/pack.scm
+++ b/guix/scripts/pack.scm
@@ -490,7 +490,8 @@ the image."
#~(begin
(use-modules (guix docker) (guix build store-copy)
(guix profiles) (guix search-paths)
- (srfi srfi-19) (ice-9 match))
+ (srfi srfi-1) (srfi srfi-19)
+ (ice-9 match))
(define environment
(map (match-lambda
@@ -499,6 +500,35 @@ the image."
value)))
(profile-search-paths #$profile)))
+ (define symlink->directives
+ ;; Return "populate directives" to make the given symlink and its
+ ;; parent directories.
+ (match-lambda
+ ((source '-> target)
+ (let ((target (string-append #$profile "/" target))
+ (parent (dirname source)))
+ `((directory ,parent)
+ (,source -> ,target))))))
+
+ (define directives
+ ;; Create a /tmp directory, as some programs expect it, and
+ ;; create SYMLINKS.
+ `((directory "/tmp" ,(getuid) ,(getgid) #o1777)
+ ,@(append-map symlink->directives '#$symlinks)))
+
+ (define tag
+ ;; Compute a meaningful "repository" name, which will show up in
+ ;; the output of "docker images".
+ (let ((manifest (profile-manifest #$profile)))
+ (let loop ((names (map manifest-entry-name
+ (manifest-entries manifest))))
+ (define str (string-join names "-"))
+ (if (< (string-length str) 40)
+ str
+ (match names
+ ((_) str)
+ ((names ... _) (loop names))))))) ;drop one entry
+
(setenv "PATH" (string-append #$archiver "/bin"))
(build-docker-image #$output
@@ -506,6 +536,7 @@ the image."
(call-with-input-file "profile"
read-reference-graph))
#$profile
+ #:repository tag
#:database #+database
#:system (or #$target (utsname:machine (uname)))
#:environment environment
@@ -513,7 +544,7 @@ the image."
#$(and entry-point
#~(list (string-append #$profile "/"
#$entry-point)))
- #:symlinks '#$symlinks
+ #:extra-files directives
#:compressor '#$(compressor-command compressor)
#:creation-time (make-time time-utc 0 1))))))
@@ -543,9 +574,9 @@ the image."
"Return the C compiler that uses the bootstrap toolchain. This is used only
by '--bootstrap', for testing purposes."
(define bootstrap-toolchain
- (list (first (assoc-ref %bootstrap-inputs "gcc"))
- (first (assoc-ref %bootstrap-inputs "binutils"))
- (first (assoc-ref %bootstrap-inputs "libc"))))
+ (list (first (assoc-ref (%bootstrap-inputs) "gcc"))
+ (first (assoc-ref (%bootstrap-inputs) "binutils"))
+ (first (assoc-ref (%bootstrap-inputs) "libc"))))
(c-compiler bootstrap-toolchain
#:guile %bootstrap-guile))
@@ -611,8 +642,13 @@ please email '~a'~%")
;;;
(define* (wrapped-package package
- #:optional (compiler (c-compiler))
+ #:optional
+ (output* "out")
+ (compiler (c-compiler))
#:key proot?)
+ "Return the OUTPUT of PACKAGE with its binaries wrapped such that they are
+relocatable. When PROOT? is true, include PRoot in the result and use it as a
+last resort for relocation."
(define runner
(local-file (search-auxiliary-file "run-in-namespace.c")))
@@ -629,6 +665,14 @@ please email '~a'~%")
(ice-9 ftw)
(ice-9 match))
+ (define input
+ ;; The OUTPUT* output of PACKAGE.
+ (ungexp package output*))
+
+ (define target
+ ;; The output we are producing.
+ (ungexp output output*))
+
(define (strip-store-prefix file)
;; Given a file name like "/gnu/store/…-foo-1.2/bin/foo", return
;; "/bin/foo".
@@ -648,7 +692,7 @@ please email '~a'~%")
(("@STORE_DIRECTORY@") (%store-directory)))
(let* ((base (strip-store-prefix program))
- (result (string-append #$output "/" base))
+ (result (string-append target "/" base))
(proot #$(and proot?
#~(string-drop
#$(file-append (proot) "/bin/proot")
@@ -667,18 +711,18 @@ please email '~a'~%")
;; Link the top-level files of PACKAGE so that search paths are
;; properly defined in PROFILE/etc/profile.
- (mkdir #$output)
+ (mkdir target)
(for-each (lambda (file)
(unless (member file '("." ".." "bin" "sbin" "libexec"))
- (let ((file* (string-append #$package "/" file)))
- (symlink (relative-file-name #$output file*)
- (string-append #$output "/" file)))))
- (scandir #$package))
+ (let ((file* (string-append input "/" file)))
+ (symlink (relative-file-name target file*)
+ (string-append target "/" file)))))
+ (scandir input))
(for-each build-wrapper
- (append (find-files #$(file-append package "/bin"))
- (find-files #$(file-append package "/sbin"))
- (find-files #$(file-append package "/libexec")))))))
+ (append (find-files (string-append input "/bin"))
+ (find-files (string-append input "/sbin"))
+ (find-files (string-append input "/libexec")))))))
(computed-file (string-append
(cond ((package? package)
@@ -691,14 +735,18 @@ please email '~a'~%")
"R")
build))
+(define (wrapped-manifest-entry entry . args)
+ (manifest-entry
+ (inherit entry)
+ (item (apply wrapped-package
+ (manifest-entry-item entry)
+ (manifest-entry-output entry)
+ args))))
+
(define (map-manifest-entries proc manifest)
"Apply PROC to all the entries of MANIFEST and return a new manifest."
(make-manifest
- (map (lambda (entry)
- (manifest-entry
- (inherit entry)
- (item (proc (manifest-entry-item entry)))))
- (manifest-entries manifest))))
+ (map proc (manifest-entries manifest))))
;;;
@@ -909,7 +957,8 @@ Create a bundle of PACKAGE.\n"))
(list (transform store package) output))
((? package? package)
(list (transform store package) "out")))
- (filter-map maybe-package-argument opts)))
+ (reverse
+ (filter-map maybe-package-argument opts))))
(manifest-file (assoc-ref opts 'manifest)))
(define properties
(if (assoc-ref opts 'save-provenance?)
@@ -960,7 +1009,7 @@ Create a bundle of PACKAGE.\n"))
;; 'glibc-bootstrap' lacks 'libc.a'.
(if relocatable?
(map-manifest-entries
- (cut wrapped-package <> #:proot? proot?)
+ (cut wrapped-manifest-entry <> #:proot? proot?)
manifest)
manifest)))
(pack-format (assoc-ref opts 'format))
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index a43c96516f..1a58d43e5c 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -39,6 +39,7 @@
#:use-module (guix scripts)
#:use-module (guix scripts build)
#:autoload (guix describe) (package-provenance)
+ #:autoload (guix store roots) (gc-roots)
#:use-module ((guix build utils)
#:select (directory-exists? mkdir-p))
#:use-module (ice-9 format)
@@ -359,6 +360,8 @@ Install, remove, or upgrade packages in a single transaction.\n"))
switch to a generation matching PATTERN"))
(display (G_ "
-p, --profile=PROFILE use PROFILE instead of the user's default profile"))
+ (display (G_ "
+ --list-profiles list the user's profiles"))
(newline)
(display (G_ "
--allow-collisions do not treat collisions in the profile as an error"))
@@ -458,6 +461,11 @@ command-line option~%")
(values (cons `(query list-generations ,arg)
result)
#f)))
+ (option '("list-profiles") #f #f
+ (lambda (opt name arg result arg-handler)
+ (values (cons `(query list-profiles #t)
+ result)
+ #f)))
(option '(#\d "delete-generations") #f #t
(lambda (opt name arg result arg-handler)
(values (alist-cons 'delete-generations arg
@@ -607,7 +615,11 @@ and upgrades."
(let-values (((package output)
(specification->package+output spec)))
(package->manifest-entry* package output))))
- (_ #f))
+ (('install . obj)
+ (leave (G_ "cannot install non-package object: ~s~%")
+ obj))
+ (_
+ #f))
opts))
(fold manifest-transaction-install-entry
@@ -746,6 +758,19 @@ processed, #f otherwise."
(string<? name1 name2))))))
#t))
+ (('list-profiles _)
+ (let ((profiles (delete-duplicates
+ (filter-map (lambda (root)
+ (and (or (zero? (getuid))
+ (user-owned? root))
+ (generation-profile root)))
+ (gc-roots)))))
+ (leave-on-EPIPE
+ (for-each (lambda (profile)
+ (display (user-friendly-profile profile))
+ (newline))
+ (sort profiles string<?)))))
+
(('search _)
(let* ((patterns (filter-map (match-lambda
(('query 'search rx) rx)
@@ -760,7 +785,8 @@ processed, #f otherwise."
(('show requested-name)
(let-values (((name version)
(package-name->name+version requested-name)))
- (match (find-packages-by-name name version)
+ (match (remove package-superseded
+ (find-packages-by-name name version))
(()
(leave (G_ "~a~@[@~a~]: package not found~%") name version))
(packages
diff --git a/guix/scripts/pull.scm b/guix/scripts/pull.scm
index 54bbaddf30..04970cf503 100644
--- a/guix/scripts/pull.scm
+++ b/guix/scripts/pull.scm
@@ -19,6 +19,7 @@
(define-module (guix scripts pull)
#:use-module (guix ui)
+ #:use-module (guix colors)
#:use-module (guix utils)
#:use-module ((guix status) #:select (with-status-verbosity))
#:use-module (guix scripts)
@@ -38,7 +39,8 @@
#:use-module (guix git)
#:use-module (git)
#:use-module (gnu packages)
- #:use-module ((guix scripts package) #:select (build-and-use-profile))
+ #:use-module ((guix scripts package) #:select (build-and-use-profile
+ delete-matching-generations))
#:use-module ((gnu packages base) #:select (canonical-package))
#:use-module (gnu packages guile)
#:use-module ((gnu packages bootstrap)
@@ -92,6 +94,14 @@ Download and deploy the latest version of Guix.\n"))
-l, --list-generations[=PATTERN]
list generations matching PATTERN"))
(display (G_ "
+ --roll-back roll back to the previous generation"))
+ (display (G_ "
+ -d, --delete-generations[=PATTERN]
+ delete generations matching PATTERN"))
+ (display (G_ "
+ -S, --switch-generation=PATTERN
+ switch to a generation matching PATTERN"))
+ (display (G_ "
-p, --profile=PROFILE use PROFILE instead of ~/.config/guix/current"))
(display (G_ "
-v, --verbosity=LEVEL use the given verbosity LEVEL"))
@@ -120,6 +130,18 @@ Download and deploy the latest version of Guix.\n"))
(lambda (opt name arg result)
(cons `(query list-generations ,arg)
result)))
+ (option '("roll-back") #f #f
+ (lambda (opt name arg result)
+ (cons '(generation roll-back)
+ result)))
+ (option '(#\S "switch-generation") #t #f
+ (lambda (opt name arg result)
+ (cons `(generation switch ,arg)
+ result)))
+ (option '(#\d "delete-generations") #f #t
+ (lambda (opt name arg result)
+ (cons `(generation delete ,arg)
+ result)))
(option '(#\N "news") #f #f
(lambda (opt name arg result)
(cons '(query display-news) result)))
@@ -167,7 +189,7 @@ Download and deploy the latest version of Guix.\n"))
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."
+newest generation of PROFILE. Return true when there's more info to display."
(match (memv (generation-number profile)
(reverse (profile-generations profile)))
((current previous _ ...)
@@ -190,7 +212,162 @@ newest generation of PROFILE."
#:concise? concise?
#:heading
(G_ "New in this revision:\n")))))
- (_ #t)))
+ (_ #f)))
+
+(define (display-channel channel)
+ "Display information about CHANNEL."
+ (format (current-error-port)
+ ;; TRANSLATORS: This describes a "channel"; the first placeholder is
+ ;; the channel name (e.g., "guix") and the second placeholder is its
+ ;; URL.
+ (G_ " ~a at ~a~%")
+ (channel-name channel)
+ (channel-url channel)))
+
+(define (channel=? channel1 channel2)
+ "Return true if CHANNEL1 and CHANNEL2 are the same for all practical
+purposes."
+ ;; Assume that the URL matters less than the name.
+ (eq? (channel-name channel1) (channel-name channel2)))
+
+(define (display-news-entry-title entry language port)
+ "Display the title of ENTRY, a news entry, to PORT."
+ (define title
+ (channel-news-entry-title entry))
+
+ (format port " ~a~%"
+ (highlight
+ (string-trim-right
+ (texi->plain-text (or (assoc-ref title language)
+ (assoc-ref title (%default-message-language))
+ ""))))))
+
+(define (display-news-entry entry language port)
+ "Display ENTRY, a <channel-news-entry>, in LANGUAGE, a language code, to
+PORT."
+ (define body
+ (channel-news-entry-body entry))
+
+ (display-news-entry-title entry language port)
+ (format port (dim (G_ " commit ~a~%"))
+ (channel-news-entry-commit entry))
+ (newline port)
+ (format port " ~a~%"
+ (indented-string
+ (parameterize ((%text-width (- (%text-width) 4)))
+ (string-trim-right
+ (texi->plain-text (or (assoc-ref body language)
+ (assoc-ref body (%default-message-language))
+ ""))))
+ 4)))
+
+(define* (display-channel-specific-news new old
+ #:key (port (current-output-port))
+ concise?)
+ "Display channel news applicable the commits between OLD and NEW, where OLD
+and NEW are <channel> records with a proper 'commit' field. When CONCISE? is
+true, display nothing but the news titles. Return true if there are more news
+to display."
+ (let ((channel new)
+ (old (channel-commit old))
+ (new (channel-commit new)))
+ (when (and old new)
+ (let ((language (current-message-language)))
+ (match (channel-news-for-commit channel new old)
+ (() ;no news is good news
+ #f)
+ ((entries ...)
+ (newline port)
+ (format port (G_ "News for channel '~a'~%")
+ (channel-name channel))
+ (for-each (if concise?
+ (cut display-news-entry-title <> language port)
+ (cut display-news-entry <> language port))
+ entries)
+ (newline port)
+ #t))))))
+
+(define* (display-channel-news profile
+ #:optional
+ (previous
+ (and=> (relative-generation profile -1)
+ (cut generation-file-name profile <>))))
+ "Display news about the channels of PROFILE compared to PREVIOUS."
+ (when previous
+ (let ((old-channels (profile-channels previous))
+ (new-channels (profile-channels profile)))
+ (and (pair? old-channels) (pair? new-channels)
+ (begin
+ (match (lset-difference channel=? new-channels old-channels)
+ (()
+ #t)
+ (new
+ (let ((count (length new)))
+ (format (current-error-port)
+ (N_ " ~a new channel:~%"
+ " ~a new channels:~%" count)
+ count)
+ (for-each display-channel new))))
+ (match (lset-difference channel=? old-channels new-channels)
+ (()
+ #t)
+ (removed
+ (let ((count (length removed)))
+ (format (current-error-port)
+ (N_ " ~a channel removed:~%"
+ " ~a channels removed:~%" count)
+ count)
+ (for-each display-channel removed))))
+
+ ;; Display channel-specific news for those channels that were
+ ;; here before and are still around afterwards.
+ (for-each (match-lambda
+ ((new old)
+ (display-channel-specific-news new old)))
+ (filter-map (lambda (new)
+ (define old
+ (find (cut channel=? new <>)
+ old-channels))
+
+ (and old (list new old)))
+ new-channels)))))))
+
+(define* (display-channel-news-headlines profile)
+ "Display the titles of news about the channels of PROFILE compared to its
+previous generation. Return true if there are news to display."
+ (define previous
+ (and=> (relative-generation profile -1)
+ (cut generation-file-name profile <>)))
+
+ (when previous
+ (let ((old-channels (profile-channels previous))
+ (new-channels (profile-channels profile)))
+ ;; Find the channels present in both PROFILE and PREVIOUS, and print
+ ;; their news.
+ (and (pair? old-channels) (pair? new-channels)
+ (let ((channels (filter-map (lambda (new)
+ (define old
+ (find (cut channel=? new <>)
+ old-channels))
+
+ (and old (list new old)))
+ new-channels)))
+ (define more?
+ (map (match-lambda
+ ((new old)
+ (display-channel-specific-news new old
+ #:concise? #t)))
+ channels))
+
+ (any ->bool more?))))))
+
+(define (display-news profile)
+ ;; Display profile news, with the understanding that this process represents
+ ;; the newest generation.
+ (display-profile-news profile
+ #:current-is-newer? #t)
+
+ (display-channel-news profile))
(define* (build-and-install instances profile
#:key use-substitutes? verbose? dry-run?)
@@ -211,7 +388,12 @@ true, display what would be built without actually building it."
#:dry-run? dry-run?)
(munless dry-run?
(return (newline))
- (return (display-profile-news profile #:concise? #t))
+ (return
+ (let ((more? (list (display-profile-news profile #:concise? #t)
+ (display-channel-news-headlines profile))))
+ (when (any ->bool more?)
+ (display-hint
+ (G_ "Run @command{guix pull --news} to read all the news.")))))
(if guix-command
(let ((new (map (cut string-append <> "/bin/guix")
(list (user-friendly-profile profile)
@@ -293,8 +475,15 @@ true, display what would be built without actually building it."
;; In 0.15.0+ we'd create ~/.config/guix/current-[0-9]*-link symlinks. Move
;; them to %PROFILE-DIRECTORY.
- (unless (string=? %profile-directory
- (dirname (canonicalize-profile %user-profile-directory)))
+ ;;
+ ;; XXX: Ubuntu's 'sudo' preserves $HOME by default, and thus the second
+ ;; condition below is always false when one runs "sudo guix pull". As a
+ ;; workaround, skip this code when $SUDO_USER is set. See
+ ;; <https://bugs.gnu.org/36785>.
+ (unless (or (getenv "SUDO_USER")
+ (string=? %profile-directory
+ (dirname
+ (canonicalize-profile %user-profile-directory))))
(migrate-generations %user-profile-directory %profile-directory))
;; Make sure ~/.config/guix/current points to /var/guix/profiles/….
@@ -404,7 +593,9 @@ it."
"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. When CONCISE? is true, do not
-display long package lists that would fill the user's screen."
+display long package lists that would fill the user's screen.
+
+Return true when there is more package info to display."
(define (pretty str column)
(indented-string (fill-paragraph str (- (%text-width) 4)
column)
@@ -447,11 +638,9 @@ display long package lists that would fill the user's screen."
(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.")))))
+ (and concise?
+ (or (> new-count concise/max-item-count)
+ (> upgraded-count concise/max-item-count)))))
(define (display-profile-content-diff profile gen1 gen2)
"Display the changes in PROFILE GEN2 compared to generation GEN1."
@@ -475,6 +664,8 @@ list of package changes.")))))
((first second rest ...)
(display-profile-content-diff profile
first second)
+ (display-channel-news (generation-file-name profile second)
+ (generation-file-name profile first))
(loop (cons second rest)))
((_) #t)
(() #t))))))
@@ -493,10 +684,23 @@ list of package changes.")))))
((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))))
+ (display-news profile))))
+
+(define (process-generation-change opts profile)
+ "Process a request to change the current generation (roll-back, switch, delete)."
+ (unless (assoc-ref opts 'dry-run?)
+ (match (assoc-ref opts 'generation)
+ (('roll-back)
+ (with-store store
+ (roll-back* store profile)))
+ (('switch pattern)
+ (let ((number (relative-generation-spec->number profile pattern)))
+ (if number
+ (switch-to-generation* profile number)
+ (leave (G_ "cannot switch to generation '~a'~%") pattern))))
+ (('delete pattern)
+ (with-store store
+ (delete-matching-generations store profile pattern))))))
(define (channel-list opts)
"Return the list of channels to use. If OPTS specify a channel file,
@@ -560,18 +764,18 @@ Use '~/.config/guix/channels.scm' instead."))
(with-git-error-handling
(let* ((opts (parse-command-line args %options
(list %default-options)))
- (cache (string-append (cache-directory) "/pull"))
(channels (channel-list opts))
(profile (or (assoc-ref opts 'profile) %current-profile)))
(cond ((assoc-ref opts 'query)
(process-query opts profile))
+ ((assoc-ref opts 'generation)
+ (process-generation-change 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?))
- (%repository-cache-directory cache))
+ (%graft? (assoc-ref opts 'graft?)))
(set-build-options-from-command-line store opts)
(honor-x509-certificates store)
diff --git a/guix/scripts/refresh.scm b/guix/scripts/refresh.scm
index dd7026a6a4..daf6fcf947 100644
--- a/guix/scripts/refresh.scm
+++ b/guix/scripts/refresh.scm
@@ -285,10 +285,9 @@ update would trigger a complete rebuild."
(exit 0))
(define (warn-no-updater package)
- (format (current-error-port)
- (G_ "~a: warning: no updater for ~a~%")
- (location->string (package-location package))
- (package-name package)))
+ (warning (package-location package)
+ (G_ "no updater for ~a~%")
+ (package-name package)))
(define* (update-package store package updaters
#:key (key-download 'interactive) warn?)
@@ -306,11 +305,10 @@ warn about packages that have no matching updater."
(when version
(if (and=> tarball file-exists?)
(begin
- (format (current-error-port)
- (G_ "~a: ~a: updating from version ~a to version ~a...~%")
- (location->string loc)
- (package-name package)
- (package-version package) version)
+ (info loc
+ (G_ "~a: updating from version ~a to version ~a...~%")
+ (package-name package)
+ (package-version package) version)
(for-each
(lambda (change)
(format (current-error-port)
@@ -350,31 +348,36 @@ WARN? is true and no updater exists for PACKAGE, print a warning."
(case (version-compare (upstream-source-version source)
(package-version package))
((>)
- (format (current-error-port)
- (G_ "~a: ~a would be upgraded from ~a to ~a~%")
- (location->string loc)
- (package-name package) (package-version package)
- (upstream-source-version source)))
+ (info loc
+ (G_ "~a would be upgraded from ~a to ~a~%")
+ (package-name package) (package-version package)
+ (upstream-source-version source)))
((=)
(when warn?
- (format (current-error-port)
- (G_ "~a: info: ~a is already the latest version of ~a~%")
- (location->string loc)
- (package-version package)
- (package-name package))))
+ (info loc
+ (G_ "~a is already the latest version of ~a~%")
+ (package-version package)
+ (package-name package))))
(else
(when warn?
- (format (current-error-port)
- (G_ "~a: warning: ~a is greater than \
+ (warning loc
+ (G_ "~a is greater than \
the latest known version of ~a (~a)~%")
- (location->string loc)
- (package-version package)
- (package-name package)
- (upstream-source-version source)))))))
+ (package-version package)
+ (package-name package)
+ (upstream-source-version source)))))))
(#f
(when warn?
- (warn-no-updater package)))))
-
+ ;; Distinguish between "no updater" and "failing updater."
+ (match (lookup-updater package updaters)
+ ((? upstream-updater? updater)
+ (warning (package-location package)
+ (G_ "'~a' updater failed to determine available \
+releases for ~a~%")
+ (upstream-updater-name updater)
+ (package-name package)))
+ (#f
+ (warn-no-updater package)))))))
;;;
diff --git a/guix/scripts/search.scm b/guix/scripts/search.scm
index 8fceb83668..827b2eb7a9 100644
--- a/guix/scripts/search.scm
+++ b/guix/scripts/search.scm
@@ -19,6 +19,8 @@
(define-module (guix scripts search)
#:use-module (guix ui)
#:use-module (guix scripts package)
+ #:use-module ((guix scripts build)
+ #:select (%standard-build-options))
#:use-module (guix scripts)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
@@ -36,6 +38,9 @@ This is an alias for 'guix package -s'.\n"))
(display (G_ "
-V, --version display version information and exit"))
(newline)
+ (display (G_ "
+ -L, --load-path=DIR prepend DIR to the package module search path"))
+ (newline)
(show-bug-report-information))
(define %options
@@ -46,7 +51,11 @@ This is an alias for 'guix package -s'.\n"))
(exit 0)))
(option '(#\V "version") #f #f
(lambda args
- (show-version-and-exit "guix search")))))
+ (show-version-and-exit "guix search")))
+
+ (find (lambda (option)
+ (member "load-path" (option-names option)))
+ %standard-build-options)))
(define (guix-search . args)
(define (handle-argument arg result)
diff --git a/guix/scripts/show.scm b/guix/scripts/show.scm
new file mode 100644
index 0000000000..ef64b5755b
--- /dev/null
+++ b/guix/scripts/show.scm
@@ -0,0 +1,76 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Simon Tournier <zimon.toutoune@gmail.com>
+;;;
+;;; 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 show)
+ #:use-module (guix ui)
+ #:use-module (guix scripts package)
+ #:use-module ((guix scripts build)
+ #:select (%standard-build-options))
+ #:use-module (guix scripts)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (srfi srfi-37)
+ #:export (guix-show))
+
+(define (show-help)
+ (display (G_ "Usage: guix show [OPTION] PACKAGE...
+Show details about PACKAGE."))
+ (display (G_"
+This is an alias for 'guix package --show='.\n"))
+ (newline)
+ (display (G_ "
+ -h, --help display this help and exit"))
+ (display (G_ "
+ -V, --version display version information and exit"))
+ (newline)
+ (display (G_ "
+ -L, --load-path=DIR prepend DIR to the package module search path"))
+ (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 show")))
+
+ (find (lambda (option)
+ (member "load-path" (option-names option)))
+ %standard-build-options)))
+
+(define (guix-show . args)
+ (define (handle-argument arg result)
+ ;; Treat all non-option arguments as regexps.
+ (cons `(query show ,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 package to show~%")))
+
+ (guix-package* opts))
diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm
index 9fc3a10e98..27b014db68 100644
--- a/guix/scripts/system.scm
+++ b/guix/scripts/system.scm
@@ -384,12 +384,14 @@ STORE is an open connection to the store."
(bootloader bootloader)))
;; Make the specified system generation the default entry.
- (params (profile-boot-parameters %system-profile (list number)))
+ (params (first (profile-boot-parameters %system-profile
+ (list number))))
(old-generations
(delv number (reverse (generation-numbers %system-profile))))
(old-params (profile-boot-parameters
%system-profile old-generations))
- (entries (map boot-parameters->menu-entry params))
+ (entries (cons (boot-parameters->menu-entry params)
+ (boot-parameters-bootloader-menu-entries params)))
(old-entries (map boot-parameters->menu-entry old-params)))
(run-with-store store
(mlet* %store-monad