David Craven <da...@craven.ch> skribis: > * guix/import/crate.scm (crate-fetch, make-crate-sexp, > crate->guix-package, guix-package->crate-name, string->license, > crate-name->package-name): New variables. > * guix/scripts/import/crate.scm (%default-options, show-help, %options, > guix-import-crate): New variables. > * guix/scripts/import.scm (importers): Add crate to list of importers. > * tests/crate.scm (test-json, test-source-hash, > guix-package->crate-name, crate->guix-package): New variables.
Woow, great stuff! Overall this looks almost ready to me. Make sure to mention this new importer in guix.texi, under “Invoking guix import”. [...] > +(define-module (guix import crate) > + #:use-module (gnu packages rust) Is this package needed? Maybe for the definition of ‘crate-uri’? I think ‘crate-uri’ should rather go to (guix import crate) or (guix build-system rust) when that exists. > +(define (crate-fetch name) > + "Return an alist representation of the crates.io metadata for the package > NAME, > +or #f on failure." > + ;; XXX: We want to silence the download progress report, which is > especially > + ;; annoying for 'guix refresh', but we have to use a file port. > + (call-with-output-file "/dev/null" > + (lambda (null) > + (with-error-to-port null > + (lambda () > + (json-fetch (string-append "https://crates.io/api/v1/crates/" > + name))))))) I don’t really like ‘json-fetch’ because it creates a temporary file, writes progress report info, etc. (there are cases where we really need it, for instance when using mirror:// URLs, though). What about using (guix http-client): (let* ((port (http-fetch …)) (result (json->scm port))) (close-port port) (hash-table->alist result)) ? > +;; TODO: Import inputs and native-inputs > +(define (make-crate-sexp name version home-page synopsis description license) > + "Return the `package' s-expression for a rust package with the given NAME, > +VERSION, SOURCE-URL, HOME-PAGE, SYNOPSIS, DESCRIPTION, and LICENSE." > + (call-with-temporary-output-file > + (lambda (temp port) > + (and (url-fetch (crate-uri name version) temp) Likewise, I’d rather use ‘http-fetch’ and avoid the temporary file. > +(define (crate->guix-package crate-name) > + "Fetch the metadata for CRATE-NAME from crates.io, and return the > +`package' s-expression corresponding to that package, or #f on failure." > + (let ((crate (crate-fetch crate-name))) > + (let ((name (assoc-ref* crate "crate" "name")) > + (version (assoc-ref* crate "crate" "max_version")) > + (home-page (assoc-ref* crate "crate" "homepage")) > + (synopsis (assoc-ref* crate "crate" "description")) > + (description (assoc-ref* crate "crate" "description")) > + (license (string->license (assoc-ref* crate "crate" "license")))) > + (make-crate-sexp name version home-page synopsis description > license)))) Note for later: In an eventual patch, we should consider using something like ‘alist-let*’ in (gnu services herd) instead of ‘assoc-ref*’. > +(define (guix-package->crate-name package) > + "Return the crate NAME of a PACKAGE." Lowercase “name”, and s/a//. > + (string-join (cdr (string-split (package-name package) #\-)) "-")) I’d prefer: (match (string-split …) (("rust" rest ...) (string-join rest "-"))) cdr is evl! :-) > --- /dev/null > +++ b/guix/scripts/import/crate.scm > @@ -0,0 +1,94 @@ > + Extra line. :-) Could you send an updated patch? Thank you! Ludo’.