import: Add stackage importer and updater.

* guix/import/stackage.scm: New file.
* guix/scripts/import/stackage.scm: New file.
* Makefile.am (MODULES): Add new files.
* guix/scripts/import.scm (importers): Add "stackage".
* guix/scripts/refresh.scm (%updaters): Add %stackage-updater.
* doc/guix.texi (Invoking 'guix import'): Document the importer.
  (Invoking 'guix refresh'): Add stackage to option --type valid values.
* guix/import/hackage.scm (guix-package->hackage-name, hackage-fetch,
  hackage-source-url, hackage-cabal-url, hackage-package?): Export them.
master
Federico Beffa 2017-02-06 18:19:26 +01:00
parent 81e0bc1834
commit bc5844d149
No known key found for this signature in database
GPG Key ID: 58936E0E2F1B5A4C
7 changed files with 294 additions and 3 deletions

View File

@ -126,6 +126,7 @@ MODULES = \
guix/import/cabal.scm \
guix/import/cran.scm \
guix/import/hackage.scm \
guix/import/stackage.scm \
guix/import/elpa.scm \
guix/scripts.scm \
guix/scripts/download.scm \
@ -147,6 +148,7 @@ MODULES = \
guix/scripts/import/gnu.scm \
guix/scripts/import/nix.scm \
guix/scripts/import/hackage.scm \
guix/scripts/import/stackage.scm \
guix/scripts/import/elpa.scm \
guix/scripts/environment.scm \
guix/scripts/publish.scm \

View File

@ -31,7 +31,8 @@ Copyright @copyright{} 2016 Jan Nieuwenhuizen@*
Copyright @copyright{} 2016 Julien Lepiller@*
Copyright @copyright{} 2016 Alex ter Weele@*
Copyright @copyright{} 2017 Clément Lassieur@*
Copyright @copyright{} 2017 Mathieu Othacehe
Copyright @copyright{} 2017 Mathieu Othacehe@*
Copyright @copyright{} 2017 Federico Beffa
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
@ -5340,6 +5341,34 @@ package name by an at-sign and a version number as in the following example:
guix import hackage mtl@@2.1.3.1
@end example
@item stackage
@cindex stackage
The @code{stackage} importer is a wrapper around the @code{hackage} one.
It takes a package name, looks up the package version included in a
long-term support (LTS) @uref{https://www.stackage.org, Stackage}
release and uses the @code{hackage} importer to retrieve its metadata.
Note that it is up to you to select an LTS release compatible with the
GHC compiler used by Guix.
Specific command-line options are:
@table @code
@item --no-test-dependencies
@itemx -t
Do not include dependencies required only by the test suites.
@item --lts-version=@var{version}
@itemx -r @var{version}
@var{version} is the desired LTS release version. If omitted the latest
release is used.
@end table
The command below imports metadata for the @code{HTTP} Haskell package
included in the LTS Stackage release version 7.18:
@example
guix import stackage --lts-version=7.18 HTTP
@end example
@item elpa
@cindex elpa
Import metadata from an Emacs Lisp Package Archive (ELPA) package
@ -5504,6 +5533,8 @@ the updater for @uref{https://rubygems.org, RubyGems} packages.
the updater for @uref{https://github.com, GitHub} packages.
@item hackage
the updater for @uref{https://hackage.haskell.org, Hackage} packages.
@item stackage
the updater for @uref{https://www.stackage.org, Stackage} packages.
@item crate
the updater for @uref{https://crates.io, Crates} packages.
@end table

View File

@ -37,7 +37,13 @@
#:use-module (guix packages)
#:use-module ((guix utils) #:select (call-with-temporary-output-file))
#:export (hackage->guix-package
%hackage-updater))
%hackage-updater
guix-package->hackage-name
hackage-fetch
hackage-source-url
hackage-cabal-url
hackage-package?))
(define ghc-standard-libraries
;; List of libraries distributed with ghc (7.10.2). We include GHC itself as

135
guix/import/stackage.scm Normal file
View File

@ -0,0 +1,135 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2017 Federico Beffa <beffa@fbengineering.ch>
;;;
;;; 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 stackage)
#:use-module (ice-9 match)
#:use-module (ice-9 regex)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:use-module (guix import json)
#:use-module (guix import hackage)
#:use-module (guix memoization)
#:use-module (guix packages)
#:use-module (guix upstream)
#:use-module (guix ui)
#:export (stackage->guix-package
%stackage-updater))
;;;
;;; Stackage info fetcher and access functions
;;;
(define %stackage-url "http://www.stackage.org")
(define (lts-info-ghc-version lts-info)
"Retruns the version of the GHC compiler contained in LTS-INFO."
(match lts-info
((("snapshot" ("ghc" . version) _ _) _) version)
(_ #f)))
(define (lts-info-packages lts-info)
"Retruns the alist of packages contained in LTS-INFO."
(match lts-info
((_ ("packages" pkg ...)) pkg)
(_ '())))
(define stackage-lts-info-fetch
;; "Retrieve the information about the LTS Stackage release VERSION."
(memoize
(lambda* (#:optional (version ""))
(let* ((url (if (string=? "" version)
(string-append %stackage-url "/lts")
(string-append %stackage-url "/lts-" version)))
(lts-info (json-fetch url)))
(if lts-info
(reverse lts-info)
(leave (_ "LTS release version not found: ~A~%") version))))))
(define (stackage-package-name pkg-info)
(assoc-ref pkg-info "name"))
(define (stackage-package-version pkg-info)
(assoc-ref pkg-info "version"))
(define (lts-package-version pkgs-info name)
"Return the version of the package with upstream NAME included in PKGS-INFO."
(let ((pkg (find (lambda (pkg) (string=? (stackage-package-name pkg) name))
pkgs-info)))
(stackage-package-version pkg)))
;;;
;;; Importer entry point
;;;
(define (hackage-name-version name version)
(and version (string-append name "@" version)))
(define* (stackage->guix-package package-name ; upstream name
#:key
(include-test-dependencies? #t)
(lts-version "")
(packages-info
(lts-info-packages
(stackage-lts-info-fetch lts-version))))
"Fetch Cabal file for PACKAGE-NAME from hackage.haskell.org. The retrieved
vesion corresponds to the version of PACKAGE-NAME specified in the LTS-VERSION
release at stackage.org. Return the `package' S-expression corresponding to
that package, or #f on failure. PACKAGES-INFO is the alist with the packages
included in the Stackage LTS release."
(let* ((version (lts-package-version packages-info package-name))
(name-version (hackage-name-version package-name version)))
(if name-version
(hackage->guix-package name-version
#:include-test-dependencies?
include-test-dependencies?)
(leave (_ "package not found: ~A~%") package-name))))
;;;
;;; Updater
;;;
(define latest-lts-release
(let ((pkgs-info (mlambda () (lts-info-packages (stackage-lts-info-fetch)))))
(lambda* (package)
"Return an <upstream-source> for the latest Stackage LTS release of
PACKAGE or #f it the package is not inlucded in the Stackage LTS release."
(let* ((hackage-name (guix-package->hackage-name package))
(version (lts-package-version (pkgs-info) hackage-name))
(name-version (hackage-name-version hackage-name version)))
(match (and=> name-version hackage-fetch)
(#f (format (current-error-port)
"warning: failed to parse ~a~%"
(hackage-cabal-url hackage-name))
#f)
(_ (let ((url (hackage-source-url hackage-name version)))
(upstream-source
(package (package-name package))
(version version)
(urls (list url))))))))))
(define %stackage-updater
(upstream-updater
(name 'stackage)
(description "Updater for Stackage LTS packages")
(pred hackage-package?)
(latest latest-lts-release)))
;;; stackage.scm ends here

View File

@ -73,7 +73,8 @@ rather than \\n."
;;; Entry point.
;;;
(define importers '("gnu" "nix" "pypi" "cpan" "hackage" "elpa" "gem" "cran" "crate"))
(define importers '("gnu" "nix" "pypi" "cpan" "hackage" "stackage" "elpa" "gem"
"cran" "crate"))
(define (resolve-importer name)
(let ((module (resolve-interface

View File

@ -0,0 +1,115 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2017 Federico Beffa <beffa@fbengineering.ch>
;;;
;;; 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 stackage)
#:use-module (guix ui)
#:use-module (guix utils)
#:use-module (guix packages)
#:use-module (guix scripts)
#:use-module (guix import stackage)
#: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-stackage))
;;;
;;; Command-line options.
;;;
(define %default-options
`((lts-version . "")
(include-test-dependencies? . #t)))
(define (show-help)
(display (_ "Usage: guix import stackage PACKAGE-NAME
Import and convert the LTS Stackage package for PACKAGE-NAME.\n"))
(display (_ "
-r VERSION, --lts-version=VERSION
specify the LTS version to use"))
(display (_ "
-h, --help display this help and exit"))
(display (_ "
-t, --no-test-dependencies don't include test-only dependencies"))
(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 stackage")))
(option '(#\t "no-test-dependencies") #f #f
(lambda (opt name arg result)
(alist-cons 'include-test-dependencies? #f
(alist-delete 'include-test-dependencies?
result))))
(option '(#\r "lts-version") #t #f
(lambda (opt name arg result)
(alist-cons 'lts-version arg
(alist-delete 'lts-version
result))))
%standard-import-options))
;;;
;;; Entry point.
;;;
(define (guix-import-stackage . 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 (stackage->guix-package
package-name
#:include-test-dependencies?
(assoc-ref opts 'include-test-dependencies?)
#:lts-version (assoc-ref opts 'lts-version))))
(unless sexp
(leave (_ "failed to download cabal file for package '~a'~%")
package-name))
sexp))
(()
(leave (_ "too few arguments~%")))
((many ...)
(leave (_ "too many arguments~%"))))))
;;; stackage.scm ends here

View File

@ -205,6 +205,7 @@ unavailable optional dependencies such as Guile-JSON."
%elpa-updater
%cran-updater
%bioconductor-updater
((guix import stackage) => %stackage-updater)
%hackage-updater
((guix import cpan) => %cpan-updater)
((guix import pypi) => %pypi-updater)