From 5a9ef8a960706a55764f5bbc67ac83dd48516016 Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Fri, 17 May 2019 00:26:07 -0700 Subject: import: crate: Define dependencies as arguments. * guix/import/crate.scm: (crate-fetch)[input-crates]: Rename to dev-crates. [native-input-crates]: Rename to dev-dep-crates. [inputs]: Rename to cargo-inputs. [native-inputs]: Rename to cargo-development-inputs. (maybe-cargo-inputs, maybe-cargo-development-inputs, maybe-arguments): Add them. (make-crate-sexp)[inputs]: Rename to cargo-inputs. [native-inputs]: Rename to cargo-development-inputs. [maybe-native-inputs, maybe-inputs]: Replace with maybe-arguments. * guix/import/utils.scm: (package-names->package-inputs): Make public. Add docstring. * tests/crate.scm (crate->guix-package): Update the match pattern. Signed-off-by: Chris Marusich --- tests/crate.scm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/crate.scm b/tests/crate.scm index a1dcfd5e52..a4a328d507 100644 --- a/tests/crate.scm +++ b/tests/crate.scm @@ -89,9 +89,9 @@ ('base32 (? string? hash))))) ('build-system 'cargo-build-system) - ('inputs + ('arguments ('quasiquote - (("rust-bar" ('unquote 'rust-bar) "src")))) + (('#:cargo-inputs (("rust-bar" ('unquote rust-bar))))))) ('home-page "http://example.com") ('synopsis "summary") ('description "summary") -- cgit v1.2.3 From ca45da9fc9b1eee399ce4344b18cbb129daeca4c Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Thu, 13 Jun 2019 21:39:14 +0200 Subject: 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 . * guix/import/cabal.scm (): 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 --- guix/import/cabal.scm | 7 ++++-- guix/import/hackage.scm | 62 +++++++++++++++++++++++++++++++++++-------------- tests/hackage.scm | 45 +++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 20 deletions(-) (limited to 'tests') diff --git a/guix/import/cabal.scm b/guix/import/cabal.scm index 1a87be0b00..7dfe771e41 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 - (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 366256b40d..6f426af900 100644 --- a/guix/import/hackage.scm +++ b/guix/import/hackage.scm @@ -117,19 +117,34 @@ version is returned." (#f name) (m (match:substring m 1))))))) +(define (read-cabal-and-hash port) + "Read a Cabal file from PORT and return it and its hash in nix-base32 +format as two values." + (let-values (((port get-hash) (open-sha256-input-port port))) + (values (read-cabal (canonical-newline-port port)) + (bytevector->nix-base32-string (get-hash))))) + +(define (hackage-fetch-and-hash name-version) + "Fetch the latest Cabal revision for the package NAME-VERSION, and return +two values: the parsed Cabal file and its hash in nix-base32 format. If the +version part is omitted from the package name, then fetch the latest +version. On failure, both return values will be #f." + (guard (c ((and (http-get-error? c) + (= 404 (http-get-error-code c))) + (values #f #f))) ;"expected" if package is unknown + (let*-values (((name version) (package-name->name+version name-version)) + ((url) (hackage-cabal-url name version)) + ((port _) (http-fetch url)) + ((cabal hash) (read-cabal-and-hash port))) + (close-port port) + (values cabal hash)))) + (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." - (guard (c ((and (http-get-error? c) - (= 404 (http-get-error-code c))) - #f)) ;"expected" if package is unknown - (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)))) - (close-port port) - result)))) + (let-values (((cabal hash) (hackage-fetch-and-hash name-version))) + cabal)) (define string->license ;; List of valid values from @@ -198,15 +213,20 @@ 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)) @@ -252,9 +272,14 @@ representation of a Cabal file as produced by 'read-cabal'." (list 'quasiquote inputs)))))) (define (maybe-arguments) - (if (not include-test-dependencies?) - '((arguments `(#:tests? #f))) - '())) + (match (append (if (not include-test-dependencies?) + '(#:tests? #f) + '()) + (if (not (string-null? revision)) + `(#:cabal-revision (,revision ,cabal-hash)) + '())) + (() '()) + (args `((arguments (,'quasiquote ,args)))))) (let ((tarball (with-store store (download-to-store store source-url)))) @@ -294,10 +319,11 @@ 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 <> + (let-values (((cabal-meta cabal-hash) + (if port + (read-cabal-and-hash port) + (hackage-fetch-and-hash package-name)))) + (and=> cabal-meta (compose (cut hackage-module->sexp <> cabal-hash #:include-test-dependencies? include-test-dependencies?) (cut eval-cabal <> cabal-environment))))) diff --git a/tests/hackage.scm b/tests/hackage.scm index 38a5825af7..14176b2cf9 100644 --- a/tests/hackage.scm +++ b/tests/hackage.scm @@ -274,6 +274,51 @@ executable cabal (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")) -- cgit v1.2.3 From 5c7f87881a52a6424fc6722376b990284a06de5a Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Mon, 17 Jun 2019 22:48:44 +0200 Subject: tests: Avoid 'delete-paths' calls for 'derivation-prerequisites-to-build'. * tests/derivations.scm ("derivation-prerequisites-to-build when outputs already present"): Insert random text in BUILDER, and remove two calls to 'delete-paths'. Use 'derivation->output-path' for INPUT-PATH instead of an old idiom. --- tests/derivations.scm | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'tests') diff --git a/tests/derivations.scm b/tests/derivations.scm index c421d094a4..93f4cdd8ee 100644 --- a/tests/derivations.scm +++ b/tests/derivations.scm @@ -816,20 +816,17 @@ (null? (derivation-prerequisites-to-build %store drv)))) (test-assert "derivation-prerequisites-to-build when outputs already present" - (let* ((builder '(begin (mkdir %output) #t)) + (let* ((builder `(begin ,(random-text) (mkdir %output) #t)) (input-drv (build-expression->derivation %store "input" builder)) - (input-path (derivation-output-path - (assoc-ref (derivation-outputs input-drv) - "out"))) + (input-path (derivation->output-path input-drv)) (drv (build-expression->derivation %store "something" builder #:inputs `(("i" ,input-drv)))) (output (derivation->output-path drv))) - ;; Make sure these things are not already built. - (when (valid-path? %store input-path) - (delete-paths %store (list input-path))) - (when (valid-path? %store output) - (delete-paths %store (list output))) + ;; Assume these things are not already built. + (when (or (valid-path? %store input-path) + (valid-path? %store output)) + (error "things already built" input-drv)) (and (equal? (map derivation-input-path (derivation-prerequisites-to-build %store drv)) -- cgit v1.2.3 From 3149c002644b927e0245d237cdda3a6aeca00e4a Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Sun, 16 Jun 2019 16:18:29 +0200 Subject: utils: canonical-newline-port: Fix handling of carriage return at buffer end. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prior to this change the added test fails for me locally at byte 1024. It might depend on some default buffer sizes. Fixes . * tests/utils.scm ("canonical-newline-port-1024"): Add test. * guix/utils.scm (canonical-newline-port): Correct comments on CR/LF. Remove CR even when they're at the end of the buffer. Signed-off-by: Ludovic Courtès --- guix/utils.scm | 6 +++--- tests/utils.scm | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/guix/utils.scm b/guix/utils.scm index 709cdf9353..f480c3291f 100644 --- a/guix/utils.scm +++ b/guix/utils.scm @@ -718,7 +718,7 @@ environment variable name like \"XDG_CONFIG_HOME\"; SUFFIX is a suffix like (define (canonical-newline-port port) "Return an input port that wraps PORT such that all newlines consist - of a single carriage return." + of a single linefeed." (define (get-position) (if (port-has-port-position? port) (port-position port) #f)) (define (set-position! position) @@ -730,11 +730,11 @@ environment variable name like \"XDG_CONFIG_HOME\"; SUFFIX is a suffix like (let loop ((count 0) (byte (get-u8 port))) (cond ((eof-object? byte) count) + ;; XXX: consume all CRs even if not followed by LF. + ((eqv? byte (char->integer #\return)) (loop count (get-u8 port))) ((= count (- n 1)) (bytevector-u8-set! bv (+ start count) byte) n) - ;; XXX: consume all LFs even if not followed by CR. - ((eqv? byte (char->integer #\return)) (loop count (get-u8 port))) (else (bytevector-u8-set! bv (+ start count) byte) (loop (+ count 1) (get-u8 port)))))) diff --git a/tests/utils.scm b/tests/utils.scm index 44861384ab..f78ec356bd 100644 --- a/tests/utils.scm +++ b/tests/utils.scm @@ -230,6 +230,12 @@ skip these tests." "This is a journey\r\nInto the sound\r\nA journey ...\n"))) (get-string-all (canonical-newline-port port)))) +(test-equal "canonical-newline-port-1024" + (string-concatenate (make-list 100 "0123456789abcde\n")) + (let ((port (open-string-input-port + (string-concatenate + (make-list 100 "0123456789abcde\r\n"))))) + (get-string-all (canonical-newline-port port)))) (test-equal "edit-expression" "(display \"GNU Guix\")\n(newline)\n" -- cgit v1.2.3 From b46a9b9a5e833989396565c9d924cc97ce080703 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Sun, 16 Jun 2019 16:55:36 +0200 Subject: import: hackage: Add two expected failing test cases. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds failing test cases for two hackage import bugs: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=25138 https://debbugs.gnu.org/cgi/bugreport.cgi?bug=35743 * tests/hackage.scm: Make comment style consistent. Add two cabal parsing tests, marked as expected failures. Signed-off-by: Ludovic Courtès --- tests/hackage.scm | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/hackage.scm b/tests/hackage.scm index 14176b2cf9..77e333cbfc 100644 --- a/tests/hackage.scm +++ b/tests/hackage.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2015 Federico Beffa +;;; Copyright © 2019 Robert Vollmert ;;; ;;; This file is part of GNU Guix. ;;; @@ -236,7 +237,7 @@ library (test-assert "hackage->guix-package test 6" (eval-test-with-cabal test-cabal-6 match-ghc-foo-6)) -;; Check multi-line layouted description +;; Check multi-line layouted description. (define test-cabal-multiline-layout "name: foo version: 1.0.0 @@ -254,7 +255,7 @@ executable cabal (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 +;; Check multi-line braced description. (define test-cabal-multiline-braced "name: foo version: 1.0.0 @@ -274,6 +275,53 @@ executable cabal (test-assert "hackage->guix-package test multiline desc (braced)" (eval-test-with-cabal test-cabal-multiline-braced match-ghc-foo)) +;; Check mixed layout. Compare e.g. warp. +(define test-cabal-mixed-layout + "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 + ghc-options: -Wall +") + +;; Fails: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=35743 +(test-expect-fail 1) +(test-assert "hackage->guix-package test mixed layout" + (eval-test-with-cabal test-cabal-mixed-layout match-ghc-foo)) + +;; Check flag executable. Compare e.g. darcs. +(define test-cabal-flag-executable + "name: foo +version: 1.0.0 +homepage: http://test.org +synopsis: synopsis +description: description +license: BSD3 +flag executable + description: Build executable + default: True +executable cabal + if !flag(executable) + buildable: False + else + buildable: True + + build-depends: + HTTP >= 4000.2.5 && < 4000.3, + mtl >= 2.0 && < 3 +") + +;; Fails: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=25138 +(test-expect-fail 1) +(test-assert "hackage->guix-package test flag executable" + (eval-test-with-cabal test-cabal-flag-executable match-ghc-foo)) + ;; Check Hackage Cabal revisions. (define test-cabal-revision "name: foo -- cgit v1.2.3