* [bug#35859] line ending fix
2019-05-22 20:11 [bug#35859] [PATCH] hackage import: Setup.hs generation and revision support Robert Vollmert
@ 2019-05-23 8:50 ` Robert Vollmert
2019-05-23 13:27 ` [bug#35859] fixed patch set, including test fixes Robert Vollmert
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Robert Vollmert @ 2019-05-23 8:50 UTC (permalink / raw)
To: 35859
[-- Attachment #1: Type: text/plain, Size: 73 bytes --]
Updated patch to deal with CRLF line endings when computing cabal hash.
[-- Attachment #2: 0005-guix-import-hackage-handle-hackage-revisions.patch --]
[-- Type: application/octet-stream, Size: 7881 bytes --]
From ee2300e5605745a71e77c0972aebc21e826c581a Mon Sep 17 00:00:00 2001
From: Robert Vollmert <rob@vllmrt.net>
Date: Fri, 17 May 2019 22:52:24 +0200
Subject: [PATCH 5/5] guix: import: hackage: handle hackage revisions
Hackage packages can have metadata revision (cabal-file only)
that aren't reflected in the source archive. haskell-build-system
has support for this, but previously `guix import hackage` would
create a definition based on the new cabal file but building using
the old cabal file.
Compare https://debbugs.gnu.org/cgi/bugreport.cgi?bug=35750.
* guix/import/cabal.scm: Parse `x-revision:` property.
* guix/import/hackage.scm: Compute hash of cabal file, and write
cabal-revision build system arguments.
---
guix/import/cabal.scm | 7 +++--
guix/import/hackage.scm | 61 ++++++++++++++++++++++++++++++-----------
2 files changed, 50 insertions(+), 18 deletions(-)
diff --git a/guix/import/cabal.scm b/guix/import/cabal.scm
index 3028ed2882..312927a573 100644
--- a/guix/import/cabal.scm
+++ b/guix/import/cabal.scm
@@ -40,6 +40,7 @@
cabal-package?
cabal-package-name
cabal-package-version
+ cabal-package-revision
cabal-package-license
cabal-package-home-page
cabal-package-source-repository
@@ -638,13 +639,14 @@ If #f use the function 'port-filename' to obtain it."
;; information of the Cabal file, but only the ones we currently are
;; interested in.
(define-record-type <cabal-package>
- (make-cabal-package name version license home-page source-repository
+ (make-cabal-package name version revision license home-page source-repository
synopsis description
executables lib test-suites
flags eval-environment custom-setup)
cabal-package?
(name cabal-package-name)
(version cabal-package-version)
+ (revision cabal-package-revision)
(license cabal-package-license)
(home-page cabal-package-home-page)
(source-repository cabal-package-source-repository)
@@ -838,6 +840,7 @@ See the manual for limitations.")))))))
(define (cabal-evaluated-sexp->package evaluated-sexp)
(let* ((name (lookup-join evaluated-sexp "name"))
(version (lookup-join evaluated-sexp "version"))
+ (revision (lookup-join evaluated-sexp "x-revision"))
(license (lookup-join evaluated-sexp "license"))
(home-page (lookup-join evaluated-sexp "homepage"))
(home-page-or-hackage
@@ -856,7 +859,7 @@ See the manual for limitations.")))))))
(custom-setup (match (make-cabal-section evaluated-sexp 'custom-setup)
((x) x)
(_ #f))))
- (make-cabal-package name version license home-page-or-hackage
+ (make-cabal-package name version revision license home-page-or-hackage
source-repository synopsis description executables lib
test-suites flags eval-environment custom-setup)))
diff --git a/guix/import/hackage.scm b/guix/import/hackage.scm
index 5b80a7ea1d..0bd9034087 100644
--- a/guix/import/hackage.scm
+++ b/guix/import/hackage.scm
@@ -117,9 +117,15 @@ version is returned."
(#f name)
(m (match:substring m 1)))))))
-(define (hackage-fetch name-version)
- "Return the Cabal file for the package NAME-VERSION, or #f on failure. If
-the version part is omitted from the package name, then return the latest
+(define (read-cabal-and-hash port)
+ (let-values (((port get-hash) (open-sha256-input-port port)))
+ (cons
+ (read-cabal (canonical-newline-port port))
+ (bytevector->nix-base32-string (get-hash)))))
+
+(define (hackage-fetch-and-hash name-version)
+ "Return the Cabal file and hash for the package NAME-VERSION, or #f on failure.
+If the version part is omitted from the package name, then return the latest
version."
(guard (c ((and (http-get-error? c)
(= 404 (http-get-error-code c)))
@@ -127,10 +133,18 @@ version."
(let-values (((name version) (package-name->name+version name-version)))
(let* ((url (hackage-cabal-url name version))
(port (http-fetch url))
- (result (read-cabal (canonical-newline-port port))))
+ (result (read-cabal-and-hash port)))
(close-port port)
result))))
+(define (hackage-fetch name-version)
+ "Return the Cabal file for the package NAME-VERSION, or #f on failure. If
+the version part is omitted from the package name, then return the latest
+version."
+ (match (hackage-fetch-and-hash name-version)
+ ((cabal . hash) cabal)
+ (_ #f)))
+
(define string->license
;; List of valid values from
;; https://www.haskell.org
@@ -196,15 +210,19 @@ package being processed and is used to filter references to itself."
(cons own-name ghc-standard-libraries))))
dependencies))
-(define* (hackage-module->sexp cabal #:key (include-test-dependencies? #t))
+(define* (hackage-module->sexp cabal cabal-hash #:key (include-test-dependencies? #t))
"Return the `package' S-expression for a Cabal package. CABAL is the
-representation of a Cabal file as produced by 'read-cabal'."
+representation of a Cabal file as produced by 'read-cabal'. CABAL-HASH is
+the hash of the Cabal file."
(define name
(cabal-package-name cabal))
(define version
(cabal-package-version cabal))
+
+ (define revision
+ (cabal-package-revision cabal))
(define source-url
(hackage-source-url name version))
@@ -250,9 +268,17 @@ representation of a Cabal file as produced by 'read-cabal'."
(list 'quasiquote inputs))))))
(define (maybe-arguments)
- (if (not include-test-dependencies?)
- '((arguments `(#:tests? #f)))
- '()))
+ (define testargs (if (not include-test-dependencies?)
+ '(#:tests? #f)
+ '()))
+ (define revargs (if (not (string-null? revision))
+ `(#:cabal-revision (,revision ,cabal-hash))
+ '()))
+ (define args (append testargs revargs))
+ (if (not (nil? args))
+ (let ((qargs `(,'quasiquote ,args)))
+ `((arguments ,qargs)))
+ '()))
(let ((tarball (with-store store
(download-to-store store source-url))))
@@ -293,13 +319,16 @@ symbol 'true' or 'false'. The value associated with other keys has to conform
to the Cabal file format definition. The default value associated with the
keys \"os\", \"arch\" and \"impl\" is \"linux\", \"x86_64\" and \"ghc\"
respectively."
- (let ((cabal-meta (if port
- (read-cabal (canonical-newline-port port))
- (hackage-fetch package-name))))
- (and=> cabal-meta (compose (cut hackage-module->sexp <>
- #:include-test-dependencies?
- include-test-dependencies?)
- (cut eval-cabal <> cabal-environment))))))
+ (match
+ (if port (read-cabal-and-hash port)
+ (hackage-fetch-and-hash package-name))
+ ((cabal-meta . cabal-hash)
+ (and=> cabal-meta (compose (cut hackage-module->sexp <>
+ cabal-hash
+ #:include-test-dependencies?
+ include-test-dependencies?)
+ (cut eval-cabal <> cabal-environment))))
+ (_ #f))))
(define hackage->guix-package
(memoize hackage->guix-package-impl))
--
2.21.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [bug#35859] fixed patch set, including test fixes
2019-05-22 20:11 [bug#35859] [PATCH] hackage import: Setup.hs generation and revision support Robert Vollmert
2019-05-23 8:50 ` [bug#35859] line ending fix Robert Vollmert
@ 2019-05-23 13:27 ` Robert Vollmert
2019-05-24 14:56 ` [bug#35859] fixes bug in patch 0003 Robert Vollmert
2019-05-24 14:58 ` [bug#35859] improves output in patch 0010 Robert Vollmert
3 siblings, 0 replies; 5+ messages in thread
From: Robert Vollmert @ 2019-05-23 13:27 UTC (permalink / raw)
To: 35859
[-- Attachment #1: Type: text/plain, Size: 379 bytes --]
The previous version of this patch caused some test failures due
to conflict with the hackage-fetch mocking in tests/hackage.scm.
This set reworks the tests to not mock, and incorporates updated
versions of the previous patch sets
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=35812
(fix cabal tests)
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=35846
(braced properties)
[-- Attachment #2: 0001-tests-fix-cabal-tests-to-test-and-pass.patch --]
[-- Type: application/octet-stream, Size: 5453 bytes --]
From 8b6dac85a9f6c4e851c1a75a4958dff7915fb2f1 Mon Sep 17 00:00:00 2001
From: Robert Vollmert <rob@vllmrt.net>
Date: Fri, 17 May 2019 10:48:42 +0200
Subject: [PATCH 01/11] tests: fix cabal tests to test and pass
* guix/import/hackage.scm: export unmemoized import function
* tests/hackage.scm: use unmemoized import function to make tests independent
* tests/hackage.scm: fix failing test-cabal-6 by providing expected output
---
guix/import/hackage.scm | 31 +++++++++++++++++--------------
tests/hackage.scm | 39 ++++++++++++++++++++++++++++++++++++---
2 files changed, 53 insertions(+), 17 deletions(-)
diff --git a/guix/import/hackage.scm b/guix/import/hackage.scm
index 2a51420d14..5b80a7ea1d 100644
--- a/guix/import/hackage.scm
+++ b/guix/import/hackage.scm
@@ -40,6 +40,7 @@
#:use-module (guix packages)
#:use-module ((guix utils) #:select (call-with-temporary-output-file))
#:export (hackage->guix-package
+ hackage->guix-package-impl
hackage-recursive-import
%hackage-updater
@@ -277,13 +278,12 @@ representation of a Cabal file as produced by 'read-cabal'."
(license ,(string->license (cabal-package-license cabal))))
(append hackage-dependencies hackage-native-dependencies))))
-(define hackage->guix-package
- (memoize
- (lambda* (package-name #:key
- (include-test-dependencies? #t)
- (port #f)
- (cabal-environment '()))
- "Fetch the Cabal file for PACKAGE-NAME from hackage.haskell.org, or, if the
+(define hackage->guix-package-impl
+ (lambda* (package-name #:key
+ (include-test-dependencies? #t)
+ (port #f)
+ (cabal-environment '()))
+ "Fetch the Cabal file for PACKAGE-NAME from hackage.haskell.org, or, if the
called with keyword parameter PORT, from PORT. Return the `package'
S-expression corresponding to that package, or #f on failure.
CABAL-ENVIRONMENT is an alist defining the environment in which the Cabal
@@ -293,13 +293,16 @@ symbol 'true' or 'false'. The value associated with other keys has to conform
to the Cabal file format definition. The default value associated with the
keys \"os\", \"arch\" and \"impl\" is \"linux\", \"x86_64\" and \"ghc\"
respectively."
- (let ((cabal-meta (if port
- (read-cabal (canonical-newline-port port))
- (hackage-fetch package-name))))
- (and=> cabal-meta (compose (cut hackage-module->sexp <>
- #:include-test-dependencies?
- include-test-dependencies?)
- (cut eval-cabal <> cabal-environment)))))))
+ (let ((cabal-meta (if port
+ (read-cabal (canonical-newline-port port))
+ (hackage-fetch package-name))))
+ (and=> cabal-meta (compose (cut hackage-module->sexp <>
+ #:include-test-dependencies?
+ include-test-dependencies?)
+ (cut eval-cabal <> cabal-environment))))))
+
+(define hackage->guix-package
+ (memoize hackage->guix-package-impl))
(define* (hackage-recursive-import package-name . args)
(recursive-import package-name #f
diff --git a/tests/hackage.scm b/tests/hackage.scm
index e17851a213..e56aa996d6 100644
--- a/tests/hackage.scm
+++ b/tests/hackage.scm
@@ -161,7 +161,7 @@ library
(lambda (name-version)
(call-with-input-string test-cabal
read-cabal)))
- (match (hackage->guix-package "foo" #:cabal-environment cabal-environment)
+ (match (hackage->guix-package-impl "foo" #:cabal-environment cabal-environment)
(('package
('name "ghc-foo")
('version "1.0.0")
@@ -207,8 +207,41 @@ library
#:cabal-environment '(("impl" . "ghc-7.8"))))
(test-assert "hackage->guix-package test 6"
- (eval-test-with-cabal test-cabal-6
- #:cabal-environment '(("impl" . "ghc-7.8"))))
+ (mock
+ ((guix import hackage) hackage-fetch
+ (lambda (name-version)
+ (call-with-input-string test-cabal-6
+ read-cabal)))
+ (match (hackage->guix-package-impl "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-b" ('unquote 'ghc-b))
+ ("ghc-http" ('unquote 'ghc-http))
+ ("ghc-mtl" ('unquote 'ghc-mtl)))))
+ ('native-inputs
+ ('quasiquote
+ (("ghc-haskell-gi" ('unquote 'ghc-haskell-gi)))))
+ ('home-page "http://test.org")
+ ('synopsis (? string?))
+ ('description (? string?))
+ ('license 'bsd-3))
+ #t)
+ (x
+ (pk 'fail x #f)))))
(test-assert "read-cabal test 1"
(match (call-with-input-string test-read-cabal-1 read-cabal)
--
2.21.0
[-- Attachment #3: 0002-tests-hackage-test-multiline-cabal-description.patch --]
[-- Type: application/octet-stream, Size: 1514 bytes --]
From 1a001cd80d8f5c3e763f8632e10f959775aa7887 Mon Sep 17 00:00:00 2001
From: Robert Vollmert <rob@vllmrt.net>
Date: Sat, 18 May 2019 03:37:43 +0200
Subject: [PATCH 02/11] tests: hackage: test multiline cabal description
* tests/hackage.scm: Add test case with multi-line description.
---
tests/hackage.scm | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/tests/hackage.scm b/tests/hackage.scm
index e56aa996d6..41cea73fe7 100644
--- a/tests/hackage.scm
+++ b/tests/hackage.scm
@@ -128,6 +128,21 @@ library
mtl >= 2.0 && < 3
")
+;; Check multi-line layouted description
+(define test-cabal-7
+ "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
+")
+
;; 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.
@@ -243,6 +258,10 @@ library
(x
(pk 'fail x #f)))))
+(test-assert "hackage->guix-package test 7"
+ (eval-test-with-cabal test-cabal-7
+ #:cabal-environment '(("impl" . "ghc-7.8"))))
+
(test-assert "read-cabal test 1"
(match (call-with-input-string test-read-cabal-1 read-cabal)
((("name" ("test-me"))
--
2.21.0
[-- Attachment #4: 0003-guix-import-cabal-parse-braced-description-propertie.patch --]
[-- Type: application/octet-stream, Size: 5244 bytes --]
From 59ab5435e3cb77831a97831d82f5ab419345719b Mon Sep 17 00:00:00 2001
From: Robert Vollmert <rob@vllmrt.net>
Date: Fri, 17 May 2019 14:26:36 +0200
Subject: [PATCH 03/11] guix: import: cabal: parse braced description
properties
* guix/import/cabal.scm: generalize property bracing to both
layouted and simple braced blocks
* guix/tests/hackage.scm: test braced description import
---
guix/import/cabal.scm | 35 ++++++++++++++++++++++++++++-------
tests/hackage.scm | 22 ++++++++++++++++++++++
2 files changed, 50 insertions(+), 7 deletions(-)
diff --git a/guix/import/cabal.scm b/guix/import/cabal.scm
index 13c2f3f48c..3028ed2882 100644
--- a/guix/import/cabal.scm
+++ b/guix/import/cabal.scm
@@ -270,6 +270,10 @@ following lines with indentation larger than MIN-INDENT."
(peek-next-line-indent port)))
val)))
+(define* (read-braced-value port)
+ "Read up to a closing brace."
+ (string-trim-both (read-delimited "}" port 'trim)))
+
(define (lex-white-space port bol)
"Consume white spaces and comment lines on PORT. If a new line is started return #t,
otherwise return BOL (beginning-of-line)."
@@ -343,8 +347,11 @@ matching a string against the created regexp."
(make-regexp pat))))
(cut regexp-exec rx <>)))
-(define is-property (make-rx-matcher "([a-z0-9-]+)[ \t]*:[ \t]*(\\w?.*)$"
- regexp/icase))
+(define is-layout-property (make-rx-matcher "([a-z0-9-]+)[ \t]*:[ \t]*(\\w?[^\\{\\}]*)$"
+ regexp/icase))
+
+(define is-braced-property (make-rx-matcher "([a-z0-9-]+)[ \t]*:[ \t]*\\{[ \t]*$"
+ regexp/icase))
(define is-flag (make-rx-matcher "^flag +([a-z0-9_-]+)"
regexp/icase))
@@ -435,13 +442,19 @@ string with the read characters."
(begin (unread-char c) (list->string res)))))
(else (list->string res)))))
-(define (lex-property k-v-rx-res loc port)
+(define (lex-layout-property k-v-rx-res loc port)
(let ((key (string-downcase (match:substring k-v-rx-res 1)))
(value (match:substring k-v-rx-res 2)))
(make-lexical-token
'PROPERTY loc
(list key `(,(read-value port value (current-indentation)))))))
+(define (lex-braced-property k-rx-res loc port)
+ (let ((key (string-downcase (match:substring k-rx-res 1))))
+ (make-lexical-token
+ 'PROPERTY loc
+ (list key `(,(read-braced-value port))))))
+
(define (lex-rx-res rx-res token loc)
(let ((name (string-downcase (match:substring rx-res 1))))
(make-lexical-token token loc name)))
@@ -552,7 +565,6 @@ LOC is the current port location."
the current port location."
(let* ((s (read-delimited "\n{}" port 'peek)))
(cond
- ((is-property s) => (cut lex-property <> loc port))
((is-flag s) => (cut lex-flag <> loc))
((is-src-repo s) => (cut lex-src-repo <> loc))
((is-exec s) => (cut lex-exec <> loc))
@@ -561,13 +573,22 @@ the current port location."
((is-benchmark s) => (cut lex-benchmark <> loc))
((is-lib s) (lex-lib loc))
((is-else s) (lex-else loc))
- (else
- #f))))
+ (else (unread-string s port) #f))))
+
+(define (lex-property port loc)
+ (let* ((s (read-delimited "\n" port 'peek)))
+ (cond
+ ((is-braced-property s) => (cut lex-braced-property <> loc port))
+ ((is-layout-property s) => (cut lex-layout-property <> loc port))
+ (else #f))))
(define (lex-token port)
(let* ((loc (make-source-location (cabal-file-name) (port-line port)
(port-column port) -1 -1)))
- (or (lex-single-char port loc) (lex-word port loc) (lex-line port loc))))
+ (or (lex-single-char port loc)
+ (lex-word port loc)
+ (lex-line port loc)
+ (lex-property port loc))))
;; Lexer- and error-function generators
diff --git a/tests/hackage.scm b/tests/hackage.scm
index 41cea73fe7..733d540c20 100644
--- a/tests/hackage.scm
+++ b/tests/hackage.scm
@@ -143,6 +143,24 @@ executable cabal
mtl >= 2.0 && < 3
")
+;; Check braces instead of layout
+(define test-cabal-8
+ "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
+")
+
+
;; 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.
@@ -262,6 +280,10 @@ library
(eval-test-with-cabal test-cabal-7
#:cabal-environment '(("impl" . "ghc-7.8"))))
+(test-assert "hackage->guix-package test 8"
+ (eval-test-with-cabal test-cabal-8
+ #:cabal-environment '(("impl" . "ghc-7.8"))))
+
(test-assert "read-cabal test 1"
(match (call-with-input-string test-read-cabal-1 read-cabal)
((("name" ("test-me"))
--
2.21.0
[-- Attachment #5: 0004-tests-hackage-avoid-mock-and-extract-test-data.patch --]
[-- Type: application/octet-stream, Size: 6445 bytes --]
From 716761b051b27d78bf1f374ac287a94b14cc2bca Mon Sep 17 00:00:00 2001
From: Robert Vollmert <rob@vllmrt.net>
Date: Sat, 18 May 2019 04:58:18 +0200
Subject: [PATCH 04/11] tests: hackage: avoid mock, and extract test data
This is partially in order to make tests depend less on the
implementation of `hackage-fetch`, in preparation for hackage
revision import.
* tests/hackage.scm: Provide cabal input port directly, instead
of mocking hackage-fetch. And make cabal tests more explicit and
consistent by defining package pattern per test.
---
tests/hackage.scm | 141 +++++++++++++++++++++-------------------------
1 file changed, 65 insertions(+), 76 deletions(-)
diff --git a/tests/hackage.scm b/tests/hackage.scm
index 733d540c20..5f47e909c6 100644
--- a/tests/hackage.scm
+++ b/tests/hackage.scm
@@ -188,101 +188,90 @@ library
(test-begin "hackage")
-(define* (eval-test-with-cabal test-cabal #:key (cabal-environment '()))
- (mock
- ((guix import hackage) hackage-fetch
- (lambda (name-version)
- (call-with-input-string test-cabal
- read-cabal)))
- (match (hackage->guix-package-impl "foo" #:cabal-environment cabal-environment)
- (('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))
- ("ghc-mtl" ('unquote 'ghc-mtl)))))
- ('home-page "http://test.org")
- ('synopsis (? string?))
- ('description (? string?))
- ('license 'bsd-3))
- #t)
- (x
- (pk 'fail x #f)))))
+(define ghc-foo-pattern
+ '('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))
+ ("ghc-mtl" ('unquote 'ghc-mtl)))))
+ ('home-page "http://test.org")
+ ('synopsis (? string?))
+ ('description (? string?))
+ ('license 'bsd-3)))
+
+(define* (eval-test-with-cabal test-cabal package-pattern #:key (cabal-environment '()))
+ (define port (open-input-string test-cabal))
+ (match (hackage->guix-package-impl "foo" #:port port #:cabal-environment cabal-environment)
+ (package-pattern #t)
+ (x (pk 'fail x #f))))
(test-assert "hackage->guix-package test 1"
- (eval-test-with-cabal test-cabal-1))
+ (eval-test-with-cabal test-cabal-1 ghc-foo-pattern))
(test-assert "hackage->guix-package test 2"
- (eval-test-with-cabal test-cabal-2))
+ (eval-test-with-cabal test-cabal-2 ghc-foo-pattern))
(test-assert "hackage->guix-package test 3"
- (eval-test-with-cabal test-cabal-3
+ (eval-test-with-cabal test-cabal-3 ghc-foo-pattern
#:cabal-environment '(("impl" . "ghc-7.8"))))
(test-assert "hackage->guix-package test 4"
- (eval-test-with-cabal test-cabal-4
+ (eval-test-with-cabal test-cabal-4 ghc-foo-pattern
#:cabal-environment '(("impl" . "ghc-7.8"))))
(test-assert "hackage->guix-package test 5"
- (eval-test-with-cabal test-cabal-5
+ (eval-test-with-cabal test-cabal-5 ghc-foo-pattern
#:cabal-environment '(("impl" . "ghc-7.8"))))
+(define ghc-foo-pattern-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))
+ ("ghc-mtl" ('unquote 'ghc-mtl)))))
+ ('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"
- (mock
- ((guix import hackage) hackage-fetch
- (lambda (name-version)
- (call-with-input-string test-cabal-6
- read-cabal)))
- (match (hackage->guix-package-impl "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-b" ('unquote 'ghc-b))
- ("ghc-http" ('unquote 'ghc-http))
- ("ghc-mtl" ('unquote 'ghc-mtl)))))
- ('native-inputs
- ('quasiquote
- (("ghc-haskell-gi" ('unquote 'ghc-haskell-gi)))))
- ('home-page "http://test.org")
- ('synopsis (? string?))
- ('description (? string?))
- ('license 'bsd-3))
- #t)
- (x
- (pk 'fail x #f)))))
+ (eval-test-with-cabal test-cabal-6 ghc-foo-pattern-6))
(test-assert "hackage->guix-package test 7"
- (eval-test-with-cabal test-cabal-7
- #:cabal-environment '(("impl" . "ghc-7.8"))))
+ (eval-test-with-cabal test-cabal-7 ghc-foo-pattern))
(test-assert "hackage->guix-package test 8"
- (eval-test-with-cabal test-cabal-8
- #:cabal-environment '(("impl" . "ghc-7.8"))))
+ (eval-test-with-cabal test-cabal-8 ghc-foo-pattern))
(test-assert "read-cabal test 1"
(match (call-with-input-string test-read-cabal-1 read-cabal)
--
2.21.0
[-- Attachment #6: 0005-gnu-ghc-easy-plot-remove-superfluous-Setup.hs-rename.patch --]
[-- Type: application/octet-stream, Size: 1291 bytes --]
From 03d28f656160a541cbc33c9b8dc693d2b9b4774c Mon Sep 17 00:00:00 2001
From: Robert Vollmert <rob@vllmrt.net>
Date: Fri, 17 May 2019 16:28:44 +0200
Subject: [PATCH 05/11] gnu: ghc-easy-plot: remove superfluous Setup.hs rename
step
haskell-build-system already uses whichever of Setup.hs and
Setup.lhs exists.
* gnu/packages/haskell.scm (ghc-easy-plot): don't rename
Setup.lhs to Setup.hs
---
gnu/packages/haskell.scm | 4 ----
1 file changed, 4 deletions(-)
diff --git a/gnu/packages/haskell.scm b/gnu/packages/haskell.scm
index 61c6119322..c40581a8cd 100644
--- a/gnu/packages/haskell.scm
+++ b/gnu/packages/haskell.scm
@@ -8063,10 +8063,6 @@ interface for statistics based on hmatrix and GSL.")
(base32 "18kndgvdj2apjpfga6fp7m16y1gx8zrwp3c5vfj03sx4v6jvciqk"))))
(build-system haskell-build-system)
(propagated-inputs `(("gnuplot" ,gnuplot)))
- (arguments
- `(#:phases (modify-phases %standard-phases
- (add-after 'unpack 'fix-setup-suffix
- (lambda _ (rename-file "Setup.lhs" "Setup.hs") #t)))))
(home-page "https://hub.darcs.net/scravy/easyplot")
(synopsis "Haskell plotting library based on gnuplot")
(description "This package provides a plotting library for
--
2.21.0
[-- Attachment #7: 0006-guix-haskell-build-system-correct-haddock-phase-docu.patch --]
[-- Type: application/octet-stream, Size: 960 bytes --]
From 97d51b39acb8d08a63f39256c0c763b948085d01 Mon Sep 17 00:00:00 2001
From: Robert Vollmert <rob@vllmrt.net>
Date: Fri, 17 May 2019 18:58:55 +0200
Subject: [PATCH 06/11] guix: haskell-build-system: correct haddock phase
documentation
* guix/build/haskell-build-system.scm (haddock): Correct docstring
---
guix/build/haskell-build-system.scm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/guix/build/haskell-build-system.scm b/guix/build/haskell-build-system.scm
index 23d97e6602..5c5b32322b 100644
--- a/guix/build/haskell-build-system.scm
+++ b/guix/build/haskell-build-system.scm
@@ -260,7 +260,7 @@ given Haskell package."
#t)
(define* (haddock #:key outputs haddock? haddock-flags #:allow-other-keys)
- "Run the test suite of a given Haskell package."
+ "Generate haddock documentation of a given Haskell package."
(when haddock?
(run-setuphs "haddock" haddock-flags))
#t)
--
2.21.0
[-- Attachment #8: 0007-guix-haskell-build-system-generate-Setup.hs-if-not-e.patch --]
[-- Type: application/octet-stream, Size: 1723 bytes --]
From a502063aa4c26f171f081fdcab30a2b157534de8 Mon Sep 17 00:00:00 2001
From: Robert Vollmert <rob@vllmrt.net>
Date: Fri, 17 May 2019 16:26:31 +0200
Subject: [PATCH 07/11] guix: haskell-build-system: generate Setup.hs if not
exists
The default Setup.hs is boilerplate that is frequently left out of
source packages, causing build failure for package definitions as
generated by `guix import hackage`. Compare
<https://github.com/phadej/time-compat/issues/4>
* guix/build/haskell-build-system.scm: Generate Setup.hs if missing,
after unpack phase.
---
guix/build/haskell-build-system.scm | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/guix/build/haskell-build-system.scm b/guix/build/haskell-build-system.scm
index 5c5b32322b..0c648e510f 100644
--- a/guix/build/haskell-build-system.scm
+++ b/guix/build/haskell-build-system.scm
@@ -275,9 +275,21 @@ given Haskell package."
(_ (error "Could not find a Cabal file to patch."))))
#t)
+(define* (generate-setup #:rest empty)
+ "Generate boilerplate Setup.hs if missing."
+ (when (not (or (file-exists? "Setup.hs")
+ (file-exists? "Setup.lhs")))
+ (format #t "generating missing Setup.hs~%")
+ (with-output-to-file "Setup.hs"
+ (lambda ()
+ (format #t "import Distribution.Simple~%")
+ (format #t "main = defaultMain~%"))))
+ #t)
+
(define %standard-phases
(modify-phases gnu:%standard-phases
(add-after 'unpack 'patch-cabal-file patch-cabal-file)
+ (add-after 'unpack 'generate-setup generate-setup)
(delete 'bootstrap)
(add-before 'configure 'setup-compiler setup-compiler)
(add-before 'install 'haddock haddock)
--
2.21.0
[-- Attachment #9: 0008-gnu-haskell-leave-Setup.hs-generation-to-build-syste.patch --]
[-- Type: application/octet-stream, Size: 3483 bytes --]
From f013a4894022606d526020eb64fb5301832096d7 Mon Sep 17 00:00:00 2001
From: Robert Vollmert <rob@vllmrt.net>
Date: Fri, 17 May 2019 16:29:08 +0200
Subject: [PATCH 08/11] gnu: haskell: leave Setup.hs generation to build system
Remove explicit Setup.hs generation from the configure step
now that haskell-build-system does it.
* gnu/packages/haskell.scm (ghc-foundation, ghc-inline-c,
ghc-inline-c-cpp, ghc-rio): Don't generate Setup.hs
---
gnu/packages/haskell.scm | 42 ----------------------------------------
1 file changed, 42 deletions(-)
diff --git a/gnu/packages/haskell.scm b/gnu/packages/haskell.scm
index c40581a8cd..f12371f3ce 100644
--- a/gnu/packages/haskell.scm
+++ b/gnu/packages/haskell.scm
@@ -9688,16 +9688,6 @@ packages.")
(base32
"1q43y8wfj0wf9gdq2kzphwjwq6m5pvryy1lqgk954aq5z3ks1lsf"))))
(build-system haskell-build-system)
- (arguments
- `(#:phases
- (modify-phases %standard-phases
- (add-after 'unpack 'add-setup-script
- (lambda _
- ;; The usual "Setup.hs" script is missing from the source.
- (with-output-to-file "Setup.hs"
- (lambda ()
- (format #t "import Distribution.Simple~%")
- (format #t "main = defaultMain~%"))))))))
(inputs `(("ghc-basement" ,ghc-basement)))
(home-page "https://github.com/haskell-foundation/foundation")
(synopsis "Alternative prelude with batteries and no dependencies")
@@ -10575,16 +10565,6 @@ widths to the Char type.")
(base32
"064h8a4hp53a479d3ak0vmqbx8hi0cpg7zn4wp23rjy26dka8p7g"))))
(build-system haskell-build-system)
- (arguments
- `(#:phases
- (modify-phases %standard-phases
- (add-after 'unpack 'add-setup-script
- (lambda _
- ;; The usual "Setup.hs" script is missing from the source.
- (with-output-to-file "Setup.hs"
- (lambda ()
- (format #t "import Distribution.Simple~%")
- (format #t "main = defaultMain~%"))))))))
(inputs
`(("ghc-exceptions" ,ghc-exceptions)
("ghc-hashable" ,ghc-hashable)
@@ -11107,17 +11087,6 @@ DOS/Windows paths and markup languages (such as XML).")
(base32
"0vbfrsqsi7mdziqsnj68bsqlwbqxxhvrmy9rv6w8z18d1m8w3n6h"))))
(build-system haskell-build-system)
- (arguments
- `(#:phases
- (modify-phases %standard-phases
- (add-after 'unpack 'create-Setup.hs
- (lambda _
- (with-output-to-file "Setup.hs"
- (lambda _
- (display "\
-import Distribution.Simple
-main = defaultMain")))
- #t)))))
(inputs
`(("ghc-ansi-wl-pprint" ,ghc-ansi-wl-pprint)
("ghc-cryptohash" ,ghc-cryptohash)
@@ -11251,17 +11220,6 @@ handling wrong.")
(base32
"1rk7fmpkmxw9hhwr8df29kadnf0ybnwj64ggdbnsdrpfyhnkisci"))))
(build-system haskell-build-system)
- (arguments
- `(#:phases
- (modify-phases %standard-phases
- (add-after 'unpack 'create-Setup.hs
- (lambda _
- (with-output-to-file "Setup.hs"
- (lambda _
- (display "\
-import Distribution.Simple
-main = defaultMain")))
- #t)))))
(inputs
`(("ghc-inline-c" ,ghc-inline-c)
("ghc-safe-exceptions" ,ghc-safe-exceptions)))
--
2.21.0
[-- Attachment #10: 0009-guix-import-hackage-handle-hackage-revisions.patch --]
[-- Type: application/octet-stream, Size: 7883 bytes --]
From 649804c95c3946aac9ea146889dcbafdd300bb22 Mon Sep 17 00:00:00 2001
From: Robert Vollmert <rob@vllmrt.net>
Date: Fri, 17 May 2019 22:52:24 +0200
Subject: [PATCH 09/11] guix: import: hackage: handle hackage revisions
Hackage packages can have metadata revision (cabal-file only)
that aren't reflected in the source archive. haskell-build-system
has support for this, but previously `guix import hackage` would
create a definition based on the new cabal file but building using
the old cabal file.
Compare https://debbugs.gnu.org/cgi/bugreport.cgi?bug=35750.
* guix/import/cabal.scm: Parse `x-revision:` property.
* guix/import/hackage.scm: Compute hash of cabal file, and write
cabal-revision build system arguments.
---
guix/import/cabal.scm | 7 +++--
guix/import/hackage.scm | 61 ++++++++++++++++++++++++++++++-----------
2 files changed, 50 insertions(+), 18 deletions(-)
diff --git a/guix/import/cabal.scm b/guix/import/cabal.scm
index 3028ed2882..312927a573 100644
--- a/guix/import/cabal.scm
+++ b/guix/import/cabal.scm
@@ -40,6 +40,7 @@
cabal-package?
cabal-package-name
cabal-package-version
+ cabal-package-revision
cabal-package-license
cabal-package-home-page
cabal-package-source-repository
@@ -638,13 +639,14 @@ If #f use the function 'port-filename' to obtain it."
;; information of the Cabal file, but only the ones we currently are
;; interested in.
(define-record-type <cabal-package>
- (make-cabal-package name version license home-page source-repository
+ (make-cabal-package name version revision license home-page source-repository
synopsis description
executables lib test-suites
flags eval-environment custom-setup)
cabal-package?
(name cabal-package-name)
(version cabal-package-version)
+ (revision cabal-package-revision)
(license cabal-package-license)
(home-page cabal-package-home-page)
(source-repository cabal-package-source-repository)
@@ -838,6 +840,7 @@ See the manual for limitations.")))))))
(define (cabal-evaluated-sexp->package evaluated-sexp)
(let* ((name (lookup-join evaluated-sexp "name"))
(version (lookup-join evaluated-sexp "version"))
+ (revision (lookup-join evaluated-sexp "x-revision"))
(license (lookup-join evaluated-sexp "license"))
(home-page (lookup-join evaluated-sexp "homepage"))
(home-page-or-hackage
@@ -856,7 +859,7 @@ See the manual for limitations.")))))))
(custom-setup (match (make-cabal-section evaluated-sexp 'custom-setup)
((x) x)
(_ #f))))
- (make-cabal-package name version license home-page-or-hackage
+ (make-cabal-package name version revision license home-page-or-hackage
source-repository synopsis description executables lib
test-suites flags eval-environment custom-setup)))
diff --git a/guix/import/hackage.scm b/guix/import/hackage.scm
index 5b80a7ea1d..0bd9034087 100644
--- a/guix/import/hackage.scm
+++ b/guix/import/hackage.scm
@@ -117,9 +117,15 @@ version is returned."
(#f name)
(m (match:substring m 1)))))))
-(define (hackage-fetch name-version)
- "Return the Cabal file for the package NAME-VERSION, or #f on failure. If
-the version part is omitted from the package name, then return the latest
+(define (read-cabal-and-hash port)
+ (let-values (((port get-hash) (open-sha256-input-port port)))
+ (cons
+ (read-cabal (canonical-newline-port port))
+ (bytevector->nix-base32-string (get-hash)))))
+
+(define (hackage-fetch-and-hash name-version)
+ "Return the Cabal file and hash for the package NAME-VERSION, or #f on failure.
+If the version part is omitted from the package name, then return the latest
version."
(guard (c ((and (http-get-error? c)
(= 404 (http-get-error-code c)))
@@ -127,10 +133,18 @@ version."
(let-values (((name version) (package-name->name+version name-version)))
(let* ((url (hackage-cabal-url name version))
(port (http-fetch url))
- (result (read-cabal (canonical-newline-port port))))
+ (result (read-cabal-and-hash port)))
(close-port port)
result))))
+(define (hackage-fetch name-version)
+ "Return the Cabal file for the package NAME-VERSION, or #f on failure. If
+the version part is omitted from the package name, then return the latest
+version."
+ (match (hackage-fetch-and-hash name-version)
+ ((cabal . hash) cabal)
+ (_ #f)))
+
(define string->license
;; List of valid values from
;; https://www.haskell.org
@@ -196,15 +210,19 @@ package being processed and is used to filter references to itself."
(cons own-name ghc-standard-libraries))))
dependencies))
-(define* (hackage-module->sexp cabal #:key (include-test-dependencies? #t))
+(define* (hackage-module->sexp cabal cabal-hash #:key (include-test-dependencies? #t))
"Return the `package' S-expression for a Cabal package. CABAL is the
-representation of a Cabal file as produced by 'read-cabal'."
+representation of a Cabal file as produced by 'read-cabal'. CABAL-HASH is
+the hash of the Cabal file."
(define name
(cabal-package-name cabal))
(define version
(cabal-package-version cabal))
+
+ (define revision
+ (cabal-package-revision cabal))
(define source-url
(hackage-source-url name version))
@@ -250,9 +268,17 @@ representation of a Cabal file as produced by 'read-cabal'."
(list 'quasiquote inputs))))))
(define (maybe-arguments)
- (if (not include-test-dependencies?)
- '((arguments `(#:tests? #f)))
- '()))
+ (define testargs (if (not include-test-dependencies?)
+ '(#:tests? #f)
+ '()))
+ (define revargs (if (not (string-null? revision))
+ `(#:cabal-revision (,revision ,cabal-hash))
+ '()))
+ (define args (append testargs revargs))
+ (if (not (nil? args))
+ (let ((qargs `(,'quasiquote ,args)))
+ `((arguments ,qargs)))
+ '()))
(let ((tarball (with-store store
(download-to-store store source-url))))
@@ -293,13 +319,16 @@ symbol 'true' or 'false'. The value associated with other keys has to conform
to the Cabal file format definition. The default value associated with the
keys \"os\", \"arch\" and \"impl\" is \"linux\", \"x86_64\" and \"ghc\"
respectively."
- (let ((cabal-meta (if port
- (read-cabal (canonical-newline-port port))
- (hackage-fetch package-name))))
- (and=> cabal-meta (compose (cut hackage-module->sexp <>
- #:include-test-dependencies?
- include-test-dependencies?)
- (cut eval-cabal <> cabal-environment))))))
+ (match
+ (if port (read-cabal-and-hash port)
+ (hackage-fetch-and-hash package-name))
+ ((cabal-meta . cabal-hash)
+ (and=> cabal-meta (compose (cut hackage-module->sexp <>
+ cabal-hash
+ #:include-test-dependencies?
+ include-test-dependencies?)
+ (cut eval-cabal <> cabal-environment))))
+ (_ #f))))
(define hackage->guix-package
(memoize hackage->guix-package-impl))
--
2.21.0
[-- Attachment #11: 0010-guix-import-hackage-log-when-we-start-with-a-file.patch --]
[-- Type: application/octet-stream, Size: 1105 bytes --]
From 742b3db4c60e052e65c21dae1d5771f32cf01963 Mon Sep 17 00:00:00 2001
From: Robert Vollmert <rob@vllmrt.net>
Date: Sat, 18 May 2019 03:37:27 +0200
Subject: [PATCH 10/11] guix: import: hackage: log when we start with a file
This helps figuring out what errors are in relation to, particularly
during recursive import.
* guix/import/hackage.scm: Log before fetching/parsing a cabal file.
---
guix/import/hackage.scm | 1 +
1 file changed, 1 insertion(+)
diff --git a/guix/import/hackage.scm b/guix/import/hackage.scm
index 0bd9034087..d8baac0850 100644
--- a/guix/import/hackage.scm
+++ b/guix/import/hackage.scm
@@ -319,6 +319,7 @@ symbol 'true' or 'false'. The value associated with other keys has to conform
to the Cabal file format definition. The default value associated with the
keys \"os\", \"arch\" and \"impl\" is \"linux\", \"x86_64\" and \"ghc\"
respectively."
+ (format (current-error-port) "reading cabal file for ~a~%" package-name)
(match
(if port (read-cabal-and-hash port)
(hackage-fetch-and-hash package-name))
--
2.21.0
^ permalink raw reply related [flat|nested] 5+ messages in thread