Subject: [PATCH 2/5] import: opam: Add recursive option.

From: Julien Lepiller <[email-masked]>
Date: Thu, 20 Dec 2018 12:01:00 +0100

* guix/script/import/opam.scm: Add recursive option.
* guix/import/opam.scm (opam->guix-package): return two values.
(opam-recursive-import): New variable.
---
 guix/import/opam.scm         | 70 ++++++++++++++++++++++++------------
 guix/scripts/import/opam.scm | 27 +++++++++++---
 2 files changed, 69 insertions(+), 28 deletions(-)

diff --git a/guix/import/opam.scm b/guix/import/opam.scm
index c42a5d767..cdf05e7d2 100644
--- a/guix/import/opam.scm
+++ b/guix/import/opam.scm
@@ -33,7 +33,8 @@
   #:use-module (guix utils)
   #:use-module (guix import utils)
   #:use-module ((guix licenses) #:prefix license:)
-  #:export (opam->guix-package))
+  #:export (opam->guix-package
+            opam-recursive-import))
 
 ;; Define a PEG parser for the opam format
 (define-peg-pattern SP none (or " " "\n"))
@@ -128,7 +129,6 @@ path to the repository."
     (else (string-append "ocaml-" name))))
 
 (define (metadata-ref file lookup)
-  (pk 'file file 'lookup lookup)
   (fold (lambda (record acc)
           (match record
             ((record key val)
@@ -166,6 +166,21 @@ path to the repository."
     (('conditional-value val condition)
      (if (native? condition) (dependency->input val) ""))))
 
+(define (dependency->name dependency)
+  (match dependency
+    (('string-pat str) str)
+    (('conditional-value val condition)
+     (dependency->name val))))
+
+(define (dependency-list->names lst)
+  (filter
+    (lambda (name)
+      (not (or
+             (string-prefix? "conf-" name)
+             (equal? name "ocaml")
+             (equal? name "findlib"))))
+    (map dependency->name lst)))
+
 (define (ocaml-names->guix-names names)
   (map ocaml-name->guix-name
        (remove (lambda (name)
@@ -193,32 +208,41 @@ path to the repository."
 (define (opam->guix-package name)
   (and-let* ((repository (get-opam-repository))
              (version (find-latest-version name repository))
-             (file (string-append repository "/packages/" name "/" name "." (pk 'version version) "/opam"))
+             (file (string-append repository "/packages/" name "/" name "." version "/opam"))
              (opam-content (get-metadata file))
-             (url-dict (metadata-ref (pk 'metadata opam-content) "url"))
+             (url-dict (metadata-ref opam-content "url"))
              (source-url (metadata-ref url-dict "src"))
              (requirements (metadata-ref opam-content "depends"))
+             (dependencies (dependency-list->names requirements))
              (inputs (dependency-list->inputs (depends->inputs requirements)))
              (native-inputs (dependency-list->inputs (depends->native-inputs requirements))))
         (call-with-temporary-output-file
           (lambda (temp port)
             (and (url-fetch source-url temp)
-                 `(package
-                    (name ,(ocaml-name->guix-name name))
-                    (version ,(metadata-ref opam-content "version"))
-                    (source
-                      (origin
-                        (method url-fetch)
-                        (uri ,source-url)
-                        (sha256 (base32 ,(guix-hash-url temp)))))
-                    (build-system ocaml-build-system)
-                    ,@(if (null? inputs)
-                        '()
-                        `((inputs ,(list 'quasiquote inputs))))
-                    ,@(if (null? native-inputs)
-                        '()
-                        `((native-inputs ,(list 'quasiquote native-inputs))))
-                    (home-page ,(metadata-ref opam-content "homepage"))
-                    (synopsis ,(metadata-ref opam-content "synopsis"))
-                    (description ,(metadata-ref opam-content "description"))
-                    (license #f)))))))
+                 (values
+                  `(package
+                     (name ,(ocaml-name->guix-name name))
+                     (version ,(metadata-ref opam-content "version"))
+                     (source
+                       (origin
+                         (method url-fetch)
+                         (uri ,source-url)
+                         (sha256 (base32 ,(guix-hash-url temp)))))
+                     (build-system ocaml-build-system)
+                     ,@(if (null? inputs)
+                         '()
+                         `((inputs ,(list 'quasiquote inputs))))
+                     ,@(if (null? native-inputs)
+                         '()
+                         `((native-inputs ,(list 'quasiquote native-inputs))))
+                     (home-page ,(metadata-ref opam-content "homepage"))
+                     (synopsis ,(metadata-ref opam-content "synopsis"))
+                     (description ,(metadata-ref opam-content "description"))
+                     (license #f))
+                  dependencies))))))
+
+(define (opam-recursive-import package-name)
+  (recursive-import package-name #f
+                    #:repo->guix-package (lambda (name repo)
+                                           (opam->guix-package name))
+                    #:guix-name ocaml-name->guix-name))
diff --git a/guix/scripts/import/opam.scm b/guix/scripts/import/opam.scm
index b54987874..2d249a213 100644
--- a/guix/scripts/import/opam.scm
+++ b/guix/scripts/import/opam.scm
@@ -25,6 +25,7 @@
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-11)
   #:use-module (srfi srfi-37)
+  #:use-module (srfi srfi-41)
   #:use-module (ice-9 match)
   #:use-module (ice-9 format)
   #:export (guix-import-opam))
@@ -43,6 +44,8 @@ Import and convert the opam package for PACKAGE-NAME.\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))
@@ -56,6 +59,9 @@ Import and convert the opam package for PACKAGE-NAME.\n"))
          (option '(#\V "version") #f #f
                  (lambda args
                    (show-version-and-exit "guix import opam")))
+         (option '(#\r "recursive") #f #f
+                 (lambda (opt name arg result)
+                   (alist-cons 'recursive #t result)))
          %standard-import-options))
 
 
@@ -81,11 +87,22 @@ Import and convert the opam package for PACKAGE-NAME.\n"))
                            (reverse opts))))
     (match args
       ((package-name)
-       (let ((sexp (opam->guix-package package-name)))
-         (unless sexp
-           (leave (G_ "failed to download meta-data for package '~a'~%")
-                  package-name))
-         sexp))
+       (if (assoc-ref opts 'recursive)
+           ;; Recursive import
+           (map (match-lambda
+                  ((and ('package ('name name) . rest) pkg)
+                   `(define-public ,(string->symbol name)
+                      ,pkg))
+                  (_ #f))
+                (reverse
+                 (stream->list
+                  (opam-recursive-import package-name))))
+           ;; Single import
+           (let ((sexp (opam->guix-package package-name)))
+             (unless sexp
+               (leave (G_ "failed to download meta-data for package '~a'~%")
+                      package-name))
+             sexp)))
       (()
        (leave (G_ "too few arguments~%")))
       ((many ...)
-- 
2.19.2