[bug#77093,rust-team,17/18] import: crate: Add ‘--lockfile’ option.
Commit Message
* guix/scripts/import/crate.scm (%options): Add ‘--lockfile’ option.
* guix/scripts/import/crate.scm (show-help): Add it.
(guix-import-crate): Use it.
* doc/guix.texi (Invoking guix import): Document it.
* tests/crate.scm (temp-file): New variable.
("crate-lockfile-import"): New test.
Change-Id: I291478e04adf9f2df0bf216425a5e8aeba0bedd9
---
doc/guix.texi | 15 ++++++
guix/scripts/import/crate.scm | 58 +++++++++++++++++++----
tests/crate.scm | 88 +++++++++++++++++++++++++++++++++++
3 files changed, 151 insertions(+), 10 deletions(-)
Comments
On Tue, Mar 18, 2025 at 03:24:30PM +0800, Hilton Chain wrote:
> * guix/scripts/import/crate.scm (%options): Add ‘--lockfile’ option.
> * guix/scripts/import/crate.scm (show-help): Add it.
> (guix-import-crate): Use it.
> * doc/guix.texi (Invoking guix import): Document it.
> * tests/crate.scm (temp-file): New variable.
> ("crate-lockfile-import"): New test.
>
> Change-Id: I291478e04adf9f2df0bf216425a5e8aeba0bedd9
> ---
> doc/guix.texi | 15 ++++++
> guix/scripts/import/crate.scm | 58 +++++++++++++++++++----
> tests/crate.scm | 88 +++++++++++++++++++++++++++++++++++
> 3 files changed, 151 insertions(+), 10 deletions(-)
>
> diff --git a/doc/guix.texi b/doc/guix.texi
> index c20e1d7f9c..029c8cf59c 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -14703,6 +14703,21 @@ Invoking guix import
> If a crate dependency is not (yet) packaged, make the corresponding
> input in @code{#:cargo-inputs} or @code{#:cargo-development-inputs} into
> a comment.
> +@item --lockfile=@var{file}
> +@itemx -f @var{file}
> +When @option{--lockfile} is specified, importer will ignore other
> +options and won't output package definitions, instead generating source
> +definition for all dependencies in @var{file}, a @file{Cargo.lock} file.
When @option{--lockfile} is specified, the importer will ignore other
options and won't output package definitions, instead generating source
definitions for all dependencies in @var{file}, a @file{Cargo.lock} file.
> +For example:
> +
> +@example
> +guix import crate --lockfile=/path/to/Cargo.lock my-package
> +@end example
> +
> +generates sources from @file{/path/to/Cargo.lock}, and a list
> +@code{my-package-cargo-inputs} referencing these sources. The generated
> +list is intended for package's base @code{inputs}, replacing
> +@code{#:cargo-inputs} and @code{#:cargo-development-inputs}.
generates sources from @file{/path/to/Cargo.lock} and a list
@code{my-package-cargo-inputs} referencing these sources. The generated
list is intended for the package's @code{inputs}, replacing
@code{#:cargo-inputs} and @code{#:cargo-development-inputs}.
> @end table
>
> @item elm
> diff --git a/guix/scripts/import/crate.scm b/guix/scripts/import/crate.scm
> index 723cbb3665..3b536e135a 100644
> --- a/guix/scripts/import/crate.scm
> +++ b/guix/scripts/import/crate.scm
> @@ -25,11 +25,13 @@
> (define-module (guix scripts import crate)
> #:use-module (guix ui)
> #:use-module (guix utils)
> + #:use-module (guix read-print)
> #:use-module (guix scripts)
> #:use-module (guix import crate)
> #:use-module (guix scripts import)
> #:use-module (srfi srfi-1)
> #:use-module (srfi srfi-11)
> + #:use-module (srfi srfi-26)
> #:use-module (srfi srfi-37)
> #:use-module (ice-9 match)
> #:use-module (ice-9 format)
> @@ -60,6 +62,9 @@ (define (show-help)
> sufficient package exists for it"))
> (newline)
> (display (G_ "
> + -f, --lockfile=FILE import dependencies from FILE, a 'Cargo.lock' file"))
> + (newline)
> + (display (G_ "
> -h, --help display this help and exit"))
> (display (G_ "
> -V, --version display version information and exit"))
> @@ -87,6 +92,9 @@ (define %options
> (option '("mark-missing") #f #f
> (lambda (opt name arg result)
> (alist-cons 'mark-missing #t result)))
> + (option '(#\f "lockfile") #f #t
> + (lambda (opt name arg result)
> + (alist-cons 'lockfile arg result)))
> %standard-import-options))
>
>
> @@ -101,6 +109,8 @@ (define (guix-import-crate . args)
> #:build-options? #f))
>
> (let* ((opts (parse-options))
> + (lockfile (assoc-ref opts 'lockfile))
> + (file-to-insert (assoc-ref opts 'file-to-insert))
> (args (filter-map (match-lambda
> (('argument . value)
> value)
> @@ -111,16 +121,44 @@ (define (guix-import-crate . args)
> (define-values (name version)
> (package-name->name+version spec))
>
> - (match (if (assoc-ref opts 'recursive)
> - (crate-recursive-import
> - name #:version version
> - #:recursive-dev-dependencies?
> - (assoc-ref opts 'recursive-dev-dependencies)
> - #:allow-yanked? (assoc-ref opts 'allow-yanked))
> - (crate->guix-package
> - name #:version version #:include-dev-deps? #t
> - #:allow-yanked? (assoc-ref opts 'allow-yanked)
> - #:mark-missing? (assoc-ref opts 'mark-missing)))
> + (match (cond
> + ((and=> lockfile
> + (lambda (file)
> + (or (file-exists? file)
> + (leave (G_ "file '~a' does not exist~%") file))))
> + (let-values (((crate-definitions input-list)
> + (cargo-lock->definitions lockfile name)))
> + (if file-to-insert
> + ;; Adjusted from ‘--insert’ option of guix-import.
> + (let ((term (second input-list)))
> + (begin
> + ;; Remove existing input list definition.
> + (and=> (find-definition-location file-to-insert term)
> + delete-expression)
> + ;; Insert input list alphabetically.
> + (or (and=> (find-definition-insertion-location
> + file-to-insert term)
> + (cut insert-expression <> input-list))
> + (let ((port (open-file file-to-insert "a")))
> + (newline port)
> + (pretty-print-with-comments port input-list)
> + (newline port)
> + (newline port)
> + (close-port port))))
> + crate-definitions)
> + `(,@crate-definitions
> + ,input-list))))
> + ((assoc-ref opts 'recursive)
> + (crate-recursive-import
> + name #:version version
> + #:recursive-dev-dependencies?
> + (assoc-ref opts 'recursive-dev-dependencies)
> + #:allow-yanked? (assoc-ref opts 'allow-yanked)))
> + (else
> + (crate->guix-package
> + name #:version version #:include-dev-deps? #t
> + #:allow-yanked? (assoc-ref opts 'allow-yanked)
> + #:mark-missing? (assoc-ref opts 'mark-missing))))
> ((or #f '())
> (leave (G_ "failed to download meta-data for package '~a'~%")
> (if version
> diff --git a/tests/crate.scm b/tests/crate.scm
> index d0dc779cd2..d46f753f9c 100644
> --- a/tests/crate.scm
> +++ b/tests/crate.scm
> @@ -34,6 +34,7 @@ (define-module (test-crate)
> #:use-module (gnu packages)
> #:use-module (ice-9 iconv)
> #:use-module (ice-9 match)
> + #:use-module (srfi srfi-11)
> #:use-module (srfi srfi-64))
>
>
> @@ -476,6 +477,9 @@ (define rust-leaf-bob-3.0.2-yanked
> (description #f)
> (license #f)))
>
> +(define temp-file
> + (string-append "t-utils-" (number->string (getpid))))
> +
>
> (test-begin "crate")
>
> @@ -1178,4 +1182,88 @@ (define rust-leaf-bob-3.0.2-yanked
> (x
> (pk 'fail (pretty-print-with-comments (current-output-port) x) #f)))))
>
> +
> +(test-assert "crate-lockfile-import"
> + (begin
> + (call-with-output-file temp-file
> + (lambda (port)
> + (display "\
> +# This file is automatically @generated by Cargo.
> +# It is not intended for manual editing.
> +version = 3
> +
> +[[package]]
> +name = \"adler2\"
> +version = \"2.0.0\"
> +source = \"registry+https://github.com/rust-lang/crates.io-index\"
> +checksum = \"512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627\"
> +
> +[[package]]
> +name = \"aho-corasick\"
> +version = \"1.1.3\"
> +source = \"registry+https://github.com/rust-lang/crates.io-index\"
> +checksum = \"8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916\"
> +dependencies = [
> + \"memchr\",
> +]
> +
> +[[package]]
> +name = \"smithay\"
> +version = \"0.4.0\"
> +source = \"git+https://github.com/Smithay/smithay.git?rev=\
> +0cd3345c59f7cb139521f267956a1a4e33248393#\
> +0cd3345c59f7cb139521f267956a1a4e33248393\"
> +dependencies = [
> + \"appendlist\",
> +]
> +
> +[[package]]
> +name = \"test\"
> +version = \"25.2.0\"\n" port)))
> + (mock
> + ((guix scripts download) guix-download
> + (lambda _
> + (format #t "~a~%~a~%"
> + "/gnu/store/in056fyrz6nvy3jpxrxglgj30g0lwniv-smithay-0cd3345"
> + "191h87bpzg0l1ihfb4hmx00b86pfb5mwwc6s8i49al0vigc14l37")))
> + (let-values
> + (((crates-definitions input-list)
> + (cargo-lock->definitions temp-file "test")))
> + (and
> + (match crates-definitions
> + (((define 'rust-adler2-2.0.0
> + (crate-source
> + "adler2" "2.0.0"
> + "09r6drylvgy8vv8k20lnbvwq8gp09h7smfn6h1rxsy15pgh629si"))
> + (define 'rust-aho-corasick-1.1.3
> + (crate-source
> + "aho-corasick" "1.1.3"
> + "05mrpkvdgp5d20y2p989f187ry9diliijgwrs254fs9s1m1x6q4f"))
> + (define 'rust-smithay-0.4.0.0cd3345
> + ($ <comment>
> + ";; TODO: Define standalone package if this is a workspace.\n"
> + #f)
> + (origin
> + (method git-fetch)
> + (uri (git-reference
> + (url "https://github.com/Smithay/smithay.git")
> + (commit "0cd3345c59f7cb139521f267956a1a4e33248393")))
> + (file-name (git-file-name "rust-smithay" "0.4.0.0cd3345"))
> + (sha256
> + (base32
> + "191h87bpzg0l1ihfb4hmx00b86pfb5mwwc6s8i49al0vigc14l37")))))
> + #t)
> + (x
> + (pk 'fail (pretty-print-with-comments (current-output-port) x) #f)))
> + (match input-list
> + ((define-public 'test-cargo-inputs
> + (list rust-adler2-2.0.0
> + rust-aho-corasick-1.1.3
> + rust-smithay-0.4.0.0cd3345))
> + #t)
> + (x
> + (pk 'fail x #f))))))))
> +
> (test-end "crate")
> +
> +(false-if-exception (delete-file temp-file))
> --
> 2.48.1
>
>
>
@@ -14703,6 +14703,21 @@ Invoking guix import
If a crate dependency is not (yet) packaged, make the corresponding
input in @code{#:cargo-inputs} or @code{#:cargo-development-inputs} into
a comment.
+@item --lockfile=@var{file}
+@itemx -f @var{file}
+When @option{--lockfile} is specified, importer will ignore other
+options and won't output package definitions, instead generating source
+definition for all dependencies in @var{file}, a @file{Cargo.lock} file.
+For example:
+
+@example
+guix import crate --lockfile=/path/to/Cargo.lock my-package
+@end example
+
+generates sources from @file{/path/to/Cargo.lock}, and a list
+@code{my-package-cargo-inputs} referencing these sources. The generated
+list is intended for package's base @code{inputs}, replacing
+@code{#:cargo-inputs} and @code{#:cargo-development-inputs}.
@end table
@item elm
@@ -25,11 +25,13 @@
(define-module (guix scripts import crate)
#:use-module (guix ui)
#:use-module (guix utils)
+ #:use-module (guix read-print)
#:use-module (guix scripts)
#:use-module (guix import crate)
#:use-module (guix scripts import)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-11)
+ #:use-module (srfi srfi-26)
#:use-module (srfi srfi-37)
#:use-module (ice-9 match)
#:use-module (ice-9 format)
@@ -60,6 +62,9 @@ (define (show-help)
sufficient package exists for it"))
(newline)
(display (G_ "
+ -f, --lockfile=FILE import dependencies from FILE, a 'Cargo.lock' file"))
+ (newline)
+ (display (G_ "
-h, --help display this help and exit"))
(display (G_ "
-V, --version display version information and exit"))
@@ -87,6 +92,9 @@ (define %options
(option '("mark-missing") #f #f
(lambda (opt name arg result)
(alist-cons 'mark-missing #t result)))
+ (option '(#\f "lockfile") #f #t
+ (lambda (opt name arg result)
+ (alist-cons 'lockfile arg result)))
%standard-import-options))
@@ -101,6 +109,8 @@ (define (guix-import-crate . args)
#:build-options? #f))
(let* ((opts (parse-options))
+ (lockfile (assoc-ref opts 'lockfile))
+ (file-to-insert (assoc-ref opts 'file-to-insert))
(args (filter-map (match-lambda
(('argument . value)
value)
@@ -111,16 +121,44 @@ (define (guix-import-crate . args)
(define-values (name version)
(package-name->name+version spec))
- (match (if (assoc-ref opts 'recursive)
- (crate-recursive-import
- name #:version version
- #:recursive-dev-dependencies?
- (assoc-ref opts 'recursive-dev-dependencies)
- #:allow-yanked? (assoc-ref opts 'allow-yanked))
- (crate->guix-package
- name #:version version #:include-dev-deps? #t
- #:allow-yanked? (assoc-ref opts 'allow-yanked)
- #:mark-missing? (assoc-ref opts 'mark-missing)))
+ (match (cond
+ ((and=> lockfile
+ (lambda (file)
+ (or (file-exists? file)
+ (leave (G_ "file '~a' does not exist~%") file))))
+ (let-values (((crate-definitions input-list)
+ (cargo-lock->definitions lockfile name)))
+ (if file-to-insert
+ ;; Adjusted from ‘--insert’ option of guix-import.
+ (let ((term (second input-list)))
+ (begin
+ ;; Remove existing input list definition.
+ (and=> (find-definition-location file-to-insert term)
+ delete-expression)
+ ;; Insert input list alphabetically.
+ (or (and=> (find-definition-insertion-location
+ file-to-insert term)
+ (cut insert-expression <> input-list))
+ (let ((port (open-file file-to-insert "a")))
+ (newline port)
+ (pretty-print-with-comments port input-list)
+ (newline port)
+ (newline port)
+ (close-port port))))
+ crate-definitions)
+ `(,@crate-definitions
+ ,input-list))))
+ ((assoc-ref opts 'recursive)
+ (crate-recursive-import
+ name #:version version
+ #:recursive-dev-dependencies?
+ (assoc-ref opts 'recursive-dev-dependencies)
+ #:allow-yanked? (assoc-ref opts 'allow-yanked)))
+ (else
+ (crate->guix-package
+ name #:version version #:include-dev-deps? #t
+ #:allow-yanked? (assoc-ref opts 'allow-yanked)
+ #:mark-missing? (assoc-ref opts 'mark-missing))))
((or #f '())
(leave (G_ "failed to download meta-data for package '~a'~%")
(if version
@@ -34,6 +34,7 @@ (define-module (test-crate)
#:use-module (gnu packages)
#:use-module (ice-9 iconv)
#:use-module (ice-9 match)
+ #:use-module (srfi srfi-11)
#:use-module (srfi srfi-64))
@@ -476,6 +477,9 @@ (define rust-leaf-bob-3.0.2-yanked
(description #f)
(license #f)))
+(define temp-file
+ (string-append "t-utils-" (number->string (getpid))))
+
(test-begin "crate")
@@ -1178,4 +1182,88 @@ (define rust-leaf-bob-3.0.2-yanked
(x
(pk 'fail (pretty-print-with-comments (current-output-port) x) #f)))))
+
+(test-assert "crate-lockfile-import"
+ (begin
+ (call-with-output-file temp-file
+ (lambda (port)
+ (display "\
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = \"adler2\"
+version = \"2.0.0\"
+source = \"registry+https://github.com/rust-lang/crates.io-index\"
+checksum = \"512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627\"
+
+[[package]]
+name = \"aho-corasick\"
+version = \"1.1.3\"
+source = \"registry+https://github.com/rust-lang/crates.io-index\"
+checksum = \"8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916\"
+dependencies = [
+ \"memchr\",
+]
+
+[[package]]
+name = \"smithay\"
+version = \"0.4.0\"
+source = \"git+https://github.com/Smithay/smithay.git?rev=\
+0cd3345c59f7cb139521f267956a1a4e33248393#\
+0cd3345c59f7cb139521f267956a1a4e33248393\"
+dependencies = [
+ \"appendlist\",
+]
+
+[[package]]
+name = \"test\"
+version = \"25.2.0\"\n" port)))
+ (mock
+ ((guix scripts download) guix-download
+ (lambda _
+ (format #t "~a~%~a~%"
+ "/gnu/store/in056fyrz6nvy3jpxrxglgj30g0lwniv-smithay-0cd3345"
+ "191h87bpzg0l1ihfb4hmx00b86pfb5mwwc6s8i49al0vigc14l37")))
+ (let-values
+ (((crates-definitions input-list)
+ (cargo-lock->definitions temp-file "test")))
+ (and
+ (match crates-definitions
+ (((define 'rust-adler2-2.0.0
+ (crate-source
+ "adler2" "2.0.0"
+ "09r6drylvgy8vv8k20lnbvwq8gp09h7smfn6h1rxsy15pgh629si"))
+ (define 'rust-aho-corasick-1.1.3
+ (crate-source
+ "aho-corasick" "1.1.3"
+ "05mrpkvdgp5d20y2p989f187ry9diliijgwrs254fs9s1m1x6q4f"))
+ (define 'rust-smithay-0.4.0.0cd3345
+ ($ <comment>
+ ";; TODO: Define standalone package if this is a workspace.\n"
+ #f)
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/Smithay/smithay.git")
+ (commit "0cd3345c59f7cb139521f267956a1a4e33248393")))
+ (file-name (git-file-name "rust-smithay" "0.4.0.0cd3345"))
+ (sha256
+ (base32
+ "191h87bpzg0l1ihfb4hmx00b86pfb5mwwc6s8i49al0vigc14l37")))))
+ #t)
+ (x
+ (pk 'fail (pretty-print-with-comments (current-output-port) x) #f)))
+ (match input-list
+ ((define-public 'test-cargo-inputs
+ (list rust-adler2-2.0.0
+ rust-aho-corasick-1.1.3
+ rust-smithay-0.4.0.0cd3345))
+ #t)
+ (x
+ (pk 'fail x #f))))))))
+
(test-end "crate")
+
+(false-if-exception (delete-file temp-file))