guix/tests/hackage.scm
Robert Vollmert ca45da9fc9
import: hackage: Handle Hackage revisions.
Hackage packages can have metadata revisions (Cabal file only) that are
not reflected in the source archive.  The Haskell build system has
support for this, but until now the Hackage importer would create a
package based on the revised Cabal file which would then build using the
old Cabal file.

Fixes <https://bugs.gnu.org/35750>.

* guix/import/cabal.scm (<cabal-package>): Add 'revision' field.
(eval-cabal): Parse 'x-revision:' property.
* guix/import/hackage.scm (read-cabal-and-hash): New procedure.
(hackage-fetch-and-hash): New procedure.
(hackage-fetch): Rewrite using 'hackage-fetch-and-hash'.
(hackage-module->sexp): Add 'cabal-hash' argument and use it to populate
the '#:cabal-revision' argument.
(hackage->guix-package): Use the new '-and-hash' functions to get the
hash of the Cabal file and pass it to 'hackage-module->sexp'.
* guix/tests/hackage.scm: Test import of Cabal file revision.

Signed-off-by: Timothy Sample <samplet@ngyro.com>
2019-06-13 22:18:52 -04:00

342 lines
9.2 KiB
Scheme

;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2015 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 (test-hackage)
#:use-module (guix import cabal)
#:use-module (guix import hackage)
#:use-module (guix tests)
#:use-module (srfi srfi-64)
#:use-module (ice-9 match))
(define test-cabal-1
"name: foo
version: 1.0.0
homepage: http://test.org
synopsis: synopsis
description: description
license: BSD3
executable cabal
build-depends:
HTTP >= 4000.2.5 && < 4000.3,
mtl >= 2.0 && < 3
")
(define test-cabal-2
"name: foo
version: 1.0.0
homepage: http://test.org
synopsis: synopsis
description: description
license: BSD3
executable cabal {
build-depends:
HTTP >= 4000.2.5 && < 4000.3,
mtl >= 2.0 && < 3
}
")
;; Check compiler implementation test with and without spaces.
(define test-cabal-3
"name: foo
version: 1.0.0
homepage: http://test.org
synopsis: synopsis
description: description
license: BSD3
library
if impl(ghc >= 7.2 && < 7.6)
Build-depends: ghc-a
if impl(ghc>=7.2&&<7.6)
Build-depends: ghc-b
if impl(ghc == 7.8)
Build-depends:
HTTP >= 4000.2.5 && < 4000.3,
mtl >= 2.0 && < 3
")
;; Check "-any", "-none" when name is different.
(define test-cabal-4
"name: foo
version: 1.0.0
homepage: http://test.org
synopsis: synopsis
description: description
license: BSD3
library
if impl(ghcjs -any)
Build-depends: ghc-a
if impl(ghc>=7.2&&<7.6)
Build-depends: ghc-b
if impl(ghc == 7.8)
Build-depends:
HTTP >= 4000.2.5 && < 4000.3,
mtl >= 2.0 && < 3
")
;; Check "-any", "-none".
(define test-cabal-5
"name: foo
version: 1.0.0
homepage: http://test.org
synopsis: synopsis
description: description
license: BSD3
library
if impl(ghc == 7.8)
Build-depends:
HTTP >= 4000.2.5 && < 4000.3,
if impl(ghc -any)
Build-depends: mtl >= 2.0 && < 3
if impl(ghc>=7.2&&<7.6)
Build-depends: ghc-b
")
;; Check "custom-setup".
(define test-cabal-6
"name: foo
build-type: Custom
version: 1.0.0
homepage: http://test.org
synopsis: synopsis
description: description
license: BSD3
custom-setup
setup-depends: base >= 4.7 && < 5,
Cabal >= 1.24,
haskell-gi == 0.21.*
library
if impl(ghc>=7.2&&<7.6)
Build-depends: ghc-b
if impl(ghc == 7.8)
Build-depends:
HTTP >= 4000.2.5 && < 4000.3,
mtl >= 2.0 && < 3
")
;; A fragment of a real Cabal file with minor modification to check precedence
;; of 'and' over 'or', missing final newline, spaces between keywords and
;; parentheses and between key and column.
(define test-read-cabal-1
"name: test-me
library
-- Choose which library versions to use.
if flag(base4point8)
Build-depends: base >= 4.8 && < 5
else
if flag(base4)
Build-depends: base >= 4 && < 4.8
else
if flag(base3)
Build-depends: base >= 3 && < 4
else
Build-depends: base < 3
if flag(base4point8) || flag (base4) && flag(base3)
Build-depends: random
Build-depends : containers
-- Modules that are always built.
Exposed-Modules:
Test.QuickCheck.Exception")
(test-begin "hackage")
(define-syntax-rule (define-package-matcher name pattern)
(define* (name obj)
(match obj
(pattern #t)
(x (pk 'fail x #f)))))
(define-package-matcher match-ghc-foo
('package
('name "ghc-foo")
('version "1.0.0")
('source
('origin
('method 'url-fetch)
('uri ('string-append
"https://hackage.haskell.org/package/foo/foo-"
'version
".tar.gz"))
('sha256
('base32
(? string? hash)))))
('build-system 'haskell-build-system)
('inputs
('quasiquote
(("ghc-http" ('unquote 'ghc-http)))))
('home-page "http://test.org")
('synopsis (? string?))
('description (? string?))
('license 'bsd-3)))
(define* (eval-test-with-cabal test-cabal matcher #:key (cabal-environment '()))
(define port (open-input-string test-cabal))
(matcher (hackage->guix-package "foo" #:port port #:cabal-environment cabal-environment)))
(test-assert "hackage->guix-package test 1"
(eval-test-with-cabal test-cabal-1 match-ghc-foo))
(test-assert "hackage->guix-package test 2"
(eval-test-with-cabal test-cabal-2 match-ghc-foo))
(test-assert "hackage->guix-package test 3"
(eval-test-with-cabal test-cabal-3 match-ghc-foo
#:cabal-environment '(("impl" . "ghc-7.8"))))
(test-assert "hackage->guix-package test 4"
(eval-test-with-cabal test-cabal-4 match-ghc-foo
#:cabal-environment '(("impl" . "ghc-7.8"))))
(test-assert "hackage->guix-package test 5"
(eval-test-with-cabal test-cabal-5 match-ghc-foo
#:cabal-environment '(("impl" . "ghc-7.8"))))
(define-package-matcher match-ghc-foo-6
('package
('name "ghc-foo")
('version "1.0.0")
('source
('origin
('method 'url-fetch)
('uri ('string-append
"https://hackage.haskell.org/package/foo/foo-"
'version
".tar.gz"))
('sha256
('base32
(? string? hash)))))
('build-system 'haskell-build-system)
('inputs
('quasiquote
(("ghc-b" ('unquote 'ghc-b))
("ghc-http" ('unquote 'ghc-http)))))
('native-inputs
('quasiquote
(("ghc-haskell-gi" ('unquote 'ghc-haskell-gi)))))
('home-page "http://test.org")
('synopsis (? string?))
('description (? string?))
('license 'bsd-3)))
(test-assert "hackage->guix-package test 6"
(eval-test-with-cabal test-cabal-6 match-ghc-foo-6))
;; Check multi-line layouted description
(define test-cabal-multiline-layout
"name: foo
version: 1.0.0
homepage: http://test.org
synopsis: synopsis
description: first line
second line
license: BSD3
executable cabal
build-depends:
HTTP >= 4000.2.5 && < 4000.3,
mtl >= 2.0 && < 3
")
(test-assert "hackage->guix-package test multiline desc (layout)"
(eval-test-with-cabal test-cabal-multiline-layout match-ghc-foo))
;; Check multi-line braced description
(define test-cabal-multiline-braced
"name: foo
version: 1.0.0
homepage: http://test.org
synopsis: synopsis
description: {
first line
second line
}
license: BSD3
executable cabal
build-depends:
HTTP >= 4000.2.5 && < 4000.3,
mtl >= 2.0 && < 3
")
(test-assert "hackage->guix-package test multiline desc (braced)"
(eval-test-with-cabal test-cabal-multiline-braced match-ghc-foo))
;; Check Hackage Cabal revisions.
(define test-cabal-revision
"name: foo
version: 1.0.0
x-revision: 2
homepage: http://test.org
synopsis: synopsis
description: description
license: BSD3
executable cabal
build-depends:
HTTP >= 4000.2.5 && < 4000.3,
mtl >= 2.0 && < 3
")
(define-package-matcher match-ghc-foo-revision
('package
('name "ghc-foo")
('version "1.0.0")
('source
('origin
('method 'url-fetch)
('uri ('string-append
"https://hackage.haskell.org/package/foo/foo-"
'version
".tar.gz"))
('sha256
('base32
(? string? hash)))))
('build-system 'haskell-build-system)
('inputs
('quasiquote
(("ghc-http" ('unquote 'ghc-http)))))
('arguments
('quasiquote
('#:cabal-revision
("2" "0xxd88fb659f0krljidbvvmkh9ppjnx83j0nqzx8whcg4n5qbyng"))))
('home-page "http://test.org")
('synopsis (? string?))
('description (? string?))
('license 'bsd-3)))
(test-assert "hackage->guix-package test cabal revision"
(eval-test-with-cabal test-cabal-revision match-ghc-foo-revision))
(test-assert "read-cabal test 1"
(match (call-with-input-string test-read-cabal-1 read-cabal)
((("name" ("test-me"))
('section 'library
(('if ('flag "base4point8")
(("build-depends" ("base >= 4.8 && < 5")))
(('if ('flag "base4")
(("build-depends" ("base >= 4 && < 4.8")))
(('if ('flag "base3")
(("build-depends" ("base >= 3 && < 4")))
(("build-depends" ("base < 3"))))))))
('if ('or ('flag "base4point8")
('and ('flag "base4") ('flag "base3")))
(("build-depends" ("random")))
())
("build-depends" ("containers"))
("exposed-modules" ("Test.QuickCheck.Exception")))))
#t)
(x (pk 'fail x #f))))
(test-end "hackage")