Building off of the new and improved Ruby build system, here are two patches that add a handy RubyGems importer.
>From b60252c0c52f8ab4b096c00238acab9798ee64f4 Mon Sep 17 00:00:00 2001 From: David Thompson <dthomps...@worcester.edu> Date: Sun, 16 Aug 2015 21:09:19 -0400 Subject: [PATCH 1/2] import: pypi: Move generally useful procedures to utils module. * guix/import/pypi.scm (make-pypi-sexp): Factorize license to symbol conversion code. (string->license, snake-case, guix-hash-url): Move from here... * guix/import/utils.scm: ... to here. (license->symbol): New procedure. --- guix/import/pypi.scm | 29 +---------------------------- guix/import/utils.scm | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/guix/import/pypi.scm b/guix/import/pypi.scm index 10d5bad..06d21fe 100644 --- a/guix/import/pypi.scm +++ b/guix/import/pypi.scm @@ -31,8 +31,6 @@ #:use-module (guix utils) #:use-module (guix import utils) #:use-module (guix import json) - #:use-module (guix base32) - #:use-module (guix hash) #:use-module (guix packages) #:use-module (guix licenses) #:use-module (guix build-system python) @@ -49,16 +47,6 @@ DELIMETER." ((elem . rest) (cons* elem delimiter (join rest delimiter))))) -(define string->license - (match-lambda - ("GNU LGPL" lgpl2.0) - ("GPL" gpl3) - ((or "BSD" "BSD License") bsd-3) - ((or "MIT" "MIT license" "Expat license") expat) - ("Public domain" public-domain) - ("Apache License, Version 2.0" asl2.0) - (_ #f))) - (define (pypi-fetch name) "Return an alist representation of the PyPI metadata for the package NAME, or #f on failure." @@ -75,15 +63,6 @@ or #f on failure." (assoc-ref* pypi-package "info" "name") (assoc-ref* pypi-package "info" "version"))))) -(define (snake-case str) - "Return a downcased version of the string STR where underscores are replaced -with dashes." - (string-join (string-split (string-downcase str) #\_) "-")) - -(define (guix-hash-url filename) - "Return the hash of FILENAME in nix-base32 format." - (bytevector->nix-base32-string (file-sha256 filename))) - (define (python->package-name name) "Given the NAME of a package on PyPI, return a Guix-compliant name for the package." @@ -205,13 +184,7 @@ VERSION, SOURCE-URL, HOME-PAGE, SYNOPSIS, DESCRIPTION, and LICENSE." (home-page ,home-page) (synopsis ,synopsis) (description ,description) - (license ,(assoc-ref `((,lgpl2.0 . lgpl2.0) - (,gpl3 . gpl3) - (,bsd-3 . bsd-3) - (,expat . expat) - (,public-domain . public-domain) - (,asl2.0 . asl2.0)) - license))))))) + (license ,(license->symbol license))))))) (define (pypi->guix-package package-name) "Fetch the metadata for PACKAGE-NAME from pypi.python.org, and return the diff --git a/guix/import/utils.scm b/guix/import/utils.scm index 969491d..0734fa1 100644 --- a/guix/import/utils.scm +++ b/guix/import/utils.scm @@ -21,6 +21,8 @@ #:use-module (ice-9 regex) #:use-module (srfi srfi-1) #:use-module (guix hash) + #:use-module (guix base32) + #:use-module (guix licenses) #:use-module (guix utils) #:use-module ((guix build download) #:prefix build:) #:export (factorize-uri @@ -29,7 +31,13 @@ flatten assoc-ref* - url-fetch)) + url-fetch + guix-hash-url + + string->license + license->symbol + + snake-case)) (define (factorize-uri uri version) "Factorize URI, a package tarball URI as a string, such that any occurrences @@ -95,3 +103,36 @@ recursively apply the procedure to the sub-list." "Save the contents of URL to FILE-NAME. Return #f on failure." (parameterize ((current-output-port (current-error-port))) (build:url-fetch url file-name))) + +(define (guix-hash-url filename) + "Return the hash of FILENAME in nix-base32 format." + (bytevector->nix-base32-string (file-sha256 filename))) + +(define (string->license str) + "Convert the string STR into a license object." + (match str + ("GNU LGPL" lgpl2.0) + ("GPL" gpl3) + ((or "BSD" "BSD License") bsd-3) + ((or "MIT" "MIT license" "Expat license") expat) + ("Public domain" public-domain) + ((or "Apache License, Version 2.0" "Apache 2.0") asl2.0) + (_ #f))) + +(define (license->symbol license) + "Convert license to a symbol representing the variable the object is bound +to in the (guix licenses) module, or #f if there is no such known license." + ;; TODO: Traverse list public variables in (guix licenses) instead so we + ;; don't have to maintain a list manualy. + (assoc-ref `((,lgpl2.0 . lgpl2.0) + (,gpl3 . gpl3) + (,bsd-3 . bsd-3) + (,expat . expat) + (,public-domain . public-domain) + (,asl2.0 . asl2.0)) + license)) + +(define (snake-case str) + "Return a downcased version of the string STR where underscores are replaced +with dashes." + (string-join (string-split (string-downcase str) #\_) "-")) -- 2.4.3
>From 683a434d7ee88667a218dd1494f1fee53c83fb5a Mon Sep 17 00:00:00 2001 From: David Thompson <dthomps...@worcester.edu> Date: Sun, 16 Aug 2015 21:15:45 -0400 Subject: [PATCH 2/2] import: Add Ruby gem importer. * gnu/scripts/import.scm (importers): Add "gem". * gnu/import/gem.scm: New file. * gnu/scripts/import/gem.scm: New file. * Makefile.am (MODULES): Add them. --- Makefile.am | 3 +- guix/import/gem.scm | 97 +++++++++++++++++++++++++++++++++++++++++++++ guix/scripts/import.scm | 2 +- guix/scripts/import/gem.scm | 91 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 guix/import/gem.scm create mode 100644 guix/scripts/import/gem.scm diff --git a/Makefile.am b/Makefile.am index ada4cbe..f9203ec 100644 --- a/Makefile.am +++ b/Makefile.am @@ -213,7 +213,8 @@ MODULES += \ guix/import/pypi.scm \ guix/scripts/import/pypi.scm \ guix/import/cpan.scm \ - guix/scripts/import/cpan.scm + guix/scripts/import/gem.scm \ + guix/import/gem.scm SCM_TESTS += \ tests/pypi.scm \ diff --git a/guix/import/gem.scm b/guix/import/gem.scm new file mode 100644 index 0000000..a0115f5 --- /dev/null +++ b/guix/import/gem.scm @@ -0,0 +1,97 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2015 David Thompson <da...@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 import gem) + #:use-module (ice-9 match) + #:use-module (ice-9 pretty-print) + #:use-module (json) + #:use-module (web uri) + #:use-module (guix utils) + #:use-module (guix import utils) + #:use-module (guix import json) + #:use-module (guix packages) + #:use-module (guix licenses) + #:export (gem->guix-package)) + +(define (rubygems-fetch name) + "Return an alist representation of the RubyGems metadata for the package NAME, +or #f on failure." + (json-fetch + (string-append "https://rubygems.org/api/v1/gems/" name ".json"))) + +(define (ruby-package-name name) + "Given the NAME of a package on RubyGems, return a Guix-compliant name for +the package." + (if (string-prefix? "ruby-" name) + (snake-case name) + (string-append "ruby-" (snake-case name)))) + +(define (make-gem-sexp name version source-url home-page description + dependencies licenses) + "Return the `package' s-expression for a Ruby package with the given NAME, +VERSION, SOURCE-URL, HOME-PAGE, DESCRIPTION, DEPENDENCIES, and LICENSES." + (call-with-temporary-output-file + (lambda (temp port) + (and (url-fetch source-url temp) + `(package + (name ,(ruby-package-name name)) + (version ,version) + (source (origin + (method url-fetch) + (uri (rubygems-uri ,name version)) + (sha256 + (base32 + ,(guix-hash-url temp))))) + (build-system ruby-build-system) + ,@(if (null? dependencies) + '() + `(propagated-inputs + (,'quasiquote + ,(map (lambda (name) + `(,name + (,'unquote + ,(string->symbol name)))) + dependencies)))) + (synopsis ,description) ; nothing better to use + (description ,description) + (home-page ,home-page) + (license ,(match licenses + ((license) (license->symbol license)) + (_ (map license->symbol licenses))))))))) + +(define (gem->guix-package package-name) + "Fetch the metadata for PACKAGE-NAME from rubygems.org, and return the +`package' s-expression corresponding to that package, or #f on failure." + (let ((package (rubygems-fetch package-name))) + (and package + (let ((name (assoc-ref package "name")) + (version (assoc-ref package "version")) + (source-url (assoc-ref package "gem_uri")) + (description (assoc-ref package "info")) + (home-page (assoc-ref package "homepage_uri")) + (dependencies (map (lambda (dep) + (let ((name (assoc-ref dep "name"))) + (if (string=? name "bundler") + "bundler" ; special case, no prefix + (ruby-package-name name)))) + (assoc-ref* package "dependencies" + "runtime"))) + (licenses (map string->license + (assoc-ref package "licenses")))) + (make-gem-sexp name version source-url home-page + description dependencies licenses))))) diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm index d0bdec1..6cd762a 100644 --- a/guix/scripts/import.scm +++ b/guix/scripts/import.scm @@ -73,7 +73,7 @@ rather than \\n." ;;; Entry point. ;;; -(define importers '("gnu" "nix" "pypi" "cpan" "hackage" "elpa")) +(define importers '("gnu" "nix" "pypi" "cpan" "hackage" "elpa" "gem")) (define (resolve-importer name) (let ((module (resolve-interface diff --git a/guix/scripts/import/gem.scm b/guix/scripts/import/gem.scm new file mode 100644 index 0000000..9f8094f --- /dev/null +++ b/guix/scripts/import/gem.scm @@ -0,0 +1,91 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2015 David Thompson <da...@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 gem) + #:use-module (guix ui) + #:use-module (guix utils) + #:use-module (guix import gem) + #: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-gem)) + + +;;; +;;; Command-line options. +;;; + +(define %default-options + '()) + +(define (show-help) + (display (_ "Usage: guix import gem PACKAGE-NAME +Import and convert the RubyGems package for PACKAGE-NAME.\n")) + (display (_ " + -h, --help display this help and exit")) + (display (_ " + -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 pypi"))) + %standard-import-options)) + + +;;; +;;; Entry point. +;;; + +(define (guix-import-gem . args) + (define (parse-options) + ;; Return the alist of option values. + (args-fold* args %options + (lambda (opt name arg result) + (leave (_ "~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 (gem->guix-package package-name))) + (unless sexp + (leave (_ "failed to download meta-data for package '~a'~%") + package-name)) + sexp)) + (() + (leave (_ "too few arguments~%"))) + ((many ...) + (leave (_ "too many arguments~%")))))) -- 2.4.3
-- David Thompson GPG Key: 0FF1D807