* [bug#31736] [PATCH] Add an opam importer @ 2018-06-06 17:23 Julien Lepiller 2018-06-06 17:37 ` Julien Lepiller 0 siblings, 1 reply; 6+ messages in thread From: Julien Lepiller @ 2018-06-06 17:23 UTC (permalink / raw) To: 31736 [-- Attachment #1: Type: text/plain, Size: 77 bytes --] Hi, this patch adds an importer for ocaml packages from the opam repository. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-guix-Add-opam-importer.patch --] [-- Type: text/x-patch, Size: 14277 bytes --] From 04268bfc1a64c2c69f25977d76af8af34f7e0024 Mon Sep 17 00:00:00 2001 From: Julien Lepiller <julien@lepiller.eu> Date: Wed, 6 Jun 2018 19:14:39 +0200 Subject: [PATCH] guix: Add opam importer. * guix/scripts/import.scm (importers): Add opam. * guix/scripts/import/opam.scm: New file. * guix/import/opam.scm: New file. * Makefile.am: Add them. --- Makefile.am | 2 + guix/import/opam.scm | 210 +++++++++++++++++++++++++++++++++++ guix/scripts/import.scm | 2 +- guix/scripts/import/opam.scm | 92 +++++++++++++++ 4 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 guix/import/opam.scm create mode 100644 guix/scripts/import/opam.scm diff --git a/Makefile.am b/Makefile.am index 7898a3648..6bf077d1b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -230,11 +230,13 @@ MODULES += \ guix/import/github.scm \ guix/import/gnome.scm \ guix/import/json.scm \ + guix/import/opam.scm \ guix/import/pypi.scm \ guix/import/stackage.scm \ guix/scripts/import/crate.scm \ guix/scripts/import/gem.scm \ guix/scripts/import/json.scm \ + guix/scripts/import/opam.scm \ guix/scripts/import/pypi.scm \ guix/scripts/import/stackage.scm \ guix/scripts/weather.scm diff --git a/guix/import/opam.scm b/guix/import/opam.scm new file mode 100644 index 000000000..92bcef292 --- /dev/null +++ b/guix/import/opam.scm @@ -0,0 +1,210 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2014 David Thompson <davet@gnu.org> +;;; Copyright © 2015 Cyril Roelandt <tipecaml@gmail.com> +;;; Copyright © 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.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 import opam) + #:use-module (ice-9 binary-ports) + #:use-module (ice-9 match) + #:use-module (ice-9 pretty-print) + #:use-module (ice-9 regex) + #:use-module ((ice-9 rdelim) #:select (read-line)) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) + #:use-module (srfi srfi-34) + #:use-module (srfi srfi-35) + #:use-module (rnrs bytevectors) + #:use-module (web uri) + #:use-module (guix http-client) + #:use-module (guix ui) + #:use-module (guix utils) + #:use-module ((guix build utils) + #:select ((package-name->name+version + . hyphen-package-name->name+version))) + #:use-module (guix import utils) + #:use-module ((guix download) #:prefix download:) + #:use-module (guix import json) + #:use-module (guix packages) + #:use-module (guix upstream) + #:use-module ((guix licenses) #:prefix license:) + #:use-module (guix build-system python) + #:export (opam-urls + urls->htable + opam->guix-package + %opam-updater)) + +(define (opam-urls) + "Fetch the urls.txt file from the opam repository and returns the list of +URLs it contains." + (let ((port (http-fetch/cached (string->uri "https://opam.ocaml.org/urls.txt")))) + (let loop ((result '())) + (let ((line (read-line port))) + (if (eof-object? line) + (begin + (close port) + result) + (loop (cons line result))))))) + +(define (htable-update htable line) + "Parse @var{line} to get the name and version of the package and adds them +to the hashtable." + (let* ((line (string-split line #\ )) + (url (car line))) + (unless (equal? url "repo") + (let ((sp (string-split url #\/))) + (when (equal? (car sp) "packages") + (let* ((versionstr (car (cdr (cdr sp)))) + (name1 (car (cdr sp))) + (name2 (car (string-split versionstr #\.))) + (version (string-join (cdr (string-split versionstr #\.)) "."))) + (when (equal? name1 name2) + (let ((curr (hash-ref htable name1 '()))) + (hash-set! htable name1 (cons version curr)))))))))) + +(define (urls->htable urls) + "Transform urls.txt in a hashtable whose keys are package names and values +the list of available versions." + (let ((htable (make-hash-table))) + (let loop ((urls urls)) + (if (eq? (length urls) 0) + htable + (begin + (htable-update htable (car urls)) + (loop (cdr urls))))))) + +(define (latest-version versions) + "Find the most recent version from a list of versions." + (let loop ((versions (cdr versions)) (m (car versions))) + (if (eq? (length versions) 0) + m + (loop (cdr versions) (if (version>? m (car versions)) m (car versions)))))) + +(define (fetch-url uri) + "Fetch and parse the url file. Return the URL the package can be downloaded +from." + (let ((port (http-fetch uri))) + (let loop ((result #f)) + (let ((line (read-line port))) + (if (eof-object? line) + (begin + (close port) + result) + (let* ((line (string-split line #\ )) + (key (car line))) + (if (equal? key "archive:") + (loop (string-trim-both (car (cdr line)) #\")) + (loop result)))))))) + +(define (fetch-metadata uri) + "Fetch and parse the opam file. Return an association list containing the +homepage, the license and the list of inputs." + (let ((port (http-fetch uri))) + (let loop ((result '()) (deps? #f)) + (let ((line (read-line port))) + (if (eof-object? line) + (begin + (close port) + result) + (let* ((line (string-split line #\ )) + (key (car line)) + (deps? (if deps? (not (equal? key "]")) (equal? key "depends:"))) + (val (string-trim-both (string-join (cdr line) "") #\"))) + (cond + ((equal? key "homepage:") + (loop (cons `("homepage" . ,val) result) deps?)) + ((equal? key "license:") + (loop (cons `("license" . ,val) result) deps?)) + ((and deps? (not (equal? val "["))) + (let ((curr (assoc-ref result "inputs")) + (new (string-trim-both (car (string-split val #\{)) (list->char-set '(#\] #\[ #\"))))) + (loop (cons `("inputs" . ,(cons new (if curr curr '()))) result) + (if (string-contains val "]") #f deps?)))) + (else (loop result deps?))))))))) + +(define (string->license str) + (cond + ((equal? str "MIT") '(license:expat)) + ((equal? str "GPL2") '(license:gpl2)) + ((equal? str "LGPLv2") '(license:lgpl2)) + (else `()))) + +(define (deps->inputs deps) + "Transform the list of dependencies in a list of inputs. Filter out anything +that looks like a native-input." + (if (eq? deps #f) + '() + (let ((inputs + (map (lambda (input) + (list input (list 'unquote (string->symbol input)))) + (map (lambda (input) + (cond + ((equal? input "ocamlfind") "ocaml-findlib") + ((string-prefix? "ocaml" input) input) + (else (string-append "ocaml-" input)))) + (filter (lambda (input) (not (string-prefix? "conf-" input))) deps))))) + (if (eq? (length inputs) 0) #f inputs)))) + +(define (deps->native-inputs deps) + "Transform the list of dependencies in a list of native-inputs. Filter out +anything that doesn't look like a native-input." + (if (eq? deps #f) + '() + (let ((inputs + (map (lambda (input) + (list input (list 'unquote (string->symbol input)))) + (map (lambda (input) (substring input 5)) + (filter (lambda (input) (string-prefix? "conf-" input)) deps))))) + (if (eq? (length inputs) 0) #f inputs)))) + +(define (opam->guix-package name) + (let* ((htable (urls->htable (opam-urls))) + (versions (hash-ref htable name))) + (unless (eq? versions #f) + (let* ((version (latest-version versions)) + (package-url (string-append "https://opam.ocaml.org/packages/" name + "/" name "." version "/")) + (url-url (string-append package-url "url")) + (opam-url (string-append package-url "opam")) + (source-url (fetch-url url-url)) + (metadata (fetch-metadata opam-url)) + (deps (assoc-ref metadata "inputs")) + (native-inputs (deps->native-inputs deps)) + (inputs (deps->inputs deps))) + (call-with-temporary-output-file + (lambda (temp port) + (and (url-fetch source-url temp) + `(package + (name ,name) + (version ,version) + (source + (origin + (method url-fetch) + (uri ,source-url) + (sha256 (base32 ,(guix-hash-url temp))))) + (build-system ocaml-build-system) + ,@(if (eq? (length inputs) 0) + '() + `((inputs ,(list 'quasiquote inputs)))) + ,@(if (eq? (length native-inputs) 0) + '() + `((native-inputs ,(list 'quasiquote native-inputs)))) + (home-page ,(assoc-ref metadata "homepage")) + (synopsis "") + (description "") + (license ,@(string->license (assoc-ref metadata "license"))))))))))) diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm index 67bc7a755..bc03179e5 100644 --- a/guix/scripts/import.scm +++ b/guix/scripts/import.scm @@ -74,7 +74,7 @@ rather than \\n." ;;; (define importers '("gnu" "nix" "pypi" "cpan" "hackage" "stackage" "elpa" "gem" - "cran" "crate" "texlive" "json")) + "cran" "crate" "texlive" "json" "opam")) (define (resolve-importer name) (let ((module (resolve-interface diff --git a/guix/scripts/import/opam.scm b/guix/scripts/import/opam.scm new file mode 100644 index 000000000..ab8bbcb5b --- /dev/null +++ b/guix/scripts/import/opam.scm @@ -0,0 +1,92 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2014 David Thompson <davet@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 import opam) + #:use-module (guix ui) + #:use-module (guix utils) + #:use-module (guix scripts) + #:use-module (guix import opam) + #:use-module (guix scripts import) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) + #:use-module (srfi srfi-37) + #:use-module (ice-9 match) + #:use-module (ice-9 format) + #:export (guix-import-opam)) + +\f +;;; +;;; Command-line options. +;;; + +(define %default-options + '()) + +(define (show-help) + (display (G_ "Usage: guix import opam PACKAGE-NAME +Import and convert the opam package for PACKAGE-NAME.\n")) + (display (G_ " + -h, --help display this help and exit")) + (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 opam"))) + %standard-import-options)) + +\f +;;; +;;; Entry point. +;;; + +(define (guix-import-opam . args) + (define (parse-options) + ;; Return the alist of option values. + (args-fold* args %options + (lambda (opt name arg result) + (leave (G_ "~A: unrecognized option~%") name)) + (lambda (arg result) + (alist-cons 'argument arg result)) + %default-options)) + + (let* ((opts (parse-options)) + (args (filter-map (match-lambda + (('argument . value) + value) + (_ #f)) + (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)) + (() + (leave (G_ "too few arguments~%"))) + ((many ...) + (leave (G_ "too many arguments~%")))))) -- 2.17.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [bug#31736] [PATCH] Add an opam importer 2018-06-06 17:23 [bug#31736] [PATCH] Add an opam importer Julien Lepiller @ 2018-06-06 17:37 ` Julien Lepiller 2018-06-10 21:28 ` Ludovic Courtès 0 siblings, 1 reply; 6+ messages in thread From: Julien Lepiller @ 2018-06-06 17:37 UTC (permalink / raw) To: 31736 [-- Attachment #1: Type: text/plain, Size: 267 bytes --] Le Wed, 6 Jun 2018 19:23:29 +0200, Julien Lepiller <julien@lepiller.eu> a écrit : > Hi, this patch adds an importer for ocaml packages from the opam > repository. Whoops, the copyright lines and part of the code was wrong. This version should be better :) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-guix-Add-opam-importer.patch --] [-- Type: text/x-patch, Size: 13395 bytes --] From a5250186722305961f0a5d77cb8f7f36cdae0da0 Mon Sep 17 00:00:00 2001 From: Julien Lepiller <julien@lepiller.eu> Date: Wed, 6 Jun 2018 19:14:39 +0200 Subject: [PATCH] guix: Add opam importer. * guix/scripts/import.scm (importers): Add opam. * guix/scripts/import/opam.scm: New file. * guix/import/opam.scm: New file. * Makefile.am: Add them. --- Makefile.am | 2 + guix/import/opam.scm | 188 +++++++++++++++++++++++++++++++++++ guix/scripts/import.scm | 2 +- guix/scripts/import/opam.scm | 92 +++++++++++++++++ 4 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 guix/import/opam.scm create mode 100644 guix/scripts/import/opam.scm diff --git a/Makefile.am b/Makefile.am index 7898a3648..6bf077d1b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -230,11 +230,13 @@ MODULES += \ guix/import/github.scm \ guix/import/gnome.scm \ guix/import/json.scm \ + guix/import/opam.scm \ guix/import/pypi.scm \ guix/import/stackage.scm \ guix/scripts/import/crate.scm \ guix/scripts/import/gem.scm \ guix/scripts/import/json.scm \ + guix/scripts/import/opam.scm \ guix/scripts/import/pypi.scm \ guix/scripts/import/stackage.scm \ guix/scripts/weather.scm diff --git a/guix/import/opam.scm b/guix/import/opam.scm new file mode 100644 index 000000000..608f8b449 --- /dev/null +++ b/guix/import/opam.scm @@ -0,0 +1,188 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2018 Julien Lepiller <julien@lepiller.eu> +;;; +;;; 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 import opam) + #:use-module (ice-9 match) + #:use-module ((ice-9 rdelim) #:select (read-line)) + #:use-module (srfi srfi-1) + #:use-module (web uri) + #:use-module (guix http-client) + #:use-module (guix utils) + #:use-module (guix import utils) + #:use-module ((guix licenses) #:prefix license:) + #:export (opam->guix-package)) + +(define (opam-urls) + "Fetch the urls.txt file from the opam repository and returns the list of +URLs it contains." + (let ((port (http-fetch/cached (string->uri "https://opam.ocaml.org/urls.txt")))) + (let loop ((result '())) + (let ((line (read-line port))) + (if (eof-object? line) + (begin + (close port) + result) + (loop (cons line result))))))) + +(define (htable-update htable line) + "Parse @var{line} to get the name and version of the package and adds them +to the hashtable." + (let* ((line (string-split line #\ )) + (url (car line))) + (unless (equal? url "repo") + (let ((sp (string-split url #\/))) + (when (equal? (car sp) "packages") + (let* ((versionstr (car (cdr (cdr sp)))) + (name1 (car (cdr sp))) + (name2 (car (string-split versionstr #\.))) + (version (string-join (cdr (string-split versionstr #\.)) "."))) + (when (equal? name1 name2) + (let ((curr (hash-ref htable name1 '()))) + (hash-set! htable name1 (cons version curr)))))))))) + +(define (urls->htable urls) + "Transform urls.txt in a hashtable whose keys are package names and values +the list of available versions." + (let ((htable (make-hash-table))) + (let loop ((urls urls)) + (if (eq? (length urls) 0) + htable + (begin + (htable-update htable (car urls)) + (loop (cdr urls))))))) + +(define (latest-version versions) + "Find the most recent version from a list of versions." + (let loop ((versions (cdr versions)) (m (car versions))) + (if (eq? (length versions) 0) + m + (loop (cdr versions) (if (version>? m (car versions)) m (car versions)))))) + +(define (fetch-url uri) + "Fetch and parse the url file. Return the URL the package can be downloaded +from." + (let ((port (http-fetch uri))) + (let loop ((result #f)) + (let ((line (read-line port))) + (if (eof-object? line) + (begin + (close port) + result) + (let* ((line (string-split line #\ )) + (key (car line))) + (if (equal? key "archive:") + (loop (string-trim-both (car (cdr line)) #\")) + (loop result)))))))) + +(define (fetch-metadata uri) + "Fetch and parse the opam file. Return an association list containing the +homepage, the license and the list of inputs." + (let ((port (http-fetch uri))) + (let loop ((result '()) (deps? #f)) + (let ((line (read-line port))) + (if (eof-object? line) + (begin + (close port) + result) + (let* ((line (string-split line #\ )) + (key (car line)) + (deps? (if deps? (not (equal? key "]")) (equal? key "depends:"))) + (val (string-trim-both (string-join (cdr line) "") #\"))) + (cond + ((equal? key "homepage:") + (loop (cons `("homepage" . ,val) result) deps?)) + ((equal? key "license:") + (loop (cons `("license" . ,val) result) deps?)) + ((and deps? (not (equal? val "["))) + (let ((curr (assoc-ref result "inputs")) + (new (string-trim-both (car (string-split val #\{)) (list->char-set '(#\] #\[ #\"))))) + (loop (cons `("inputs" . ,(cons new (if curr curr '()))) result) + (if (string-contains val "]") #f deps?)))) + (else (loop result deps?))))))))) + +(define (string->license str) + (cond + ((equal? str "MIT") '(license:expat)) + ((equal? str "GPL2") '(license:gpl2)) + ((equal? str "LGPLv2") '(license:lgpl2)) + (else `()))) + +(define (deps->inputs deps) + "Transform the list of dependencies in a list of inputs. Filter out anything +that looks like a native-input." + (if (eq? deps #f) + '() + (let ((inputs + (map (lambda (input) + (list input (list 'unquote (string->symbol input)))) + (map (lambda (input) + (cond + ((equal? input "ocamlfind") "ocaml-findlib") + ((string-prefix? "ocaml" input) input) + (else (string-append "ocaml-" input)))) + (filter (lambda (input) (not (string-prefix? "conf-" input))) deps))))) + (if (eq? (length inputs) 0) '() inputs)))) + +(define (deps->native-inputs deps) + "Transform the list of dependencies in a list of native-inputs. Filter out +anything that doesn't look like a native-input." + (if (eq? deps #f) + '() + (let ((inputs + (map (lambda (input) + (list input (list 'unquote (string->symbol input)))) + (map (lambda (input) (substring input 5)) + (filter (lambda (input) (string-prefix? "conf-" input)) deps))))) + (if (eq? (length inputs) 0) '() inputs)))) + +(define (opam->guix-package name) + (let* ((htable (urls->htable (opam-urls))) + (versions (hash-ref htable name))) + (unless (eq? versions #f) + (let* ((version (latest-version versions)) + (package-url (string-append "https://opam.ocaml.org/packages/" name + "/" name "." version "/")) + (url-url (string-append package-url "url")) + (opam-url (string-append package-url "opam")) + (source-url (fetch-url url-url)) + (metadata (fetch-metadata opam-url)) + (deps (assoc-ref metadata "inputs")) + (native-inputs (deps->native-inputs deps)) + (inputs (deps->inputs deps))) + (call-with-temporary-output-file + (lambda (temp port) + (and (url-fetch source-url temp) + `(package + (name ,name) + (version ,version) + (source + (origin + (method url-fetch) + (uri ,source-url) + (sha256 (base32 ,(guix-hash-url temp))))) + (build-system ocaml-build-system) + ,@(if (eq? (length inputs) 0) + '() + `((inputs ,(list 'quasiquote inputs)))) + ,@(if (eq? (length native-inputs) 0) + '() + `((native-inputs ,(list 'quasiquote native-inputs)))) + (home-page ,(assoc-ref metadata "homepage")) + (synopsis "") + (description "") + (license ,@(string->license (assoc-ref metadata "license"))))))))))) diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm index 67bc7a755..bc03179e5 100644 --- a/guix/scripts/import.scm +++ b/guix/scripts/import.scm @@ -74,7 +74,7 @@ rather than \\n." ;;; (define importers '("gnu" "nix" "pypi" "cpan" "hackage" "stackage" "elpa" "gem" - "cran" "crate" "texlive" "json")) + "cran" "crate" "texlive" "json" "opam")) (define (resolve-importer name) (let ((module (resolve-interface diff --git a/guix/scripts/import/opam.scm b/guix/scripts/import/opam.scm new file mode 100644 index 000000000..b54987874 --- /dev/null +++ b/guix/scripts/import/opam.scm @@ -0,0 +1,92 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2018 Julien Lepiller <julien@lepiller.eu> +;;; +;;; 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 opam) + #:use-module (guix ui) + #:use-module (guix utils) + #:use-module (guix scripts) + #:use-module (guix import opam) + #:use-module (guix scripts import) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) + #:use-module (srfi srfi-37) + #:use-module (ice-9 match) + #:use-module (ice-9 format) + #:export (guix-import-opam)) + +\f +;;; +;;; Command-line options. +;;; + +(define %default-options + '()) + +(define (show-help) + (display (G_ "Usage: guix import opam PACKAGE-NAME +Import and convert the opam package for PACKAGE-NAME.\n")) + (display (G_ " + -h, --help display this help and exit")) + (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 opam"))) + %standard-import-options)) + +\f +;;; +;;; Entry point. +;;; + +(define (guix-import-opam . args) + (define (parse-options) + ;; Return the alist of option values. + (args-fold* args %options + (lambda (opt name arg result) + (leave (G_ "~A: unrecognized option~%") name)) + (lambda (arg result) + (alist-cons 'argument arg result)) + %default-options)) + + (let* ((opts (parse-options)) + (args (filter-map (match-lambda + (('argument . value) + value) + (_ #f)) + (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)) + (() + (leave (G_ "too few arguments~%"))) + ((many ...) + (leave (G_ "too many arguments~%")))))) -- 2.17.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [bug#31736] [PATCH] Add an opam importer 2018-06-06 17:37 ` Julien Lepiller @ 2018-06-10 21:28 ` Ludovic Courtès 2018-07-07 21:56 ` Julien Lepiller 0 siblings, 1 reply; 6+ messages in thread From: Ludovic Courtès @ 2018-06-10 21:28 UTC (permalink / raw) To: Julien Lepiller; +Cc: 31736 Salut Julien! Julien Lepiller <julien@lepiller.eu> skribis: > From a5250186722305961f0a5d77cb8f7f36cdae0da0 Mon Sep 17 00:00:00 2001 > From: Julien Lepiller <julien@lepiller.eu> > Date: Wed, 6 Jun 2018 19:14:39 +0200 > Subject: [PATCH] guix: Add opam importer. > > * guix/scripts/import.scm (importers): Add opam. > * guix/scripts/import/opam.scm: New file. > * guix/import/opam.scm: New file. > * Makefile.am: Add them. Very nice! I hope that’ll help create bridges with more fellow OCaml hackers. :-) I have some comments, mostly about style: > +(define (htable-update htable line) > + "Parse @var{line} to get the name and version of the package and adds them > +to the hashtable." > + (let* ((line (string-split line #\ )) > + (url (car line))) > + (unless (equal? url "repo") > + (let ((sp (string-split url #\/))) > + (when (equal? (car sp) "packages") > + (let* ((versionstr (car (cdr (cdr sp)))) > + (name1 (car (cdr sp))) > + (name2 (car (string-split versionstr #\.))) > + (version (string-join (cdr (string-split versionstr #\.)) "."))) > + (when (equal? name1 name2) > + (let ((curr (hash-ref htable name1 '()))) > + (hash-set! htable name1 (cons version curr)))))))))) There are a couple of things that don’t fully match the coding style (see <https://www.gnu.org/software/guix/manual/html_node/Coding-Style.html>): try to use full names for identifiers, favor a functional style (here maybe you could use a vhash¹ instead of a hash table), and, last but not least, use ‘match’ instead of ‘car’ and ‘cdr’. :-) ¹ https://www.gnu.org/software/guile/manual/html_node/VHashes.html > +(define (fetch-url uri) > + "Fetch and parse the url file. Return the URL the package can be downloaded > +from." Maybe ‘fetch-url-list’ or ‘fetch-package-urls’? > +(define (fetch-metadata uri) > + "Fetch and parse the opam file. Return an association list containing the > +homepage, the license and the list of inputs." Maybe ‘fetch-package-metadata’ to clarify that it’s per-package? > +(define (deps->inputs deps) > + "Transform the list of dependencies in a list of inputs. Filter out anything > +that looks like a native-input." So that would be ‘dependencies->inputs’. :-) > + (if (eq? deps #f) Rather: (if (not dependencies) …) > + (let ((inputs > + (map (lambda (input) > + (list input (list 'unquote (string->symbol input)))) > + (map (lambda (input) > + (cond > + ((equal? input "ocamlfind") "ocaml-findlib") > + ((string-prefix? "ocaml" input) input) > + (else (string-append "ocaml-" input)))) > + (filter (lambda (input) (not (string-prefix? "conf-" input))) deps))))) The indentation is misleading: the 2nd argument to ‘map’ should be aligned with the 1st. Perhaps you can use ‘filter-map’ here? > + (if (eq? (length inputs) 0) '() inputs)))) (eq? (length inputs) 0) → (null? inputs) Note that ‘null?’ is constant-time whereas ‘length’ is O(n). Could you add: • A few lines in guix.texi, under “Invoking guix import”; • Tests in tests/opam.scm (you can take a look at tests/cpan.scm, tests/elpa.scm, etc. for inspiration.) Thank you! Ludo’. ^ permalink raw reply [flat|nested] 6+ messages in thread
* [bug#31736] [PATCH] Add an opam importer 2018-06-10 21:28 ` Ludovic Courtès @ 2018-07-07 21:56 ` Julien Lepiller 2018-07-09 12:44 ` Ludovic Courtès 0 siblings, 1 reply; 6+ messages in thread From: Julien Lepiller @ 2018-07-07 21:56 UTC (permalink / raw) To: 31736 [-- Attachment #1: Type: text/plain, Size: 3705 bytes --] Le 2018-06-10 23:28, ludo@gnu.org a écrit : > Salut Julien! > > Julien Lepiller <julien@lepiller.eu> skribis: > >> From a5250186722305961f0a5d77cb8f7f36cdae0da0 Mon Sep 17 00:00:00 2001 >> From: Julien Lepiller <julien@lepiller.eu> >> Date: Wed, 6 Jun 2018 19:14:39 +0200 >> Subject: [PATCH] guix: Add opam importer. >> >> * guix/scripts/import.scm (importers): Add opam. >> * guix/scripts/import/opam.scm: New file. >> * guix/import/opam.scm: New file. >> * Makefile.am: Add them. > > Very nice! I hope that’ll help create bridges with more fellow OCaml > hackers. :-) > > I have some comments, mostly about style: > >> +(define (htable-update htable line) >> + "Parse @var{line} to get the name and version of the package and >> adds them >> +to the hashtable." >> + (let* ((line (string-split line #\ )) >> + (url (car line))) >> + (unless (equal? url "repo") >> + (let ((sp (string-split url #\/))) >> + (when (equal? (car sp) "packages") >> + (let* ((versionstr (car (cdr (cdr sp)))) >> + (name1 (car (cdr sp))) >> + (name2 (car (string-split versionstr #\.))) >> + (version (string-join (cdr (string-split versionstr >> #\.)) "."))) >> + (when (equal? name1 name2) >> + (let ((curr (hash-ref htable name1 '()))) >> + (hash-set! htable name1 (cons version curr)))))))))) > > There are a couple of things that don’t fully match the coding style > (see > <https://www.gnu.org/software/guix/manual/html_node/Coding-Style.html>): > try to use full names for identifiers, favor a functional style (here > maybe you could use a vhash¹ instead of a hash table), and, last but > not > least, use ‘match’ instead of ‘car’ and ‘cdr’. :-) > > ¹ https://www.gnu.org/software/guile/manual/html_node/VHashes.html > >> +(define (fetch-url uri) >> + "Fetch and parse the url file. Return the URL the package can be >> downloaded >> +from." > > Maybe ‘fetch-url-list’ or ‘fetch-package-urls’? > >> +(define (fetch-metadata uri) >> + "Fetch and parse the opam file. Return an association list >> containing the >> +homepage, the license and the list of inputs." > > Maybe ‘fetch-package-metadata’ to clarify that it’s per-package? > >> +(define (deps->inputs deps) >> + "Transform the list of dependencies in a list of inputs. Filter >> out anything >> +that looks like a native-input." > > So that would be ‘dependencies->inputs’. :-) > >> + (if (eq? deps #f) > > Rather: (if (not dependencies) …) > >> + (let ((inputs >> + (map (lambda (input) >> + (list input (list 'unquote (string->symbol >> input)))) >> + (map (lambda (input) >> + (cond >> + ((equal? input "ocamlfind") "ocaml-findlib") >> + ((string-prefix? "ocaml" input) input) >> + (else (string-append "ocaml-" input)))) >> + (filter (lambda (input) (not (string-prefix? "conf-" >> input))) deps))))) > > The indentation is misleading: the 2nd argument to ‘map’ should be > aligned with the 1st. > > Perhaps you can use ‘filter-map’ here? > >> + (if (eq? (length inputs) 0) '() inputs)))) > > (eq? (length inputs) 0) → (null? inputs) > > Note that ‘null?’ is constant-time whereas ‘length’ is O(n). > > Could you add: > > • A few lines in guix.texi, under “Invoking guix import”; > > • Tests in tests/opam.scm (you can take a look at tests/cpan.scm, > tests/elpa.scm, etc. for inspiration.) > > Thank you! > > Ludo’. Here is a new version. What do you think? [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-guix-Add-opam-importer.patch --] [-- Type: text/x-diff; name=0001-guix-Add-opam-importer.patch, Size: 19045 bytes --] From b3fd75a804a4264cb083584591a3e589886d96c8 Mon Sep 17 00:00:00 2001 From: Julien Lepiller <julien@lepiller.eu> Date: Wed, 6 Jun 2018 19:14:39 +0200 Subject: [PATCH] guix: Add opam importer. * guix/scripts/import.scm (importers): Add opam. * guix/scripts/import/opam.scm: New file. * guix/import/opam.scm: New file. * tests/opam.scm: New file. * Makefile.am: Add them. * doc/guix.texi (Invoking guix import): Document it. --- Makefile.am | 3 + doc/guix.texi | 6 ++ guix/import/opam.scm | 193 +++++++++++++++++++++++++++++++++++ guix/scripts/import.scm | 2 +- guix/scripts/import/opam.scm | 92 +++++++++++++++++ tests/opam.scm | 118 +++++++++++++++++++++ 6 files changed, 413 insertions(+), 1 deletion(-) create mode 100644 guix/import/opam.scm create mode 100644 guix/scripts/import/opam.scm create mode 100644 tests/opam.scm diff --git a/Makefile.am b/Makefile.am index 5dc04de35..618d1653e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -231,11 +231,13 @@ MODULES += \ guix/import/github.scm \ guix/import/gnome.scm \ guix/import/json.scm \ + guix/import/opam.scm \ guix/import/pypi.scm \ guix/import/stackage.scm \ guix/scripts/import/crate.scm \ guix/scripts/import/gem.scm \ guix/scripts/import/json.scm \ + guix/scripts/import/opam.scm \ guix/scripts/import/pypi.scm \ guix/scripts/import/stackage.scm \ guix/scripts/weather.scm @@ -382,6 +384,7 @@ if HAVE_GUILE_JSON SCM_TESTS += \ tests/pypi.scm \ + tests/opam.scm \ tests/cpan.scm \ tests/gem.scm \ tests/crate.scm diff --git a/doc/guix.texi b/doc/guix.texi index aeac5aaa8..509aba539 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -6651,6 +6651,12 @@ in Guix. @cindex crate Import metadata from the crates.io Rust package repository @uref{https://crates.io, crates.io}. + +@item opam +@cindex opam +@cindex ocaml +Import metadata from the @uref{https://opam.ocaml.org/, Opam} package +repository used by the OCaml community. @end table The structure of the @command{guix import} code is modular. It would be diff --git a/guix/import/opam.scm b/guix/import/opam.scm new file mode 100644 index 000000000..f252bdc31 --- /dev/null +++ b/guix/import/opam.scm @@ -0,0 +1,193 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2018 Julien Lepiller <julien@lepiller.eu> +;;; +;;; 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 import opam) + #:use-module (ice-9 match) + #:use-module (ice-9 vlist) + #:use-module ((ice-9 rdelim) #:select (read-line)) + #:use-module (srfi srfi-1) + #:use-module (web uri) + #:use-module (guix http-client) + #:use-module (guix utils) + #:use-module (guix import utils) + #:use-module ((guix licenses) #:prefix license:) + #:export (opam->guix-package)) + +(define (opam-urls) + "Fetch the urls.txt file from the opam repository and returns the list of +URLs it contains." + (let ((port (http-fetch/cached (string->uri "https://opam.ocaml.org/urls.txt")))) + (let loop ((result '())) + (let ((line (read-line port))) + (if (eof-object? line) + (begin + (close port) + result) + (loop (cons line result))))))) + +(define (vhash-ref hashtable key default) + (match (vhash-assoc key hashtable) + (#f default) + ((_ . x) x))) + +(define (hashtable-update hashtable line) + "Parse @var{line} to get the name and version of the package and adds them +to the hashtable." + (let* ((line (string-split line #\ ))) + (match line + ((url foo ...) + (if (equal? url "repo") + hashtable + (match (string-split url #\/) + ((type name1 versionstr foo ...) + (if (equal? type "packages") + (match (string-split versionstr #\.) + ((name2 versions ...) + (let ((version (string-join versions "."))) + (if (equal? name1 name2) + (let ((curr (vhash-ref hashtable name1 '()))) + (vhash-cons name1 (cons version curr) hashtable)) + hashtable))) + (_ hashtable)) + hashtable)) + (_ hashtable)))) + (_ hashtable)))) + +(define (urls->hashtable urls) + "Transform urls.txt in a hashtable whose keys are package names and values +the list of available versions." + (let ((hashtable vlist-null)) + (let loop ((urls urls) (hashtable hashtable)) + (match urls + (() hashtable) + ((url rest ...) (loop rest (hashtable-update hashtable url))))))) + +(define (latest-version versions) + "Find the most recent version from a list of versions." + (match versions + ((first rest ...) + (let loop ((versions rest) (m first)) + (match versions + (() m) + ((first rest ...) + (loop rest (if (version>? m first) m first)))))))) + +(define (fetch-package-url uri) + "Fetch and parse the url file. Return the URL the package can be downloaded +from." + (let ((port (http-fetch uri))) + (let loop ((result #f)) + (let ((line (read-line port))) + (if (eof-object? line) + (begin + (close port) + result) + (let* ((line (string-split line #\ ))) + (match line + ((key value rest ...) + (if (member key '("archive:" "http:")) + (loop (string-trim-both value #\")) + (loop result)))))))))) + +(define (fetch-package-metadata uri) + "Fetch and parse the opam file. Return an association list containing the +homepage, the license and the list of inputs." + (let ((port (http-fetch uri))) + (let loop ((result '()) (dependencies? #f)) + (let ((line (read-line port))) + (if (eof-object? line) + (begin + (close port) + result) + (let* ((line (string-split line #\ ))) + (match line + ((key value ...) + (let ((dependencies? + (if dependencies? + (not (equal? key "]")) + (equal? key "depends:"))) + (val (string-trim-both (string-join value "") #\"))) + (cond + ((equal? key "homepage:") + (loop (cons `("homepage" . ,val) result) dependencies?)) + ((equal? key "license:") + (loop (cons `("license" . ,val) result) dependencies?)) + ((and dependencies? (not (equal? val "["))) + (match (string-split val #\{) + ((val rest ...) + (let ((curr (assoc-ref result "inputs")) + (new (string-trim-both + val (list->char-set '(#\] #\[ #\"))))) + (loop (cons `("inputs" . ,(cons new (if curr curr '()))) result) + (if (string-contains val "]") #f dependencies?)))))) + (else (loop result dependencies?)))))))))))) + +(define (string->license str) + (cond + ((equal? str "MIT") '(license:expat)) + ((equal? str "GPL2") '(license:gpl2)) + ((equal? str "LGPLv2") '(license:lgpl2)) + (else `()))) + +(define (ocaml-name->guix-name name) + (cond + ((equal? name "ocamlfind") "ocaml-findlib") + ((string-prefix? "ocaml" name) name) + ((string-prefix? "conf-" name) (substring name 5)) + (else (string-append "ocaml-" name)))) + +(define (dependencies->inputs dependencies) + "Transform the list of dependencies in a list of inputs." + (if (not dependencies) + '() + (map (lambda (input) + (list input (list 'unquote (string->symbol input)))) + (map ocaml-name->guix-name dependencies)))) + +(define (opam->guix-package name) + (let* ((hashtable (urls->hashtable (opam-urls))) + (versions (vhash-ref hashtable name #f))) + (unless (eq? versions #f) + (let* ((version (latest-version versions)) + (package-url (string-append "https://opam.ocaml.org/packages/" name + "/" name "." version "/")) + (url-url (string-append package-url "url")) + (opam-url (string-append package-url "opam")) + (source-url (fetch-package-url url-url)) + (metadata (fetch-package-metadata opam-url)) + (dependencies (assoc-ref metadata "inputs")) + (inputs (dependencies->inputs dependencies))) + (call-with-temporary-output-file + (lambda (temp port) + (and (url-fetch source-url temp) + `(package + (name ,(ocaml-name->guix-name name)) + (version ,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)))) + (home-page ,(assoc-ref metadata "homepage")) + (synopsis "") + (description "") + (license ,@(string->license (assoc-ref metadata "license"))))))))))) diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm index 67bc7a755..bc03179e5 100644 --- a/guix/scripts/import.scm +++ b/guix/scripts/import.scm @@ -74,7 +74,7 @@ rather than \\n." ;;; (define importers '("gnu" "nix" "pypi" "cpan" "hackage" "stackage" "elpa" "gem" - "cran" "crate" "texlive" "json")) + "cran" "crate" "texlive" "json" "opam")) (define (resolve-importer name) (let ((module (resolve-interface diff --git a/guix/scripts/import/opam.scm b/guix/scripts/import/opam.scm new file mode 100644 index 000000000..b54987874 --- /dev/null +++ b/guix/scripts/import/opam.scm @@ -0,0 +1,92 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2018 Julien Lepiller <julien@lepiller.eu> +;;; +;;; 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 opam) + #:use-module (guix ui) + #:use-module (guix utils) + #:use-module (guix scripts) + #:use-module (guix import opam) + #:use-module (guix scripts import) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) + #:use-module (srfi srfi-37) + #:use-module (ice-9 match) + #:use-module (ice-9 format) + #:export (guix-import-opam)) + +\f +;;; +;;; Command-line options. +;;; + +(define %default-options + '()) + +(define (show-help) + (display (G_ "Usage: guix import opam PACKAGE-NAME +Import and convert the opam package for PACKAGE-NAME.\n")) + (display (G_ " + -h, --help display this help and exit")) + (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 opam"))) + %standard-import-options)) + +\f +;;; +;;; Entry point. +;;; + +(define (guix-import-opam . args) + (define (parse-options) + ;; Return the alist of option values. + (args-fold* args %options + (lambda (opt name arg result) + (leave (G_ "~A: unrecognized option~%") name)) + (lambda (arg result) + (alist-cons 'argument arg result)) + %default-options)) + + (let* ((opts (parse-options)) + (args (filter-map (match-lambda + (('argument . value) + value) + (_ #f)) + (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)) + (() + (leave (G_ "too few arguments~%"))) + ((many ...) + (leave (G_ "too many arguments~%")))))) diff --git a/tests/opam.scm b/tests/opam.scm new file mode 100644 index 000000000..26832174a --- /dev/null +++ b/tests/opam.scm @@ -0,0 +1,118 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2018 Julien Lepiller <julien@lepiller.eu> +;;; +;;; 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 (test-opam) + #:use-module (guix import opam) + #:use-module (guix base32) + #:use-module (guix hash) + #:use-module (guix tests) + #:use-module ((guix build utils) #:select (delete-file-recursively mkdir-p which)) + #:use-module (srfi srfi-64) + #:use-module (web uri) + #:use-module (ice-9 match)) + +(define test-url-file + "http: \"https://example.org/foo-1.0.0.tar.gz\" +checksum: \"ac8920f39a8100b94820659bc2c20817\"") + +(define test-source-hash + "") + +(define test-urls + "repo ac8920f39a8100b94820659bc2c20817 0o644 +packages/foo/foo.1.0.0/url ac8920f39a8100b94820659bc2c20817 0o644 +packages/foo/foo.1.0.0/opam ac8920f39a8100b94820659bc2c20817 0o644 +packages/foo/foo.1.0.0/descr ac8920f39a8100b94820659bc2c20817 0o644") + +(define test-opam-file +"opam-version: 1.2 +maintainer: \"Alice Doe\" +authors: \"Alice Doe, John Doe\" +homepage: \"https://example.org/\" +bug-reports: \"https://example.org/bugs\" +license: \"MIT\" +dev-repo: \"https://example.org/git\" +build: [ + \"ocaml\" \"pkg/pkg.ml\" \"build\" \"--pinned\" \"%{pinned}%\" +] +build-test: [ + \"ocaml\" \"pkg/pkg.ml\" \"build\" \"--pinned\" \"%{pinned}%\" \"--tests\" \"true\" +] +depends: [ + \"alcotest\" {test & >= \"0.7.2\"} + \"ocamlbuild\" {build & >= \"0.9.2\"} +]") + +(test-begin "opam") + +(test-assert "opam->guix-package" + ;; Replace network resources with sample data. + (mock ((guix import utils) url-fetch + (lambda (url file-name) + (match url + ("https://example.org/foo-1.0.0.tar.gz" + (begin + (mkdir-p "foo-1.0.0") + (system* "tar" "czvf" file-name "foo-1.0.0/") + (delete-file-recursively "foo-1.0.0") + (set! test-source-hash + (call-with-input-file file-name port-sha256)))) + (_ (error "Unexpected URL: " url))))) + (mock ((guix http-client) http-fetch/cached + (lambda (url . rest) + (match (uri->string url) + ("https://opam.ocaml.org/urls.txt" + (values (open-input-string test-urls) + (string-length test-urls))) + (_ (error "Unexpected URL: " url))))) + (mock ((guix http-client) http-fetch + (lambda (url . rest) + (match url + ("https://opam.ocaml.org/packages/foo/foo.1.0.0/url" + (values (open-input-string test-url-file) + (string-length test-url-file))) + ("https://opam.ocaml.org/packages/foo/foo.1.0.0/opam" + (values (open-input-string test-opam-file) + (string-length test-opam-file))) + (_ (error "Unexpected URL: " url))))) + (match (opam->guix-package "foo") + (('package + ('name "ocaml-foo") + ('version "1.0.0") + ('source ('origin + ('method 'url-fetch) + ('uri "https://example.org/foo-1.0.0.tar.gz") + ('sha256 + ('base32 + (? string? hash))))) + ('build-system 'ocaml-build-system) + ('inputs + ('quasiquote + (("ocamlbuild" ('unquote 'ocamlbuild)) + ("ocaml-alcotest" ('unquote 'ocaml-alcotest))))) + ('home-page "https://example.org/") + ('synopsis "") + ('description "") + ('license 'license:expat)) + (string=? (bytevector->nix-base32-string + test-source-hash) + hash)) + (x + (pk 'fail x #f))))))) + +(test-end "opam") -- 2.18.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [bug#31736] [PATCH] Add an opam importer 2018-07-07 21:56 ` Julien Lepiller @ 2018-07-09 12:44 ` Ludovic Courtès 2018-07-10 11:47 ` bug#31736: " Julien Lepiller 0 siblings, 1 reply; 6+ messages in thread From: Ludovic Courtès @ 2018-07-09 12:44 UTC (permalink / raw) To: Julien Lepiller; +Cc: 31736 Hello Julien, Julien Lepiller <julien@lepiller.eu> skribis: > Here is a new version. What do you think? I think it looks great. :-) > From b3fd75a804a4264cb083584591a3e589886d96c8 Mon Sep 17 00:00:00 2001 > From: Julien Lepiller <julien@lepiller.eu> > Date: Wed, 6 Jun 2018 19:14:39 +0200 > Subject: [PATCH] guix: Add opam importer. > > * guix/scripts/import.scm (importers): Add opam. > * guix/scripts/import/opam.scm: New file. > * guix/import/opam.scm: New file. > * tests/opam.scm: New file. > * Makefile.am: Add them. > * doc/guix.texi (Invoking guix import): Document it. [...] > +@item opam > +@cindex opam > +@cindex ocaml > +Import metadata from the @uref{https://opam.ocaml.org/, Opam} package > +repository used by the OCaml community. Nitpick: the proper spelling is “OPAM” and “OCaml”, so I think you need to fix these above (in the concept index as well.) Otherwise LGTM! As a next step, you can add an OPAM updater, which will hopefully take you no more than a few lines of code (see the bottom of cpam.scm, for example.) :-) Thank you! Ludo’. ^ permalink raw reply [flat|nested] 6+ messages in thread
* bug#31736: [PATCH] Add an opam importer 2018-07-09 12:44 ` Ludovic Courtès @ 2018-07-10 11:47 ` Julien Lepiller 0 siblings, 0 replies; 6+ messages in thread From: Julien Lepiller @ 2018-07-10 11:47 UTC (permalink / raw) To: 31736-done Le Mon, 09 Jul 2018 14:44:20 +0200, ludo@gnu.org (Ludovic Courtès) a écrit : > Hello Julien, > > Julien Lepiller <julien@lepiller.eu> skribis: > > > Here is a new version. What do you think? > > I think it looks great. :-) > > > From b3fd75a804a4264cb083584591a3e589886d96c8 Mon Sep 17 00:00:00 > > 2001 From: Julien Lepiller <julien@lepiller.eu> > > Date: Wed, 6 Jun 2018 19:14:39 +0200 > > Subject: [PATCH] guix: Add opam importer. > > > > * guix/scripts/import.scm (importers): Add opam. > > * guix/scripts/import/opam.scm: New file. > > * guix/import/opam.scm: New file. > > * tests/opam.scm: New file. > > * Makefile.am: Add them. > > * doc/guix.texi (Invoking guix import): Document it. > > [...] > > > +@item opam > > +@cindex opam > > +@cindex ocaml > > +Import metadata from the @uref{https://opam.ocaml.org/, Opam} > > package +repository used by the OCaml community. > > Nitpick: the proper spelling is “OPAM” and “OCaml”, so I think you > need to fix these above (in the concept index as well.) > > Otherwise LGTM! > > As a next step, you can add an OPAM updater, which will hopefully take > you no more than a few lines of code (see the bottom of cpam.scm, for > example.) > > :-) > > Thank you! > > Ludo’. Pushed as b24443bff9f9f3f36353eea2ef35e6dc3745a417 ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2018-07-10 11:49 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2018-06-06 17:23 [bug#31736] [PATCH] Add an opam importer Julien Lepiller 2018-06-06 17:37 ` Julien Lepiller 2018-06-10 21:28 ` Ludovic Courtès 2018-07-07 21:56 ` Julien Lepiller 2018-07-09 12:44 ` Ludovic Courtès 2018-07-10 11:47 ` bug#31736: " Julien Lepiller
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/guix.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).