From 09aeabb9d3cab042a52881b117f9f64a0f0e1651 Mon Sep 17 00:00:00 2001 From: Christopher Baines Date: Fri, 1 Jul 2022 09:27:55 +0100 Subject: services: guix: Support guix-build-coordinator parallel hooks. * gnu/services/guix.scm (guix-build-coordinator-configuration-parallel-hooks): New procedure. (make-guix-build-coordinator-start-script): Accept and use #:parallel-hooks. (guix-build-coordinator-shepherd-services): Pass parallel-hooks to make-guix-build-coordinator-start-script. * doc/guix.texi (Guix Build Coordinator): Document this new field. --- doc/guix.texi | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index b8c49099a4..814965b22c 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -35106,6 +35106,11 @@ allocation plan in the database. An association list of hooks. These provide a way to execute arbitrary code upon certain events, like a build result being processed. +@item @code{parallel-hooks} (default: @var{'()}) +Hooks can be configured to run in parallel. This parameter is an +association list of hooks to do in parallel, where the key is the symbol +for the hook and the value is the number of threads to run. + @item @code{guile} (default: @code{guile-3.0-latest}) The Guile package with which to run the Guix Build Coordinator. -- cgit v1.2.3 From b5c6062bcec9530a9c4044a1bd1091fdebf9bc74 Mon Sep 17 00:00:00 2001 From: Christopher Baines Date: Thu, 23 Jun 2022 12:38:37 +0100 Subject: services: nginx: Add support for extra content in upstream blocks. I'm looking at this as I'd like to use the keepalive functionality. * gnu/services/web.scm (nginx-upstream-configuration-extra-content): New procedure. (emit-nginx-upstream-config): Include the extra-content if applicable. * doc/guix.texi (NGINX): Document this. --- doc/guix.texi | 3 +++ gnu/services/web.scm | 14 +++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index 814965b22c..cf373b6cbd 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -28531,6 +28531,9 @@ prefix @samp{unix:}. For addresses using an IP address or domain name, the default port is 80, and a different port can be specified explicitly. +@item @code{extra-content} +A string or list of strings to add to the upstream block. + @end table @end deftp diff --git a/gnu/services/web.scm b/gnu/services/web.scm index 4f06d4e0bb..4434fecf02 100644 --- a/gnu/services/web.scm +++ b/gnu/services/web.scm @@ -120,6 +120,7 @@ (define-module (gnu services web) nginx-upstream-configuration? nginx-upstream-configuration-name nginx-upstream-configuration-servers + nginx-upstream-configuration-extra-content nginx-location-configuration nginx-location-configuration? @@ -517,7 +518,9 @@ (define-record-type* nginx-upstream-configuration make-nginx-upstream-configuration nginx-upstream-configuration? (name nginx-upstream-configuration-name) - (servers nginx-upstream-configuration-servers)) + (servers nginx-upstream-configuration-servers) + (extra-content nginx-upstream-configuration-extra-content + (default '()))) (define-record-type* nginx-location-configuration make-nginx-location-configuration @@ -643,6 +646,15 @@ (define (emit-nginx-upstream-config upstream) (map (lambda (server) (simple-format #f " server ~A;\n" server)) (nginx-upstream-configuration-servers upstream)) + (let ((extra-content + (nginx-upstream-configuration-extra-content upstream))) + (if (and extra-content (not (null? extra-content))) + (cons + "\n" + (map (lambda (line) + (simple-format #f " ~A\n" line)) + (flatten extra-content))) + '())) " }\n")) (define (flatten . lst) -- cgit v1.2.3 From e7ab3d33aec3993737cdbc4396a9c44a54a3ce84 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sun, 19 Jun 2022 15:50:50 +0200 Subject: challenge: Do nothing when passed zero arguments. Previously, 'guix challenge' without arguments would list live store items that had been locally built. This was deemed confusing, especially since 'list-live' is an expensive operation. * guix/scripts/challenge.scm (guix-challenge): Warn and exit with 0 when FILES is empty. * doc/guix.texi (Invoking guix challenge): Update accordingly. --- doc/guix.texi | 38 ++++++++++++++++++++++---------------- guix/scripts/challenge.scm | 5 +++-- 2 files changed, 25 insertions(+), 18 deletions(-) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index cf373b6cbd..9d9cb3dc07 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -14941,7 +14941,9 @@ any given store item. The command output looks like this: @smallexample -$ guix challenge --substitute-urls="https://@value{SUBSTITUTE-SERVER-1} https://guix.example.org" +$ guix challenge \ + --substitute-urls="https://@value{SUBSTITUTE-SERVER-1} https://guix.example.org" \ + openssl git pius coreutils grep updating substitutes from 'https://@value{SUBSTITUTE-SERVER-1}'... 100.0% updating substitutes from 'https://guix.example.org'... 100.0% /gnu/store/@dots{}-openssl-1.0.2d contents differ: @@ -14968,18 +14970,20 @@ updating substitutes from 'https://guix.example.org'... 100.0% @dots{} -6,406 store items were analyzed: - - 4,749 (74.1%) were identical - - 525 (8.2%) differed - - 1,132 (17.7%) were inconclusive +5 store items were analyzed: + - 2 (40.0%) were identical + - 3 (60.0%) differed + - 0 (0.0%) were inconclusive @end smallexample @noindent -In this example, @command{guix challenge} first scans the store to -determine the set of locally-built derivations---as opposed to store -items that were downloaded from a substitute server---and then queries -all the substitute servers. It then reports those store items for which -the servers obtained a result different from the local build. +In this example, @command{guix challenge} queries all the substitute +servers for each of the fives packages specified on the command line. +It then reports those store items for which the servers obtained a +result different from the local build (if it exists) and/or different +from one another; here, the @samp{local hash} lines indicate that a +local build result was available for each of these packages and shows +its hash. @cindex non-determinism, in package builds As an example, @code{guix.example.org} always gets a different answer. @@ -15035,19 +15039,21 @@ whether @code{@value{SUBSTITUTE-SERVER-1}} and other substitute servers obtain t same build result as you did with: @example -$ guix challenge @var{package} +guix challenge @var{package} @end example -@noindent -where @var{package} is a package specification such as -@code{guile@@2.0} or @code{glibc:debug}. - The general syntax is: @example -guix challenge @var{options} [@var{packages}@dots{}] +guix challenge @var{options} @var{argument}@dots{} @end example +@noindent +where @var{argument} is a package specification such as +@code{guile@@2.0} or @code{glibc:debug} or, alternatively, a store file +name as returned, for example, by @command{guix build} or @command{guix +gc --list-live}. + When a difference is found between the hash of a locally-built item and that of a server-provided substitute, or among substitutes provided by different servers, the command displays it as in the example above and diff --git a/guix/scripts/challenge.scm b/guix/scripts/challenge.scm index 5c0f837d13..f1e5f67dab 100644 --- a/guix/scripts/challenge.scm +++ b/guix/scripts/challenge.scm @@ -537,8 +537,9 @@ (define-command (guix-challenge . args) (current-terminal-columns (terminal-columns))) (let ((files (match files (() - (filter (cut locally-built? store <>) - (live-paths store))) + (warning + (G_ "no arguments specified, nothing to do~%")) + (exit 0)) (x files)))) (set-build-options store -- cgit v1.2.3 From cba98b58bf09f22dfbfb338884b80ab831e0be46 Mon Sep 17 00:00:00 2001 From: Ricardo Wurmus Date: Fri, 1 Jul 2022 01:08:34 +0200 Subject: services: Add anonip-service-type. * gnu/services/web.scm (anonip-configuration): New record type. (anonip-configuration?, anonip-configuration-anonip, anonip-configuration-input, anonip-configuration-output, anonip-configuration-skip-private?, anonip-configuration-column, anonip-configuration-replacement, anonip-configuration-ipv4mask, anonip-configuration-ipv6mask, anonip-configuration-increment, anonip-configuration-delimiter, anonip-configuration-regex): New procedures. (anonip-service-type): New service type. * doc/guix.texi (Log Rotation): Add subheading for Anonip Service. --- doc/guix.texi | 71 ++++++++++++++++++++++++++++++++- gnu/services/web.scm | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 179 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index 9d9cb3dc07..b97ee9fa64 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -30,7 +30,7 @@ Copyright @copyright{} 2015, 2016 Mathieu Lirzin@* Copyright @copyright{} 2014 Pierre-Antoine Rault@* Copyright @copyright{} 2015 Taylan Ulrich Bayırlı/Kammer@* Copyright @copyright{} 2015, 2016, 2017, 2019, 2020, 2021 Leo Famulari@* -Copyright @copyright{} 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ricardo Wurmus@* +Copyright @copyright{} 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Ricardo Wurmus@* Copyright @copyright{} 2016 Ben Woodcroft@* Copyright @copyright{} 2016, 2017, 2018, 2021 Chris Marusich@* Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022 Efraim Flashner@* @@ -18706,6 +18706,75 @@ String or gexp denoting the corresponding mcron job schedule @end table @end deftp +@cindex logging, anonymization +@subheading Anonip Service + +Anonip is a privacy filter that removes IP address from web server logs. +This service creates a FIFO and filters any written lines with anonip +before writing the filtered log to a target file. + +The following example sets up the FIFO +@file{/var/run/anonip/https.access.log} and writes the filtered log file +@file{/var/log/anonip/https.access.log}. + +@lisp +(service anonip-service-type + (anonip-configuration + (input "/var/run/anonip/https.access.log") + (output "/var/log/anonip/https.access.log"))) +@end lisp + +Configure your web server to write its logs to the FIFO at +@file{/var/run/anonip/https.access.log} and collect the anonymized log +file at @file{/var/web-logs/https.access.log}. + +@deftp {Data Type} anonip-configuration +This data type represents the configuration of anonip. +It has the following parameters: + +@table @asis +@item @code{anonip} (default: @code{anonip}) +The anonip package to use. + +@item @code{input} +The file name of the input log file to process. The service creates a +FIFO of this name. The web server should write its logs to this FIFO. + +@item @code{output} +The file name of the processed log file. +@end table + +The following optional settings may be provided: + +@table @asis +@item @code{skip-private?} +When @code{#true} do not mask addresses in private ranges. + +@item @code{column} +A 1-based indexed column number. Assume IP address is in the specified +column (default is 1). + +@item @code{replacement} +Replacement string in case address parsing fails, e.g. @code{"0.0.0.0"}. + +@item @code{ipv4mask} +Number of bits to mask in IPv4 addresses. + +@item @code{ipv6mask} +Number of bits to mask in IPv6 addresses. + +@item @code{increment} +Increment the IP address by the given number. By default this is zero. + +@item @code{delimiter} +Log delimiter string. + +@item @code{regex} +Regular expression for detecting IP addresses. Use this instead of @code{column}. +@end table +@end deftp + + @node Networking Setup @subsection Networking Setup diff --git a/gnu/services/web.scm b/gnu/services/web.scm index 4434fecf02..f0c7e90cbf 100644 --- a/gnu/services/web.scm +++ b/gnu/services/web.scm @@ -9,7 +9,7 @@ ;;; Copyright © 2018 Pierre-Antoine Rouby ;;; Copyright © 2018 Marius Bakke ;;; Copyright © 2019, 2020 Florian Pelz -;;; Copyright © 2020 Ricardo Wurmus +;;; Copyright © 2020, 2022 Ricardo Wurmus ;;; Copyright © 2020 Tobias Geerinckx-Rice ;;; Copyright © 2020 Arun Isaac ;;; Copyright © 2020 Oleg Pykhalov @@ -205,6 +205,21 @@ (define-module (gnu services web) tailon-service-type + anonip-configuration + anonip-configuration? + anonip-configuration-anonip + anonip-configuration-input + anonip-configuration-output + anonip-configuration-skip-private? + anonip-configuration-column + anonip-configuration-replacement + anonip-configuration-ipv4mask + anonip-configuration-ipv6mask + anonip-configuration-increment + anonip-configuration-delimiter + anonip-configuration-regex + anonip-service-type + varnish-configuration varnish-configuration? varnish-configuration-package @@ -1355,6 +1370,99 @@ (define tailon-service-type files)))))))) (default-value (tailon-configuration)))) + + +;;; +;;; Log anonymization +;;; + +(define-record-type* + anonip-configuration make-anonip-configuration + anonip-configuration? + (anonip anonip-configuration-anonip ;file-like + (default anonip)) + (input anonip-configuration-input) ;string + (output anonip-configuration-output) ;string + (skip-private? anonip-configuration-skip-private? ;boolean + (default #f)) + (column anonip-configuration-column ;number + (default #f)) + (replacement anonip-configuration-replacement ;string + (default #f)) + (ipv4mask anonip-configuration-ipv4mask ;number + (default #f)) + (ipv6mask anonip-configuration-ipv6mask ;number + (default #f)) + (increment anonip-configuration-increment ;number + (default #f)) + (delimiter anonip-configuration-delimiter ;string + (default #f)) + (regex anonip-configuration-regex ;string + (default #f))) + +(define (anonip-activation config) + (with-imported-modules '((guix build utils)) + #~(begin + (use-modules (guix build utils)) + (for-each + (lambda (directory) + (mkdir-p directory) + (chmod directory #o755)) + (list (dirname #$(anonip-configuration-input config)) + (dirname #$(anonip-configuration-output config))))))) + +(define (anonip-shepherd-service config) + (let ((input (anonip-configuration-input config)) + (output (anonip-configuration-output config)) + (optional + (lambda (accessor option) + (or (and=> (accessor config) + (lambda (value) + (list + (format #false "~a=~a" + option value)))) + (list))))) + (list (shepherd-service + (provision (list (symbol-append 'anonip- (string->symbol output)))) + (requirement '(user-processes)) + (documentation "Anonimyze the given log file location with anonip.") + (start #~(lambda _ + (unless (file-exists? #$input) + (mknod #$input 'fifo #o600 0)) + (let ((pid (fork+exec-command + (append + (list #$(file-append (anonip-configuration-anonip config) + "/bin/anonip") + (string-append "--input=" #$input) + (string-append "--output=" #$output)) + (if #$(anonip-configuration-skip-private? config) + '("--skip-private") (list)) + '#$(optional anonip-configuration-column "--column") + '#$(optional anonip-configuration-ipv4mask "--ipv4mask") + '#$(optional anonip-configuration-ipv6mask "--ipv6mask") + '#$(optional anonip-configuration-increment "--increment") + '#$(optional anonip-configuration-replacement "--replacement") + '#$(optional anonip-configuration-delimiter "--delimiter") + '#$(optional anonip-configuration-regex "--regex")) + ;; Run in a UTF-8 locale + #:environment-variables + (list (string-append "GUIX_LOCPATH=" #$glibc-utf8-locales + "/lib/locale") + "LC_ALL=en_US.utf8")))) + pid))) + (stop #~(make-kill-destructor)))))) + +(define anonip-service-type + (service-type + (name 'anonip) + (extensions + (list (service-extension shepherd-root-service-type + anonip-shepherd-service) + (service-extension activation-service-type + anonip-activation))) + (description + "Provide web server log anonymization with @command{anonip}."))) + ;;; ;;; Varnish -- cgit v1.2.3 From a3d86b341d361530127c36fbfbf77d638df2c1de Mon Sep 17 00:00:00 2001 From: Hartmut Goebel Date: Sun, 19 Jun 2022 10:26:30 +0200 Subject: style: Add option '--list-stylings'. * guix/scripts/style.scm (show-stylings): New procedure. (%options, show-help): Add "--list-stylings". * doc/guix.texi (Invoking guix style): Document "-l". --- doc/guix.texi | 4 ++++ guix/scripts/style.scm | 11 +++++++++++ 2 files changed, 15 insertions(+) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index b97ee9fa64..92346ab4ba 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -13993,6 +13993,10 @@ The @option{--input-simplification} option described below provides fine-grain control over when inputs should be simplified. @end table +@item --list-stylings +@itemx -l +List and describe the available styling rules and exit. + @item --load-path=@var{directory} @itemx -L @var{directory} Add @var{directory} to the front of the package module search path diff --git a/guix/scripts/style.scm b/guix/scripts/style.scm index ca3853af5e..09937d9e02 100644 --- a/guix/scripts/style.scm +++ b/guix/scripts/style.scm @@ -798,15 +798,26 @@ (define %options (lambda args (show-help) (exit 0))) + (option '(#\l "list-stylings") #f #f + (lambda args + (show-stylings) + (exit 0))) (option '(#\V "version") #f #f (lambda args (show-version-and-exit "guix style"))))) +(define (show-stylings) + (display (G_ "Available styling rules:\n")) + (display (G_ "- format: Format the given package definition(s)\n")) + (display (G_ "- inputs: Rewrite package inputs to the “new style”\n"))) + (define (show-help) (display (G_ "Usage: guix style [OPTION]... [PACKAGE]... Update package definitions to the latest style.\n")) (display (G_ " -S, --styling=RULE apply RULE, a styling rule")) + (display (G_ " + -l, --list-stylings display the list of available style rules")) (newline) (display (G_ " -n, --dry-run display files that would be edited but do nothing")) -- cgit v1.2.3 From ef975769724d60bf39d6e39a990271334d4e5191 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Tue, 5 Jul 2022 13:53:44 +0200 Subject: doc: Document the 'validate-runpath' phase. * doc/guix.texi (Build Systems): Replace paragraph about RUNPATH validation with a cross-reference. (Build Phases): Add 'validate-runpath' phase, with the paragraph taken above. --- doc/guix.texi | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index 92346ab4ba..097e4a362b 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -8524,14 +8524,8 @@ the number specified as the @option{--cores} option of This Boolean, @code{#t} by default, determines whether to ``validate'' the @code{RUNPATH} of ELF binaries (@code{.so} shared libraries as well as executables) previously installed by the @code{install} phase. - -This validation step consists in making sure that all the shared -libraries needed by an ELF binary, which are listed as -@code{DT_NEEDED} entries in its @code{PT_DYNAMIC} segment, appear in the -@code{DT_RUNPATH} entry of that binary. In other words, it ensures that -running or using those binaries will not result in a ``file not found'' -error at run time. @xref{Options, @option{-rpath},, ld, The GNU -Linker}, for more information on @code{RUNPATH}. +@xref{phase-validate-runpath, the @code{validate-runpath} phase}, for +details. @item #:substitutable? This Boolean, @code{#t} by default, tells whether the package outputs @@ -9610,6 +9604,21 @@ Patch shebangs on the installed executable files. Strip debugging symbols from ELF files (unless @code{#:strip-binaries?} is false), copying them to the @code{debug} output when available (@pxref{Installing Debugging Files}). + +@cindex RUNPATH, validation +@anchor{phase-validate-runpath} +@item validate-runpath +Validate the @code{RUNPATH} of ELF binaries, unless +@code{#:validate-runpath?} is false (@pxref{Build Systems}). + +This validation step consists in making sure that all the shared +libraries needed by an ELF binary, which are listed as @code{DT_NEEDED} +entries in its @code{PT_DYNAMIC} segment, appear in the +@code{DT_RUNPATH} entry of that binary. In other words, it ensures that +running or using those binaries will not result in a ``file not found'' +error at run time. @xref{Options, @option{-rpath},, ld, The GNU +Linker}, for more information on @code{RUNPATH}. + @end table Other build systems have similar phases, with some variations. For -- cgit v1.2.3 From e103d6148567d2248cd951f2e2507bdaf4914c29 Mon Sep 17 00:00:00 2001 From: jgart Date: Sat, 15 Jan 2022 14:45:22 -0500 Subject: doc: Document the documentation process. * doc/contributing.texi (Contributing): Add Writing Documentation section. Co-authored-by: Julien Lepiller Co-authored-by: Matt Trzcinski Co-authored-by: Fabio Natali Co-authored-by: Gabor Boskovits Co-authored-by: Luis Felipe Signed-off-by: Maxim Cournoyer --- doc/contributing.texi | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'doc') diff --git a/doc/contributing.texi b/doc/contributing.texi index e1902f120f..dcb45ad34c 100644 --- a/doc/contributing.texi +++ b/doc/contributing.texi @@ -29,6 +29,7 @@ choice. * Tracking Bugs and Patches:: Keeping it all organized. * Commit Access:: Pushing to the official repository. * Updating the Guix Package:: Updating the Guix package definition. +* Writing Documentation:: Improving documentation in GNU Guix. * Translating Guix:: Make Guix speak your native language. @end menu @@ -1779,6 +1780,47 @@ This check can be disabled, @emph{at your own peril}, by setting the this variable is set, the updated package source is also added to the store. This is used as part of the release process of Guix. +@cindex documentation +@node Writing Documentation +@section Writing Documentation + +Guix is documented using the Texinfo system. If you are not yet +familiar with it, we accept contributions for documentation in most +formats. That includes plain text, Markdown, Org, etc. + +Documentation contributions can be sent to +@email{guix-patches@@gnu.org}. Prepend @samp{[DOCUMENTATION]} to the +subject. + +When you need to make more than a simple addition to the documentation, +we prefer that you send a proper patch as opposed to sending an email +as described above. @xref{Submitting Patches} for more information on +how to send your patches. + +To modify the documentation, you need to edit @file{doc/guix.texi} and +@file{doc/contributing.texi} (which contains this documentation +section), or @file{doc/guix-cookbook.texi} for the cookbook. If +you compiled the Guix repository before, you will have +many more @file{.texi} files that are translations of these +documents. Do not modify them, the translation is managed through +@uref{https://translate.fedoraproject.org/projects/guix, Weblate}. +@xref{Translating Guix} for more information. + +To render documentation, you must first make sure that you ran +@command{./configure} in your source tree (@pxref{Running Guix Before +It Is Installed}). After that you can run one of the following +commands: + +@itemize +@item @samp{make doc/guix.info} to compile the Info manual. + You can check it with @command{info doc/guix.info}. +@item @samp{make doc/guix.html} to compile the HTML version. + You can point your browser to the relevant file in the + @file{doc/guix.html} directory. +@item @samp{make doc/guix-cookbook.info} for the cookbook Info manual. +@item @samp{make doc/guix-cookbook.html} for the cookbook HTML version. +@end itemize + @cindex translation @cindex l10n @cindex i18n -- cgit v1.2.3 From da7bee91fa8ec76e647eb1f2c488a5bc41b0ecba Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 8 Jul 2022 15:47:25 +0200 Subject: doc: cookbook: Suggest 'guix shell'. * doc/guix-cookbook.texi (A Scheme Crash Course): Suggest 'guix shell' instead of 'guix environment'. (Customizing the Kernel, The benefits of manifests): Likewise. --- doc/guix-cookbook.texi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/guix-cookbook.texi b/doc/guix-cookbook.texi index 06fb872177..414bf76c2f 100644 --- a/doc/guix-cookbook.texi +++ b/doc/guix-cookbook.texi @@ -122,7 +122,7 @@ language, install it with @code{guix install guile} and start a @dfn{REPL}---short for @uref{https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop, @dfn{read-eval-print loop}}---by running @code{guile} from the command line. -Alternatively you can also run @code{guix environment --ad-hoc guile -- guile} +Alternatively you can also run @code{guix shell guile -- guile} if you'd rather not have Guile installed in your user profile. In the following examples, lines show what you would type at the REPL; @@ -1600,7 +1600,7 @@ letting you know what you're missing. If the file is blank then you're missing everything. The next step is to run: @example shell -guix environment linux-libre -- make localmodconfig +guix shell -D linux-libre -- make localmodconfig @end example and note the output. Do note that the @file{.config} file is still empty. @@ -2787,7 +2787,7 @@ Maybe a dependency from our manifest has been updated; or we may have run garbage-collected. @item -Eventually, we set to work on that project again, so we run @code{guix environment +Eventually, we set to work on that project again, so we run @code{guix shell -m manifest.scm}. But now we have to wait for Guix to build and install stuff! @end enumerate -- cgit v1.2.3 From 9100acb6fb6687f197e557bcf16c465ba97e4fdb Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 8 Jul 2022 17:27:49 +0200 Subject: doc: cookbook: Link to "A Scheme Primer". * doc/guix-cookbook.texi (A Scheme Crash Course): Link to "A Scheme Primer". Group references in @quotation for clarity. --- doc/guix-cookbook.texi | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) (limited to 'doc') diff --git a/doc/guix-cookbook.texi b/doc/guix-cookbook.texi index 414bf76c2f..b61adc06da 100644 --- a/doc/guix-cookbook.texi +++ b/doc/guix-cookbook.texi @@ -284,24 +284,41 @@ depends on the @code{(guix store)} module and it exports two variables, @code{ruby-build} and @code{ruby-build-system}. @end itemize -For a more detailed introduction, check out -@uref{http://www.troubleshooters.com/codecorn/scheme_guile/hello.htm, Scheme -at a Glance}, by Steve Litt. - -One of the reference Scheme books is the seminal ``Structure and -Interpretation of Computer Programs'', by Harold Abelson and Gerald Jay -Sussman, with Julie Sussman. You'll find a -@uref{https://mitpress.mit.edu/sites/default/files/sicp/index.html, free copy -online}, together with -@uref{https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/video-lectures/, -videos of the lectures by the authors}. The book is available in Texinfo -format as the @code{sicp} Guix package. Go ahead, run @code{guix install -sicp} and start reading with @code{info sicp} (@pxref{Top,,, sicp, Structure and Interpretation of Computer Programs}). -An @uref{https://sarabander.github.io/sicp/, unofficial ebook is also -available}. +@quotation Going further +Scheme is a language that has been widely used to teach programming and +you'll find plenty of material using it as a vehicle. Here's a +selection of documents to learn more about Scheme: + +@itemize +@item +@uref{https://spritely.institute/static/papers/scheme-primer.html, @i{A +Scheme Primer}}, by Christine Lemmer-Webber and the Spritely Institute. + +@item +@uref{http://www.troubleshooters.com/codecorn/scheme_guile/hello.htm, +@i{Scheme at a Glance}}, by Steve Litt. + +@item +@uref{https://mitpress.mit.edu/sites/default/files/sicp/index.html, +@i{Structure and Interpretation of Computer Programs}}, by Harold +Abelson and Gerald Jay Sussman, with Julie Sussman. Colloquially known +as ``SICP'', this book is a reference. + +You can also install it and read it from your computer: + +@example +guix install sicp info-reader +info sicp +@end example + +An @uref{https://sarabander.github.io/sicp/, unofficial ebook} is also +available. + +@end itemize You'll find more books, tutorials and other resources at @url{https://schemers.org/}. +@end quotation @c ********************************************************************* -- cgit v1.2.3 From 5ecbf5b1637762281992befec7fa53f966e5d0b1 Mon Sep 17 00:00:00 2001 From: Maxim Cournoyer Date: Mon, 11 Jul 2022 17:21:55 -0400 Subject: doc: Fix cross-reference to Git Info manual. Partially fixes . Partially because our git package doesn't yet include the documentation. This change will need to go to core-updates. * doc/contributing.texi (Submitting Patches): Adjust the node name. --- doc/contributing.texi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'doc') diff --git a/doc/contributing.texi b/doc/contributing.texi index dcb45ad34c..3556f052ea 100644 --- a/doc/contributing.texi +++ b/doc/contributing.texi @@ -1119,11 +1119,11 @@ Development is done using the Git distributed version control system. Thus, access to the repository is not strictly necessary. We welcome contributions in the form of patches as produced by @code{git format-patch} sent to the @email{guix-patches@@gnu.org} mailing list -(@pxref{submitting patches,, Submitting patches to a project, git, Git -User Manual}). Contributors are encouraged to take a moment to set some -Git repository options (@pxref{Configuring Git}) first, which can -improve the readability of patches. Seasoned Guix developers may also -want to look at the section on commit access (@pxref{Commit Access}). +(@pxref{Submitting patches to a project,,, git, Git User Manual}). +Contributors are encouraged to take a moment to set some Git repository +options (@pxref{Configuring Git}) first, which can improve the +readability of patches. Seasoned Guix developers may also want to look +at the section on commit access (@pxref{Commit Access}). This mailing list is backed by a Debbugs instance, which allows us to keep track of submissions (@pxref{Tracking Bugs and Patches}). Each -- cgit v1.2.3 From 8d922504b22b81f99bf2dcbb9f15498ad513040a Mon Sep 17 00:00:00 2001 From: Reily Siegel Date: Wed, 29 Jun 2022 17:05:26 -0400 Subject: gnu: home: Add Guix channels service. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * gnu/home/services/guix.scm: New file. * gnu/local.mk (GNU_SYSTEM_MODULES): Add guix.scm. * doc/guix.texi: Add documentation for home-channels-service. Signed-off-by: Ludovic Courtès --- doc/guix.texi | 33 +++++++++++++++++++++++++++++++++ gnu/home/services/guix.scm | 44 ++++++++++++++++++++++++++++++++++++++++++++ gnu/local.mk | 1 + 3 files changed, 78 insertions(+) create mode 100644 gnu/home/services/guix.scm (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index 097e4a362b..a7ac74b416 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -105,6 +105,7 @@ Copyright @copyright{} 2022 Aleksandr Vityazev@* Copyright @copyright{} 2022 Philip M@sup{c}Grath@* Copyright @copyright{} 2022 Karl Hallsby@* Copyright @copyright{} 2022 Justin Veilleux@* +Copyright @copyright{} 2022 Reily Siegel@* Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -39433,6 +39434,7 @@ services)}. * Shepherd: Shepherd Home Service. Managing User's Daemons. * SSH: Secure Shell. Setting up the secure shell client. * Desktop: Desktop Home Services. Services for graphical environments. +* Guix: Guix Home Services. Services for Guix. @end menu @c In addition to that Home Services can provide @@ -40073,6 +40075,37 @@ format. @end deftp +@node Guix Home Services +@subsection Guix Home Services + +The @code{(gnu home services guix)} module provides services for +user-specific Guix configuration. + +@defvr {Scheme Variable} home-channels-service-type +This is the service type for managing +@file{$XDG_CONFIG_HOME/guix/channels.scm}, the file that controls the +channels received on @command{guix pull} (@pxref{Channels}). Its +associated value is a list of @code{channel} records, defined in the +@code{(guix channels)} module. + +Generally, it is better to extend this service than to directly +configure it, as its default value is the default guix channel(s) +defined by @code{%default-channels}. If you configure this service +directly, be sure to include a guix channel. @xref{Specifying +Additional Channels} and @ref{Using a Custom Guix Channel} for more +details. + +A typical extension for adding a channel might look like this: + +@lisp +(simple-service 'variant-packages-service + home-channels-service-type + (list + (channel + (name 'variant-packages) + (url "https://example.org/variant-packages.git"))) +@end lisp +@end defvr @node Invoking guix home @section Invoking @code{guix home} diff --git a/gnu/home/services/guix.scm b/gnu/home/services/guix.scm new file mode 100644 index 0000000000..819b20b6c9 --- /dev/null +++ b/gnu/home/services/guix.scm @@ -0,0 +1,44 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2022 Reily Siegel +;;; +;;; 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 . + +(define-module (gnu home services guix) + #:use-module (gnu home services) + #:use-module (guix channels) + #:use-module (guix gexp) + #:use-module (ice-9 pretty-print) + #:use-module (srfi srfi-1) + #:export (home-channels-service-type)) + +(define (channels-xdg-files channels) + `(("guix/channels.scm" + ,(plain-file + "channels.scm" + (call-with-output-string + (lambda (port) + (pretty-print (cons 'list (map channel->code channels)) port))))))) + +(define home-channels-service-type + (service-type + (name 'home-channels) + (default-value %default-channels) + (compose concatenate) + (extend append) + (extensions + (list (service-extension home-xdg-configuration-files-service-type + channels-xdg-files))) + (description "Manages the per-user Guix channels specification."))) diff --git a/gnu/local.mk b/gnu/local.mk index 12b04d2c2d..6d30109a35 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -83,6 +83,7 @@ GNU_SYSTEM_MODULES = \ %D%/home/services/desktop.scm \ %D%/home/services/symlink-manager.scm \ %D%/home/services/fontutils.scm \ + %D%/home/services/guix.scm \ %D%/home/services/shells.scm \ %D%/home/services/shepherd.scm \ %D%/home/services/ssh.scm \ -- cgit v1.2.3 From 6cd6753218748205120b622e366b1b53055704d9 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Wed, 13 Jul 2022 00:18:44 +0200 Subject: doc: Prefer "guix show" over "guix package --show". * doc/contributing.texi (Synopses and Descriptions): Use "guix show" instead of "guix package --show". --- doc/contributing.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/contributing.texi b/doc/contributing.texi index 3556f052ea..6a2564b07d 100644 --- a/doc/contributing.texi +++ b/doc/contributing.texi @@ -665,7 +665,7 @@ hyperlinks (@pxref{Overview,,, texinfo, GNU Texinfo}). However you should be careful when using some characters for example @samp{@@} and curly braces which are the basic special characters in Texinfo (@pxref{Special Characters,,, texinfo, GNU Texinfo}). User interfaces -such as @command{guix package --show} take care of rendering it +such as @command{guix show} take care of rendering it appropriately. Synopses and descriptions are translated by volunteers -- cgit v1.2.3 From 5f8adea86cac1e0b126b181a4d3cc67c0503f43b Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Thu, 14 Jul 2022 01:04:59 +0200 Subject: doc: Add example of 'bash-extension'. * doc/guix.texi (Shells Home Services): Add 'bash-extension' example. --- doc/guix.texi | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index a7ac74b416..8b09bcd4eb 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -39663,6 +39663,23 @@ contents of the extensions will be added to the end of the corresponding Bash configuration files (@pxref{Bash Startup Files,,, bash, The GNU Bash Reference Manual}. +For example, here is how you would define a service that extends the +Bash service such that @file{~/.bash_profile} defines an additional +environment variable, @env{PS1}: + +@lisp +(define bash-fancy-prompt-service + (simple-service 'bash-fancy-prompt + home-bash-service-type + (home-bash-extension + (environment-variables + '(("PS1" . "\\u \\wλ ")))))) +@end lisp + +You would then add @code{bash-fancy-prompt-service} to the list in the +@code{services} field of your @code{home-environment}. The reference of +@code{home-bash-extension} follows. + @deftp {Data Type} home-bash-extension Available @code{home-bash-extension} fields are: -- cgit v1.2.3 From 4ce7f1fb24a111f3e92d5b889d1271bebf109d09 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 15 Jul 2022 17:27:08 +0200 Subject: monad-repl: Add "build", "lower", and "verbosity" commands. Fixes . Reported by Maxime Devos . * guix/monad-repl.scm (%build-verbosity): New variable. (evaluate/print-with-store): New procedure. (run-in-store): Rewrite in terms of 'evaluate/print-with-store'. (verbosity, lower, build): New meta-commands. * doc/guix.texi (Using Guix Interactively): New node. (The Store Monad): Link to it. (Invoking guix repl): Likewise. * doc/contributing.texi (Running Guix Before It Is Installed): Refer to it. (The Perfect Setup): Suggest 'guix install' rather than 'guix package -i'. --- doc/contributing.texi | 5 +- doc/guix.texi | 137 ++++++++++++++++++++++++++++++++++++++++++++++++-- guix/monad-repl.scm | 64 ++++++++++++++++++++--- 3 files changed, 192 insertions(+), 14 deletions(-) (limited to 'doc') diff --git a/doc/contributing.texi b/doc/contributing.texi index 6a2564b07d..ad312ddeb6 100644 --- a/doc/contributing.texi +++ b/doc/contributing.texi @@ -225,8 +225,7 @@ $ ./pre-inst-env guile -c '(use-modules (guix utils)) (pk (%current-system))' @noindent @cindex REPL @cindex read-eval-print loop -@dots{} and for a REPL (@pxref{Using Guile Interactively,,, guile, Guile -Reference Manual}): +@dots{} and for a REPL (@pxref{Using Guix Interactively}): @example $ ./pre-inst-env guile @@ -292,7 +291,7 @@ Manual}). First, you need more than an editor, you need wonderful @url{https://nongnu.org/geiser/, Geiser}. To set that up, run: @example -guix package -i emacs guile emacs-geiser emacs-geiser-guile +guix install emacs guile emacs-geiser emacs-geiser-guile @end example Geiser allows for interactive and incremental development from within diff --git a/doc/guix.texi b/doc/guix.texi index 8b09bcd4eb..8fc8f53d0e 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -299,6 +299,7 @@ Programming Interface * The Store Monad:: Purely functional interface to the store. * G-Expressions:: Manipulating build expressions. * Invoking guix repl:: Programming Guix in Guile. +* Using Guix Interactively:: Fine-grain interaction at the REPL. Defining Packages @@ -7100,6 +7101,7 @@ package definitions. * The Store Monad:: Purely functional interface to the store. * G-Expressions:: Manipulating build expressions. * Invoking guix repl:: Programming Guix in Guile +* Using Guix Interactively:: Fine-grain interaction at the REPL. @end menu @node Package Modules @@ -10860,8 +10862,9 @@ So, to exit the monad and get the desired effect, one must use @end lisp Note that the @code{(guix monad-repl)} module extends the Guile REPL with -new ``meta-commands'' to make it easier to deal with monadic procedures: -@code{run-in-store}, and @code{enter-store-monad}. The former is used +new ``commands'' to make it easier to deal with monadic procedures: +@code{run-in-store}, and @code{enter-store-monad} (@pxref{Using Guix +Interactively}). The former is used to ``run'' a single monadic value through the store: @example @@ -10886,6 +10889,9 @@ scheme@@(guile-user)> Note that non-monadic values cannot be returned in the @code{store-monad} REPL. +Other meta-commands are available at the REPL, such as @code{,build} to +build a file-like object (@pxref{Using Guix Interactively}). + The main syntactic forms to deal with monads in general are provided by the @code{(guix monads)} module and are described below. @@ -11778,7 +11784,8 @@ lines at the top of the script: @code{!#} @end example -Without a file name argument, a Guile REPL is started: +Without a file name argument, a Guile REPL is started, allowing for +interactive use (@pxref{Using Guix Interactively}): @example $ guix repl @@ -11834,6 +11841,130 @@ Inhibit loading of the @file{~/.guile} file. By default, that configuration file is loaded when spawning a @code{guile} REPL. @end table +@node Using Guix Interactively +@section Using Guix Interactively + +The @command{guix repl} command gives you access to a warm and friendly +@dfn{read-eval-print loop} (REPL) (@pxref{Invoking guix repl}). If +you're getting into Guix programming---defining your own packages, +writing manifests, defining services for Guix System or Guix Home, +etc.---you will surely find it convenient to toy with ideas at the REPL. + +If you use Emacs, the most convenient way to do that is with Geiser +(@pxref{The Perfect Setup}), but you do not have to use Emacs to enjoy +the REPL@. When using @command{guix repl} or @command{guile} in the +terminal, we recommend using Readline for completion and Colorized to +get colorful output. To do that, you can run: + +@example +guix install guile guile-readline guile-colorized +@end example + +@noindent +... and then create a @file{.guile} in your home directory containing +this: + +@lisp +(use-modules (ice-9 readline) (ice-9 colorized)) + +(activate-readline) +(activate-colorized) +@end lisp + +The REPL lets you evaluate Scheme code; you type a Scheme expression at +the prompt, and the REPL prints what it evaluates to: + +@example +$ guix repl +scheme@@(guix-user)> (+ 2 3) +$1 = 5 +scheme@@(guix-user)> (string-append "a" "b") +$2 = "ab" +@end example + +It becomes interesting when you start fiddling with Guix at the REPL. +The first thing you'll want to do is to ``import'' the @code{(guix)} +module, which gives access to the main part of the programming +interface, and perhaps a bunch of useful Guix modules. You could type +@code{(use-modules (guix))}, which is valid Scheme code to import a +module (@pxref{Using Guile Modules,,, guile, GNU Guile Reference +Manual}), but the REPL provides the @code{use} @dfn{command} as a +shorthand notation (@pxref{REPL Commands,,, guile, GNU Guile Reference +Manual}): + +@example +scheme@@(guix-user)> ,use (guix) +scheme@@(guix-user)> ,use (gnu packages base) +@end example + +Notice that REPL commands are introduced by a leading comma. A REPL +command like @code{use} is not valid Scheme code; it's interpreted +specially by the REPL. + +Guix extends the Guile REPL with additional commands for convenience. +Among those, the @code{build} command comes in handy: it ensures that +the given file-like object is built, building it if needed, and returns +its output file name(s). In the example below, we build the +@code{coreutils} and @code{grep} packages, as well as a ``computed +file'' (@pxref{G-Expressions, @code{computed-file}}), and we use the +@code{scandir} procedure to list the files in Grep's @code{/bin} +directory: + +@example +scheme@@(guix-user)> ,build coreutils +$1 = "/gnu/store/@dots{}-coreutils-8.32-debug" +$2 = "/gnu/store/@dots{}-coreutils-8.32" +scheme@@(guix-user)> ,build grep +$3 = "/gnu/store/@dots{}-grep-3.6" +scheme@@(guix-user)> ,build (computed-file "x" #~(mkdir #$output)) +building /gnu/store/@dots{}-x.drv... +$4 = "/gnu/store/@dots{}-x" +scheme@@(guix-user)> ,use(ice-9 ftw) +scheme@@(guix-user)> (scandir (string-append $3 "/bin")) +$5 = ("." ".." "egrep" "fgrep" "grep") +@end example + +At a lower-level, a useful command is @code{lower}: it takes a file-like +object and ``lowers'' it into a derivation (@pxref{Derivations}) or a +store file: + +@example +scheme@@(guix-user)> ,lower grep +$6 = # /gnu/store/@dots{}-grep-3.6 7f0e639115f0> +scheme@@(guix-user)> ,lower (plain-file "x" "Hello!") +$7 = "/gnu/store/@dots{}-x" +@end example + +The full list of REPL commands can be seen by typing @code{,help guix} +and is given below for reference. + +@deffn {REPL command} build @var{object} +Lower @var{object} and build it if it's not already built, returning its +output file name(s). +@end deffn + +@deffn {REPL command} lower @var{object} +Lower @var{object} into a derivation or store file name and return it. +@end deffn + +@deffn {REPL command} verbosity @var{level} +Change build verbosity to @var{level}. + +This is similar to the @option{--verbosity} command-line option +(@pxref{Common Build Options}): level 0 means total silence, level 1 +shows build events only, and higher levels print build logs. +@end deffn + +@deffn {REPL command} run-in-store @var{exp} +Run @var{exp}, a monadic expresssion, through the store monad. +@xref{The Store Monad}, for more information. +@end deffn + +@deffn {REPL command} enter-store-monad +Enter a new REPL to evaluate monadic expressions (@pxref{The Store +Monad}). You can quit this ``inner'' REPL by typing @code{,q}. +@end deffn + @c ********************************************************************* @node Utilities @chapter Utilities 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 +;;; Copyright © 2014, 2015, 2016, 2022 Ludovic Courtès ;;; ;;; This file is part of GNU Guix. ;;; @@ -21,6 +21,12 @@ (define-module (guix monad-repl) #: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 @@ (define (store-monad-language store) #: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 -- cgit v1.2.3 From fa65e645e93aae288d5122e811a1f4cd02ba64d5 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sun, 17 Jul 2022 16:22:18 +0200 Subject: doc: Tweak. * doc/guix.texi (Using Guix Interactively): Add @cindex commands. Add missing word. --- doc/guix.texi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index 8fc8f53d0e..b47a0c17e8 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -11844,6 +11844,8 @@ configuration file is loaded when spawning a @code{guile} REPL. @node Using Guix Interactively @section Using Guix Interactively +@cindex interactive use +@cindex REPL, read-eval-print loop The @command{guix repl} command gives you access to a warm and friendly @dfn{read-eval-print loop} (REPL) (@pxref{Invoking guix repl}). If you're getting into Guix programming---defining your own packages, @@ -11861,7 +11863,7 @@ guix install guile guile-readline guile-colorized @end example @noindent -... and then create a @file{.guile} in your home directory containing +... and then create a @file{.guile} file in your home directory containing this: @lisp -- cgit v1.2.3 From 969e86784bdba4737baf07d12c5c3117b7c56b48 Mon Sep 17 00:00:00 2001 From: Rostislav Svoboda Date: Tue, 5 Jul 2022 18:35:44 +0200 Subject: doc: Fix the example of "Run `make` automatically" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * doc/contributing.texi (Running Guix Before It Is Installed): add missing command separator '--'. Signed-off-by: Ludovic Courtès --- doc/contributing.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/doc/contributing.texi b/doc/contributing.texi index ad312ddeb6..02c7c5ae59 100644 --- a/doc/contributing.texi +++ b/doc/contributing.texi @@ -278,8 +278,8 @@ prepared Guile object (@file{.go}) files. You can run @command{make} automatically as you work using @command{watchexec} from the @code{watchexec} package. For example, -to build again each time you update a package file, you can run -@samp{watchexec -w gnu/packages make -j4}. +to build again each time you update a package file, run +@samp{watchexec -w gnu/packages -- make -j4}. @node The Perfect Setup @section The Perfect Setup -- cgit v1.2.3 From 55725724dd0891e1e195158d0774a3f9a8619361 Mon Sep 17 00:00:00 2001 From: Antero Mejr Date: Tue, 12 Jul 2022 22:50:07 +0000 Subject: home: Add -I, --list-installed option. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * guix/scripts/package.scm (list-installed): New procedure. * guix/scripts/home.scm (%options, show-help): Add '--list-installed'. (process-command): For 'describe' and 'list-generations', honor the 'list-installed option. (display-home-environment-generation): Add #:list-installed-regex and honor it. (list-generations): Likewise. * guix/scripts/utils.scm (pretty-print-table): New argument "left-pad". * doc/guix.texi (Invoking Guix Home): Add information and example for --list-installed flag. Co-authored-by: Ludovic Courtès --- doc/guix.texi | 18 +++++++++++++- guix/scripts/home.scm | 64 ++++++++++++++++++++++++++++++++++-------------- guix/scripts/package.scm | 33 +++++++++++++++---------- guix/utils.scm | 6 ++--- 4 files changed, 85 insertions(+), 36 deletions(-) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index b47a0c17e8..c348760dae 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -40495,6 +40495,17 @@ install anything. Describe the current home generation: its file name, as well as provenance information when available. +To show installed packages in the current home generation's profile, the +@code{--list-installed} flag is provided, with the same syntax that is +used in @command{guix package --list-installed} (@pxref{Invoking guix +package}). For instance, the following command shows a table of all the +packages with ``emacs'' in their name that are installed in the current +home generation's profile: + +@example +guix home describe --list-installed=emacs +@end example + @item list-generations List a summary of each generation of the home environment available on disk, in a human-readable way. This is similar to the @@ -40507,9 +40518,14 @@ generations displayed. For instance, the following command displays generations that are up to 10 days old: @example -$ guix home list-generations 10d +guix home list-generations 10d @end example +The @code{--list-installed} flag may also be specified, with the same +syntax that is used in @command{guix home describe}. This may be +helpful if trying to determine when a package was added to the home +profile. + @item import Generate a @dfn{home environment} from the packages in the default profile and configuration files found in the user's home directory. The 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 ;;; Copyright © 2021 Oleg Pykhalov ;;; Copyright © 2022 Ludovic Courtès +;;; Copyright © 2022 Antero Mejr ;;; ;;; This file is part of GNU Guix. ;;; @@ -143,6 +144,11 @@ (define (show-help) 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 @@ (define %options (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 @@ (define-syntax-rule (with-store* store exp ...) 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 @@ (define (search . args) (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 @@ (define-values (channels config-file) (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/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 ;;; Copyright © 2018 Steve Sprang ;;; Copyright © 2022 Josselin Poiret +;;; Copyright © 2022 Antero Mejr ;;; ;;; This file is part of GNU Guix. ;;; @@ -67,6 +68,7 @@ (define-module (guix scripts package) delete-generations delete-matching-generations guix-package + list-installed search-path-environment-variables manifest-entry-version-prefix @@ -773,6 +775,22 @@ (define absolute (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 + (($ name version output path _) + (and (regexp-exec regexp name) + (list name (or version "?") output path)))) + installed))) + rows)))) + ;;; ;;; Queries and actions. @@ -824,19 +842,8 @@ (define (diff-profiles profile numbers) #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 - (($ 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/utils.scm b/guix/utils.scm index 745da98a79..329ef62dde 100644 --- a/guix/utils.scm +++ b/guix/utils.scm @@ -1124,11 +1124,11 @@ (define* (string-closest trial tests #:key (threshold 3)) ;;; 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 @@ (define* (pretty-print-table rows #:key (max-column-width 20)) (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) -- cgit v1.2.3 From 95acd67dd3d4f1667b97561099ea66f36ee6485e Mon Sep 17 00:00:00 2001 From: Antero Mejr Date: Wed, 13 Jul 2022 15:01:22 +0000 Subject: system: Add -I, --list-installed option. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * guix/scripts/system.scm (display-system-generation): Add #:list-installed-regex and honor it. (list-generations): Likewise. (show-help, %options): Add "--list-installed". (process-command): For 'describe' and 'list-generation', honor the 'list-installed option. * doc/guix.texi (Invoking Guix System): Add information for --list-installed flag. Signed-off-by: Ludovic Courtès --- doc/guix.texi | 12 +++++++++ guix/scripts/system.scm | 67 ++++++++++++++++++++++++++++++++++--------------- 2 files changed, 59 insertions(+), 20 deletions(-) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index c348760dae..d8a3d2e90c 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -37781,6 +37781,13 @@ bootloader boot menu: Describe the running system generation: its file name, the kernel and bootloader used, etc., as well as provenance information when available. +The @code{--list-installed} flag is available, with the same +syntax that is used in @command{guix package --list-installed} +(@pxref{Invoking guix package}). When the flag is used, +the description will include a list of packages that are currently +installed in the system profile, with optional filtering based on a +regular expression. + @quotation Note The @emph{running} system generation---referred to by @file{/run/current-system}---is not necessarily the @emph{current} @@ -37808,6 +37815,11 @@ generations that are up to 10 days old: $ guix system list-generations 10d @end example +The @code{--list-installed} flag may also be specified, with the same +syntax that is used in @command{guix package --list-installed}. This +may be helpful if trying to determine when a package was added to the +system. + @end table The @command{guix system} command has even more to offer! The following 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 @@ (define-module (guix scripts system) #: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 @@ (define (shepherd-service-node-type 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 @@ (define-values (channels config-file) (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 @@ (define (show-help) 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 @@ (define %options (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 @@ (define-syntax-rule (with-store* store exp ...) ;; 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) -- cgit v1.2.3 From be7b314f3fe22273e935accac22f313e44d3d970 Mon Sep 17 00:00:00 2001 From: Ricardo Wurmus Date: Tue, 19 Jul 2022 23:44:11 +0200 Subject: import: Enable recursive import for texlive packages. * guix/import/texlive.scm (tlpdb->package): Add VERSION argument; include explicit version field in output. (texlive->guix-package): Set default value for VERSION argument; adjust call of tlpdb->package. (texlive-recursive-import): Accept REPO and VERSION keyword arguments. * guix/import/utils.scm (package->definition): Add a clause to deal with output from tlpdb->package. * guix/scripts/import/texlive.scm (%options): Add "recursive" option. (guix-import-texlive): Honor "recursive" option. * doc/guix.texi (Using TeX and LaTeX): Mention "recursive" option. --- doc/guix.texi | 10 ++++++++++ guix/import/texlive.scm | 20 +++++++++++++++----- guix/import/utils.scm | 2 ++ guix/scripts/import/texlive.scm | 25 +++++++++++++++++++------ 4 files changed, 46 insertions(+), 11 deletions(-) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index d8a3d2e90c..3c5864ec1a 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -40965,6 +40965,16 @@ package, you can try and import it (@pxref{Invoking guix import}): guix import texlive @var{package} @end example +Additional options include: + +@table @code +@item --recursive +@itemx -r +Traverse the dependency graph of the given upstream package recursively +and generate package expressions for all those packages that are not yet +in Guix. +@end table + @quotation Note @TeX{} Live packaging is still very much work in progress, but you can help! @xref{Contributing}, for more information. 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 @@ (define name->parts (cut string-split <> #\/)) ;; 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 @@ (define (tlpdb->package name package-database) (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 @@ (define (tlpdb->package name package-database) (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 @@ (define (tlpdb->package name package-database) (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 @@ (define* (package->definition guix-package #:optional append-version?/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/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 @@ (define-module (guix scripts import texlive) #: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 @@ (define %options (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 @@ (define (parse-options) (_ #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 ...) -- cgit v1.2.3