Message ID | 20220909134736.18808-2-higashi@taiju.info |
---|---|
State | Accepted |
Headers | show |
Series | Support for importing a specified version of a gem. | expand |
Context | Check | Description |
---|---|---|
cbaines/comparison | success | View comparision |
cbaines/git-branch | success | View Git branch |
cbaines/applying patch | success | View Laminar job |
cbaines/issue | success | View issue |
Hi Chris, Could you give me your opinion on this patch? Is this patch worth it? Taiju HIGASHI <higashi@taiju.info> writes: > * guix/import/gem.scm: (rubygems-fetch, gem->guix-package) > (gem-recursive-import): Fix to fetch the specified version of the gem. > * guix/scripts/import/gem.scm (show-help): Modify the help message. > (guix-import-gem): Modify the version number to be passed to subsequent > procedures > * tests/gem.scm: Add tests. > --- > guix/import/gem.scm | 19 ++++-- > guix/scripts/import/gem.scm | 39 +++++++------ > tests/gem.scm | 113 ++++++++++++++++++++++++++++++++++++ > 3 files changed, 148 insertions(+), 23 deletions(-) > > diff --git a/guix/import/gem.scm b/guix/import/gem.scm > index 0e5bb7e635..ad1343bff4 100644 > --- a/guix/import/gem.scm > +++ b/guix/import/gem.scm > @@ -5,6 +5,7 @@ > ;;; Copyright © 2020, 2021 Ludovic Courtès <ludo@gnu.org> > ;;; Copyright © 2020 Martin Becze <mjbecze@riseup.net> > ;;; Copyright © 2021 Sarah Morgensen <iskarian@mgsn.dev> > +;;; Copyright © 2022 Taiju HIGASHI <higashi@taiju.info> > ;;; > ;;; This file is part of GNU Guix. > ;;; > @@ -81,10 +82,12 @@ (define-json-mapping <gem-dependency> make-gem-dependency gem-dependency? > (requirements gem-dependency-requirements)) ;string > > > -(define (rubygems-fetch name) > - "Return a <gem> record for the package NAME, or #f on failure." > +(define* (rubygems-fetch name #:optional version) > + "Return a <gem> record for the package NAME and VERSION, or #f on failure. If VERSION is #f or missing, return the latest version gem." > (and=> (json-fetch > - (string-append "https://rubygems.org/api/v1/gems/" name ".json")) > + (if version > + (string-append "https://rubygems.org/api/v2/rubygems/" name "/versions/" version ".json") > + (string-append "https://rubygems.org/api/v1/gems/" name ".json"))) > json->gem)) > > (define (ruby-package-name name) > @@ -122,8 +125,11 @@ (define (make-gem-sexp name version hash home-page synopsis description > > (define* (gem->guix-package package-name #:key (repo 'rubygems) version) > "Fetch the metadata for PACKAGE-NAME from rubygems.org, and return the > -`package' s-expression corresponding to that package, or #f on failure." > - (let ((gem (rubygems-fetch package-name))) > +`package' s-expression corresponding to that package, or #f on failure. > +Optionally include a VERSION string to fetch a specific version gem." > + (let ((gem (if version > + (rubygems-fetch package-name version) > + (rubygems-fetch package-name)))) > (if gem > (let* ((dependencies-names (map gem-dependency-name > (gem-dependencies-runtime > @@ -189,4 +195,5 @@ (define* (gem-recursive-import package-name #:optional version) > (recursive-import package-name > #:repo '() > #:repo->guix-package gem->guix-package > - #:guix-name ruby-package-name)) > + #:guix-name ruby-package-name > + #:version version)) > diff --git a/guix/scripts/import/gem.scm b/guix/scripts/import/gem.scm > index 82deac16ad..2e646e4475 100644 > --- a/guix/scripts/import/gem.scm > +++ b/guix/scripts/import/gem.scm > @@ -4,6 +4,7 @@ > ;;; Copyright © 2021 Sarah Morgensen <iskarian@mgsn.dev> > ;;; Copyright © 2021 Brice Waegeneire <brice@waegenei.re> > ;;; Copyright © 2021 Simon Tournier <zimon.toutoune@gmail.com> > +;;; Copyright © 2022 Taiju HIGASHI <higashi@taiju.info> > ;;; > ;;; This file is part of GNU Guix. > ;;; > @@ -31,6 +32,7 @@ (define-module (guix scripts import gem) > #:use-module (srfi srfi-37) > #:use-module (ice-9 match) > #:use-module (ice-9 format) > + #:use-module (ice-9 receive) > #:export (guix-import-gem)) > > > @@ -42,8 +44,9 @@ (define %default-options > '()) > > (define (show-help) > - (display (G_ "Usage: guix import gem PACKAGE-NAME > -Import and convert the RubyGems package for PACKAGE-NAME.\n")) > + (display (G_ "Usage: guix import gem PACKAGE-NAME[@VERSION] > +Import and convert the RubyGems package for PACKAGE-NAME. Optionally, a > +version can be specified after the arobas (@) character.\n")) > (display (G_ " > -h, --help display this help and exit")) > (display (G_ " > @@ -86,21 +89,23 @@ (define (parse-options) > (_ #f)) > (reverse opts)))) > (match args > - ((package-name) > - (let ((code (if (assoc-ref opts 'recursive) > - (map (match-lambda > - ((and ('package ('name name) . rest) pkg) > - `(define-public ,(string->symbol name) > - ,pkg)) > - (_ #f)) > - (gem-recursive-import package-name 'rubygems)) > - (let ((sexp (gem->guix-package package-name))) > - (if sexp sexp #f))))) > - (match code > - ((or #f '(#f)) > - (leave (G_ "failed to download meta-data for package '~a'~%") > - package-name)) > - (_ code)))) > + ((spec) > + (receive (package-name package-version) > + (package-name->name+version spec) > + (let ((code (if (assoc-ref opts 'recursive) > + (map (match-lambda > + ((and ('package ('name name) . rest) pkg) > + `(define-public ,(string->symbol name) > + ,pkg)) > + (_ #f)) > + (gem-recursive-import package-name package-version)) > + (let ((sexp (gem->guix-package package-name #:version package-version))) > + (if sexp sexp #f))))) > + (match code > + ((or #f '(#f)) > + (leave (G_ "failed to download meta-data for package '~a'~%") > + package-name)) > + (_ code))))) > (() > (leave (G_ "too few arguments~%"))) > ((many ...) > diff --git a/tests/gem.scm b/tests/gem.scm > index c8fe15398e..6aa0d279dc 100644 > --- a/tests/gem.scm > +++ b/tests/gem.scm > @@ -3,6 +3,7 @@ > ;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net> > ;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com> > ;;; Copyright © 2021 Sarah Morgensen <iskarian@mgsn.dev> > +;;; Copyright © 2022 Taiju HIGASHI <higashi@taiju.info> > ;;; > ;;; This file is part of GNU Guix. > ;;; > @@ -44,6 +45,22 @@ (define test-foo-json > \"licenses\": [\"MIT\", \"Apache 2.0\"] > }") > > +(define test-foo-v2-json > + "{ > + \"name\": \"foo\", > + \"version\": \"2.0.0\", > + \"sha\": \"f3676eafca9987cb5fe263df1edf2538bf6dafc712b30e17be3543a9680547a8\", > + \"info\": \"A cool gem\", > + \"homepage_uri\": \"https://example.com\", > + \"dependencies\": { > + \"runtime\": [ > + { \"name\": \"bundler\" }, > + { \"name\": \"bar\" } > + ] > + }, > + \"licenses\": [\"MIT\", \"Apache 2.0\"] > +}") > + > (define test-bar-json > "{ > \"name\": \"bar\", > @@ -103,6 +120,35 @@ (define test-bundler-json > (x > (pk 'fail x #f))))) > > +(test-assert "gem->guix-package with a specific version" > + ;; Replace network resources with sample data. > + (mock ((guix http-client) http-fetch > + (lambda (url . rest) > + (match url > + ("https://rubygems.org/api/v2/rubygems/foo/versions/2.0.0.json" > + (values (open-input-string test-foo-v2-json) > + (string-length test-foo-v2-json))) > + (_ (error "Unexpected URL: " url))))) > + (match (gem->guix-package "foo" #:version "2.0.0") > + (('package > + ('name "ruby-foo") > + ('version "2.0.0") > + ('source ('origin > + ('method 'url-fetch) > + ('uri ('rubygems-uri "foo" 'version)) > + ('sha256 > + ('base32 > + "1a270mlajhrmpqbhxcqjqypnvgrq4pgixpv3w9gwp1wrrapnwrzk")))) > + ('build-system 'ruby-build-system) > + ('propagated-inputs ('list 'bundler 'ruby-bar)) > + ('synopsis "A cool gem") > + ('description "This package provides a cool gem") > + ('home-page "https://example.com") > + ('license ('list 'license:expat 'license:asl2.0))) > + #t) > + (x > + (pk 'fail x #f))))) > + > (test-assert "gem-recursive-import" > ;; Replace network resources with sample data. > (mock ((guix http-client) http-fetch > @@ -170,4 +216,71 @@ (define test-bundler-json > (x > (pk 'fail x #f))))) > > +(test-assert "gem-recursive-import with a specific version" > + ;; Replace network resources with sample data. > + (mock ((guix http-client) http-fetch > + (lambda (url . rest) > + (match url > + ("https://rubygems.org/api/v2/rubygems/foo/versions/2.0.0.json" > + (values (open-input-string test-foo-v2-json) > + (string-length test-foo-v2-json))) > + ("https://rubygems.org/api/v1/gems/bar.json" > + (values (open-input-string test-bar-json) > + (string-length test-bar-json))) > + ("https://rubygems.org/api/v1/gems/bundler.json" > + (values (open-input-string test-bundler-json) > + (string-length test-bundler-json))) > + (_ (error "Unexpected URL: " url))))) > + (match (gem-recursive-import "foo" "2.0.0") > + ((('package > + ('name "ruby-bar") > + ('version "1.0.0") > + ('source > + ('origin > + ('method 'url-fetch) > + ('uri ('rubygems-uri "bar" 'version)) > + ('sha256 > + ('base32 > + "1a270mlajhrmpqbhxcqjqypnvgrq4pgixpv3w9gwp1wrrapnwrzk")))) > + ('build-system 'ruby-build-system) > + ('propagated-inputs ('list 'bundler)) > + ('synopsis "Another cool gem") > + ('description "Another cool gem") > + ('home-page "https://example.com") > + ('license #f)) ;no licensing info > + ('package > + ('name "ruby-bundler") > + ('version "1.14.2") > + ('source > + ('origin > + ('method 'url-fetch) > + ('uri ('rubygems-uri "bundler" 'version)) > + ('sha256 > + ('base32 > + "1446xiz7zg0bz7kgx9jv84y0s4hpsg61dj5l3qb0i00avc1kxd9v")))) > + ('build-system 'ruby-build-system) > + ('synopsis "Ruby gem bundler") > + ('description "Ruby gem bundler") > + ('home-page "https://bundler.io/") > + ('license 'license:expat)) > + ('package > + ('name "ruby-foo") > + ('version "2.0.0") > + ('source > + ('origin > + ('method 'url-fetch) > + ('uri ('rubygems-uri "foo" 'version)) > + ('sha256 > + ('base32 > + "1a270mlajhrmpqbhxcqjqypnvgrq4pgixpv3w9gwp1wrrapnwrzk")))) > + ('build-system 'ruby-build-system) > + ('propagated-inputs ('list 'bundler 'ruby-bar)) > + ('synopsis "A cool gem") > + ('description "This package provides a cool gem") > + ('home-page "https://example.com") > + ('license ('list 'license:expat 'license:asl2.0)))) > + #t) > + (x > + (pk 'fail x #f))))) > + > (test-end "gem") Cheers,
Taiju HIGASHI <higashi@taiju.info> writes: > Hi Chris, > > Could you give me your opinion on this patch? > Is this patch worth it? Hey, Unfortunately I haven't had much time to look at Ruby stuff recently, but these changes look good to me. I tweaked a few minor things and pushed this as c967d1153cae419e4acbe0dbed8f558d95ced0e3. Thanks, Chris > Taiju HIGASHI <higashi@taiju.info> writes: > >> * guix/import/gem.scm: (rubygems-fetch, gem->guix-package) >> (gem-recursive-import): Fix to fetch the specified version of the gem. >> * guix/scripts/import/gem.scm (show-help): Modify the help message. >> (guix-import-gem): Modify the version number to be passed to subsequent >> procedures >> * tests/gem.scm: Add tests. >> --- >> guix/import/gem.scm | 19 ++++-- >> guix/scripts/import/gem.scm | 39 +++++++------ >> tests/gem.scm | 113 ++++++++++++++++++++++++++++++++++++ >> 3 files changed, 148 insertions(+), 23 deletions(-)
Hi Chris, Thank you for merging! Sorry to interrupt your busy schedule at the event. I'm watching the live streaming and enjoying the event too! Happy Birthday,
diff --git a/guix/import/gem.scm b/guix/import/gem.scm index 0e5bb7e635..ad1343bff4 100644 --- a/guix/import/gem.scm +++ b/guix/import/gem.scm @@ -5,6 +5,7 @@ ;;; Copyright © 2020, 2021 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2020 Martin Becze <mjbecze@riseup.net> ;;; Copyright © 2021 Sarah Morgensen <iskarian@mgsn.dev> +;;; Copyright © 2022 Taiju HIGASHI <higashi@taiju.info> ;;; ;;; This file is part of GNU Guix. ;;; @@ -81,10 +82,12 @@ (define-json-mapping <gem-dependency> make-gem-dependency gem-dependency? (requirements gem-dependency-requirements)) ;string -(define (rubygems-fetch name) - "Return a <gem> record for the package NAME, or #f on failure." +(define* (rubygems-fetch name #:optional version) + "Return a <gem> record for the package NAME and VERSION, or #f on failure. If VERSION is #f or missing, return the latest version gem." (and=> (json-fetch - (string-append "https://rubygems.org/api/v1/gems/" name ".json")) + (if version + (string-append "https://rubygems.org/api/v2/rubygems/" name "/versions/" version ".json") + (string-append "https://rubygems.org/api/v1/gems/" name ".json"))) json->gem)) (define (ruby-package-name name) @@ -122,8 +125,11 @@ (define (make-gem-sexp name version hash home-page synopsis description (define* (gem->guix-package package-name #:key (repo 'rubygems) version) "Fetch the metadata for PACKAGE-NAME from rubygems.org, and return the -`package' s-expression corresponding to that package, or #f on failure." - (let ((gem (rubygems-fetch package-name))) +`package' s-expression corresponding to that package, or #f on failure. +Optionally include a VERSION string to fetch a specific version gem." + (let ((gem (if version + (rubygems-fetch package-name version) + (rubygems-fetch package-name)))) (if gem (let* ((dependencies-names (map gem-dependency-name (gem-dependencies-runtime @@ -189,4 +195,5 @@ (define* (gem-recursive-import package-name #:optional version) (recursive-import package-name #:repo '() #:repo->guix-package gem->guix-package - #:guix-name ruby-package-name)) + #:guix-name ruby-package-name + #:version version)) diff --git a/guix/scripts/import/gem.scm b/guix/scripts/import/gem.scm index 82deac16ad..2e646e4475 100644 --- a/guix/scripts/import/gem.scm +++ b/guix/scripts/import/gem.scm @@ -4,6 +4,7 @@ ;;; Copyright © 2021 Sarah Morgensen <iskarian@mgsn.dev> ;;; Copyright © 2021 Brice Waegeneire <brice@waegenei.re> ;;; Copyright © 2021 Simon Tournier <zimon.toutoune@gmail.com> +;;; Copyright © 2022 Taiju HIGASHI <higashi@taiju.info> ;;; ;;; This file is part of GNU Guix. ;;; @@ -31,6 +32,7 @@ (define-module (guix scripts import gem) #:use-module (srfi srfi-37) #:use-module (ice-9 match) #:use-module (ice-9 format) + #:use-module (ice-9 receive) #:export (guix-import-gem)) @@ -42,8 +44,9 @@ (define %default-options '()) (define (show-help) - (display (G_ "Usage: guix import gem PACKAGE-NAME -Import and convert the RubyGems package for PACKAGE-NAME.\n")) + (display (G_ "Usage: guix import gem PACKAGE-NAME[@VERSION] +Import and convert the RubyGems package for PACKAGE-NAME. Optionally, a +version can be specified after the arobas (@) character.\n")) (display (G_ " -h, --help display this help and exit")) (display (G_ " @@ -86,21 +89,23 @@ (define (parse-options) (_ #f)) (reverse opts)))) (match args - ((package-name) - (let ((code (if (assoc-ref opts 'recursive) - (map (match-lambda - ((and ('package ('name name) . rest) pkg) - `(define-public ,(string->symbol name) - ,pkg)) - (_ #f)) - (gem-recursive-import package-name 'rubygems)) - (let ((sexp (gem->guix-package package-name))) - (if sexp sexp #f))))) - (match code - ((or #f '(#f)) - (leave (G_ "failed to download meta-data for package '~a'~%") - package-name)) - (_ code)))) + ((spec) + (receive (package-name package-version) + (package-name->name+version spec) + (let ((code (if (assoc-ref opts 'recursive) + (map (match-lambda + ((and ('package ('name name) . rest) pkg) + `(define-public ,(string->symbol name) + ,pkg)) + (_ #f)) + (gem-recursive-import package-name package-version)) + (let ((sexp (gem->guix-package package-name #:version package-version))) + (if sexp sexp #f))))) + (match code + ((or #f '(#f)) + (leave (G_ "failed to download meta-data for package '~a'~%") + package-name)) + (_ code))))) (() (leave (G_ "too few arguments~%"))) ((many ...) diff --git a/tests/gem.scm b/tests/gem.scm index c8fe15398e..6aa0d279dc 100644 --- a/tests/gem.scm +++ b/tests/gem.scm @@ -3,6 +3,7 @@ ;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net> ;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com> ;;; Copyright © 2021 Sarah Morgensen <iskarian@mgsn.dev> +;;; Copyright © 2022 Taiju HIGASHI <higashi@taiju.info> ;;; ;;; This file is part of GNU Guix. ;;; @@ -44,6 +45,22 @@ (define test-foo-json \"licenses\": [\"MIT\", \"Apache 2.0\"] }") +(define test-foo-v2-json + "{ + \"name\": \"foo\", + \"version\": \"2.0.0\", + \"sha\": \"f3676eafca9987cb5fe263df1edf2538bf6dafc712b30e17be3543a9680547a8\", + \"info\": \"A cool gem\", + \"homepage_uri\": \"https://example.com\", + \"dependencies\": { + \"runtime\": [ + { \"name\": \"bundler\" }, + { \"name\": \"bar\" } + ] + }, + \"licenses\": [\"MIT\", \"Apache 2.0\"] +}") + (define test-bar-json "{ \"name\": \"bar\", @@ -103,6 +120,35 @@ (define test-bundler-json (x (pk 'fail x #f))))) +(test-assert "gem->guix-package with a specific version" + ;; Replace network resources with sample data. + (mock ((guix http-client) http-fetch + (lambda (url . rest) + (match url + ("https://rubygems.org/api/v2/rubygems/foo/versions/2.0.0.json" + (values (open-input-string test-foo-v2-json) + (string-length test-foo-v2-json))) + (_ (error "Unexpected URL: " url))))) + (match (gem->guix-package "foo" #:version "2.0.0") + (('package + ('name "ruby-foo") + ('version "2.0.0") + ('source ('origin + ('method 'url-fetch) + ('uri ('rubygems-uri "foo" 'version)) + ('sha256 + ('base32 + "1a270mlajhrmpqbhxcqjqypnvgrq4pgixpv3w9gwp1wrrapnwrzk")))) + ('build-system 'ruby-build-system) + ('propagated-inputs ('list 'bundler 'ruby-bar)) + ('synopsis "A cool gem") + ('description "This package provides a cool gem") + ('home-page "https://example.com") + ('license ('list 'license:expat 'license:asl2.0))) + #t) + (x + (pk 'fail x #f))))) + (test-assert "gem-recursive-import" ;; Replace network resources with sample data. (mock ((guix http-client) http-fetch @@ -170,4 +216,71 @@ (define test-bundler-json (x (pk 'fail x #f))))) +(test-assert "gem-recursive-import with a specific version" + ;; Replace network resources with sample data. + (mock ((guix http-client) http-fetch + (lambda (url . rest) + (match url + ("https://rubygems.org/api/v2/rubygems/foo/versions/2.0.0.json" + (values (open-input-string test-foo-v2-json) + (string-length test-foo-v2-json))) + ("https://rubygems.org/api/v1/gems/bar.json" + (values (open-input-string test-bar-json) + (string-length test-bar-json))) + ("https://rubygems.org/api/v1/gems/bundler.json" + (values (open-input-string test-bundler-json) + (string-length test-bundler-json))) + (_ (error "Unexpected URL: " url))))) + (match (gem-recursive-import "foo" "2.0.0") + ((('package + ('name "ruby-bar") + ('version "1.0.0") + ('source + ('origin + ('method 'url-fetch) + ('uri ('rubygems-uri "bar" 'version)) + ('sha256 + ('base32 + "1a270mlajhrmpqbhxcqjqypnvgrq4pgixpv3w9gwp1wrrapnwrzk")))) + ('build-system 'ruby-build-system) + ('propagated-inputs ('list 'bundler)) + ('synopsis "Another cool gem") + ('description "Another cool gem") + ('home-page "https://example.com") + ('license #f)) ;no licensing info + ('package + ('name "ruby-bundler") + ('version "1.14.2") + ('source + ('origin + ('method 'url-fetch) + ('uri ('rubygems-uri "bundler" 'version)) + ('sha256 + ('base32 + "1446xiz7zg0bz7kgx9jv84y0s4hpsg61dj5l3qb0i00avc1kxd9v")))) + ('build-system 'ruby-build-system) + ('synopsis "Ruby gem bundler") + ('description "Ruby gem bundler") + ('home-page "https://bundler.io/") + ('license 'license:expat)) + ('package + ('name "ruby-foo") + ('version "2.0.0") + ('source + ('origin + ('method 'url-fetch) + ('uri ('rubygems-uri "foo" 'version)) + ('sha256 + ('base32 + "1a270mlajhrmpqbhxcqjqypnvgrq4pgixpv3w9gwp1wrrapnwrzk")))) + ('build-system 'ruby-build-system) + ('propagated-inputs ('list 'bundler 'ruby-bar)) + ('synopsis "A cool gem") + ('description "This package provides a cool gem") + ('home-page "https://example.com") + ('license ('list 'license:expat 'license:asl2.0)))) + #t) + (x + (pk 'fail x #f))))) + (test-end "gem")