summaryrefslogtreecommitdiff
path: root/guix
diff options
context:
space:
mode:
authorMarius Bakke <marius@gnu.org>2022-07-21 23:52:47 +0200
committerMarius Bakke <marius@gnu.org>2022-07-21 23:52:47 +0200
commitabea091dbef2d44e6eb46bd2413bdf917e14d095 (patch)
tree28f6c61dbda0acb52678944b121b66a6f50a3709 /guix
parent3b20467807c32aeac56bbbe22ffb8823f68e282b (diff)
parent3f171587bc6a47bb056f3e699e17e05f5832aea5 (diff)
Merge branch 'master' into staging
Diffstat (limited to 'guix')
-rw-r--r--guix/import/egg.scm9
-rw-r--r--guix/import/pypi.scm8
-rw-r--r--guix/import/texlive.scm20
-rw-r--r--guix/import/utils.scm2
-rw-r--r--guix/monad-repl.scm64
-rw-r--r--guix/scripts/home.scm64
-rw-r--r--guix/scripts/import/texlive.scm25
-rw-r--r--guix/scripts/package.scm33
-rw-r--r--guix/scripts/shell.scm5
-rw-r--r--guix/scripts/system.scm67
-rw-r--r--guix/upstream.scm18
-rw-r--r--guix/utils.scm6
12 files changed, 230 insertions, 91 deletions
diff --git a/guix/import/egg.scm b/guix/import/egg.scm
index 0b88020554..52196583c4 100644
--- a/guix/import/egg.scm
+++ b/guix/import/egg.scm
@@ -85,11 +85,6 @@
(define %eggs-home-page
(make-parameter "https://wiki.call-cc.org/egg"))
-(define (egg-source-url name version)
- "Return the URL to the source tarball for version VERSION of the CHICKEN egg
-NAME."
- `(egg-uri ,name version))
-
(define (egg-name->guix-name name)
"Return the package name for CHICKEN egg NAME."
(string-append package-name-prefix name))
@@ -196,7 +191,7 @@ not work."
(let* ((version* (or (assoc-ref egg-content 'version)
(find-latest-version name)))
(version (if (list? version*) (first version*) version*))
- (source-url (if source #f (egg-source-url name version)))
+ (source-url (if source #f `(egg-uri ,name version)))
(tarball (if source
#f
(with-store store
@@ -342,7 +337,7 @@ not work."
"Return an @code{<upstream-source>} for the latest release of PACKAGE."
(let* ((egg-name (guix-package->egg-name package))
(version (find-latest-version egg-name))
- (source-url (egg-source-url egg-name version)))
+ (source-url (egg-uri egg-name version)))
(upstream-source
(package (package-name package))
(version version)
diff --git a/guix/import/pypi.scm b/guix/import/pypi.scm
index 392fc9700b..4760fc3dae 100644
--- a/guix/import/pypi.scm
+++ b/guix/import/pypi.scm
@@ -161,9 +161,11 @@ or #f if there isn't any."
(define (python->package-name name)
"Given the NAME of a package on PyPI, return a Guix-compliant name for the
package."
- (if (string-prefix? "python-" name)
- (snake-case name)
- (string-append "python-" (snake-case name))))
+ (cond
+ ((string-prefix? "python-" name) (snake-case name))
+ ((or (string=? "trytond" name)
+ (string-prefix? "trytond-" name)) (snake-case name))
+ (else (string-append "python-" (snake-case name)))))
(define (guix-package->pypi-name package)
"Given a Python PACKAGE built from pypi.org, return the name of the
diff --git a/guix/import/texlive.scm b/guix/import/texlive.scm
index c741555928..116bd1f66a 100644
--- a/guix/import/texlive.scm
+++ b/guix/import/texlive.scm
@@ -246,7 +246,7 @@ of those files are returned that are unexpectedly installed."
;; entries with the same prefix.
(lambda (x y) (every equal? x y)))))
-(define (tlpdb->package name package-database)
+(define (tlpdb->package name version package-database)
(and-let* ((data (assoc-ref package-database name))
(dirs (files->directories
(map (lambda (dir)
@@ -255,7 +255,9 @@ of those files are returned that are unexpectedly installed."
(or (assoc-ref data 'runfiles) (list))
(or (assoc-ref data 'srcfiles) (list))))))
(name (guix-name name))
- (version (number->string %texlive-revision))
+ ;; TODO: we're ignoring the VERSION argument because that
+ ;; information is distributed across %texlive-tag and
+ ;; %texlive-revision.
(ref (svn-multi-reference
(url (string-append "svn://www.tug.org/texlive/tags/"
%texlive-tag "/Master/texmf-dist"))
@@ -276,6 +278,9 @@ of those files are returned that are unexpectedly installed."
(force-output port)
(get-hash))))
,@(if (assoc-ref data 'srcfiles) '() '(#:trivial? #true))))
+ ;; package->definition in (guix import utils) expects to see a
+ ;; version field.
+ (version ,version)
,@(or (and=> (assoc-ref data 'depend)
(lambda (inputs)
`((propagated-inputs
@@ -297,13 +302,18 @@ of those files are returned that are unexpectedly installed."
(define texlive->guix-package
(memoize
- (lambda* (name #:key repo version (package-database tlpdb))
+ (lambda* (name #:key
+ repo
+ (version (number->string %texlive-revision))
+ (package-database tlpdb))
"Find the metadata for NAME in the tlpdb and return the `package'
s-expression corresponding to that package, or #f on failure."
- (tlpdb->package name (package-database)))))
+ (tlpdb->package name version (package-database)))))
-(define (texlive-recursive-import name)
+(define* (texlive-recursive-import name #:key repo version)
(recursive-import name
+ #:repo repo
+ #:version version
#:repo->guix-package texlive->guix-package
#:guix-name guix-name))
diff --git a/guix/import/utils.scm b/guix/import/utils.scm
index 26eebfece5..668b8c8083 100644
--- a/guix/import/utils.scm
+++ b/guix/import/utils.scm
@@ -341,6 +341,8 @@ APPEND-VERSION?/string is a string, append this string."
(match guix-package
((or
('package ('name name) ('version version) . rest)
+ ('package ('inherit ('simple-texlive-package name . _))
+ ('version version) . rest)
('let _ ('package ('name name) ('version version) . rest)))
`(define-public ,(string->symbol
diff --git a/guix/monad-repl.scm b/guix/monad-repl.scm
index aefabdeebb..8a6053edd5 100644
--- a/guix/monad-repl.scm
+++ b/guix/monad-repl.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2014, 2015, 2016, 2022 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -21,6 +21,12 @@
#:use-module (guix monads)
#:use-module (guix utils)
#:use-module (guix packages)
+ #:use-module (guix status)
+ #:autoload (guix gexp) (lower-object)
+ #:use-module ((guix derivations)
+ #:select (derivation?
+ derivation->output-paths built-derivations))
+ #:use-module (ice-9 match)
#:use-module (ice-9 pretty-print)
#:use-module (system repl repl)
#:use-module (system repl common)
@@ -69,16 +75,58 @@
#:guile-for-build guile)
'store-monad)))
+(define %build-verbosity
+ ;; Current build verbosity level.
+ 1)
+
+(define* (evaluate/print-with-store mvalue #:key build?)
+ "Run monadic value MVALUE in the store monad and print its value."
+ (with-store store
+ (set-build-options store
+ #:print-build-trace #t
+ #:print-extended-build-trace? #t
+ #:multiplexed-build-output? #t)
+ (with-status-verbosity %build-verbosity
+ (let* ((guile (or (%guile-for-build)
+ (default-guile-derivation store)))
+ (values (run-with-store store
+ (if build?
+ (mlet %store-monad ((obj mvalue))
+ (if (derivation? obj)
+ (mbegin %store-monad
+ (built-derivations (list obj))
+ (return
+ (match (derivation->output-paths obj)
+ (((_ . files) ...) files))))
+ (return (list obj))))
+ (mlet %store-monad ((obj mvalue))
+ (return (list obj))))
+ #:guile-for-build guile)))
+ (for-each (lambda (value)
+ (run-hook before-print-hook value)
+ (pretty-print value))
+ values)))))
+
(define-meta-command ((run-in-store guix) repl (form))
"run-in-store EXP
Run EXP through the store monad."
- (with-store store
- (let* ((guile (or (%guile-for-build)
- (default-guile-derivation store)))
- (value (run-with-store store (repl-eval repl form)
- #:guile-for-build guile)))
- (run-hook before-print-hook value)
- (pretty-print value))))
+ (evaluate/print-with-store (repl-eval repl form)))
+
+(define-meta-command ((verbosity guix) repl (level))
+ "verbosity LEVEL
+Change build verbosity to LEVEL."
+ (set! %build-verbosity (repl-eval repl level)))
+
+(define-meta-command ((lower guix) repl (form))
+ "lower OBJECT
+Lower OBJECT into a derivation or store file and return it."
+ (evaluate/print-with-store (lower-object (repl-eval repl form))))
+
+(define-meta-command ((build guix) repl (form))
+ "build OBJECT
+Lower OBJECT and build it, returning its output file name(s)."
+ (evaluate/print-with-store (lower-object (repl-eval repl form))
+ #:build? #t))
(define-meta-command ((enter-store-monad guix) repl)
"enter-store-monad
diff --git a/guix/scripts/home.scm b/guix/scripts/home.scm
index 0f5c3388a1..4add7e7c69 100644
--- a/guix/scripts/home.scm
+++ b/guix/scripts/home.scm
@@ -4,6 +4,7 @@
;;; Copyright © 2021 Pierre Langlois <pierre.langlois@gmx.com>
;;; Copyright © 2021 Oleg Pykhalov <go.wigust@gmail.com>
;;; Copyright © 2022 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2022 Antero Mejr <antero@mailbox.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -143,6 +144,11 @@ Some ACTIONS support additional ARGS.\n"))
use BACKEND for 'extension-graph' and 'shepherd-graph'"))
(newline)
(display (G_ "
+ -I, --list-installed[=REGEXP]
+ for 'describe' or 'list-generations', list installed
+ packages matching REGEXP"))
+ (newline)
+ (display (G_ "
-h, --help display this help and exit"))
(display (G_ "
-V, --version display version information and exit"))
@@ -183,6 +189,9 @@ Some ACTIONS support additional ARGS.\n"))
(option '("graph-backend") #t #f
(lambda (opt name arg result)
(alist-cons 'graph-backend arg result)))
+ (option '(#\I "list-installed") #f #t
+ (lambda (opt name arg result)
+ (alist-cons 'list-installed (or arg "") result)))
;; Container options.
(option '(#\N "network") #f #f
@@ -569,17 +578,20 @@ Run @command{guix home reconfigure ~a/home-configuration.scm} to effectively
deploy the home environment described by these files.\n")
destination))))
((describe)
- (match (generation-number %guix-home)
- (0
- (leave (G_ "no home environment generation, nothing to describe~%")))
- (generation
- (display-home-environment-generation generation))))
+ (let ((list-installed-regex (assoc-ref opts 'list-installed)))
+ (match (generation-number %guix-home)
+ (0
+ (leave (G_ "no home environment generation, nothing to describe~%")))
+ (generation
+ (display-home-environment-generation
+ generation #:list-installed-regex list-installed-regex)))))
((list-generations)
- (let ((pattern (match args
+ (let ((list-installed-regex (assoc-ref opts 'list-installed))
+ (pattern (match args
(() #f)
((pattern) pattern)
(x (leave (G_ "wrong number of arguments~%"))))))
- (list-generations pattern)))
+ (list-generations pattern #:list-installed-regex list-installed-regex)))
((switch-generation)
(let ((pattern (match args
((pattern) pattern)
@@ -748,9 +760,11 @@ description matches REGEXPS sorted by relevance, and their score."
(define* (display-home-environment-generation
number
- #:optional (profile %guix-home))
- "Display a summary of home-environment generation NUMBER in a
-human-readable format."
+ #:optional (profile %guix-home)
+ #:key (list-installed-regex #f))
+ "Display a summary of home-environment generation NUMBER in a human-readable
+format. List packages in that home environment that match
+LIST-INSTALLED-REGEX."
(define (display-channel channel)
(format #t " ~a:~%" (channel-name channel))
(format #t (G_ " repository URL: ~a~%") (channel-url channel))
@@ -782,24 +796,36 @@ human-readable format."
(format #t (G_ " configuration file: ~a~%")
(if (supports-hyperlinks?)
(file-hyperlink config-file)
- config-file))))))
-
-(define* (list-generations pattern #:optional (profile %guix-home))
- "Display in a human-readable format all the home environment
-generations matching PATTERN, a string. When PATTERN is #f, display
-all the home environment generations."
+ config-file)))
+ (when list-installed-regex
+ (format #t (G_ " packages:\n"))
+ (pretty-print-table (list-installed
+ list-installed-regex
+ (list (string-append generation "/profile")))
+ #:left-pad 4)))))
+
+(define* (list-generations pattern #:optional (profile %guix-home)
+ #:key (list-installed-regex #f))
+ "Display in a human-readable format all the home environment generations
+matching PATTERN, a string. When PATTERN is #f, display all the home
+environment generations. List installed packages that match
+LIST-INSTALLED-REGEX."
(cond ((not (file-exists? profile)) ; XXX: race condition
(raise (condition (&profile-not-found-error
(profile profile)))))
((not pattern)
- (for-each display-home-environment-generation (profile-generations profile)))
+ (for-each (cut display-home-environment-generation <>
+ #:list-installed-regex list-installed-regex)
+ (profile-generations profile)))
((matching-generations pattern profile)
=>
(lambda (numbers)
(if (null-list? numbers)
(exit 1)
- (leave-on-EPIPE
- (for-each display-home-environment-generation numbers)))))))
+ (leave-on-EPIPE (for-each
+ (cut display-home-environment-generation <>
+ #:list-installed-regex list-installed-regex)
+ numbers)))))))
;;;
diff --git a/guix/scripts/import/texlive.scm b/guix/scripts/import/texlive.scm
index c5dcc07ea1..203386e31c 100644
--- a/guix/scripts/import/texlive.scm
+++ b/guix/scripts/import/texlive.scm
@@ -22,11 +22,13 @@
#:use-module (guix utils)
#:use-module (guix scripts)
#:use-module (guix import texlive)
+ #:use-module (guix import utils)
#:use-module (guix scripts import)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-11)
#:use-module (srfi srfi-37)
#:use-module (srfi srfi-41)
+ #:use-module (srfi srfi-71)
#:use-module (ice-9 match)
#:use-module (ice-9 format)
#:export (guix-import-texlive))
@@ -58,6 +60,9 @@ Import and convert the Texlive package for PACKAGE-NAME.\n"))
(option '(#\V "version") #f #f
(lambda args
(show-version-and-exit "guix import texlive")))
+ (option '(#\r "recursive") #f #f
+ (lambda (opt name arg result)
+ (alist-cons 'recursive #t result)))
%standard-import-options))
@@ -78,12 +83,20 @@ Import and convert the Texlive package for PACKAGE-NAME.\n"))
(_ #f))
(reverse opts))))
(match args
- ((name)
- (let ((sexp (texlive->guix-package name)))
- (unless sexp
- (leave (G_ "failed to import package '~a'~%")
- name))
- sexp))
+ ((spec)
+ (let ((name version (package-name->name+version spec)))
+ (if (assoc-ref opts 'recursive)
+ ;; Recursive import
+ (with-error-handling
+ (map package->definition
+ (filter identity (texlive-recursive-import name
+ #:version version))))
+ ;; Single import
+ (let ((sexp (texlive->guix-package name #:version version)))
+ (unless sexp
+ (leave (G_ "failed to download description for package '~a'~%")
+ name))
+ sexp))))
(()
(leave (G_ "too few arguments~%")))
((many ...)
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index 99a6cfaa29..7d92598efa 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -11,6 +11,7 @@
;;; Copyright © 2020 Simon Tournier <zimon.toutoune@gmail.com>
;;; Copyright © 2018 Steve Sprang <scs@stevesprang.com>
;;; Copyright © 2022 Josselin Poiret <dev@jpoiret.xyz>
+;;; Copyright © 2022 Antero Mejr <antero@mailbox.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -67,6 +68,7 @@
delete-generations
delete-matching-generations
guix-package
+ list-installed
search-path-environment-variables
manifest-entry-version-prefix
@@ -773,6 +775,22 @@ doesn't need it."
(add-indirect-root store absolute))
+(define (list-installed regexp profiles)
+ "Write to the current output port the list of packages matching REGEXP in
+PROFILES."
+ (let* ((regexp (and regexp (make-regexp* regexp regexp/icase)))
+ (manifest (concatenate-manifests
+ (map profile-manifest profiles)))
+ (installed (manifest-entries manifest)))
+ (leave-on-EPIPE
+ (let ((rows (filter-map
+ (match-lambda
+ (($ <manifest-entry> name version output path _)
+ (and (regexp-exec regexp name)
+ (list name (or version "?") output path))))
+ installed)))
+ rows))))
+
;;;
;;; Queries and actions.
@@ -824,19 +842,8 @@ processed, #f otherwise."
#t)
(('list-installed regexp)
- (let* ((regexp (and regexp (make-regexp* regexp regexp/icase)))
- (manifest (concatenate-manifests
- (map profile-manifest profiles)))
- (installed (manifest-entries manifest)))
- (leave-on-EPIPE
- (let ((rows (filter-map
- (match-lambda
- (($ <manifest-entry> name version output path _)
- (and (regexp-exec regexp name)
- (list name (or version "?") output path))))
- installed)))
- ;; Show most recently installed packages last.
- (pretty-print-table (reverse rows)))))
+ ;; Show most recently installed packages last.
+ (pretty-print-table (reverse (list-installed regexp profiles)))
#t)
(('list-available regexp)
diff --git a/guix/scripts/shell.scm b/guix/scripts/shell.scm
index 004ed7af2e..c115a00320 100644
--- a/guix/scripts/shell.scm
+++ b/guix/scripts/shell.scm
@@ -390,6 +390,11 @@ return #f and #f."
;; If the user already specified a profile, there's nothing more to
;; cache.
(values #f #f))
+ ((('export-manifest? . #t) . _)
+ ;; When exporting a manifest, compute it anew so that '-D' packages
+ ;; lead to 'package-development-manifest' expressions rather than an
+ ;; expanded list of inputs.
+ (values #f #f))
((('system . system) . rest)
(loop rest system file specs))
((_ . rest) (loop rest system file specs)))))
diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm
index b9084a401c..bfde0a88ca 100644
--- a/guix/scripts/system.scm
+++ b/guix/scripts/system.scm
@@ -50,7 +50,8 @@
#:use-module (guix channels)
#:use-module (guix scripts build)
#:autoload (guix scripts package) (delete-generations
- delete-matching-generations)
+ delete-matching-generations
+ list-installed)
#:autoload (guix scripts pull) (channel-commit-hyperlink)
#:autoload (guix graph) (export-graph node-type
graph-backend-name lookup-backend)
@@ -480,8 +481,10 @@ list of services."
;;;
(define* (display-system-generation number
- #:optional (profile %system-profile))
- "Display a summary of system generation NUMBER in a human-readable format."
+ #:optional (profile %system-profile)
+ #:key (list-installed-regex #f))
+ "Display a summary of system generation NUMBER in a human-readable format.
+List packages in that system that match LIST-INSTALLED-REGEX."
(define (display-channel channel)
(format #t " ~a:~%" (channel-name channel))
(format #t (G_ " repository URL: ~a~%") (channel-url channel))
@@ -544,23 +547,35 @@ list of services."
(format #t (G_ " configuration file: ~a~%")
(if (supports-hyperlinks?)
(file-hyperlink config-file)
- config-file))))))
-
-(define* (list-generations pattern #:optional (profile %system-profile))
+ config-file)))
+ (when list-installed-regex
+ (format #t (G_ " packages:\n"))
+ (pretty-print-table (list-installed
+ list-installed-regex
+ (list (string-append generation "/profile")))
+ #:left-pad 4)))))
+
+(define* (list-generations pattern #:optional (profile %system-profile)
+ #:key (list-installed-regex #f))
"Display in a human-readable format all the system generations matching
-PATTERN, a string. When PATTERN is #f, display all the system generations."
+PATTERN, a string. When PATTERN is #f, display all the system generations.
+List installed packages that match LIST-INSTALLED-REGEX."
(cond ((not (file-exists? profile)) ; XXX: race condition
(raise (condition (&profile-not-found-error
(profile profile)))))
((not pattern)
- (for-each display-system-generation (profile-generations profile)))
+ (for-each (cut display-system-generation <>
+ #:list-installed-regex list-installed-regex)
+ (profile-generations profile)))
((matching-generations pattern profile)
=>
(lambda (numbers)
(if (null-list? numbers)
(exit 1)
(leave-on-EPIPE
- (for-each display-system-generation numbers)))))))
+ (for-each (cut display-system-generation <>
+ #:list-installed-regex list-installed-regex)
+ numbers)))))))
;;;
@@ -1032,6 +1047,11 @@ Some ACTIONS support additional ARGS.\n"))
use BACKEND for 'extension-graphs' and 'shepherd-graph'"))
(newline)
(display (G_ "
+ -I, --list-installed[=REGEXP]
+ for 'describe' and 'list-generations', list installed
+ packages matching REGEXP"))
+ (newline)
+ (display (G_ "
-h, --help display this help and exit"))
(display (G_ "
-V, --version display version information and exit"))
@@ -1135,6 +1155,9 @@ Some ACTIONS support additional ARGS.\n"))
(option '("graph-backend") #t #f
(lambda (opt name arg result)
(alist-cons 'graph-backend arg result)))
+ (option '(#\I "list-installed") #f #t
+ (lambda (opt name arg result)
+ (alist-cons 'list-installed (or arg "") result)))
%standard-build-options))
(define %default-options
@@ -1322,25 +1345,29 @@ argument list and OPTS is the option alist."
;; The following commands do not need to use the store, and they do not need
;; an operating system configuration file.
((list-generations)
- (let ((pattern (match args
+ (let ((list-installed-regex (assoc-ref opts 'list-installed))
+ (pattern (match args
(() #f)
((pattern) pattern)
(x (leave (G_ "wrong number of arguments~%"))))))
- (list-generations pattern)))
+ (list-generations pattern #:list-installed-regex list-installed-regex)))
((describe)
;; Describe the running system, which is not necessarily the current
;; generation. /run/current-system might point to
;; /var/guix/profiles/system-N-link, or it might point directly to
;; /gnu/store/…-system. Try both.
- (match (generation-number "/run/current-system" %system-profile)
- (0
- (match (generation-number %system-profile)
- (0
- (leave (G_ "no system generation, nothing to describe~%")))
- (generation
- (display-system-generation generation))))
- (generation
- (display-system-generation generation))))
+ (let ((list-installed-regex (assoc-ref opts 'list-installed)))
+ (match (generation-number "/run/current-system" %system-profile)
+ (0
+ (match (generation-number %system-profile)
+ (0
+ (leave (G_ "no system generation, nothing to describe~%")))
+ (generation
+ (display-system-generation
+ generation #:list-installed-regex list-installed-regex))))
+ (generation
+ (display-system-generation
+ generation #:list-installed-regex list-installed-regex)))))
((search)
(apply (resolve-subcommand "search") args))
((edit)
diff --git a/guix/upstream.scm b/guix/upstream.scm
index 9b49d1641f..cbfd1aa609 100644
--- a/guix/upstream.scm
+++ b/guix/upstream.scm
@@ -251,13 +251,17 @@ correspond to the same version."
#:warn warn-about-load-error)))
(define %updaters
- ;; The list of publically-known updaters.
- (delay (fold-module-public-variables (lambda (obj result)
- (if (upstream-updater? obj)
- (cons obj result)
- result))
- '()
- (importer-modules))))
+ ;; The list of publically-known updaters, alphabetically sorted.
+ (delay
+ (sort (fold-module-public-variables (lambda (obj result)
+ (if (upstream-updater? obj)
+ (cons obj result)
+ result))
+ '()
+ (importer-modules))
+ (lambda (updater1 updater2)
+ (string<? (symbol->string (upstream-updater-name updater1))
+ (symbol->string (upstream-updater-name updater2)))))))
;; Tests need to mock this variable so mark it as "non-declarative".
(set! %updaters %updaters)
diff --git a/guix/utils.scm b/guix/utils.scm
index 745da98a79..329ef62dde 100644
--- a/guix/utils.scm
+++ b/guix/utils.scm
@@ -1124,11 +1124,11 @@ according to THRESHOLD, then #f is returned."
;;; Prettified output.
;;;
-(define* (pretty-print-table rows #:key (max-column-width 20))
+(define* (pretty-print-table rows #:key (max-column-width 20) (left-pad 0))
"Print ROWS in neat columns. All rows should be lists of strings and each
row should have the same length. The columns are separated by a tab
character, and aligned using spaces. The maximum width of each column is
-bound by MAX-COLUMN-WIDTH."
+bound by MAX-COLUMN-WIDTH. Each row is prefixed with LEFT-PAD spaces."
(let* ((number-of-columns-to-pad (if (null? rows)
0
(1- (length (first rows)))))
@@ -1143,7 +1143,7 @@ bound by MAX-COLUMN-WIDTH."
(map (cut min <> max-column-width)
column-widths)))
(fmt (string-append (string-join column-formats "\t") "\t~a")))
- (for-each (cut format #t "~?~%" fmt <>) rows)))
+ (for-each (cut format #t "~v_~?~%" left-pad fmt <>) rows)))
;;; Local Variables:
;;; eval: (put 'call-with-progress-reporter 'scheme-indent-function 1)