diff options
Diffstat (limited to 'guix/scripts')
-rw-r--r-- | guix/scripts/archive.scm | 20 | ||||
-rw-r--r-- | guix/scripts/build.scm | 92 | ||||
-rw-r--r-- | guix/scripts/describe.scm | 1 | ||||
-rw-r--r-- | guix/scripts/edit.scm | 30 | ||||
-rw-r--r-- | guix/scripts/environment.scm | 20 | ||||
-rw-r--r-- | guix/scripts/graph.scm | 15 | ||||
-rw-r--r-- | guix/scripts/home.scm | 9 | ||||
-rw-r--r-- | guix/scripts/home/edit.scm | 66 | ||||
-rw-r--r-- | guix/scripts/home/import.scm | 4 | ||||
-rw-r--r-- | guix/scripts/import.scm | 42 | ||||
-rw-r--r-- | guix/scripts/import/elm.scm | 107 | ||||
-rw-r--r-- | guix/scripts/pack.scm | 28 | ||||
-rw-r--r-- | guix/scripts/package.scm | 67 | ||||
-rw-r--r-- | guix/scripts/publish.scm | 121 | ||||
-rw-r--r-- | guix/scripts/pull.scm | 14 | ||||
-rw-r--r-- | guix/scripts/shell.scm | 109 | ||||
-rw-r--r-- | guix/scripts/size.scm | 13 | ||||
-rw-r--r-- | guix/scripts/style.scm | 25 | ||||
-rwxr-xr-x | guix/scripts/substitute.scm | 12 | ||||
-rw-r--r-- | guix/scripts/system.scm | 13 | ||||
-rw-r--r-- | guix/scripts/system/edit.scm | 64 | ||||
-rw-r--r-- | guix/scripts/system/reconfigure.scm | 8 | ||||
-rw-r--r-- | guix/scripts/system/search.scm | 40 | ||||
-rw-r--r-- | guix/scripts/weather.scm | 30 |
24 files changed, 660 insertions, 290 deletions
diff --git a/guix/scripts/archive.scm b/guix/scripts/archive.scm index f8678aa5f9..1e961c84e6 100644 --- a/guix/scripts/archive.scm +++ b/guix/scripts/archive.scm @@ -93,14 +93,14 @@ Export/import one or more packages from/to the store.\n")) (display (G_ " -S, --source build the packages' source derivations")) (display (G_ " - -s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\"")) - (display (G_ " - --target=TRIPLET cross-build for TRIPLET--e.g., \"armel-linux-gnu\"")) - (display (G_ " -v, --verbosity=LEVEL use the given verbosity LEVEL")) (newline) (show-build-options-help) + (newline) + (show-cross-build-options-help) + (newline) + (show-native-build-options-help) (newline) (display (G_ " @@ -166,14 +166,6 @@ Export/import one or more packages from/to the store.\n")) (option '(#\S "source") #f #f (lambda (opt name arg result) (alist-cons 'source? #t result))) - (option '(#\s "system") #t #f - (lambda (opt name arg result) - (alist-cons 'system arg - (alist-delete 'system result eq?)))) - (option '("target") #t #f - (lambda (opt name arg result) - (alist-cons 'target arg - (alist-delete 'target result eq?)))) (option '(#\e "expression") #t #f (lambda (opt name arg result) (alist-cons 'expression arg result))) @@ -186,7 +178,9 @@ Export/import one or more packages from/to the store.\n")) (lambda (opt name arg result) (alist-cons 'dry-run? #t result))) - %standard-build-options)) + (append %standard-build-options + %standard-cross-build-options + %standard-native-build-options))) (define (derivation-from-expression store str package-derivation system source?) diff --git a/guix/scripts/build.scm b/guix/scripts/build.scm index d9cdb6e5e0..75bbb701ae 100644 --- a/guix/scripts/build.scm +++ b/guix/scripts/build.scm @@ -21,6 +21,7 @@ (define-module (guix scripts build) #:use-module (guix ui) + #:use-module (guix colors) #:use-module (guix scripts) #:autoload (guix import json) (json->scheme-file) #:use-module (guix store) @@ -47,6 +48,7 @@ #:use-module (srfi srfi-35) #:use-module (srfi srfi-37) #:use-module (gnu packages) + #:use-module (guix platform) #:use-module ((guix status) #:select (with-status-verbosity)) #:use-module ((guix progress) #:select (current-terminal-columns)) #:use-module ((guix build syscalls) #:select (terminal-columns)) @@ -54,9 +56,15 @@ #:export (log-url %standard-build-options + %standard-cross-build-options + %standard-native-build-options + set-build-options-from-command-line set-build-options-from-command-line* + show-build-options-help + show-cross-build-options-help + show-native-build-options-help guix-build register-root @@ -184,6 +192,18 @@ options handled by 'set-build-options-from-command-line', and listed in (display (G_ " --debug=LEVEL produce debugging output at LEVEL"))) +(define (show-cross-build-options-help) + (display (G_ " + --list-targets list available targets")) + (display (G_ " + --target=TRIPLET cross-build for TRIPLET--e.g., \"aarch64-linux-gnu\""))) + +(define (show-native-build-options-help) + (display (G_ " + --list-systems list available systems")) + (display (G_ " + -s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\""))) + (define (set-build-options-from-command-line store opts) "Given OPTS, an alist as returned by 'args-fold' given '%standard-build-options', set the corresponding build options on STORE." @@ -319,6 +339,59 @@ use '--no-offload' instead~%"))) (leave (G_ "not a number: '~a' option argument: ~a~%") name arg))))))) +(define (list-systems) + "Print the available systems." + (display (G_ "The available systems are:\n")) + (newline) + (let ((systems* + (map (lambda (system) + (if (string=? system (%current-system)) + (highlight + (string-append system " [current]")) + system)) + (systems)))) + (format #t "~{ - ~a ~%~}" + (sort systems* string<?)))) + +(define (list-targets) + "Print the available targets." + (display (G_ "The available targets are:\n")) + (newline) + (format #t "~{ - ~a ~%~}" + (sort (targets) string<?))) + +(define %standard-cross-build-options + ;; Build options related to cross builds. + (list + (option '("list-targets") #f #f + (lambda (opt name arg result) + (list-targets) + (exit 0))) + (option '("target") #t #f + (lambda (opt name arg result . rest) + (let ((t (false-if-exception + (first (member arg (targets)))))) + (if t + (apply values (alist-cons 'target t result) rest) + (leave (G_ "'~a' is not a supported target~%") + arg))))))) + +(define %standard-native-build-options + ;; Build options related to native builds. + (list + (option '("list-systems") #f #f + (lambda (opt name arg result) + (list-systems) + (exit 0))) + (option '(#\s "system") #t #f + (lambda (opt name arg result . rest) + (let ((s (false-if-exception + (first (member arg (systems)))))) + (if s + (apply values (alist-cons 'system s result) rest) + (leave (G_ "'~a' is not a supported system~%") + arg))))))) + ;;; ;;; Command-line options. @@ -353,10 +426,6 @@ Build the given PACKAGE-OR-DERIVATION and return their output paths.\n")) --sources[=TYPE] build source derivations; TYPE may optionally be one of \"package\", \"all\" (default), or \"transitive\"")) (display (G_ " - -s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\"")) - (display (G_ " - --target=TRIPLET cross-build for TRIPLET--e.g., \"armel-linux-gnu\"")) - (display (G_ " -d, --derivations return the derivation paths of the given packages")) (display (G_ " --check rebuild items to check for non-determinism issues")) @@ -374,6 +443,10 @@ Build the given PACKAGE-OR-DERIVATION and return their output paths.\n")) (newline) (show-build-options-help) (newline) + (show-cross-build-options-help) + (newline) + (show-native-build-options-help) + (newline) (show-transformation-options-help) (newline) (display (G_ " @@ -420,13 +493,6 @@ must be one of 'package', 'all', or 'transitive'~%") (alist-cons 'build-mode (build-mode repair) result) rest))) - (option '(#\s "system") #t #f - (lambda (opt name arg result) - (alist-cons 'system arg result))) - (option '("target") #t #f - (lambda (opt name arg result) - (alist-cons 'target arg - (alist-delete 'target result eq?)))) (option '(#\d "derivations") #f #f (lambda (opt name arg result) (alist-cons 'derivations-only? #t result))) @@ -459,7 +525,9 @@ must be one of 'package', 'all', or 'transitive'~%") (alist-cons 'log-file? #t result))) (append %transformation-options - %standard-build-options))) + %standard-build-options + %standard-cross-build-options + %standard-native-build-options))) (define (options->things-to-build opts) "Read the arguments from OPTS and return a list of high-level objects to diff --git a/guix/scripts/describe.scm b/guix/scripts/describe.scm index a3e3338f7e..7e4f682053 100644 --- a/guix/scripts/describe.scm +++ b/guix/scripts/describe.scm @@ -27,6 +27,7 @@ #:use-module (guix scripts) #:use-module (guix describe) #:use-module (guix profiles) + #:autoload (guix colors) (supports-hyperlinks? hyperlink) #:autoload (guix openpgp) (openpgp-format-fingerprint) #:use-module (git) #:autoload (json builder) (scm->json-string) diff --git a/guix/scripts/edit.scm b/guix/scripts/edit.scm index a2e1ffb434..8e777d1405 100644 --- a/guix/scripts/edit.scm +++ b/guix/scripts/edit.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2015, 2016, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2015-2016, 2019-2022 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2015 Mathieu Lirzin <mthl@gnu.org> ;;; Copyright © 2020, 2021 Simon Tournier <zimon.toutoune@gmail.com> ;;; @@ -27,6 +27,7 @@ #:use-module (srfi srfi-1) #:use-module (srfi srfi-37) #:export (%editor + spawn-editor guix-edit)) (define %options @@ -77,6 +78,21 @@ line." (location-line location))) (search-path* %load-path (location-file location)))) +(define (spawn-editor locations) + "Spawn (%editor) to edit the code at LOCATIONS, a list of <location> +records, and exit." + (catch 'system-error + (lambda () + (let ((file-names (append-map location->location-specification + locations))) + ;; Use `system' instead of `exec' in order to sanely handle + ;; possible command line arguments in %EDITOR. + (exit (system (string-join (cons (%editor) file-names)))))) + (lambda args + (let ((errno (system-error-errno args))) + (leave (G_ "failed to launch '~a': ~a~%") + (%editor) (strerror errno)))))) + (define-command (guix-edit . args) (category packaging) @@ -94,14 +110,4 @@ line." (when (null? specs) (leave (G_ "no packages specified, nothing to edit~%"))) - (catch 'system-error - (lambda () - (let ((file-names (append-map location->location-specification - locations))) - ;; Use `system' instead of `exec' in order to sanely handle - ;; possible command line arguments in %EDITOR. - (exit (system (string-join (cons (%editor) file-names)))))) - (lambda args - (let ((errno (system-error-errno args))) - (leave (G_ "failed to launch '~a': ~a~%") - (%editor) (strerror errno)))))))) + (spawn-editor locations)))) diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm index ec071402f4..3216235937 100644 --- a/guix/scripts/environment.scm +++ b/guix/scripts/environment.scm @@ -56,6 +56,7 @@ #:use-module (srfi srfi-37) #:use-module (srfi srfi-98) #:export (assert-container-features + load-manifest guix-environment guix-environment* show-environment-options-help @@ -95,8 +96,6 @@ shell'." (display (G_ " --search-paths display needed environment variable definitions")) (display (G_ " - -s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\"")) - (display (G_ " -r, --root=FILE make FILE a symlink to the result, and register it as a garbage collector root")) (display (G_ " @@ -144,6 +143,8 @@ COMMAND or an interactive shell in that environment.\n")) (newline) (show-build-options-help) (newline) + (show-native-build-options-help) + (newline) (show-transformation-options-help) (newline) (display (G_ " @@ -225,10 +226,6 @@ use '--preserve' instead~%")) (option '(#\n "dry-run") #f #f (lambda (opt name arg result) (alist-cons 'dry-run? #t result))) - (option '(#\s "system") #t #f - (lambda (opt name arg result) - (alist-cons 'system arg - (alist-delete 'system result eq?)))) (option '(#\C "container") #f #f (lambda (opt name arg result) (alist-cons 'container? #t result))) @@ -272,7 +269,8 @@ use '--preserve' instead~%")) (alist-cons 'bootstrap? #t result))) (append %transformation-options - %standard-build-options))) + %standard-build-options + %standard-native-build-options))) (define (pick-all alist key) "Return a list of values in ALIST associated with KEY." @@ -285,6 +283,11 @@ use '--preserve' instead~%")) (_ memo))) '() alist)) +(define (load-manifest file) ;TODO: factorize + "Load the user-profile manifest (Scheme code) from FILE and return it." + (let ((user-module (make-user-module '((guix profiles) (gnu))))) + (load* file user-module))) + (define (options/resolve-packages store opts) "Return OPTS with package specification strings replaced by manifest entries for the corresponding packages." @@ -331,8 +334,7 @@ for the corresponding packages." (let ((module (make-user-module '()))) (packages->outputs (load* file module) mode))) (('manifest . file) - (let ((module (make-user-module '((guix profiles) (gnu))))) - (manifest-entries (load* file module)))) + (manifest-entries (load-manifest file))) (_ '())) opts) manifest-entry=?))) diff --git a/guix/scripts/graph.scm b/guix/scripts/graph.scm index 535875c858..2f102180c9 100644 --- a/guix/scripts/graph.scm +++ b/guix/scripts/graph.scm @@ -39,7 +39,9 @@ options->transformation %transformation-options)) #:use-module ((guix scripts build) - #:select (%standard-build-options)) + #:select (%standard-build-options + %standard-native-build-options + show-native-build-options-help)) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) #:use-module (srfi srfi-34) @@ -504,10 +506,6 @@ package modules, while attempting to retain user package modules." (option '(#\e "expression") #t #f (lambda (opt name arg result) (alist-cons 'expression arg result))) - (option '(#\s "system") #t #f - (lambda (opt name arg result) - (alist-cons 'system arg - (alist-delete 'system result eq?)))) (find (lambda (option) (member "load-path" (option-names option))) %standard-build-options) @@ -519,7 +517,8 @@ package modules, while attempting to retain user package modules." (lambda args (show-version-and-exit "guix graph"))) - %transformation-options)) + (append %transformation-options + %standard-native-build-options))) (define (show-help) ;; TRANSLATORS: Here 'dot' is the name of a program; it must not be @@ -540,8 +539,6 @@ Emit a representation of the dependency graph of PACKAGE...\n")) --path display the shortest path between the given nodes")) (display (G_ " -e, --expression=EXPR consider the package EXPR evaluates to")) - (display (G_ " - -s, --system=SYSTEM consider the graph for SYSTEM--e.g., \"i686-linux\"")) (newline) (display (G_ " -L, --load-path=DIR prepend DIR to the package module search path")) @@ -553,6 +550,8 @@ Emit a representation of the dependency graph of PACKAGE...\n")) (display (G_ " -V, --version display version information and exit")) (newline) + (show-native-build-options-help) + (newline) (show-bug-report-information)) (define %default-options diff --git a/guix/scripts/home.scm b/guix/scripts/home.scm index af2643014d..0f5c3388a1 100644 --- a/guix/scripts/home.scm +++ b/guix/scripts/home.scm @@ -45,6 +45,7 @@ #:use-module (guix channels) #:use-module (guix derivations) #:use-module (guix ui) + #:autoload (guix colors) (supports-hyperlinks? file-hyperlink) #:use-module (guix grafts) #:use-module (guix packages) #:use-module (guix profiles) @@ -59,6 +60,7 @@ #:autoload (guix scripts pull) (channel-commit-hyperlink) #:autoload (guix scripts system) (service-node-type shepherd-service-node-type) + #:autoload (guix scripts home edit) (guix-home-edit) #:autoload (guix scripts home import) (import-manifest) #:use-module ((guix status) #:select (with-status-verbosity)) #:use-module ((guix build utils) #:select (mkdir-p)) @@ -92,6 +94,8 @@ Some ACTIONS support additional ARGS.\n")) (newline) (display (G_ "\ search search for existing service types\n")) + (display (G_ "\ + edit edit the definition of an existing service type\n")) (display (G_ " container run the home environment configuration in a container\n")) (display (G_ "\ @@ -538,6 +542,8 @@ argument list and OPTS is the option alist." ;; an home environment file. ((search) (apply search args)) + ((edit) + (apply guix-home-edit args)) ((import) (let* ((profiles (delete-duplicates (match (filter-map (match-lambda @@ -610,7 +616,7 @@ deploy the home environment described by these files.\n") extension-graph shepherd-graph list-generations describe delete-generations roll-back - switch-generation search + switch-generation search edit import container) (alist-cons 'action action result)) (else (leave (G_ "~a: unknown action~%") action)))))) @@ -732,6 +738,7 @@ description matches REGEXPS sorted by relevance, and their score." (leave-on-EPIPE (display-search-results matches (current-output-port) #:print service-type->recutils + #:regexps regexps #:command "guix home search"))))) diff --git a/guix/scripts/home/edit.scm b/guix/scripts/home/edit.scm new file mode 100644 index 0000000000..a6c05675b3 --- /dev/null +++ b/guix/scripts/home/edit.scm @@ -0,0 +1,66 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2022 Ludovic Courtès <ludo@gnu.org> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (guix scripts home edit) + #:use-module (guix diagnostics) + #:use-module (guix i18n) + #:use-module (guix ui) + #:autoload (guix utils) (string-closest) + #:use-module (gnu services) + #:use-module (gnu home services) + #:use-module (srfi srfi-1) + #:use-module (ice-9 match) + #:autoload (guix scripts edit) (spawn-editor) + #:export (guix-home-edit)) + +(define (service-type-not-found type) + "Report an error about @var{type} not being found and exit." + (report-error (G_ "~a: no such service type~%") type) + + (let* ((type (symbol->string type)) + (available (fold-home-service-types (lambda (type lst) + (cons (symbol->string + (service-type-name type)) + lst)) + '())) + (closest (string-closest type available))) + (unless (or (not closest) (string=? closest type)) + (display-hint (format #f (G_ "Did you mean @code{~a}?~%") + closest)))) + + (exit 1)) + + +(define (guix-home-edit . args) + (when (null? args) + (leave (G_ "no service types specified, nothing to edit~%"))) + + (with-error-handling + (let* ((types (append-map (lambda (type) + (let ((type (string->symbol type))) + (match (lookup-home-service-types type) + (() (service-type-not-found type)) + ((one) (list one)) + (lst + (warning (N_ "~a: ~a matching service type~%" + "~a: ~a matching service types~%" + (length lst)) + type (length lst)) + lst)))) + args))) + (spawn-editor (filter-map service-type-location types))))) diff --git a/guix/scripts/home/import.scm b/guix/scripts/home/import.scm index 575fe8f688..825ccb1e73 100644 --- a/guix/scripts/home/import.scm +++ b/guix/scripts/home/import.scm @@ -3,6 +3,7 @@ ;;; Copyright © 2021 Andrew Tropin <andrew@trop.in> ;;; Copyright © 2021-2022 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2022 Arjan Adriaanse <arjan@adriaan.se> +;;; Copyright © 2022 Antero Mejr <antero@mailbox.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -170,8 +171,7 @@ user's files to CONFIGURATION-DIRECTORY; the generated sexp refers to them." ,@(delete-duplicates (concatenate modules))) (home-environment - (packages (map (compose list specification->package+output) - ,packages)) + (packages (specifications->packages ,packages)) (services (list ,@services))))))))) (define* (import-manifest diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm index 40fa6759ae..62aa7bdbc5 100644 --- a/guix/scripts/import.scm +++ b/guix/scripts/import.scm @@ -2,9 +2,10 @@ ;;; Copyright © 2012, 2013, 2014, 2020, 2021 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2014 David Thompson <davet@gnu.org> ;;; Copyright © 2018 Kyle Meyer <kyle@kyleam.com> -;;; Copyright © 2019 Ricardo Wurmus <rekado@elephly.net> +;;; Copyright © 2019, 2022 Ricardo Wurmus <rekado@elephly.net> ;;; Copyright © 2021 Simon Tournier <zimon.toutoune@gmail.com> ;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz> +;;; Copyright © 2022 Philip McGrath <philip@philipmcgrath.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -24,6 +25,7 @@ (define-module (guix scripts import) #:use-module (guix ui) #:use-module (guix scripts) + #:use-module (guix scripts style) #:use-module (guix utils) #:use-module (srfi srfi-1) #:use-module (srfi srfi-11) @@ -31,43 +33,11 @@ #:use-module (srfi srfi-37) #:use-module (ice-9 format) #:use-module (ice-9 match) - #:use-module (ice-9 pretty-print) #:export (%standard-import-options guix-import)) ;;; -;;; Helper. -;;; - -(define (newline-rewriting-port output) - "Return an output port that rewrites strings containing the \\n escape -to an actual newline. This works around the behavior of `pretty-print' -and `write', which output these as \\n instead of actual newlines, -whereas we want the `description' field to contain actual newlines -rather than \\n." - (define (write-string str) - (let loop ((chars (string->list str))) - (match chars - (() - #t) - ((#\\ #\n rest ...) - (newline output) - (loop rest)) - ((chr rest ...) - (write-char chr output) - (loop rest))))) - - (make-soft-port (vector (cut write-char <>) - write-string - (lambda _ #t) ; flush - #f - (lambda _ #t) ; close - #f) - "w")) - - -;;; ;;; Command line options. ;;; @@ -80,7 +50,7 @@ rather than \\n." (define importers '("gnu" "pypi" "cpan" "hackage" "stackage" "egg" "elpa" "gem" "go" "cran" "crate" "texlive" "json" "opam" - "minetest")) + "minetest" "elm")) (define (resolve-importer name) (let ((module (resolve-interface @@ -118,9 +88,7 @@ Run IMPORTER with ARGS.\n")) ((importer args ...) (if (member importer importers) (let ((print (lambda (expr) - (pretty-print expr (newline-rewriting-port - (current-output-port)) - #:max-expr-width 80)))) + (pretty-print-with-comments (current-output-port) expr)))) (match (apply (resolve-importer importer) args) ((and expr (or ('package _ ...) ('let _ ...) diff --git a/guix/scripts/import/elm.scm b/guix/scripts/import/elm.scm new file mode 100644 index 0000000000..68dcbf1070 --- /dev/null +++ b/guix/scripts/import/elm.scm @@ -0,0 +1,107 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2022 Philip McGrath <philip@philipmcgrath.com> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (guix scripts import elm) + #:use-module (guix ui) + #:use-module (guix utils) + #:use-module (guix scripts) + #:use-module (guix import elm) + #:use-module (guix scripts import) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) + #:use-module (srfi srfi-37) + #:use-module (srfi srfi-71) + #:use-module (ice-9 match) + #:use-module (ice-9 format) + #:export (guix-import-elm)) + + +;;; +;;; Command-line options. +;;; + +(define %default-options + '()) + +(define (show-help) + (display (G_ "Usage: guix import elm PACKAGE-NAME + +Import and convert the Elm package PACKAGE-NAME. Optionally, a version +can be specified after the arobas (@) character.\n")) + (display (G_ " + -h, --help display this help and exit")) + (display (G_ " + -r, --recursive import packages recursively")) + (display (G_ " + -V, --version display version information and exit")) + (newline) + (show-bug-report-information)) + +(define %options + ;; Specification of the command-line options. + (cons* (option '(#\h "help") #f #f + (lambda args + (show-help) + (exit 0))) + (option '(#\V "version") #f #f + (lambda args + (show-version-and-exit "guix import elm"))) + (option '(#\r "recursive") #f #f + (lambda (opt name arg result) + (alist-cons 'recursive #t result))) + %standard-import-options)) + + +;;; +;;; Entry point. +;;; + +(define (guix-import-elm . args) + (define (parse-options) + ;; Return the alist of option values. + (parse-command-line args %options (list %default-options) + #:build-options? #f)) + + (let* ((opts (parse-options)) + (args (filter-map (match-lambda + (('argument . value) + value) + (_ #f)) + (reverse opts)))) + (match args + ((spec) + (with-error-handling + (let ((name version (package-name->name+version spec))) + (if (assoc-ref opts 'recursive) + ;; Recursive import + (map (match-lambda + ((and ('package ('name name) . rest) pkg) + `(define-public ,(string->symbol name) + ,pkg)) + (_ #f)) + (elm-recursive-import name version)) + ;; Single import + (let ((sexp (elm->guix-package name #:version version))) + (unless sexp + (leave (G_ "failed to download meta-data for package '~a'~%") + name)) + sexp))))) + (() + (leave (G_ "too few arguments~%"))) + ((many ...) + (leave (G_ "too many arguments~%")))))) diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm index 38bc021665..d3ee69840c 100644 --- a/guix/scripts/pack.scm +++ b/guix/scripts/pack.scm @@ -5,9 +5,9 @@ ;;; Copyright © 2018 Chris Marusich <cmmarusich@gmail.com> ;;; Copyright © 2018 Efraim Flashner <efraim@flashner.co.il> ;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr> -;;; Copyright © 2020 Maxim Cournoyer <maxim.cournoyer@gmail.com> +;;; Copyright © 2020, 2021, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com> ;;; Copyright © 2020 Eric Bavier <bavier@posteo.net> -;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com> +;;; Copyright © 2022 Alex Griffin <a@ajgrf.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -63,7 +63,7 @@ #:use-module (ice-9 match) #:export (compressor? compressor-name - compressor-extenstion + compressor-extension compressor-command %compressors lookup-compressor @@ -750,7 +750,7 @@ Valid compressors are: ~a~%") compressor-name %valid-compressors))) (match (manifest-entries manifest) ((entry) entry) - (() #f))) + (_ #f))) (define package-name (or (and=> single-entry manifest-entry-name) (manifest->friendly-name manifest))) @@ -1244,17 +1244,9 @@ last resort for relocation." (option '(#\m "manifest") #t #f (lambda (opt name arg result) (alist-cons 'manifest arg result))) - (option '(#\s "system") #t #f - (lambda (opt name arg result) - (alist-cons 'system arg - (alist-delete 'system result eq?)))) (option '("entry-point") #t #f (lambda (opt name arg result) (alist-cons 'entry-point arg result))) - (option '("target") #t #f - (lambda (opt name arg result) - (alist-cons 'target arg - (alist-delete 'target result eq?)))) (option '(#\C "compression") #t #f (lambda (opt name arg result) (alist-cons 'compressor (lookup-compressor arg) @@ -1305,13 +1297,19 @@ last resort for relocation." (append %deb-format-options %transformation-options - %standard-build-options))) + %standard-build-options + %standard-cross-build-options + %standard-native-build-options))) (define (show-help) (display (G_ "Usage: guix pack [OPTION]... PACKAGE... Create a bundle of PACKAGE.\n")) (show-build-options-help) (newline) + (show-cross-build-options-help) + (newline) + (show-native-build-options-help) + (newline) (show-transformation-options-help) (newline) (show-deb-format-options) @@ -1325,10 +1323,6 @@ Create a bundle of PACKAGE.\n")) (display (G_ " -e, --expression=EXPR consider the package EXPR evaluates to")) (display (G_ " - -s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\"")) - (display (G_ " - --target=TRIPLET cross-build for TRIPLET--e.g., \"armel-linux-gnu\"")) - (display (G_ " -C, --compression=TOOL compress using TOOL--e.g., \"lzip\"")) (display (G_ " -S, --symlink=SPEC create symlinks to the profile according to SPEC")) diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm index 9699c70c6d..99a6cfaa29 100644 --- a/guix/scripts/package.scm +++ b/guix/scripts/package.scm @@ -10,6 +10,7 @@ ;;; Copyright © 2020 Ricardo Wurmus <rekado@elephly.net> ;;; Copyright © 2020 Simon Tournier <zimon.toutoune@gmail.com> ;;; Copyright © 2018 Steve Sprang <scs@stevesprang.com> +;;; Copyright © 2022 Josselin Poiret <dev@jpoiret.xyz> ;;; ;;; This file is part of GNU Guix. ;;; @@ -203,8 +204,12 @@ non-zero relevance score." (match m2 ((package2 . score2) (if (= score1 score2) - (string>? (package-full-name package1) - (package-full-name package2)) + (if (string=? (package-name package1) + (package-name package2)) + (version>? (package-version package1) + (package-version package2)) + (string>? (package-name package1) + (package-name package2))) (> score1 score2)))))))))) (define (transaction-upgrade-entry store entry transaction) @@ -334,24 +339,8 @@ Alternately, see @command{guix package --search-paths -p ~s}.") "Search among all the versions of ENTRY's package that are available, and return the shortest unambiguous version prefix for this package. If only one version of ENTRY's package is available, return the empty string." - (let ((name (manifest-entry-name entry))) - (match (map package-version (find-packages-by-name name)) - ((_) - ;; A single version of NAME is available, so do not specify the - ;; version number, even if the available version doesn't match ENTRY. - "") - (versions - ;; If ENTRY uses the latest version, don't specify any version. - ;; Otherwise return the shortest unique version prefix. Note that - ;; this is based on the currently available packages, which could - ;; differ from the packages available in the revision that was used - ;; to build MANIFEST. - (let ((current (manifest-entry-version entry))) - (if (every (cut version>? current <>) - (delete current versions)) - "" - (version-unique-prefix (manifest-entry-version entry) - versions))))))) + (package-unique-version-prefix (manifest-entry-name entry) + (manifest-entry-version entry))) (define* (export-manifest manifest #:optional (port (current-output-port))) @@ -710,10 +699,10 @@ the resulting manifest entry." (manifest-entry-with-provenance (package->manifest-entry package output))) -(define (options->installable opts manifest transaction) - "Given MANIFEST, the current manifest, and OPTS, the result of 'args-fold', -return an variant of TRANSACTION that accounts for the specified installations -and upgrades." +(define (options->installable opts manifest transform transaction) + "Given MANIFEST, the current manifest, OPTS, and TRANSFORM, the result of +'args-fold', return an variant of TRANSACTION that accounts for the specified +installations, upgrades and transformations." (define upgrade? (options->upgrade-predicate opts)) @@ -730,13 +719,14 @@ and upgrades." (('install . (? package? p)) ;; When given a package via `-e', install the first of its ;; outputs (XXX). - (package->manifest-entry* p "out")) + (package->manifest-entry* (transform p) "out")) (('install . (? string? spec)) (if (store-path? spec) (store-item->manifest-entry spec) (let-values (((package output) (specification->package+output spec))) - (package->manifest-entry* package output)))) + (package->manifest-entry* (transform package) + output)))) (('install . obj) (leave (G_ "cannot install non-package object: ~s~%") obj)) @@ -901,7 +891,8 @@ processed, #f otherwise." (regexps (map (cut make-regexp* <> regexp/icase) patterns)) (matches (find-packages-by-description regexps))) (leave-on-EPIPE - (display-search-results matches (current-output-port))) + (display-search-results matches (current-output-port) + #:regexps regexps)) #t)) (('show _) @@ -994,16 +985,6 @@ processed, #f otherwise." (define profile (or (assoc-ref opts 'profile) %current-profile)) (define transform (options->transformation opts)) - (define (transform-entry entry) - (let ((item (transform (manifest-entry-item entry)))) - (manifest-entry-with-transformations - (manifest-entry - (inherit entry) - (item item) - (version (if (package? item) - (package-version item) - (manifest-entry-version entry))))))) - (when (equal? profile %current-profile) ;; Normally the daemon created %CURRENT-PROFILE when we connected, unless ;; it's a version that lacks the fix for <https://bugs.gnu.org/37744> @@ -1036,16 +1017,12 @@ processed, #f otherwise." (map load-manifest files)))))) (step1 (options->removable opts manifest (manifest-transaction))) - (step2 (options->installable opts manifest step1)) - (step3 (manifest-transaction - (inherit step2) - (install (map transform-entry - (manifest-transaction-install step2))))) - (new (manifest-perform-transaction manifest step3)) + (step2 (options->installable opts manifest transform step1)) + (new (manifest-perform-transaction manifest step2)) (trans (if (null? files) - step3 + step2 (fold manifest-transaction-install-entry - step3 + step2 (manifest-entries manifest))))) (warn-about-old-distro) diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm index 870dfc11e9..3bf3bd9c7c 100644 --- a/guix/scripts/publish.scm +++ b/guix/scripts/publish.scm @@ -25,7 +25,6 @@ #:use-module ((system repl server) #:prefix repl:) #:use-module (ice-9 binary-ports) #:use-module (ice-9 format) - #:use-module (ice-9 iconv) #:use-module (ice-9 match) #:use-module (ice-9 poll) #:use-module (ice-9 regex) @@ -36,11 +35,11 @@ #:use-module (srfi srfi-2) #:use-module (srfi srfi-9) #:use-module (srfi srfi-9 gnu) - #:use-module (srfi srfi-11) #:use-module (srfi srfi-19) #:use-module (srfi srfi-26) #:use-module (srfi srfi-34) #:use-module (srfi srfi-37) + #:use-module (srfi srfi-71) #:use-module (web http) #:use-module (web request) #:use-module (web response) @@ -406,18 +405,15 @@ appropriate duration. NAR-PATH specifies the prefix for nar URLs." (let ((store-path (hash-part->path store hash))) (if (string-null? store-path) (not-found request #:phrase "" #:ttl negative-ttl) - (values `((content-type . (application/x-nix-narinfo - (charset . "UTF-8"))) - (x-nar-path . ,nar-path) - (x-narinfo-compressions . ,compressions) + (values `((content-type . (application/x-nix-narinfo)) ,@(if ttl `((cache-control (max-age . ,ttl))) '())) - ;; Do not call narinfo-string directly here as it is an - ;; expensive call that could potentially block the main - ;; thread. Instead, create the narinfo string in the - ;; http-write procedure. - store-path)))) + (cut display + (narinfo-string store store-path + #:nar-path nar-path + #:compressions compressions) + <>))))) (define* (nar-cache-file directory item #:key (compression %no-compression)) @@ -672,38 +668,19 @@ requested using POOL." (link narinfo other))) others)))))) -(define (compression->sexp compression) - "Return the SEXP representation of COMPRESSION." - (match compression - (($ <compression> type level) - `(compression ,type ,level)))) - -(define (sexp->compression sexp) - "Turn the given SEXP into a <compression> record and return it." - (match sexp - (('compression type level) - (compression type level)))) - ;; XXX: Declare the 'X-Nar-Compression' HTTP header, which is in fact for ;; internal consumption: it allows us to pass the compression info to ;; 'http-write', as part of the workaround to <http://bugs.gnu.org/21093>. (declare-header! "X-Nar-Compression" (lambda (str) - (sexp->compression - (call-with-input-string str read))) + (match (call-with-input-string str read) + (('compression type level) + (compression type level)))) compression? (lambda (compression port) - (write (compression->sexp compression) port))) - -;; This header is used to pass the supported compressions to http-write in -;; order to format on-the-fly narinfo responses. -(declare-header! "X-Narinfo-Compressions" - (lambda (str) - (map sexp->compression - (call-with-input-string str read))) - (cut every compression? <>) - (lambda (compressions port) - (write (map compression->sexp compressions) port))) + (match compression + (($ <compression> type level) + (write `(compression ,type ,level) port))))) (define* (render-nar store request store-item #:key (compression %no-compression)) @@ -858,8 +835,7 @@ example: \"/foo/bar\" yields '(\"foo\" \"bar\")." "Return RESPONSE's headers minus 'Content-Length' and our internal headers." (fold alist-delete (response-headers response) - '(content-length x-raw-file x-nar-compression - x-narinfo-compressions x-nar-path))) + '(content-length x-raw-file x-nar-compression))) (define (sans-content-length response) "Return RESPONSE without its 'content-length' header." @@ -993,38 +969,6 @@ blocking." (unless keep-alive? (close-port client))) (values)))))) - (('application/x-nix-narinfo . _) - (let ((compressions (assoc-ref (response-headers response) - 'x-narinfo-compressions)) - (nar-path (assoc-ref (response-headers response) - 'x-nar-path))) - (if nar-path - (begin - (when (keep-alive? response) - (keep-alive client)) - (call-with-new-thread - (lambda () - (set-thread-name "publish narinfo") - (let* ((narinfo - (with-store store - (narinfo-string store (utf8->string body) - #:nar-path nar-path - #:compressions compressions))) - (narinfo-bv (string->bytevector narinfo "UTF-8")) - (narinfo-length - (bytevector-length narinfo-bv)) - (response (write-response - (with-content-length response - narinfo-length) - client)) - (output (response-port response))) - (configure-socket client) - (put-bytevector output narinfo-bv) - (force-output output) - (unless (keep-alive? response) - (close-port output)) - (values))))) - (%http-write server client response body)))) (_ (match (assoc-ref (response-headers response) 'x-raw-file) ((? string? file) @@ -1190,8 +1134,7 @@ headers." ;; Preserve the request's 'connection' header in the response, so that the ;; server can close the connection if this is requested by the client. (lambda (request body) - (let-values (((response response-body) - (handle request body))) + (let ((response response-body (handle request body))) (values (preserve-connection-headers request response) response-body)))) @@ -1236,6 +1179,23 @@ headers." (bind sock address) sock)) +(define (systemd-socket) + "If this program is being spawned through systemd-style \"socket +activation\", whereby the listening socket is passed as file descriptor 3, +return the corresponding socket. Otherwise return #f." + (and (equal? (and=> (getenv "LISTEN_PID") string->number) + (getpid)) + (match (getenv "LISTEN_FDS") + ((= string->number 1) + (let ((sock (fdopen 3 "r+0"))) + (configure-socket sock) + sock)) + ((= string->number (? integer? n)) + (leave (G_ "~a: unexpected number of startup file descriptors") + n)) + (_ + #f)))) + (define (gather-user-privileges user) "Switch to the identity of USER, a user name." (catch 'misc-error @@ -1281,7 +1241,12 @@ headers." (make-socket-address (sockaddr:fam addr) (sockaddr:addr addr) port))) - (socket (open-server-socket address)) + (socket style (match (systemd-socket) + (#f + (values (open-server-socket address) + 'normal)) + (socket + (values socket 'systemd)))) (nar-path (assoc-ref opts 'nar-path)) (repl-port (assoc-ref opts 'repl)) (cache (assoc-ref opts 'cache)) @@ -1306,10 +1271,12 @@ consider using the '--user' option!~%"))) (cache-bypass-threshold (or (assoc-ref opts 'cache-bypass-threshold) (cache-bypass-threshold)))) - (info (G_ "publishing ~a on ~a, port ~d~%") - %store-directory - (inet-ntop (sockaddr:fam address) (sockaddr:addr address)) - (sockaddr:port address)) + (if (eq? style 'systemd) + (info (G_ "publishing (started via socket activation)~%")) + (info (G_ "publishing ~a on ~a, port ~d~%") + %store-directory + (inet-ntop (sockaddr:fam address) (sockaddr:addr address)) + (sockaddr:port address))) (for-each (lambda (compression) (info (G_ "using '~a' compression method, level ~a~%") diff --git a/guix/scripts/pull.scm b/guix/scripts/pull.scm index 7402782ff3..f01764637b 100644 --- a/guix/scripts/pull.scm +++ b/guix/scripts/pull.scm @@ -40,8 +40,6 @@ #:use-module (guix scripts build) #:use-module (guix scripts describe) #:autoload (guix build utils) (which mkdir-p) - #:use-module ((guix build syscalls) - #:select (with-file-lock/no-wait)) #:use-module (guix git) #:use-module (git) #:autoload (gnu packages) (fold-available-packages) @@ -119,11 +117,12 @@ Download and deploy the latest version of Guix.\n")) (display (G_ " -v, --verbosity=LEVEL use the given verbosity LEVEL")) (display (G_ " - -s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\"")) - (display (G_ " --bootstrap use the bootstrap Guile to build the new Guix")) (newline) (show-build-options-help) + (newline) + (show-native-build-options-help) + (newline) (display (G_ " -h, --help display this help and exit")) (display (G_ " @@ -184,10 +183,6 @@ Download and deploy the latest version of Guix.\n")) (lambda (opt name arg result) (alist-cons 'profile (canonicalize-profile arg) result))) - (option '(#\s "system") #t #f - (lambda (opt name arg result) - (alist-cons 'system arg - (alist-delete 'system result eq?)))) (option '(#\n "dry-run") #f #f (lambda (opt name arg result) (alist-cons 'dry-run? #t result))) @@ -208,7 +203,8 @@ Download and deploy the latest version of Guix.\n")) (lambda args (show-version-and-exit "guix pull"))) - %standard-build-options)) + (append %standard-build-options + %standard-native-build-options))) (define (warn-about-backward-updates channel start commit relation) "Warn about non-forward updates of CHANNEL from START to COMMIT, without diff --git a/guix/scripts/shell.scm b/guix/scripts/shell.scm index 1eab05d737..1a6df98829 100644 --- a/guix/scripts/shell.scm +++ b/guix/scripts/shell.scm @@ -21,7 +21,8 @@ #:use-module ((guix diagnostics) #:select (location)) #:use-module (guix scripts environment) #:autoload (guix scripts build) (show-build-options-help) - #:autoload (guix transformations) (transformation-option-key? + #:autoload (guix transformations) (options->transformation + transformation-option-key? show-transformation-options-help) #:use-module (guix scripts) #:use-module (guix packages) @@ -41,7 +42,12 @@ #:use-module ((guix build utils) #:select (mkdir-p)) #:use-module (guix cache) #:use-module ((ice-9 ftw) #:select (scandir)) - #:autoload (gnu packages) (cache-is-authoritative?) + #:autoload (ice-9 pretty-print) (pretty-print) + #:autoload (gnu packages) (cache-is-authoritative? + package-unique-version-prefix + specification->package + specification->package+output + specifications->manifest) #:export (guix-shell)) (define (show-help) @@ -55,10 +61,13 @@ interactive shell in that environment.\n")) -D, --development include the development inputs of the next package")) (display (G_ " -f, --file=FILE add to the environment the package FILE evaluates to")) + (display (G_ " -q inhibit loading of 'guix.scm' and 'manifest.scm'")) (display (G_ " --rebuild-cache rebuild cached environment, if any")) + (display (G_ " + --export-manifest print a manifest for the given options")) (show-environment-options-help) (newline) @@ -112,6 +121,10 @@ interactive shell in that environment.\n")) ;; 'wrapped-option'. (alist-delete 'ad-hoc? result))) + (option '("export-manifest") #f #f + (lambda (opt name arg result) + (alist-cons 'export-manifest? #t result))) + ;; For consistency with 'guix package', support '-f' rather than ;; '-l' like 'guix environment' does. (option '(#\f "file") #t #f @@ -382,6 +395,94 @@ return #f and #f." ;;; +;;; Exporting a manifest. +;;; + +(define (manifest-entry-version-prefix entry) + "Search among all the versions of ENTRY's package that are available, and +return the shortest unambiguous version prefix for this package." + (package-unique-version-prefix (manifest-entry-name entry) + (manifest-entry-version entry))) + +(define (manifest->code* manifest extra-manifests) + "Like 'manifest->code', but insert a 'concatenate-manifests' call that +concatenates MANIFESTS, a list of expressions." + (if (null? (manifest-entries manifest)) + (match extra-manifests + ((one) one) + (lst `(concatenate-manifests (list ,@extra-manifests)))) + (match (manifest->code manifest + #:entry-package-version + manifest-entry-version-prefix) + (('begin exp ... last) + `(begin + ,@exp + ,(match extra-manifests + (() last) + (_ `(concatenate-manifests + (list ,last ,@extra-manifests))))))))) + +(define (export-manifest opts port) + "Write to PORT a manifest corresponding to OPTS." + (define (manifest-lift proc) + (lambda (entry) + (match (manifest-entry-item entry) + ((? package? p) + (manifest-entry + (inherit (package->manifest-entry (proc p))) + (output (manifest-entry-output entry)))) + (_ + entry)))) + + (define (validated-spec spec) + ;; Return SPEC if it's a valid package spec. + (specification->package+output spec) + spec) + + (let* ((transform (options->transformation opts)) + (specs (reverse + (filter-map (match-lambda + (('package 'ad-hoc-package spec) + (validated-spec spec)) + (_ #f)) + opts))) + (extras (reverse + (filter-map (match-lambda + (('package 'package spec) + ;; Make sure SPEC is valid. + (specification->package spec) + + ;; XXX: This is an approximation: + ;; transformation options are not applied. + `(package->development-manifest + (specification->package ,spec))) + (_ #f)) + opts))) + (manifest (concatenate-manifests + (cons (map-manifest-entries + (manifest-lift transform) + (specifications->manifest specs)) + (filter-map (match-lambda + (('manifest . file) + (load-manifest file)) + (_ #f)) + opts))))) + (display (G_ "\ +;; What follows is a \"manifest\" equivalent to the command line you gave. +;; You can store it in a file that you may then pass to any 'guix' command +;; that accepts a '--manifest' (or '-m') option.\n") + port) + (match (manifest->code* manifest extras) + (('begin exp ...) + (for-each (lambda (exp) + (newline port) + (pretty-print exp port)) + exp)) + (exp + (pretty-print exp port))))) + + +;;; ;;; One-time hints. ;;; @@ -445,4 +546,6 @@ to make sure your shell does not clobber environment variables."))) ) cache-entries #:entry-expiration entry-expiration))) - (guix-environment* opts)) + (if (assoc-ref opts 'export-manifest?) + (export-manifest opts (current-output-port)) + (guix-environment* opts))) diff --git a/guix/scripts/size.scm b/guix/scripts/size.scm index e46983382a..5bb970443c 100644 --- a/guix/scripts/size.scm +++ b/guix/scripts/size.scm @@ -235,8 +235,6 @@ Report the size of the PACKAGE or STORE-ITEM, with its dependencies.\n")) (display (G_ " --substitute-urls=URLS fetch substitute from URLS if they are authorized")) - (display (G_ " - -s, --system=SYSTEM consider packages for SYSTEM--e.g., \"i686-linux\"")) ;; TRANSLATORS: "closure" and "self" must not be translated. (display (G_ " --sort=KEY sort according to KEY--\"closure\" or \"self\"")) @@ -251,15 +249,13 @@ Report the size of the PACKAGE or STORE-ITEM, with its dependencies.\n")) (display (G_ " -V, --version display version information and exit")) (newline) + (show-native-build-options-help) + (newline) (show-bug-report-information)) (define %options ;; Specifications of the command-line options. - (list (option '(#\s "system") #t #f - (lambda (opt name arg result) - (alist-cons 'system arg - (alist-delete 'system result eq?)))) - (option '("substitute-urls") #t #f + (cons* (option '("substitute-urls") #t #f (lambda (opt name arg result . rest) (apply values (alist-cons 'substitute-urls @@ -287,7 +283,8 @@ Report the size of the PACKAGE or STORE-ITEM, with its dependencies.\n")) (exit 0))) (option '(#\V "version") #f #f (lambda args - (show-version-and-exit "guix size"))))) + (show-version-and-exit "guix size"))) + %standard-native-build-options)) (define %default-options `((system . ,(%current-system)) diff --git a/guix/scripts/style.scm b/guix/scripts/style.scm index fb31c694f2..8123570c38 100644 --- a/guix/scripts/style.scm +++ b/guix/scripts/style.scm @@ -66,8 +66,23 @@ (define (read-with-comments port) "Like 'read', but include <comment> objects when they're encountered." ;; Note: Instead of implementing this functionality in 'read' proper, which - ;; is the best approach long-term, this code is a later on top of 'read', + ;; is the best approach long-term, this code is a layer on top of 'read', ;; such that we don't have to rely on a specific Guile version. + (define dot (list 'dot)) + (define (dot? x) (eq? x dot)) + + (define (reverse/dot lst) + ;; Reverse LST and make it an improper list if it contains DOT. + (let loop ((result '()) + (lst lst)) + (match lst + (() result) + (((? dot?) . rest) + (let ((dotted (reverse rest))) + (set-cdr! (last-pair dotted) (car result)) + dotted)) + ((x . rest) (loop (cons x result) rest))))) + (let loop ((blank-line? #t) (return (const 'unbalanced))) (match (read-char port) @@ -85,7 +100,7 @@ (((? comment?) . _) #t) (_ #f)) (lambda () - (return (reverse lst)))) + (return (reverse/dot lst)))) lst))))) ((memv chr '(#\) #\])) (return)) @@ -107,8 +122,10 @@ (not blank-line?))) (else (unread-char chr port) - (read port))))))) - + (match (read port) + ((and token '#{.}#) + (if (eq? chr #\.) dot token)) + (token token)))))))) ;;; ;;; Comment-preserving pretty-printer. diff --git a/guix/scripts/substitute.scm b/guix/scripts/substitute.scm index 908a8334a8..c5f5d23b47 100755 --- a/guix/scripts/substitute.scm +++ b/guix/scripts/substitute.scm @@ -704,6 +704,14 @@ default value." (category internal) (synopsis "implement the build daemon's substituter protocol") + (match args + ((or ("-V") ("--version")) + (show-version-and-exit "guix substitute")) + ((or ("-h") ("--help") ()) + (show-help) + (exit 0)) + (_ #t)) + (define print-build-trace? (match (or (find-daemon-option "untrusted-print-extended-build-trace") (find-daemon-option "print-extended-build-trace")) @@ -775,10 +783,6 @@ default value." #:print-build-trace? print-build-trace?) (loop)))))) - ((or ("-V") ("--version")) - (show-version-and-exit "guix substitute")) - ((or ("-h") ("--help")) - (show-help)) (opts (leave (G_ "~a: unrecognized options~%") opts)))))) diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm index 067bf999f1..63e3b9b934 100644 --- a/guix/scripts/system.scm +++ b/guix/scripts/system.scm @@ -10,6 +10,7 @@ ;;; Copyright © 2020 Efraim Flashner <efraim@flashner.co.il> ;;; Copyright © 2021 Brice Waegeneire <brice@waegenei.re> ;;; Copyright © 2021 Simon Tournier <zimon.toutoune@gmail.com> +;;; Copyright © 2022 Tobias Geerinckx-Rice <me@tobias.gr> ;;; ;;; This file is part of GNU Guix. ;;; @@ -29,6 +30,7 @@ (define-module (guix scripts system) #:use-module (guix config) #:use-module (guix ui) + #:autoload (guix colors) (supports-hyperlinks? file-hyperlink) #:use-module ((guix status) #:select (with-status-verbosity)) #:use-module (guix store) #:autoload (guix base16) (bytevector->base16-string) @@ -65,7 +67,7 @@ (device-module-aliases matching-modules) #:use-module (gnu system linux-initrd) #:use-module (gnu image) - #:use-module (gnu platform) + #:use-module (guix platform) #:use-module (gnu system) #:use-module (gnu bootloader) #:use-module (gnu system file-systems) @@ -944,6 +946,8 @@ Some ACTIONS support additional ARGS.\n")) (display (G_ "\ search search for existing service types\n")) (display (G_ "\ + edit edit the definition of an existing service type\n")) + (display (G_ "\ reconfigure switch to a new operating system configuration\n")) (display (G_ "\ roll-back switch to the previous operating system configuration\n")) @@ -1171,7 +1175,8 @@ Some ACTIONS support additional ARGS.\n")) "extension-graph" "shepherd-graph" "list-generations" "describe" "delete-generations" "roll-back" - "switch-generation" "search" "docker-image")) + "switch-generation" "search" "edit" + "docker-image")) (define (process-action action args opts) "Process ACTION, a sub-command, with the arguments are listed in ARGS. @@ -1269,7 +1274,7 @@ resulting from command-line parsing." (export-shepherd-graph os (current-output-port) #:backend (graph-backend))) (else - (unless (memq action '(build init)) + (unless (memq action '(build init reconfigure)) (warn-about-old-distro #:suggested-command "guix system reconfigure")) @@ -1339,6 +1344,8 @@ argument list and OPTS is the option alist." (display-system-generation generation)))) ((search) (apply (resolve-subcommand "search") args)) + ((edit) + (apply (resolve-subcommand "edit") args)) ;; The following commands need to use the store, but they do not need an ;; operating system configuration file. ((delete-generations) diff --git a/guix/scripts/system/edit.scm b/guix/scripts/system/edit.scm new file mode 100644 index 0000000000..d966ee0aaa --- /dev/null +++ b/guix/scripts/system/edit.scm @@ -0,0 +1,64 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2022 Ludovic Courtès <ludo@gnu.org> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (guix scripts system edit) + #:use-module (guix diagnostics) + #:use-module (guix i18n) + #:use-module (guix ui) + #:autoload (guix utils) (string-closest) + #:use-module (gnu services) + #:use-module (srfi srfi-1) + #:use-module (ice-9 match) + #:autoload (guix scripts edit) (spawn-editor) + #:export (guix-system-edit)) + +(define (service-type-not-found type) + "Report an error about @var{type} not being found and exit." + (report-error (G_ "~a: no such service type~%") type) + + (let* ((type (symbol->string type)) + (available (fold-service-types (lambda (type lst) + (cons (symbol->string + (service-type-name type)) + lst)) + '())) + (closest (string-closest type available))) + (unless (or (not closest) (string=? closest type)) + (display-hint (format #f (G_ "Did you mean @code{~a}?~%") + closest)))) + + (exit 1)) + + +(define (guix-system-edit . args) + (when (null? args) + (leave (G_ "no service types specified, nothing to edit~%"))) + + (let* ((types (append-map (lambda (type) + (let ((type (string->symbol type))) + (match (lookup-service-types type) + (() (service-type-not-found type)) + ((one) (list one)) + (lst + (warning (N_ "~a: ~a matching service type~%" + "~a: ~a matching service types~%" + (length lst)) + type (length lst)) + lst)))) + args))) + (spawn-editor (filter-map service-type-location types)))) diff --git a/guix/scripts/system/reconfigure.scm b/guix/scripts/system/reconfigure.scm index bf23fb06af..9ca66687ee 100644 --- a/guix/scripts/system/reconfigure.scm +++ b/guix/scripts/system/reconfigure.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2014-2022 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2016 Alex Kost <alezost@gmail.com> ;;; Copyright © 2016, 2017, 2018 Chris Marusich <cmmarusich@gmail.com> ;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com> @@ -134,6 +134,7 @@ return the <live-service> objects that are currently running on MACHINE." (map (lambda (service) (list (live-service-provision service) (live-service-requirement service) + (live-service-transient? service) (match (live-service-running service) (#f #f) (#t #t) @@ -143,8 +144,9 @@ return the <live-service> objects that are currently running on MACHINE." (mlet %store-monad ((services (eval exp))) (return (map (match-lambda - ((provision requirement running) - (live-service provision requirement running))) + ((provision requirement transient? running) + (live-service provision requirement + transient? running))) services)))) ;; XXX: Currently, this does NOT attempt to restart running services. See diff --git a/guix/scripts/system/search.scm b/guix/scripts/system/search.scm index bf49ea2341..44f00194cd 100644 --- a/guix/scripts/system/search.scm +++ b/guix/scripts/system/search.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2017-2019, 2022 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2018 Clément Lassieur <clement@lassieur.org> ;;; ;;; This file is part of GNU Guix. @@ -20,6 +20,8 @@ (define-module (guix scripts system search) #:use-module (guix ui) #:use-module (guix utils) + #:autoload (guix colors) (color-output? highlight supports-hyperlinks?) + #:autoload (guix diagnostics) (location->hyperlink) #:use-module (gnu services) #:use-module (gnu services shepherd) #:use-module (srfi srfi-1) @@ -68,10 +70,15 @@ provided TYPE has a default value." #:optional (width (%text-width)) #:key (extra-fields '()) - (hyperlinks? (supports-hyperlinks? port))) + (hyperlinks? (supports-hyperlinks? port)) + (highlighting identity)) "Write to PORT a recutils record of TYPE, arranging to fit within WIDTH columns. When HYPERLINKS? is true, emit hyperlink escape sequences when -appropriate." +appropriate. Pass the description through HIGHLIGHTING, a one-argument +procedure that may return a colorized version of its argument." + (define port* + (or (pager-wrapped-port port) port)) + (define width* ;; The available number of columns once we've taken into account space for ;; the initial "+ " prefix. @@ -85,8 +92,15 @@ appropriate." (fill-paragraph list width* (string-length "extends: "))))) + (define highlighting* + (if (color-output? port*) + highlighting + identity)) + ;; Note: Don't i18n field names so that people can post-process it. - (format port "name: ~a~%" (service-type-name type)) + (format port "name: ~a~%" + (highlight (symbol->string (service-type-name type)) + port*)) (format port "location: ~a~%" (or (and=> (service-type-location type) (if hyperlinks? location->hyperlink location->string)) @@ -107,14 +121,15 @@ appropriate." (when (service-type-description type) (format port "~a~%" - (string->recutils - (string-trim-right - (parameterize ((%text-width width*)) - (texi->plain-text - (string-append "description: " - (or (and=> (service-type-description type) P_) - "")))) - #\newline)))) + (highlighting* + (string->recutils + (string-trim-right + (parameterize ((%text-width width*)) + (texi->plain-text + (string-append "description: " + (or (and=> (service-type-description type) P_) + "")))) + #\newline))))) (for-each (match-lambda ((field . value) @@ -174,4 +189,5 @@ description matches REGEXPS sorted by relevance, and their score." (leave-on-EPIPE (display-search-results matches (current-output-port) #:print service-type->recutils + #:regexps regexps #:command "guix system search"))))) diff --git a/guix/scripts/weather.scm b/guix/scripts/weather.scm index 60a697d1ac..b7d8165262 100644 --- a/guix/scripts/weather.scm +++ b/guix/scripts/weather.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2017-2022 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2017 Ricardo Wurmus <rekado@elephly.net> ;;; Copyright © 2018 Kyle Meyer <kyle@kyleam.com> ;;; Copyright © 2020 Simon Tournier <zimon.toutoune@gmail.com> @@ -31,6 +31,7 @@ #:use-module (guix store) #:use-module (guix grafts) #:use-module (guix gexp) + #:use-module (guix colors) #:use-module ((guix build syscalls) #:select (terminal-columns)) #:use-module ((guix build utils) #:select (every*)) #:use-module (guix substitutes) @@ -39,6 +40,7 @@ #:use-module (guix ci) #:use-module (guix sets) #:use-module (guix graph) + #:use-module (guix scripts build) #:autoload (guix scripts graph) (%bag-node-type) #:use-module (gnu packages) #:use-module (web uri) @@ -203,7 +205,7 @@ In case ITEMS is an empty list, return 1 instead." #:make-progress-reporter (lambda* (total #:key url #:allow-other-keys) (progress-reporter/bar total))))) - (format #t "~a~%" server) + (format #t (highlight "~a~%") server) (let ((obtained (length narinfos)) (requested (length items)) (missing (lset-difference string=? @@ -215,9 +217,17 @@ In case ITEMS is an empty list, return 1 instead." (time (+ (time-second time) (/ (time-nanosecond time) 1e9)))) (when (> requested 0) - (format #t (G_ " ~,1f% substitutes available (~h out of ~h)~%") - (* 100. (/ obtained requested 1.)) - obtained requested)) + (let* ((ratio (/ obtained requested 1.)) + (colorize (cond ((> ratio 0.80) + (coloring-procedure (color BOLD GREEN))) + ((< ratio 0.50) + (coloring-procedure (color BOLD RED))) + (else + highlight)))) + (format #t + (colorize (G_ " ~,1f% substitutes available (~h out of ~h)~%")) + (* 100. ratio) + obtained requested))) (let ((total (/ (reduce + 0 sizes) MiB))) (match (length sizes) ((? zero?) @@ -330,18 +340,18 @@ Report the availability of substitutes.\n")) COUNT dependents")) (display (G_ " --display-missing display the list of missing substitutes")) - (display (G_ " - -s, --system=SYSTEM consider substitutes for SYSTEM--e.g., \"i686-linux\"")) (newline) (display (G_ " -h, --help display this help and exit")) (display (G_ " -V, --version display version information and exit")) (newline) + (show-native-build-options-help) + (newline) (show-bug-report-information)) (define %options - (list (option '(#\h "help") #f #f + (cons* (option '(#\h "help") #f #f (lambda args (show-help) (exit 0))) @@ -371,9 +381,7 @@ Report the availability of substitutes.\n")) (option '("display-missing") #f #f (lambda (opt name arg result) (alist-cons 'display-missing? #t result))) - (option '(#\s "system") #t #f - (lambda (opt name arg result) - (alist-cons 'system arg result))))) + %standard-native-build-options)) (define %default-options `((substitute-urls . ,%default-substitute-urls))) |