summaryrefslogtreecommitdiff
path: root/guix/import
diff options
context:
space:
mode:
Diffstat (limited to 'guix/import')
-rw-r--r--guix/import/cabal.scm35
-rw-r--r--guix/import/cran.scm4
-rw-r--r--guix/import/crate.scm47
-rw-r--r--guix/import/hackage.scm59
-rw-r--r--guix/import/print.scm13
-rw-r--r--guix/import/utils.scm95
6 files changed, 145 insertions, 108 deletions
diff --git a/guix/import/cabal.scm b/guix/import/cabal.scm
index 13c2f3f48c..1a87be0b00 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/guix/import/cran.scm b/guix/import/cran.scm
index 4763fccd36..3240094444 100644
--- a/guix/import/cran.scm
+++ b/guix/import/cran.scm
@@ -313,7 +313,9 @@ from the alist META, which was derived from the R package's DESCRIPTION file."
(tarball (download source-url))
(sysdepends (append
(if (needs-zlib? tarball) '("zlib") '())
- (map string-downcase (listify meta "SystemRequirements"))))
+ (filter (lambda (name)
+ (not (member name invalid-packages)))
+ (map string-downcase (listify meta "SystemRequirements")))))
(propagate (filter (lambda (name)
(not (member name (append default-r-packages
invalid-packages))))
diff --git a/guix/import/crate.scm b/guix/import/crate.scm
index e0b400d054..9a73d9fe16 100644
--- a/guix/import/crate.scm
+++ b/guix/import/crate.scm
@@ -65,29 +65,53 @@
(path (string-append "/" version "/dependencies"))
(deps-json (json-fetch-alist (string-append crate-url name path)))
(deps (assoc-ref deps-json "dependencies"))
- (input-crates (filter (crate-kind-predicate "normal") deps))
- (native-input-crates
+ (dep-crates (filter (crate-kind-predicate "normal") deps))
+ (dev-dep-crates
(filter (lambda (dep)
(not ((crate-kind-predicate "normal") dep))) deps))
- (inputs (crates->inputs input-crates))
- (native-inputs (crates->inputs native-input-crates))
+ (cargo-inputs (crates->inputs dep-crates))
+ (cargo-development-inputs (crates->inputs dev-dep-crates))
(home-page (match homepage
(() repository)
(_ homepage))))
(callback #:name name #:version version
- #:inputs inputs #:native-inputs native-inputs
+ #:cargo-inputs cargo-inputs
+ #:cargo-development-inputs cargo-development-inputs
#:home-page home-page #:synopsis synopsis
#:description description #:license license)))
-(define* (make-crate-sexp #:key name version inputs native-inputs
+(define (maybe-cargo-inputs package-names)
+ (match (package-names->package-inputs package-names)
+ (()
+ '())
+ ((package-inputs ...)
+ `((#:cargo-inputs ,package-inputs)))))
+
+(define (maybe-cargo-development-inputs package-names)
+ (match (package-names->package-inputs package-names)
+ (()
+ '())
+ ((package-inputs ...)
+ `((#:cargo-development-inputs ,package-inputs)))))
+
+(define (maybe-arguments arguments)
+ (match arguments
+ (()
+ '())
+ ((args ...)
+ `((arguments (,'quasiquote ,args))))))
+
+(define* (make-crate-sexp #:key name version cargo-inputs cargo-development-inputs
home-page synopsis description license
#:allow-other-keys)
"Return the `package' s-expression for a rust package with the given NAME,
-VERSION, INPUTS, NATIVE-INPUTS, HOME-PAGE, SYNOPSIS, DESCRIPTION, and LICENSE."
+VERSION, CARGO-INPUTS, CARGO-DEVELOPMENT-INPUTS, HOME-PAGE, SYNOPSIS, DESCRIPTION,
+and LICENSE."
(let* ((port (http-fetch (crate-uri name version)))
(guix-name (crate-name->package-name name))
- (inputs (map crate-name->package-name inputs))
- (native-inputs (map crate-name->package-name native-inputs))
+ (cargo-inputs (map crate-name->package-name cargo-inputs))
+ (cargo-development-inputs (map crate-name->package-name
+ cargo-development-inputs))
(pkg `(package
(name ,guix-name)
(version ,version)
@@ -99,8 +123,9 @@ VERSION, INPUTS, NATIVE-INPUTS, HOME-PAGE, SYNOPSIS, DESCRIPTION, and LICENSE."
(base32
,(bytevector->nix-base32-string (port-sha256 port))))))
(build-system cargo-build-system)
- ,@(maybe-native-inputs native-inputs "src")
- ,@(maybe-inputs inputs "src")
+ ,@(maybe-arguments (append (maybe-cargo-inputs cargo-inputs)
+ (maybe-cargo-development-inputs
+ cargo-development-inputs)))
(home-page ,(match home-page
(() "")
(_ home-page)))
diff --git a/guix/import/hackage.scm b/guix/import/hackage.scm
index 2a51420d14..366256b40d 100644
--- a/guix/import/hackage.scm
+++ b/guix/import/hackage.scm
@@ -51,34 +51,35 @@
hackage-package?))
(define ghc-standard-libraries
- ;; List of libraries distributed with ghc (7.10.2). We include GHC itself as
- ;; some packages list it.
- '("array"
+ ;; List of libraries distributed with ghc (8.4.3).
+ ;; https://downloads.haskell.org/~ghc/8.4.3/docs/html/users_guide/8.4.3-notes.html
+ '("ghc"
+ "cabal" ;; in the output of `ghc-pkg list` Cabal is uppercased, but
+ ;; hackage-name->package-name takes this into account.
+ "win32" ;; similarly uppercased
+ "array"
"base"
- "bin-package-db"
"binary"
"bytestring"
- "cabal" ;; in the output of `ghc-pkg list` Cabal is uppercased, but
- ;; hackage-name->package-name takes this into account.
"containers"
"deepseq"
"directory"
"filepath"
- "ghc"
+ "ghc-boot"
+ "ghc-compact"
"ghc-prim"
+ "ghci"
"haskeline"
- "hoopl"
"hpc"
"integer-gmp"
- "pretty"
+ "mtl"
+ "parsec"
"process"
- "rts"
"template-haskell"
- "terminfo"
+ "text"
"time"
"transformers"
"unix"
- "win32"
"xhtml"))
(define package-name-prefix "ghc-")
@@ -145,10 +146,12 @@ version."
("LGPL" "'lgpl??")
("BSD2" 'bsd-2)
("BSD3" 'bsd-3)
+ ("BSD-3-Clause" 'bsd-3)
("MIT" 'expat)
("ISC" 'isc)
("MPL" 'mpl2.0)
("Apache-2.0" 'asl2.0)
+ ("PublicDomain" 'public-domain)
((x) (string->license x))
((lst ...) `(list ,@(map string->license lst)))
(_ #f)))
@@ -277,13 +280,11 @@ 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 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,18 +294,22 @@ 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/m ;memoized variant
+ (memoize hackage->guix-package))
(define* (hackage-recursive-import package-name . args)
(recursive-import package-name #f
#:repo->guix-package (lambda (name repo)
- (apply hackage->guix-package (cons name args)))
+ (apply hackage->guix-package/m
+ (cons name args)))
#:guix-name hackage-name->package-name))
(define (hackage-package? package)
diff --git a/guix/import/print.scm b/guix/import/print.scm
index 0bec32c8dc..4c2a91fa4f 100644
--- a/guix/import/print.scm
+++ b/guix/import/print.scm
@@ -94,12 +94,13 @@ when evaluated."
(map (match-lambda
((label pkg . out)
(let ((mod (package-module-name pkg)))
- (list label
- ;; FIXME: using '@ certainly isn't pretty, but it
- ;; avoids having to import the individual package
- ;; modules.
- (list 'unquote
- (list '@ mod (variable-name pkg mod)))))))
+ (cons* label
+ ;; FIXME: using '@ certainly isn't pretty, but it
+ ;; avoids having to import the individual package
+ ;; modules.
+ (list 'unquote
+ (list '@ mod (variable-name pkg mod)))
+ out))))
lsts)))
(let ((name (package-name package))
diff --git a/guix/import/utils.scm b/guix/import/utils.scm
index 516c0cfaa2..84503ab907 100644
--- a/guix/import/utils.scm
+++ b/guix/import/utils.scm
@@ -1,9 +1,10 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2012, 2013, 2018 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2012, 2013, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016 Jelle Licht <jlicht@fsfe.org>
;;; Copyright © 2016 David Craven <david@craven.ch>
;;; Copyright © 2017 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
+;;; Copyright © 2019 Robert Vollmert <rob@vllmrt.net>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -51,6 +52,7 @@
url-fetch
guix-hash-url
+ package-names->package-inputs
maybe-inputs
maybe-native-inputs
package->definition
@@ -235,6 +237,9 @@ into a proper sentence and by using two spaces between sentences."
cleaned 'pre ". " 'post)))
(define* (package-names->package-inputs names #:optional (output #f))
+ "Given a list of PACKAGE-NAMES, and an optional OUTPUT, tries to generate a
+quoted list of inputs, as suitable to use in an 'inputs' field of a package
+definition."
(map (lambda (input)
(cons* input (list 'unquote (string->symbol input))
(or (and output (list output))
@@ -286,7 +291,7 @@ package value."
(map (lambda (spec)
(let-values (((pkg out) (specification->package+output spec)))
(match out
- (("out") (list (package-name pkg) pkg))
+ ("out" (list (package-name pkg) pkg))
(_ (list (package-name pkg) pkg out)))))
specs))
@@ -378,57 +383,35 @@ separated by PRED."
#:allow-other-keys)
"Generate a stream of package expressions for PACKAGE-NAME and all its
dependencies."
- (receive (package . dependencies)
- (repo->guix-package package-name repo)
- (if (not package)
- stream-null
-
- ;; Generate a lazy stream of package expressions for all unknown
- ;; dependencies in the graph.
- (let* ((make-state (lambda (queue done)
- (cons queue done)))
- (next (match-lambda
- (((next . rest) . done) next)))
- (imported (match-lambda
- ((queue . done) done)))
- (done? (match-lambda
- ((queue . done)
- (zero? (length queue)))))
- (unknown? (lambda* (dependency #:optional (done '()))
- (and (not (member dependency
- done))
- (null? (find-packages-by-name
- (guix-name dependency))))))
- (update (lambda (state new-queue)
- (match state
- (((head . tail) . done)
- (make-state (lset-difference
- equal?
- (lset-union equal? new-queue tail)
- done)
- (cons head done)))))))
- (stream-cons
- package
- (stream-unfold
- ;; map: produce a stream element
- (lambda (state)
- (repo->guix-package (next state) repo))
-
- ;; predicate
- (negate done?)
-
- ;; generator: update the queue
- (lambda (state)
- (receive (package . dependencies)
- (repo->guix-package (next state) repo)
- (if package
- (update state (filter (cut unknown? <>
- (cons (next state)
- (imported state)))
- (car dependencies)))
- ;; TODO: Try the other archives before giving up
- (update state (imported state)))))
-
- ;; initial state
- (make-state (filter unknown? (car dependencies))
- (list package-name))))))))
+ (define (exists? dependency)
+ (not (null? (find-packages-by-name (guix-name dependency)))))
+ (define initial-state (list #f (list package-name) (list)))
+ (define (step state)
+ (match state
+ ((prev (next . rest) done)
+ (define (handle? dep)
+ (and
+ (not (equal? dep next))
+ (not (member dep done))
+ (not (exists? dep))))
+ (receive (package . dependencies) (repo->guix-package next repo)
+ (list
+ (if package package '()) ;; default #f on failure would interrupt
+ (if package
+ (lset-union equal? rest (filter handle? (car dependencies)))
+ rest)
+ (cons next done))))
+ ((prev '() done)
+ (list #f '() done))))
+
+ ;; Generate a lazy stream of package expressions for all unknown
+ ;; dependencies in the graph.
+ (stream-unfold
+ ;; map: produce a stream element
+ (match-lambda ((latest queue done) latest))
+ ;; predicate
+ (match-lambda ((latest queue done) latest))
+ ;; generator: update the queue
+ step
+ ;; initial state
+ (step initial-state)))