diff mbox series

[bug#68935,v2,5/6] import: Insert packages into modules alphabetically.

Message ID c14cf3064d0b349f0947583b4b7a9ab63d4785af.1707505804.git.herman@rimm.ee
State New
Headers show
Series [bug#68935,v2,1/6] doc: Note SVN dependency of texlive importer. | expand

Commit Message

Herman Rimm Feb. 9, 2024, 7:25 p.m. UTC
* guix/scripts/import.scm (guix-import): Add 'insert' option.
(define-import): Add procedure.
* doc/guix.texi (Invoking guix import): Describe 'insert' option.

Change-Id: Id021095355283ade79acde120890eb2ce9173cf7
---
 doc/guix.texi           | 14 ++++++--
 guix/scripts/import.scm | 80 ++++++++++++++++++++++++++---------------
 2 files changed, 63 insertions(+), 31 deletions(-)

Comments

Herman Rimm Feb. 10, 2024, 3:06 p.m. UTC | #1
Hi,

On Fri, Feb 09, 2024 at 08:25:17PM +0100, Herman Rimm wrote:
> diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm
> index 77fcfe3990..850887e720 100644
> --- a/guix/scripts/import.scm
> +++ b/guix/scripts/import.scm
> @@ -67,10 +67,39 @@ (define (show-help)
>    (display (G_ "
>    -h, --help             display this help and exit"))
>    (display (G_ "
> +  -i, --insert           insert into package module alphabetically"))
> +  (display (G_ "
>    -V, --version          display version information and exit"))
>    (newline)
>    (show-bug-report-information))
>  
> +(define (define-import importer args proc)
> +  "Wrap package expressions from IMPORTER with 'define-public and invoke
> +PROC callback."
> +  (if (member importer importers)
> +      (match (apply (resolve-importer importer) args)
> +        ((and expr (or ('package _ ...)
> +                       ('let _ ...)))
> +         (proc (package->definition expr)))
> +        ((and expr ('define-public _ ...))

With doc/package-hello.json file:

  [
    {
      "name": "myhello",
      "version": "2.10",
      "source": "mirror://gnu/hello/hello-2.10.tar.gz",
      "build-system": "gnu",
      "arguments": {
        "tests?": false
      },
      "home-page": "https://www.gnu.org/software/hello/",
      "synopsis": "Hello, GNU world: An example GNU package",
      "description": "GNU Hello prints a greeting.",
      "license": "GPL-3.0+",
      "native-inputs": ["gettext"]
    }
  ]

'guix import json doc/package-hello.json' produces:

  Starting download of /tmp/guix-file.BLTipY
  From https://ftpmirror.gnu.org/gnu/hello/hello-2.10.tar.gz...
  following redirection to `https://mirrors.ibiblio.org/gnu/hello/hello-2.10.tar.gz'...
   …10.tar.gz  709KiB                   1.6MiB/s 00:00 ▕██████████████████▏ 100.0%
  (define-public myhello
    (package
      (name "myhello")
      (version "2.10")
      (source
       (origin
         (method url-fetch)
         (uri (string-append "mirror://gnu/hello/hello-" version ".tar.gz"))
         (sha256
          (base32 "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"))))
      (build-system (@ (guix build-system gnu) gnu-build-system))
      (arguments
       `(#:tests? #f))
      (native-inputs (list (@ (gnu packages gettext) gnu-gettext)))
      (home-page "https://www.gnu.org/software/hello/")
      (synopsis "Hello, GNU world: An example GNU package")
      (description "GNU Hello prints a greeting.")
      (license license:gpl3+)))
  
  Backtrace:
             4 (primitive-load "/home/herman/.cache/guix/inferiors/umi…")
  In guix/ui.scm:
     2324:7  3 (run-guix . _)
    2287:10  2 (run-guix-command _ . _)
  In srfi/srfi-1.scm:
      634:9  1 (for-each #<procedure 7f31b8f81380 at guix/scripts/imp…> …)
  In guix/scripts/import.scm:
      88:21  0 (_ _)
  
  guix/scripts/import.scm:88:21: Throw to key `match-error' with args `("match" "no matching pattern" myhello)'.

I think I can remove the (myhello) variable expression after definition
from the JSON importer in a future revision. Just a heads up.

Also I provided a reduced package-hello.json, because after fixing the
comma syntax, importing the file gives:

  Starting download of /tmp/guix-file.dVsYSt
  From https://ftpmirror.gnu.org/gnu/hello/hello-2.10.tar.gz...
  following redirection to `https://mirrors.ibiblio.org/gnu/hello/hello-2.10.tar.gz'...
   …10.tar.gz  709KiB                   1.5MiB/s 00:00 ▕██████████████████▏ 100.0%
  
  Starting download of /tmp/guix-file.B2wURN
  From https://example.com/greeter-1.0.tar.gz...
  download failed "https://example.com/greeter-1.0.tar.gz" 404 "Not Found"
  
  Starting download of /tmp/guix-file.B2wURN
  From https://web.archive.org/web/20240210155936/https://example.com/greeter-1.0.tar.gz...
  following redirection to `https://web.archive.org/web/20221219143408/http://example.com/greeter-1.0.tar.gz'...
  download failed "https://web.archive.org/web/20221219143408/http://example.com/greeter-1.0.tar.gz" 404 "Not Found"
  Trying to use Disarchive to assemble /tmp/guix-file.B2wURN...
  could not find its Disarchive specification
  failed to download "/tmp/guix-file.B2wURN" from "https://example.com/greeter-1.0.tar.gz"
  Backtrace:
            13 (primitive-load "/home/herman/.cache/guix/inferiors/umi…")
  In guix/ui.scm:
     2324:7 12 (run-guix . _)
    2287:10 11 (run-guix-command _ . _)
  In guix/scripts/import.scm:
       80:6 10 (guix-import . _)
  In ice-9/boot-9.scm:
    1747:15  9 (with-exception-handler #<procedure 7f890505d3f0 at ic…> …)
  In guix/scripts/import/json.scm:
      91:16  8 (_)
  In ice-9/boot-9.scm:
    1747:15  7 (with-exception-handler #<procedure 7f890505d3c0 at ic…> …)
  In guix/import/json.scm:
      72:19  6 (_)
  In srfi/srfi-1.scm:
     460:18  5 (fold #<procedure 7f890424dd60 at guix/import/json.scm…> …)
  In guix/import/json.scm:
      81:55  4 (_ (("inputs" . #("myhello" "hello")) ("license" . #) …) …)
  In guix/import/utils.scm:
     543:12  3 (alist->package (("inputs" . #("myhello" "hello")) # …) _)
     162:33  2 (source-spec->object "https://example.com/greeter-1.0.t…")
  In ice-9/ports.scm:
     450:11  1 (call-with-input-file #f #<procedure 7f88f0ba9b40 at g…> …)
  In unknown file:
             0 (open-file #f "r" #:encoding #f #:guess-encoding #f)

Can greeter have a real source? What should it be?

Cheers,
Herman Rimm
Herman Rimm Feb. 16, 2024, 4:06 p.m. UTC | #2
Hi,

On Fri, Feb 09, 2024 at 08:25:17PM +0100, Herman Rimm wrote:
> +    ((or ("-i" module importer args ...)
> +         ("--insert" module importer args ...))
> +     (let ((find-and-insert
> +             (lambda (expr)
> +               (let ((insert
> +                       (lambda (source-properties)
> +                         (if source-properties
> +                          (insert-expression source-properties expr)
> +                          (let ((port (open-file file "a")))
It should be 'module' instead of 'file' here. I will rename 'module' to
'file' in the next revision though.

Cheers,
Herman
Ludovic Courtès Feb. 19, 2024, 9:43 p.m. UTC | #3
Herman Rimm <herman@rimm.ee> skribis:

> * guix/scripts/import.scm (guix-import): Add 'insert' option.
> (define-import): Add procedure.
> * doc/guix.texi (Invoking guix import): Describe 'insert' option.
>
> Change-Id: Id021095355283ade79acde120890eb2ce9173cf7

[...]

> +(define (define-import importer args proc)
> +  "Wrap package expressions from IMPORTER with 'define-public and invoke
> +PROC callback."

s/define-import/import-as-definitions/ for clarity?

> +        ((? list? expressions)

Rather: (expressions ...).

(It’s equivalent but more customary.)

Otherwise LGTM, thanks!

Ludo’.
diff mbox series

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index 2908085c36..c73db5cbbf 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -124,6 +124,7 @@ 
 Copyright @copyright{} 2023 Saku Laesvuori@*
 Copyright @copyright{} 2023 Graham James Addis@*
 Copyright @copyright{} 2023 Tomas Volf@*
+Copyright @copyright{} 2024 Herman Rimm@*
 
 Permission is granted to copy, distribute and/or modify this document
 under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -14178,12 +14179,21 @@  Invoking guix import
 The general syntax is:
 
 @example
-guix import @var{importer} @var{options}@dots{}
+guix import [@var{global-options}@dots{}] @var{importer} @var{package} [@var{options}@dots{}]
 @end example
 
 @var{importer} specifies the source from which to import package
 metadata, and @var{options} specifies a package identifier and other
-options specific to @var{importer}.
+options specific to @var{importer}. @command{guix import} itself has the
+following @var{global-options}:
+
+@table @code
+@item --insert=@var{file}
+@itemx -i @var{file}
+Insert the package definition(s) that the @var{importer} generated into the
+specified @var{file}, either in alphabetical order among existing package
+definitions, or at the end of the file otherwise.
+@end table
 
 Some of the importers rely on the ability to run the @command{gpgv} command.
 For these, GnuPG must be installed and in @code{$PATH}; run @code{guix install
diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm
index 77fcfe3990..850887e720 100644
--- a/guix/scripts/import.scm
+++ b/guix/scripts/import.scm
@@ -67,10 +67,39 @@  (define (show-help)
   (display (G_ "
   -h, --help             display this help and exit"))
   (display (G_ "
+  -i, --insert           insert into package module alphabetically"))
+  (display (G_ "
   -V, --version          display version information and exit"))
   (newline)
   (show-bug-report-information))
 
+(define (define-import importer args proc)
+  "Wrap package expressions from IMPORTER with 'define-public and invoke
+PROC callback."
+  (if (member importer importers)
+      (match (apply (resolve-importer importer) args)
+        ((and expr (or ('package _ ...)
+                       ('let _ ...)))
+         (proc (package->definition expr)))
+        ((and expr ('define-public _ ...))
+         (proc expr))
+        ((? list? expressions)
+         (for-each (lambda (expr)
+                     (match expr
+                       ((and expr (or ('package _ ...)
+                                      ('let _ ...)))
+                        (proc (package->definition expr)))
+                       ((and expr ('define-public _ ...))
+                        (proc expr))))
+                   expressions))
+        (x
+         (leave (G_ "'~a' import failed~%") importer)))
+      (let ((hint (string-closest importer importers #:threshold 3)))
+        (report-error (G_ "~a: invalid importer~%") importer)
+        (when hint
+          (display-hint (G_ "Did you mean @code{~a}?~%") hint))
+        (exit 1))))
+
 (define-command (guix-import . args)
   (category packaging)
   (synopsis "import a package definition from an external repository")
@@ -84,33 +113,26 @@  (define-command (guix-import . args)
      (exit 0))
     ((or ("-V") ("--version"))
      (show-version-and-exit "guix import"))
+    ((or ("-i" module importer args ...)
+         ("--insert" module importer args ...))
+     (let ((find-and-insert
+             (lambda (expr)
+               (let ((insert
+                       (lambda (source-properties)
+                         (if source-properties
+                          (insert-expression source-properties expr)
+                          (let ((port (open-file file "a")))
+                            (pretty-print-with-comments port expr)
+                            (newline port)
+                            (close-port port))))))
+                 (find-expression module expr insert)))))
+       (define-import importer args find-and-insert)))
     ((importer args ...)
-     (if (member importer importers)
-         (let ((print (lambda (expr)
-                        (leave-on-EPIPE
-                         (pretty-print-with-comments (current-output-port) expr)))))
-           (match (apply (resolve-importer importer) args)
-             ((and expr (or ('package _ ...)
-                            ('let _ ...)))
-              (print (package->definition expr)))
-             ((and expr ('define-public _ ...))
-              (print expr))
-             ((? list? expressions)
-              (for-each (lambda (expr)
-                          (match expr
-                            ((and expr (or ('package _ ...)
-                                           ('let _ ...)))
-                             (print (package->definition expr)))
-                            ((and expr ('define-public _ ...))
-                             (print expr)))
-                          ;; Two newlines: one after the closing paren, and
-                          ;; one to leave a blank line.
-                          (newline) (newline))
-                        expressions))
-             (x
-              (leave (G_ "'~a' import failed~%") importer))))
-         (let ((hint (string-closest importer importers #:threshold 3)))
-           (report-error (G_ "~a: invalid importer~%") importer)
-           (when hint
-             (display-hint (G_ "Did you mean @code{~a}?~%") hint))
-           (exit 1))))))
+     (let ((print (lambda (expr)
+                    (leave-on-EPIPE
+                      (pretty-print-with-comments
+                        (current-output-port) expr)
+                      ;; Two newlines: one after the closing paren, and
+                      ;; one to leave a blank line.
+                      (newline) (newline)))))
+       (define-import importer args print)))))