commit 530efb82f6712d7b55c168b8a7382da4cf06f4ab
parent 75f9d76322dcf9c6ccb9b963235336fe811ec9c0
Author: Zack Newman <zack@philomathiclife.com>
Date: Fri, 17 Oct 2025 09:27:28 -0600
pass package name to commands. use test instead of t for backcompat. add ignore-msrv opt.
Diffstat:
| M | README.md | | | 195 | +++++++++++++++++++++++++++++++++++++++++-------------------------------------- |
| M | src/args.rs | | | 494 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------- |
| M | src/cargo.rs | | | 134 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- |
| M | src/main.rs | | | 19 | +++++++++++-------- |
| M | src/manifest.rs | | | 497 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- |
5 files changed, 925 insertions(+), 414 deletions(-)
diff --git a/README.md b/README.md
@@ -4,8 +4,8 @@ CI app for Rust code
[<img alt="git" src="https://git.philomathiclife.com/badges/ci-cargo.svg" height="20">](https://git.philomathiclife.com/ci-cargo/log.html)
[<img alt="crates.io" src="https://img.shields.io/crates/v/ci-cargo.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/ci-cargo)
-`ci-cargo` is a CLI application that runs [`cargo`](https://doc.rust-lang.org/cargo/index.html) with
-`clippy`, `t --tests`, and `t --doc` for all possible combinations of features defined in `Cargo.toml`.
+`ci-cargo` is a CLI application that runs [`cargo`](https://doc.rust-lang.org/cargo/index.html) with `check`,
+`clippy`, `test --tests`, and `test --doc` for all possible combinations of features defined in `Cargo.toml`.
The toolchain(s) used depend on platform support for [`rustup`](https://rust-lang.github.io/rustup/), the existence
of `rust-toolchain.toml`, the defined MSRV (if there is one), and if `--default-toolchain`, `--skip-msrv`, or
@@ -19,8 +19,8 @@ If the above are not met, `cargo` will be used instead. `cargo +<MSRV>` will als
conditions are met:
* `--skip-msrv` was not passed.
-* Package has an MSRV defined via `rust-version` that is semantically less than the `stable` or default toolchain
- used.
+* Package has an MSRV defined via `rust-version` that is less than the `stable` or not equivalent to the default
+ toolchain used.
* `--rustup-home` was passed or the platform supports `rustup`.
`ci-cargo` avoids superfluous combinations of features. For example if feature `foo` depends on feature `bar` and
@@ -39,16 +39,18 @@ build works on both the stable or default toolchain _and_ the stated MSRV (if on
## Commands
-* `<none>`: `cargo clippy` and `cargo t` are invoked for each combination of features.
-* `help`/`h`: Prints help message.
-* `version`/`v`: Prints version info.
-* `clippy`/`c`: `cargo clippy` is invoked for each combination of features.
-* `tests`/`t`: `cargo t --tests` is invoked for each combination of features.
-* `doc_tests`/`d`: `cargo t --doc` is invoked for each combination of features.
+* `<none>`: `cargo clippy` and `cargo test` are invoked for each combination of features.
+* `help`: Prints help message.
+* `version`: Prints version info.
+* `check`: `cargo check` is invoked for each combination of features.
+* `clippy`: `cargo clippy` is invoked for each combination of features.
+* `tests`: `cargo test --tests` is invoked for each combination of features.
+* `doc-tests`: `cargo test --doc` is invoked for each combination of features.
## Options
-* `--all-targets`: `cargo clippy --all-targets` is invoked for each combination of features.
+* `--all-targets`: `cargo clippy --all-targets` or `cargo check --all-targets` is invoked for each combination of
+ features.
* `--allow-implied-features`: Features implied by optional dependencies are allowed; by default features must be
explicitly defined or an error will occur (e.g., `foo = ["dep:bar"]`).
* `--cargo-home <PATH>`: Sets the storage directory used by `cargo`.
@@ -68,8 +70,9 @@ build works on both the stable or default toolchain _and_ the stated MSRV (if on
represents the empty set of features (i.e., `--no-default-features`). For example `--ignore-features`, will error
since no features were passed. `--ignore-features ''` will ignore the empty set of features. `--ignore-features a,`
will ignore the empty set of features and any combination of features that depend on feature `a`.
-* `--ignored`: `cargo t --tests -- --ignored` is invoked for each combination of features.
-* `--include-ignored`: `cargo t --tests -- --include-ignored` is invoked for each combination of features.
+* `--ignore-msrv`: `--ignore-rust-version` is passed to the commands for the default toolchain.
+* `--ignored`: `cargo test -- --ignored` is invoked for each combination of features.
+* `--include-ignored`: `cargo test -- --include-ignored` is invoked for each combination of features.
* `--progress`: Writes the current progress to `stdout`.
* `--rustup-home <PATH>`: Sets the storage directory used by `rustup`.
* `--skip-msrv`: `cargo +<MSRV>` is not used.
@@ -78,10 +81,12 @@ build works on both the stable or default toolchain _and_ the stated MSRV (if on
Any unique sequence of the above options are allowed to be passed after the command so long as the following
conditions are met:
-* No options are allowed for the `help`/`h` or `version`/`v` commands.
-* `--all-targets` and `--deny-warnings` are allowed iff `clippy`/`c` or no command is passed.
-* `--ignored` is allowed iff `tests`/`t` or no command is passed and `--include-ignored` is not passed.
-* `--include-ignored` is allowed iff `tests`/`t` or no command is passed and `--ignored` is not passed.
+* No options are allowed for the `help` or `version` commands.
+* `--all-targets` is allowed iff `check`, `clippy`, or no command is passed.
+* `--deny-warnings` is allowed iff `clippy` or no command is passed.
+* `--ignored` is allowed iff `tests` or no command is passed and `--include-ignored` is not passed.
+* `--include-ignored` is allowed iff `tests` or no command is passed and `--ignored` is not passed.
+* `--ignore-msrv` is allowed iff the `stable` toolchain is used.
## `ci-cargo` in action
@@ -167,78 +172,78 @@ foo = []
bar = ["fizz"]
fizz = []
[zack@laptop example]$ ci-cargo --all-targets --include-ignored --progress --summary
-Toolchain (1/2): cargo +stable. Features (1/32, 5 skipped): buzz,fizz,foo. Command (1/2): clippy. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (1/32, 5 skipped): buzz,fizz,foo. Command (2/2): t. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (2/32, 6 skipped): fizz,foo. Command (1/2): clippy. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (2/32, 6 skipped): fizz,foo. Command (2/2): t. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (3/32, 10 skipped): bar,buzz,foo. Command (1/2): clippy. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (3/32, 10 skipped): bar,buzz,foo. Command (2/2): t. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (4/32, 10 skipped): buzz,foo. Command (1/2): clippy. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (4/32, 10 skipped): buzz,foo. Command (2/2): t. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (5/32, 10 skipped): bar,foo. Command (1/2): clippy. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (5/32, 10 skipped): bar,foo. Command (2/2): t. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (6/32, 10 skipped): foo. Command (1/2): clippy. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (6/32, 10 skipped): foo. Command (2/2): t. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (7/32, 11 skipped): buzz,default,fizz. Command (1/2): clippy. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (7/32, 11 skipped): buzz,default,fizz. Command (2/2): t. Time running: 0 s.
-Toolchain (1/2): cargo +stable. Features (8/32, 12 skipped): default,fizz. Command (1/2): clippy. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (8/32, 12 skipped): default,fizz. Command (2/2): t. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (9/32, 13 skipped): buzz,fizz. Command (1/2): clippy. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (9/32, 13 skipped): buzz,fizz. Command (2/2): t. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (10/32, 14 skipped): fizz. Command (1/2): clippy. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (10/32, 14 skipped): fizz. Command (2/2): t. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (11/32, 14 skipped): bar,buzz,default. Command (1/2): clippy. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (11/32, 14 skipped): bar,buzz,default. Command (2/2): t. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (12/32, 14 skipped): buzz,default. Command (1/2): clippy. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (12/32, 14 skipped): buzz,default. Command (2/2): t. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (13/32, 14 skipped): bar,default. Command (1/2): clippy. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (13/32, 14 skipped): bar,default. Command (2/2): t. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (14/32, 14 skipped): default. Command (1/2): clippy. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (14/32, 14 skipped): default. Command (2/2): t. Time running: 1 s.
-Toolchain (1/2): cargo +stable. Features (15/32, 14 skipped): bar,buzz. Command (1/2): clippy. Time running: 2 s.
-Toolchain (1/2): cargo +stable. Features (15/32, 14 skipped): bar,buzz. Command (2/2): t. Time running: 2 s.
-Toolchain (1/2): cargo +stable. Features (16/32, 14 skipped): buzz. Command (1/2): clippy. Time running: 2 s.
-Toolchain (1/2): cargo +stable. Features (16/32, 14 skipped): buzz. Command (2/2): t. Time running: 2 s.
-Toolchain (1/2): cargo +stable. Features (17/32, 14 skipped): bar. Command (1/2): clippy. Time running: 2 s.
-Toolchain (1/2): cargo +stable. Features (17/32, 14 skipped): bar. Command (2/2): t. Time running: 2 s.
-Toolchain (1/2): cargo +stable. Features (18/32, 14 skipped): <none>. Command (1/2): clippy. Time running: 2 s.
-Toolchain (1/2): cargo +stable. Features (18/32, 14 skipped): <none>. Command (2/2): t. Time running: 2 s.
-Toolchain (2/2): cargo +1.89.0. Features (1/32, 5 skipped): buzz,fizz,foo. Command (1/2): clippy. Time running: 2 s.
-Toolchain (2/2): cargo +1.89.0. Features (1/32, 5 skipped): buzz,fizz,foo. Command (2/2): t. Time running: 2 s.
-Toolchain (2/2): cargo +1.89.0. Features (2/32, 6 skipped): fizz,foo. Command (1/2): clippy. Time running: 2 s.
-Toolchain (2/2): cargo +1.89.0. Features (2/32, 6 skipped): fizz,foo. Command (2/2): t. Time running: 2 s.
-Toolchain (2/2): cargo +1.89.0. Features (3/32, 10 skipped): bar,buzz,foo. Command (1/2): clippy. Time running: 2 s.
-Toolchain (2/2): cargo +1.89.0. Features (3/32, 10 skipped): bar,buzz,foo. Command (2/2): t. Time running: 2 s.
-Toolchain (2/2): cargo +1.89.0. Features (4/32, 10 skipped): buzz,foo. Command (1/2): clippy. Time running: 3 s.
-Toolchain (2/2): cargo +1.89.0. Features (4/32, 10 skipped): buzz,foo. Command (2/2): t. Time running: 3 s.
-Toolchain (2/2): cargo +1.89.0. Features (5/32, 10 skipped): bar,foo. Command (1/2): clippy. Time running: 3 s.
-Toolchain (2/2): cargo +1.89.0. Features (5/32, 10 skipped): bar,foo. Command (2/2): t. Time running: 3 s.
-Toolchain (2/2): cargo +1.89.0. Features (6/32, 10 skipped): foo. Command (1/2): clippy. Time running: 3 s.
-Toolchain (2/2): cargo +1.89.0. Features (6/32, 10 skipped): foo. Command (2/2): t. Time running: 3 s.
-Toolchain (2/2): cargo +1.89.0. Features (7/32, 11 skipped): buzz,default,fizz. Command (1/2): clippy. Time running: 3 s.
-Toolchain (2/2): cargo +1.89.0. Features (7/32, 11 skipped): buzz,default,fizz. Command (2/2): t. Time running: 3 s.
-Toolchain (2/2): cargo +1.89.0. Features (8/32, 12 skipped): default,fizz. Command (1/2): clippy. Time running: 3 s.
-Toolchain (2/2): cargo +1.89.0. Features (8/32, 12 skipped): default,fizz. Command (2/2): t. Time running: 3 s.
-Toolchain (2/2): cargo +1.89.0. Features (9/32, 13 skipped): buzz,fizz. Command (1/2): clippy. Time running: 3 s.
-Toolchain (2/2): cargo +1.89.0. Features (9/32, 13 skipped): buzz,fizz. Command (2/2): t. Time running: 3 s.
-Toolchain (2/2): cargo +1.89.0. Features (10/32, 14 skipped): fizz. Command (1/2): clippy. Time running: 3 s.
-Toolchain (2/2): cargo +1.89.0. Features (10/32, 14 skipped): fizz. Command (2/2): t. Time running: 4 s.
-Toolchain (2/2): cargo +1.89.0. Features (11/32, 14 skipped): bar,buzz,default. Command (1/2): clippy. Time running: 4 s.
-Toolchain (2/2): cargo +1.89.0. Features (11/32, 14 skipped): bar,buzz,default. Command (2/2): t. Time running: 4 s.
-Toolchain (2/2): cargo +1.89.0. Features (12/32, 14 skipped): buzz,default. Command (1/2): clippy. Time running: 4 s.
-Toolchain (2/2): cargo +1.89.0. Features (12/32, 14 skipped): buzz,default. Command (2/2): t. Time running: 4 s.
-Toolchain (2/2): cargo +1.89.0. Features (13/32, 14 skipped): bar,default. Command (1/2): clippy. Time running: 4 s.
-Toolchain (2/2): cargo +1.89.0. Features (13/32, 14 skipped): bar,default. Command (2/2): t. Time running: 4 s.
-Toolchain (2/2): cargo +1.89.0. Features (14/32, 14 skipped): default. Command (1/2): clippy. Time running: 4 s.
-Toolchain (2/2): cargo +1.89.0. Features (14/32, 14 skipped): default. Command (2/2): t. Time running: 4 s.
-Toolchain (2/2): cargo +1.89.0. Features (15/32, 14 skipped): bar,buzz. Command (1/2): clippy. Time running: 4 s.
-Toolchain (2/2): cargo +1.89.0. Features (15/32, 14 skipped): bar,buzz. Command (2/2): t. Time running: 4 s.
-Toolchain (2/2): cargo +1.89.0. Features (16/32, 14 skipped): buzz. Command (1/2): clippy. Time running: 4 s.
-Toolchain (2/2): cargo +1.89.0. Features (16/32, 14 skipped): buzz. Command (2/2): t. Time running: 4 s.
-Toolchain (2/2): cargo +1.89.0. Features (17/32, 14 skipped): bar. Command (1/2): clippy. Time running: 5 s.
-Toolchain (2/2): cargo +1.89.0. Features (17/32, 14 skipped): bar. Command (2/2): t. Time running: 5 s.
-Toolchain (2/2): cargo +1.89.0. Features (18/32, 14 skipped): <none>. Command (1/2): clippy. Time running: 5 s.
-Toolchain (2/2): cargo +1.89.0. Features (18/32, 14 skipped): <none>. Command (2/2): t. Time running: 5 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (1/32, 5 skipped): buzz,fizz,foo. Command (1/2): clippy. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (1/32, 5 skipped): buzz,fizz,foo. Command (2/2): test. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (2/32, 6 skipped): fizz,foo. Command (1/2): clippy. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (2/32, 6 skipped): fizz,foo. Command (2/2): test. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (3/32, 10 skipped): bar,buzz,foo. Command (1/2): clippy. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (3/32, 10 skipped): bar,buzz,foo. Command (2/2): test. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (4/32, 10 skipped): buzz,foo. Command (1/2): clippy. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (4/32, 10 skipped): buzz,foo. Command (2/2): test. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (5/32, 10 skipped): bar,foo. Command (1/2): clippy. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (5/32, 10 skipped): bar,foo. Command (2/2): test. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (6/32, 10 skipped): foo. Command (1/2): clippy. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (6/32, 10 skipped): foo. Command (2/2): test. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (7/32, 11 skipped): buzz,default,fizz. Command (1/2): clippy. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (7/32, 11 skipped): buzz,default,fizz. Command (2/2): test. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (8/32, 12 skipped): default,fizz. Command (1/2): clippy. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (8/32, 12 skipped): default,fizz. Command (2/2): test. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (9/32, 13 skipped): buzz,fizz. Command (1/2): clippy. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (9/32, 13 skipped): buzz,fizz. Command (2/2): test. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (10/32, 14 skipped): fizz. Command (1/2): clippy. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (10/32, 14 skipped): fizz. Command (2/2): test. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (11/32, 14 skipped): bar,buzz,default. Command (1/2): clippy. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (11/32, 14 skipped): bar,buzz,default. Command (2/2): test. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (12/32, 14 skipped): buzz,default. Command (1/2): clippy. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (12/32, 14 skipped): buzz,default. Command (2/2): test. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (13/32, 14 skipped): bar,default. Command (1/2): clippy. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (13/32, 14 skipped): bar,default. Command (2/2): test. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (14/32, 14 skipped): default. Command (1/2): clippy. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (14/32, 14 skipped): default. Command (2/2): test. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (15/32, 14 skipped): bar,buzz. Command (1/2): clippy. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (15/32, 14 skipped): bar,buzz. Command (2/2): test. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (16/32, 14 skipped): buzz. Command (1/2): clippy. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (16/32, 14 skipped): buzz. Command (2/2): test. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (17/32, 14 skipped): bar. Command (1/2): clippy. Time running: 4 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (17/32, 14 skipped): bar. Command (2/2): test. Time running: 4 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (18/32, 14 skipped): <none>. Command (1/2): clippy. Time running: 4 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (18/32, 14 skipped): <none>. Command (2/2): test. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (1/32, 5 skipped): buzz,fizz,foo. Command (1/2): clippy. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (1/32, 5 skipped): buzz,fizz,foo. Command (2/2): test. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (2/32, 6 skipped): fizz,foo. Command (1/2): clippy. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (2/32, 6 skipped): fizz,foo. Command (2/2): test. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (3/32, 10 skipped): bar,buzz,foo. Command (1/2): clippy. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (3/32, 10 skipped): bar,buzz,foo. Command (2/2): test. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (4/32, 10 skipped): buzz,foo. Command (1/2): clippy. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (4/32, 10 skipped): buzz,foo. Command (2/2): test. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (5/32, 10 skipped): bar,foo. Command (1/2): clippy. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (5/32, 10 skipped): bar,foo. Command (2/2): test. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (6/32, 10 skipped): foo. Command (1/2): clippy. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (6/32, 10 skipped): foo. Command (2/2): test. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (7/32, 11 skipped): buzz,default,fizz. Command (1/2): clippy. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (7/32, 11 skipped): buzz,default,fizz. Command (2/2): test. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (8/32, 12 skipped): default,fizz. Command (1/2): clippy. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (8/32, 12 skipped): default,fizz. Command (2/2): test. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (9/32, 13 skipped): buzz,fizz. Command (1/2): clippy. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (9/32, 13 skipped): buzz,fizz. Command (2/2): test. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (10/32, 14 skipped): fizz. Command (1/2): clippy. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (10/32, 14 skipped): fizz. Command (2/2): test. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (11/32, 14 skipped): bar,buzz,default. Command (1/2): clippy. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (11/32, 14 skipped): bar,buzz,default. Command (2/2): test. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (12/32, 14 skipped): buzz,default. Command (1/2): clippy. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (12/32, 14 skipped): buzz,default. Command (2/2): test. Time running: 8 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (13/32, 14 skipped): bar,default. Command (1/2): clippy. Time running: 8 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (13/32, 14 skipped): bar,default. Command (2/2): test. Time running: 8 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (14/32, 14 skipped): default. Command (1/2): clippy. Time running: 8 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (14/32, 14 skipped): default. Command (2/2): test. Time running: 8 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (15/32, 14 skipped): bar,buzz. Command (1/2): clippy. Time running: 8 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (15/32, 14 skipped): bar,buzz. Command (2/2): test. Time running: 8 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (16/32, 14 skipped): buzz. Command (1/2): clippy. Time running: 9 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (16/32, 14 skipped): buzz. Command (2/2): test. Time running: 9 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (17/32, 14 skipped): bar. Command (1/2): clippy. Time running: 9 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (17/32, 14 skipped): bar. Command (2/2): test. Time running: 9 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (18/32, 14 skipped): <none>. Command (1/2): clippy. Time running: 9 s.
+Package: example. Toolchain (2/2): cargo +1.89.0. Features (18/32, 14 skipped): <none>. Command (2/2): test. Time running: 9 s.
Toolchains used: cargo +stable and cargo +1.89.0
Features used:
buzz,fizz,foo
@@ -259,16 +264,18 @@ bar,buzz
buzz
bar
<none>
-[zack@laptop example]$ ci-cargo clippy --deny-warnings --ignore-compile-errors --ignore-features buzz, --skip-msrv
-[zack@laptop ~]$ ci-cargo t --allow-implied-features --cargo-home ~/.cargo/ --cargo-path ~/.cargo/bin --default-toolchain --dir ~/example/ --ignored --rustup-home ~/.rustup/
-[zack@laptop ~]$ ci-cargo v
+[zack@laptop example]$ ci-cargo clippy --deny-warnings --ignore-compile-errors --ignore-features buzz, --ignore-msrv --skip-msrv
+[zack@laptop ~]$ ci-cargo tests --allow-implied-features --cargo-home ~/.cargo/ --cargo-path ~/.cargo/bin --default-toolchain --dir ~/example/ --ignored --rustup-home ~/.rustup/
+[zack@laptop ~]$ ci-cargo version
ci-cargo 0.1.0
-[zack@laptop example]$ ci-cargo --summary d
-d is an unknown argument. See ci-cargo help for more information.
+[zack@laptop example]$ ci-cargo --summary doc-tests
+doc-tests is an unknown argument. See ci-cargo help for more information.
```
## Limitations
+Functionality when using old versions of `cargo` may not exist (e.g., `cargo check` wasn't available until 1.16.0).
+
There is a hard limit on the number of features allowed. Specifically the number of features can't exceed the
number of bits that make up a pointer; however practical limits will almost always be a factor long before hitting
such a hard limit due to the exponential effect features have.
diff --git a/src/args.rs b/src/args.rs
@@ -1,5 +1,5 @@
use super::{
- cargo::{CargoErr, Clippy, Options, TestKind, Tests, Toolchain},
+ cargo::{CargoErr, Check, Clippy, Options, TestKind, Tests, Toolchain},
manifest::PowerSet,
};
use core::{
@@ -18,15 +18,16 @@ pub(crate) const HELP_MSG: &str = "Continuous integration of all features using
Usage: ci-cargo [COMMAND] [OPTIONS]
Commands:
- <none> cargo clippy and cargo t
- help, h This message
- version, v Prints version info
- clippy, c cargo clippy
- tests, t cargo t --tests
- doc-tests, d cargo t --doc
+ <none> cargo clippy and cargo test
+ help This message
+ version Prints version info
+ check cargo check
+ clippy cargo clippy
+ tests cargo test --tests
+ doc-tests cargo test --doc
Options:
- --all-targets --all-targets is passed to cargo clippy
+ --all-targets --all-targets is passed to cargo clippy or cargo check
--allow-implied features Allow implied features from optional dependencies
--cargo-home <PATH> Set the storage directory used by cargo
--cargo-path <PATH> Set the path cargo is in. Defaults to cargo
@@ -36,8 +37,9 @@ Options:
--dir <PATH> Set the working directory
--ignore-compile-errors compile_error!s are ignored
--ignore-features <feats> Ignore the provided comma-separated features
- --ignored --ignored is passed to cargo t --tests
- --include-ignored --include-ignored is passed to cargo t --tests
+ --ignore-msrv --ignore-rust-version is passed to each command for the default toolchain
+ --ignored -- --ignored is passed to cargo test
+ --include-ignored -- --include-ignored is passed to cargo test
--progress Writes the progress to stdout
--rustup-home <PATH> Set the storage directory used by rustup
--skip-msrv cargo +<MSRV> is not used
@@ -46,12 +48,14 @@ Options:
Any unique sequence of the above options are allowed so long as the following
conditions are met:
-* no options are allowed for the help/h or version/v commands
-* --all-targets and --deny-warnings are allowed iff clippy/c or no command is passed
-* --ignored is allowed iff tests/t or no command is passed and --include-ignored
+* no options are allowed for the help or version commands
+* --all-targets is allowed iff check, clippy, or no command is passed
+* --deny-warnings is allowed iff clippy or no command is passed
+* --ignored is allowed iff tests or no command is passed and --include-ignored
is not passed
-* --include-ignored is allowed iff tests/t or no command is passed and --ignored
+* --include-ignored is allowed iff tests or no command is passed and --ignored
is not passed
+* --ignore-msrv is not allowed if the stable toolchain is used
cargo +stable will be used to run the command(s) if all of the following condtions are met:
@@ -63,8 +67,8 @@ If the above are not met, cargo will be used instead. cargo +<MSRV> will also be
if all of the following conditions are met:
* --skip-msrv was not passed
-* Package has an MSRV defined via rust-version that is semantically less than the stable or default
- toolchain used
+* Package has an MSRV defined via rust-version that is semantically less than the stable or not
+ equivalent to the default toolchain used
* --rustup-home was passed or the platform supports rustup
For the toolchain(s) used, the command(s) are run for each combination of features sans any provided
@@ -73,24 +77,16 @@ features in the package. An empty value is interpreted as the empty set of featu
";
/// `"help"`.
const HELP: &str = "help";
-/// `"h"`.
-const H: &str = "h";
/// `"version"`.
const VERSION: &str = "version";
-/// `"v"`.
-const V: &str = "v";
+/// `"check"`.
+const CHECK: &str = "check";
/// `"clippy"`.
const CLIPPY: &str = "clippy";
-/// `"c"`.
-const C: &str = "c";
/// `"tests"`.
const TESTS: &str = "tests";
-/// `"t"`.
-const T: &str = "t";
/// `"doc-tests"`.
const DOC_TESTS: &str = "doc-tests";
-/// `"d"`.
-const D: &str = "d";
/// `"--all-targets"`.
const ALL_TARGETS: &str = "--all-targets";
/// `"--allow-implied-features"`.
@@ -111,6 +107,8 @@ const DIR: &str = "--dir";
const IGNORE_COMPILE_ERRORS: &str = "--ignore-compile-errors";
/// `"--ignore-features"`.
const IGNORE_FEATURES: &str = "--ignore-features";
+/// `"--ignore-msrv"`.
+const IGNORE_MSRV: &str = "--ignore-msrv";
/// `"--ignored"`.
const IGNORED: &str = "--ignored";
/// `"--include-ignored"`.
@@ -147,10 +145,10 @@ pub(crate) enum ArgsErr {
MissingRustupHome,
/// Error when `--all-targets` is passed for `tests` or `doc-tests`.
AllTargetsTests,
- /// Error when `--deny-warnings` is passed for `tests` or `doc-tests`.
- DenyWarningsTests,
- /// Error when `--ignored` or `--include-ignored` is passed for `clippy` or `doc-tests`.
- IgnoredClippyDoc,
+ /// Error when `--deny-warnings` is passed for `check`, `tests`, or `doc-tests`.
+ DenyWarningsCheckTests,
+ /// Error when `--ignored` or `--include-ignored` is passed for `check`, `clippy`, or `doc-tests`.
+ IgnoredCheckClippyDoc,
/// Error when `--ignored` and `--include-ignored` are passed.
IgnoredIncludeIgnored,
/// Error when `--ignore-features` was not passed any features.
@@ -226,16 +224,16 @@ impl ArgsErr {
"{ALL_TARGETS} was passed with {TESTS} or {DOC_TESTS}.{FINAL_SENTENCE}"
)
}
- Self::DenyWarningsTests => {
+ Self::DenyWarningsCheckTests => {
writeln!(
stderr,
- "{DENY_WARNINGS} was passed with {TESTS} or {DOC_TESTS}.{FINAL_SENTENCE}"
+ "{DENY_WARNINGS} was passed with {CHECK}, {TESTS}, or {DOC_TESTS}.{FINAL_SENTENCE}"
)
}
- Self::IgnoredClippyDoc => {
+ Self::IgnoredCheckClippyDoc => {
writeln!(
stderr,
- "{IGNORED} or {INCLUDE_IGNORED} was passed with {CLIPPY} or {DOC_TESTS}.{FINAL_SENTENCE}"
+ "{IGNORED} or {INCLUDE_IGNORED} was passed with {CHECK}, {CLIPPY}, or {DOC_TESTS}.{FINAL_SENTENCE}"
)
}
Self::IgnoredIncludeIgnored => {
@@ -283,6 +281,8 @@ pub(crate) struct Opts {
pub allow_implied_features: bool,
/// `true` iff `compile_error`s should be ignored.
pub ignore_compile_errors: bool,
+ /// `true` iff `--ignore-rust-version` should be passed.
+ pub ignore_msrv: bool,
/// `true` iff progress should be written to `stdout`.
pub progress: bool,
/// `true` iff the MSRV toolchain should not be used.
@@ -308,6 +308,7 @@ impl Default for Opts {
default_toolchain: false,
allow_implied_features: false,
ignore_compile_errors: false,
+ ignore_msrv: false,
progress: false,
skip_msrv: false,
summary: false,
@@ -315,7 +316,7 @@ impl Default for Opts {
}
}
}
-/// Controls if `cargo t -tests -- --ignored` or `cargo t --tests --include-ignored` should be run.
+/// Controls if `cargo test --tests -- --ignored` or `cargo test --tests --include-ignored` should be run.
#[cfg_attr(test, derive(Debug, PartialEq))]
#[derive(Clone, Copy)]
pub(crate) enum Ignored {
@@ -383,7 +384,9 @@ impl Display for NonZeroUsizePlus1 {
}
}
/// Progress tracker for when `--progress` was passed.
-struct Progress<'toolchain> {
+struct Progress<'package, 'toolchain> {
+ /// The name of the package.
+ package: &'package str,
/// The current toolchain counter.
toolchain_counter: &'static str,
/// The total toolchains that will be used.
@@ -410,29 +413,69 @@ struct Progress<'toolchain> {
/// to it.
stdout: Option<StdoutLock<'static>>,
}
-impl Progress<'_> {
+impl<'package> Progress<'package, '_> {
/// Returns `Self` based on running both clippy and tests.
- fn all(toolchain: Toolchain<'_>, use_msrv: bool, features_total: NonZeroUsizePlus1) -> Self {
- Self::inner_new("clippy", "2", toolchain, use_msrv, features_total)
+ fn all(
+ package: &'package str,
+ toolchain: Toolchain<'_>,
+ use_msrv: bool,
+ features_total: NonZeroUsizePlus1,
+ ) -> Self {
+ Self::inner_new(package, "clippy", "2", toolchain, use_msrv, features_total)
}
/// Returns `Self` based on running clippy.
- fn clippy(toolchain: Toolchain<'_>, use_msrv: bool, features_total: NonZeroUsizePlus1) -> Self {
- Self::inner_new("clippy", "1", toolchain, use_msrv, features_total)
+ fn clippy(
+ package: &'package str,
+ toolchain: Toolchain<'_>,
+ use_msrv: bool,
+ features_total: NonZeroUsizePlus1,
+ ) -> Self {
+ Self::inner_new(package, "clippy", "1", toolchain, use_msrv, features_total)
}
/// Returns `Self` based on running tests --tests.
- fn tests(toolchain: Toolchain<'_>, use_msrv: bool, features_total: NonZeroUsizePlus1) -> Self {
- Self::inner_new("t --tests", "1", toolchain, use_msrv, features_total)
+ fn tests(
+ package: &'package str,
+ toolchain: Toolchain<'_>,
+ use_msrv: bool,
+ features_total: NonZeroUsizePlus1,
+ ) -> Self {
+ Self::inner_new(
+ package,
+ "test --tests",
+ "1",
+ toolchain,
+ use_msrv,
+ features_total,
+ )
}
/// Returns `Self` based on running tests --doc.
fn doc_tests(
+ package: &'package str,
toolchain: Toolchain<'_>,
use_msrv: bool,
features_total: NonZeroUsizePlus1,
) -> Self {
- Self::inner_new("t --doc", "1", toolchain, use_msrv, features_total)
+ Self::inner_new(
+ package,
+ "test --doc",
+ "1",
+ toolchain,
+ use_msrv,
+ features_total,
+ )
+ }
+ /// Returns `Self` based on running check.
+ fn check(
+ package: &'package str,
+ toolchain: Toolchain<'_>,
+ use_msrv: bool,
+ features_total: NonZeroUsizePlus1,
+ ) -> Self {
+ Self::inner_new(package, "check", "1", toolchain, use_msrv, features_total)
}
/// Returns `Self` based on the passed arguments.
fn inner_new(
+ package: &'package str,
cmd: &'static str,
cmd_total: &'static str,
tool: Toolchain<'_>,
@@ -445,6 +488,7 @@ impl Progress<'_> {
("cargo", "")
};
Self {
+ package,
toolchain_counter: "1",
toolchain_total: if use_msrv { "2" } else { "1" },
cargo_cmd,
@@ -468,9 +512,9 @@ impl Progress<'_> {
) {
if let Some(ref mut std) = self.stdout {
// Example:
- // "Toolchain (1/2): cargo +stable. Features (18/128, 3 skipped): foo,bar. Command (1/2): clippy. Time running: 49 s.");
+ // "Package: foo. Toolchain (1/2): cargo +stable. Features (18/128, 3 skipped): foo,bar. Command (1/2): clippy. Time running: 49 s.");
// Note `features_skipped` maxes at `usize::MAX` since the empty set is never skipped.
- if writeln!(std, "Toolchain ({}/{}): {}{}. Features ({}/{}, {} skipped): {}. Command ({}/{}): {}. Time running: {} s.", self.toolchain_counter, self.toolchain_total, self.cargo_cmd, self.toolchain, NonZeroUsizePlus1(features_counter), self.features_total, features_skipped, if features.is_empty() { "<none>" } else { features }, self.cmd_counter, self.cmd_total, self.cmd, self.time_started.elapsed().as_secs()).is_err() {
+ if writeln!(std, "Package: {}. Toolchain ({}/{}): {}{}. Features ({}/{}, {} skipped): {}. Command ({}/{}): {}. Time running: {} s.", self.package, self.toolchain_counter, self.toolchain_total, self.cargo_cmd, self.toolchain, NonZeroUsizePlus1(features_counter), self.features_total, features_skipped, if features.is_empty() { "<none>" } else { features }, self.cmd_counter, self.cmd_total, self.cmd, self.time_started.elapsed().as_secs()).is_err() {
drop(self.stdout.take());
}
}
@@ -479,7 +523,7 @@ impl Progress<'_> {
/// `cargo` command(s) we should run.
#[cfg_attr(test, derive(Debug, PartialEq))]
pub(crate) enum Cmd {
- /// Execute all `cargo` commands.
+ /// Execute `cargo clippy` and `cargo test` commands.
///
/// The first `bool` is `true` iff `--all-targets` was passed,
/// the second `bool` is `true` iff `--deny-warnings` was passed, and
@@ -491,26 +535,37 @@ pub(crate) enum Cmd {
/// The first `bool` is `true` iff `--all-targets` was passed,
/// and the second `bool` is `true` iff `--deny-warnings` was passed.
Clippy(bool, bool),
- /// `cargo clippy t --tests`.
+ /// `cargo test --tests`.
Tests(Ignored),
- /// `cargo clippy t --doc`.
+ /// `cargo test --doc`.
DocTests,
+ /// `cargo check`.
+ ///
+ /// The contained `bool` is `true` iff `--all-targets` was passed,
+ Check(bool),
}
impl Cmd {
- /// Runs the appropriate `cargo` command for all features in `power_set`.
+ /// Runs the appropriate `cargo` command(s) for all features in `power_set`.
///
/// Note the [`Toolchain`] in `options` is first used; and if `msrv.is_some()`, then [`Toolchain::Msrv`] is
/// later used.
pub(crate) fn run<'a>(
self,
- options: Options<'a, '_>,
+ options: Options<'a, '_, '_>,
msrv: Option<&'a str>,
power_set: &mut PowerSet<'_>,
progress: bool,
) -> Result<(), Box<CargoErr>> {
match self {
Self::All(all_targets, deny_warning, ignored_tests) => Self::run_all(
- progress.then(|| Progress::all(options.toolchain, msrv.is_some(), power_set.len())),
+ progress.then(|| {
+ Progress::all(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ )
+ }),
msrv,
options,
all_targets,
@@ -519,8 +574,14 @@ impl Cmd {
power_set,
),
Self::Clippy(all_targets, deny_warnings) => Self::run_clippy(
- progress
- .then(|| Progress::clippy(options.toolchain, msrv.is_some(), power_set.len())),
+ progress.then(|| {
+ Progress::clippy(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ )
+ }),
msrv,
options,
all_targets,
@@ -528,8 +589,14 @@ impl Cmd {
power_set,
),
Self::Tests(ignored_tests) => Self::run_unit_tests(
- progress
- .then(|| Progress::tests(options.toolchain, msrv.is_some(), power_set.len())),
+ progress.then(|| {
+ Progress::tests(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ )
+ }),
msrv,
options,
ignored_tests,
@@ -537,23 +604,42 @@ impl Cmd {
),
Self::DocTests => Self::run_doc_tests(
progress.then(|| {
- Progress::doc_tests(options.toolchain, msrv.is_some(), power_set.len())
+ Progress::doc_tests(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ )
}),
msrv,
options,
power_set,
),
+ Self::Check(all_targets) => Self::run_check(
+ progress.then(|| {
+ Progress::check(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ )
+ }),
+ msrv,
+ options,
+ all_targets,
+ power_set,
+ ),
}
}
- /// Runs `cargo clippy` and `cargo t` for all features in `power_set`.
+ /// Runs `cargo clippy` and `cargo test` for all features in `power_set`.
///
/// Note the [`Toolchain`] in `options` is first used; and if `msrv.is_some()`, then [`Toolchain::Msrv`] is
/// later used.
#[expect(clippy::else_if_without_else, reason = "don't want an empty else")]
fn run_all<'a>(
- mut progress: Option<Progress<'a>>,
+ mut progress: Option<Progress<'_, 'a>>,
msrv: Option<&'a str>,
- mut options: Options<'a, '_>,
+ mut options: Options<'a, '_, '_>,
all_targets: bool,
deny_warnings: bool,
ignored_tests: Ignored,
@@ -570,7 +656,7 @@ impl Cmd {
}
// Note we run tests even if a `compile_error` occurred since it may not occur for tests.
prog.cmd_counter = "2";
- prog.cmd = "t";
+ prog.cmd = "test";
prog.write_to_stdout(set, feat_counter, skip_count);
if let Err(e) = Tests::run(&mut options, TestKind::All(ignored_tests), set) {
return Err(e);
@@ -596,7 +682,7 @@ impl Cmd {
}
// Note we run tests even if a `compile_error` occurred since it may not occur for tests.
prog.cmd_counter = "2";
- prog.cmd = "t";
+ prog.cmd = "test";
prog.write_to_stdout(set, feat_counter, skip_count);
if let Err(e) = Tests::run(&mut options, TestKind::All(ignored_tests), set) {
return Err(e);
@@ -638,9 +724,9 @@ impl Cmd {
/// Note the [`Toolchain`] in `options` is first used; and if `msrv.is_some()`, then [`Toolchain::Msrv`] is
/// later used.
fn run_clippy<'a>(
- mut progress: Option<Progress<'a>>,
+ mut progress: Option<Progress<'_, 'a>>,
msrv: Option<&'a str>,
- mut options: Options<'a, '_>,
+ mut options: Options<'a, '_, '_>,
all_targets: bool,
deny_warnings: bool,
power_set: &mut PowerSet<'_>,
@@ -693,14 +779,14 @@ impl Cmd {
}
Ok(())
}
- /// Runs `cargo t --tests` for all features in `power_set`.
+ /// Runs `cargo test --tests` for all features in `power_set`.
///
/// Note the [`Toolchain`] in `options` is first used; and if `msrv.is_some()`, then [`Toolchain::Msrv`] is
/// later used.
fn run_unit_tests<'a>(
- mut progress: Option<Progress<'a>>,
+ mut progress: Option<Progress<'_, 'a>>,
msrv: Option<&'a str>,
- mut options: Options<'a, '_>,
+ mut options: Options<'a, '_, '_>,
ignored_tests: Ignored,
power_set: &mut PowerSet<'_>,
) -> Result<(), Box<CargoErr>> {
@@ -752,14 +838,14 @@ impl Cmd {
}
Ok(())
}
- /// Runs `cargo t --doc` for all features in `power_set`.
+ /// Runs `cargo test --doc` for all features in `power_set`.
///
/// Note the [`Toolchain`] in `options` is first used; and if `msrv.is_some()`, then [`Toolchain::Msrv`] is
/// later used.
fn run_doc_tests<'a>(
- mut progress: Option<Progress<'a>>,
+ mut progress: Option<Progress<'_, 'a>>,
msrv: Option<&'a str>,
- mut options: Options<'a, '_>,
+ mut options: Options<'a, '_, '_>,
power_set: &mut PowerSet<'_>,
) -> Result<(), Box<CargoErr>> {
if let Some(ref mut prog) = progress {
@@ -803,8 +889,8 @@ impl Cmd {
match Tests::run(&mut options, TestKind::Doc, set) {
Ok(no_library_target) => {
if no_library_target {
- // We don't want to continue invoking `cargo t --doc` once we know this is not a library
- // target.
+ // We don't want to continue invoking `cargo test --doc` once we know this is not a
+ // library target.
return Ok(());
}
}
@@ -824,6 +910,65 @@ impl Cmd {
}
Ok(())
}
+ /// Runs `cargo check` for all features in `power_set`.
+ ///
+ /// Note the [`Toolchain`] in `options` is first used; and if `msrv.is_some()`, then [`Toolchain::Msrv`] is
+ /// later used.
+ fn run_check<'a>(
+ mut progress: Option<Progress<'_, 'a>>,
+ msrv: Option<&'a str>,
+ mut options: Options<'a, '_, '_>,
+ all_targets: bool,
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ if let Some(ref mut prog) = progress {
+ let mut feat_counter = 1;
+ while let Some((set, skip_count)) = power_set.next_set_with_skip_count() {
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ if let Err(e) = Check::run(&mut options, all_targets, set) {
+ return Err(e);
+ }
+ // The maximum number possible is `usize::MAX + 1`; however that can only happen at the very
+ // last item. Since we never display 0, we treat 0 as `usize::MAX + 1` when we display it via
+ // [`NonZeroUsizePlus1::fmt`].
+ feat_counter = feat_counter.wrapping_add(1);
+ }
+ if let Some(msrv_val) = msrv {
+ feat_counter = 1;
+ prog.toolchain_counter = "2";
+ prog.cargo_cmd = "cargo ";
+ prog.toolchain = msrv_val;
+ options.toolchain = Toolchain::Msrv(msrv_val);
+ power_set.reset();
+ while let Some((set, skip_count)) = power_set.next_set_with_skip_count() {
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ if let Err(e) = Check::run(&mut options, all_targets, set) {
+ return Err(e);
+ }
+ // The maximum number possible is `usize::MAX + 1`; however that can only happen at the very
+ // last item. Since we never display 0, we treat 0 as `usize::MAX + 1` when we display it via
+ // [`NonZeroUsizePlus1::fmt`].
+ feat_counter = feat_counter.wrapping_add(1);
+ }
+ }
+ } else {
+ while let Some(set) = power_set.next_set() {
+ if let Err(e) = Check::run(&mut options, all_targets, set) {
+ return Err(e);
+ }
+ }
+ if let Some(msrv_val) = msrv {
+ options.toolchain = Toolchain::Msrv(msrv_val);
+ power_set.reset();
+ while let Some(set) = power_set.next_set() {
+ if let Err(e) = Check::run(&mut options, all_targets, set) {
+ return Err(e);
+ }
+ }
+ }
+ }
+ Ok(())
+ }
}
/// `ci-cargo` command to run.
#[cfg_attr(test, derive(Debug, PartialEq))]
@@ -860,6 +1005,8 @@ struct ArgOpts {
dir: Option<PathBuf>,
/// `--ignore-compile-errors`.
ignore_compile_errors: bool,
+ /// `--ignore-msrv`.
+ ignore_msrv: bool,
/// `--ignore-features` along with the features to ignore.
ignore_features: Vec<String>,
/// `--ignored`.
@@ -904,6 +1051,7 @@ impl From<ArgOpts> for Opts {
default_toolchain: value.default_toolchain,
allow_implied_features: value.allow_implied_features,
ignore_compile_errors: value.ignore_compile_errors,
+ ignore_msrv: value.ignore_msrv,
progress: value.progress,
skip_msrv: value.skip_msrv,
summary: value.summary,
@@ -1046,6 +1194,12 @@ impl MetaCmd {
return Err(ArgsErr::DuplicateOption(val));
}
}
+ IGNORE_MSRV => {
+ if opts.ignore_msrv {
+ return Err(ArgsErr::DuplicateOption(val));
+ }
+ opts.ignore_msrv = true;
+ }
IGNORED => {
if opts.ignored {
return Err(ArgsErr::DuplicateOption(val));
@@ -1099,6 +1253,10 @@ impl MetaCmd {
)
}
/// Returns data we need by reading the supplied CLI arguments.
+ #[expect(
+ clippy::too_many_lines,
+ reason = "expected even if we extract options separately"
+ )]
pub(crate) fn from_args<T: Iterator<Item = OsString>>(mut args: T) -> Result<Self, ArgsErr> {
args.next().ok_or(ArgsErr::NoArgs).and_then(|_| {
args.next().map_or_else(
@@ -1111,26 +1269,26 @@ impl MetaCmd {
|arg| {
if let Some(arg_str) = arg.to_str() {
match arg_str {
- H | HELP => {
+ HELP => {
if args.next().is_none() {
Ok(Self::Help)
} else {
Err(ArgsErr::HelpWithArgs)
}
}
- V | VERSION => {
+ VERSION => {
if args.next().is_none() {
Ok(Self::Version)
} else {
Err(ArgsErr::VersionWithArgs)
}
}
- C | CLIPPY => {
+ CLIPPY => {
let mut opts = ArgOpts::default();
Self::extract_options(&mut opts, args.next(), &mut args).and_then(
|()| {
if opts.ignored || opts.include_ignored {
- Err(ArgsErr::IgnoredClippyDoc)
+ Err(ArgsErr::IgnoredCheckClippyDoc)
} else {
Ok(Self::Cargo(
Cmd::Clippy(opts.all_targets, opts.deny_warnings),
@@ -1140,14 +1298,14 @@ impl MetaCmd {
},
)
}
- T | TESTS => {
+ TESTS => {
let mut opts = ArgOpts::default();
Self::extract_options(&mut opts, args.next(), &mut args).and_then(
|()| {
if opts.all_targets {
Err(ArgsErr::AllTargetsTests)
} else if opts.deny_warnings {
- Err(ArgsErr::DenyWarningsTests)
+ Err(ArgsErr::DenyWarningsCheckTests)
} else {
let ignored = opts.ignored();
Ok(Self::Cargo(Cmd::Tests(ignored), opts.into()))
@@ -1155,22 +1313,39 @@ impl MetaCmd {
},
)
}
- D | DOC_TESTS => {
+ DOC_TESTS => {
let mut opts = ArgOpts::default();
Self::extract_options(&mut opts, args.next(), &mut args).and_then(
|()| {
if opts.all_targets {
Err(ArgsErr::AllTargetsTests)
} else if opts.deny_warnings {
- Err(ArgsErr::DenyWarningsTests)
+ Err(ArgsErr::DenyWarningsCheckTests)
} else if opts.ignored || opts.include_ignored {
- Err(ArgsErr::IgnoredClippyDoc)
+ Err(ArgsErr::IgnoredCheckClippyDoc)
} else {
Ok(Self::Cargo(Cmd::DocTests, opts.into()))
}
},
)
}
+ CHECK => {
+ let mut opts = ArgOpts::default();
+ Self::extract_options(&mut opts, args.next(), &mut args).and_then(
+ |()| {
+ if opts.deny_warnings {
+ Err(ArgsErr::DenyWarningsCheckTests)
+ } else if opts.ignored || opts.include_ignored {
+ Err(ArgsErr::IgnoredCheckClippyDoc)
+ } else {
+ Ok(Self::Cargo(
+ Cmd::Check(opts.all_targets),
+ opts.into(),
+ ))
+ }
+ },
+ )
+ }
_ => {
let mut opts = ArgOpts::default();
Self::extract_options(&mut opts, Some(arg), &mut args).map(|()| {
@@ -1221,6 +1396,7 @@ mod tests {
default_toolchain: false,
allow_implied_features: false,
ignore_compile_errors: false,
+ ignore_msrv: false,
progress: false,
skip_msrv: false,
summary: false,
@@ -1269,7 +1445,7 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
- "t".to_owned().into(),
+ "tests".to_owned().into(),
"--deny-warnings".to_owned().into(),
"--deny-warnings".to_owned().into()
]
@@ -1283,7 +1459,7 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
- "h".to_owned().into(),
+ "help".to_owned().into(),
"--summary".to_owned().into()
]
.into_iter()
@@ -1317,7 +1493,7 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
- "t".to_owned().into(),
+ "tests".to_owned().into(),
"--all-targets".to_owned().into()
]
.into_iter()
@@ -1328,7 +1504,7 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
- "d".to_owned().into(),
+ "doc-tests".to_owned().into(),
"--all-targets".to_owned().into()
]
.into_iter()
@@ -1344,7 +1520,7 @@ mod tests {
]
.into_iter()
),
- Err(ArgsErr::DenyWarningsTests)
+ Err(ArgsErr::DenyWarningsCheckTests)
);
assert_eq!(
MetaCmd::from_args(
@@ -1355,29 +1531,51 @@ mod tests {
]
.into_iter()
),
- Err(ArgsErr::DenyWarningsTests)
+ Err(ArgsErr::DenyWarningsCheckTests)
+ );
+ assert_eq!(
+ MetaCmd::from_args(
+ [
+ OsString::new(),
+ "check".to_owned().into(),
+ "--deny-warnings".to_owned().into()
+ ]
+ .into_iter()
+ ),
+ Err(ArgsErr::DenyWarningsCheckTests)
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
- "c".to_owned().into(),
+ "clippy".to_owned().into(),
"--ignored".to_owned().into()
]
.into_iter()
),
- Err(ArgsErr::IgnoredClippyDoc)
+ Err(ArgsErr::IgnoredCheckClippyDoc)
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
- "d".to_owned().into(),
+ "doc-tests".to_owned().into(),
"--ignored".to_owned().into()
]
.into_iter()
),
- Err(ArgsErr::IgnoredClippyDoc)
+ Err(ArgsErr::IgnoredCheckClippyDoc)
+ );
+ assert_eq!(
+ MetaCmd::from_args(
+ [
+ OsString::new(),
+ "check".to_owned().into(),
+ "--ignored".to_owned().into()
+ ]
+ .into_iter()
+ ),
+ Err(ArgsErr::IgnoredCheckClippyDoc)
);
assert_eq!(
MetaCmd::from_args(
@@ -1388,7 +1586,7 @@ mod tests {
]
.into_iter()
),
- Err(ArgsErr::IgnoredClippyDoc)
+ Err(ArgsErr::IgnoredCheckClippyDoc)
);
assert_eq!(
MetaCmd::from_args(
@@ -1399,7 +1597,18 @@ mod tests {
]
.into_iter()
),
- Err(ArgsErr::IgnoredClippyDoc)
+ Err(ArgsErr::IgnoredCheckClippyDoc)
+ );
+ assert_eq!(
+ MetaCmd::from_args(
+ [
+ OsString::new(),
+ "check".to_owned().into(),
+ "--include-ignored".to_owned().into()
+ ]
+ .into_iter()
+ ),
+ Err(ArgsErr::IgnoredCheckClippyDoc)
);
assert_eq!(
MetaCmd::from_args(
@@ -1505,6 +1714,7 @@ mod tests {
"--ignore-compile-errors".to_owned().into(),
"--ignore-features".to_owned().into(),
"--include-ignored".to_owned().into(),
+ "--ignore-msrv".to_owned().into(),
"--rustup-home".to_owned().into(),
OsString::new(),
"--progress".to_owned().into(),
@@ -1524,6 +1734,7 @@ mod tests {
default_toolchain: true,
allow_implied_features: true,
ignore_compile_errors: true,
+ ignore_msrv: true,
progress: true,
skip_msrv: true,
summary: true,
@@ -1535,7 +1746,7 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
- "c".to_owned().into(),
+ "clippy".to_owned().into(),
"--all-targets".to_owned().into(),
"--allow-implied-features".to_owned().into(),
"--cargo-home".to_owned().into(),
@@ -1550,6 +1761,7 @@ mod tests {
"--ignore-compile-errors".to_owned().into(),
"--ignore-features".to_owned().into(),
",a".to_owned().into(),
+ "--ignore-msrv".to_owned().into(),
"--rustup-home".to_owned().into(),
"a".to_owned().into(),
"--progress".to_owned().into(),
@@ -1569,6 +1781,7 @@ mod tests {
default_toolchain: true,
allow_implied_features: true,
ignore_compile_errors: true,
+ ignore_msrv: true,
progress: true,
skip_msrv: true,
summary: true,
@@ -1597,6 +1810,7 @@ mod tests {
default_toolchain: false,
allow_implied_features: false,
ignore_compile_errors: false,
+ ignore_msrv: false,
progress: false,
skip_msrv: false,
summary: false,
@@ -1621,6 +1835,7 @@ mod tests {
"--ignore-compile-errors".to_owned().into(),
"--ignore-features".to_owned().into(),
OsString::new(),
+ "--ignore-msrv".to_owned().into(),
"--ignored".to_owned().into(),
"--rustup-home".to_owned().into(),
OsString::new(),
@@ -1641,6 +1856,7 @@ mod tests {
default_toolchain: true,
allow_implied_features: true,
ignore_compile_errors: true,
+ ignore_msrv: true,
progress: true,
skip_msrv: true,
summary: true,
@@ -1649,7 +1865,7 @@ mod tests {
))
);
assert_eq!(
- MetaCmd::from_args([OsString::new(), "t".to_owned().into(),].into_iter()),
+ MetaCmd::from_args([OsString::new(), "tests".to_owned().into(),].into_iter()),
Ok(MetaCmd::Cargo(
Cmd::Tests(Ignored::None),
Opts {
@@ -1661,6 +1877,7 @@ mod tests {
default_toolchain: false,
allow_implied_features: false,
ignore_compile_errors: false,
+ ignore_msrv: false,
progress: false,
skip_msrv: false,
summary: false,
@@ -1672,7 +1889,7 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
- "t".to_owned().into(),
+ "tests".to_owned().into(),
"--include-ignored".to_owned().into()
]
.into_iter()
@@ -1688,6 +1905,7 @@ mod tests {
default_toolchain: false,
allow_implied_features: false,
ignore_compile_errors: false,
+ ignore_msrv: false,
progress: false,
skip_msrv: false,
summary: false,
@@ -1712,6 +1930,7 @@ mod tests {
"--ignore-compile-errors".to_owned().into(),
"--ignore-features".to_owned().into(),
"a,".to_owned().into(),
+ "--ignore-msrv".to_owned().into(),
"--rustup-home".to_owned().into(),
OsString::new(),
"--progress".to_owned().into(),
@@ -1731,6 +1950,7 @@ mod tests {
default_toolchain: true,
allow_implied_features: true,
ignore_compile_errors: true,
+ ignore_msrv: true,
progress: true,
skip_msrv: true,
summary: true,
@@ -1739,7 +1959,7 @@ mod tests {
))
);
assert_eq!(
- MetaCmd::from_args([OsString::new(), "d".to_owned().into(),].into_iter()),
+ MetaCmd::from_args([OsString::new(), "doc-tests".to_owned().into(),].into_iter()),
Ok(MetaCmd::Cargo(
Cmd::DocTests,
Opts {
@@ -1751,6 +1971,74 @@ mod tests {
default_toolchain: false,
allow_implied_features: false,
ignore_compile_errors: false,
+ ignore_msrv: false,
+ progress: false,
+ skip_msrv: false,
+ summary: false,
+ ignore_features: Vec::new(),
+ }
+ ))
+ );
+ assert_eq!(
+ MetaCmd::from_args(
+ [
+ OsString::new(),
+ "check".to_owned().into(),
+ "--all-targets".to_owned().into(),
+ "--allow-implied-features".to_owned().into(),
+ "--cargo-home".to_owned().into(),
+ "--ignored".to_owned().into(),
+ "--cargo-path".to_owned().into(),
+ "cargo".to_owned().into(),
+ "--color".to_owned().into(),
+ "--default-toolchain".to_owned().into(),
+ "--dir".to_owned().into(),
+ OsString::new(),
+ "--ignore-compile-errors".to_owned().into(),
+ "--ignore-features".to_owned().into(),
+ "a,".to_owned().into(),
+ "--ignore-msrv".to_owned().into(),
+ "--rustup-home".to_owned().into(),
+ OsString::new(),
+ "--progress".to_owned().into(),
+ "--skip-msrv".to_owned().into(),
+ "--summary".to_owned().into(),
+ ]
+ .into_iter()
+ ),
+ Ok(MetaCmd::Cargo(
+ Cmd::Check(true),
+ Opts {
+ exec_dir: Some(PathBuf::new()),
+ rustup_home: Some(PathBuf::new()),
+ cargo_home: Some("--ignored".to_owned().into()),
+ cargo_path: "cargo/cargo".to_owned().into(),
+ color: true,
+ default_toolchain: true,
+ allow_implied_features: true,
+ ignore_compile_errors: true,
+ ignore_msrv: true,
+ progress: true,
+ skip_msrv: true,
+ summary: true,
+ ignore_features: vec!["a".to_owned(), String::new()],
+ }
+ ))
+ );
+ assert_eq!(
+ MetaCmd::from_args([OsString::new(), "check".to_owned().into(),].into_iter()),
+ Ok(MetaCmd::Cargo(
+ Cmd::Check(false),
+ Opts {
+ exec_dir: None,
+ rustup_home: None,
+ cargo_home: None,
+ cargo_path: "cargo".to_owned().into(),
+ color: false,
+ default_toolchain: false,
+ allow_implied_features: false,
+ ignore_compile_errors: false,
+ ignore_msrv: false,
progress: false,
skip_msrv: false,
summary: false,
@@ -1778,6 +2066,7 @@ mod tests {
default_toolchain: false,
allow_implied_features: false,
ignore_compile_errors: false,
+ ignore_msrv: false,
progress: false,
skip_msrv: false,
summary: false,
@@ -1805,6 +2094,7 @@ mod tests {
default_toolchain: false,
allow_implied_features: false,
ignore_compile_errors: false,
+ ignore_msrv: false,
progress: false,
skip_msrv: false,
summary: false,
@@ -1832,6 +2122,7 @@ mod tests {
default_toolchain: false,
allow_implied_features: false,
ignore_compile_errors: false,
+ ignore_msrv: false,
progress: false,
skip_msrv: false,
summary: false,
@@ -1860,6 +2151,7 @@ mod tests {
default_toolchain: false,
allow_implied_features: false,
ignore_compile_errors: false,
+ ignore_msrv: false,
progress: false,
skip_msrv: false,
summary: false,
@@ -1873,18 +2165,10 @@ mod tests {
))
);
assert_eq!(
- MetaCmd::from_args([OsString::new(), "h".to_owned().into(),].into_iter()),
- Ok(MetaCmd::Help)
- );
- assert_eq!(
MetaCmd::from_args([OsString::new(), "help".to_owned().into(),].into_iter()),
Ok(MetaCmd::Help)
);
assert_eq!(
- MetaCmd::from_args([OsString::new(), "v".to_owned().into(),].into_iter()),
- Ok(MetaCmd::Version)
- );
- assert_eq!(
MetaCmd::from_args([OsString::new(), "version".to_owned().into(),].into_iter()),
Ok(MetaCmd::Version)
);
diff --git a/src/cargo.rs b/src/cargo.rs
@@ -217,19 +217,25 @@ pub(crate) struct Version {
/// Patch version.
pub patch: u64,
}
+/// `"+stable"`.
+const PLUS_STABLE: &str = "+stable";
/// `"RUSTUP_HOME"`.
const RUSTUP_HOME: &str = "RUSTUP_HOME";
/// `"CARGO_HOME"`.
const CARGO_HOME: &str = "CARGO_HOME";
-/// `"-q"`.
-const DASH_Q: &str = "-q";
/// Toolchain to use.
+#[expect(
+ variant_size_differences,
+ reason = "fine. This doesn't get triggered if the other variants were unit variants despite Toolchain being the same size."
+)]
#[derive(Clone, Copy)]
pub(crate) enum Toolchain<'a> {
/// `cargo +stable`.
Stable,
/// `cargo`.
- Default,
+ ///
+ /// Contained `bool` is `true` iff `--ignore-rust-version` should be passed.
+ Default(bool),
/// `cargo +<MSRV>`.
Msrv(&'a str),
}
@@ -306,7 +312,7 @@ impl Toolchain<'_> {
Self::Stable => {
_ = cmd.arg(PLUS_STABLE);
}
- Self::Default => {}
+ Self::Default(_) => {}
Self::Msrv(val) => {
_ = cmd.arg(val);
}
@@ -337,8 +343,10 @@ impl Toolchain<'_> {
}
}
}
-/// `"+stable"`.
-const PLUS_STABLE: &str = "+stable";
+/// `"-p"`.
+const DASH_P: &str = "-p";
+/// `"-q"`.
+const DASH_Q: &str = "-q";
/// `"--color"`.
const DASH_DASH_COLOR: &str = "--color";
/// `"always"`.
@@ -347,14 +355,16 @@ const ALWAYS: &str = "always";
const NEVER: &str = "never";
/// `"--no-default-features"`.
const DASH_DASH_NO_DEFAULT_FEATURES: &str = "--no-default-features";
-/// `"-F"`.
-const DASH_F: &str = "-F";
+/// `"--features"`.
+const DASH_DASH_FEATURES: &str = "--features";
/// `"--"`.
const DASH_DASH: &str = "--";
/// `"default"`.
const DEFAULT: &str = "default";
+/// `"--ignore-rust-version"`.
+const DASH_DASH_IGNORE_RUST_VERSION: &str = "--ignore-rust-version";
/// Common options to pass to [`Clippy::run`] and [`Tests::run`].
-pub(crate) struct Options<'toolchain, 'errs> {
+pub(crate) struct Options<'toolchain, 'package, 'errs> {
/// The `cargo` toolchain to use.
pub toolchain: Toolchain<'toolchain>,
/// The path to the `rustup` storage directory.
@@ -363,6 +373,8 @@ pub(crate) struct Options<'toolchain, 'errs> {
pub cargo_path: PathBuf,
/// The path to the `cargo` storage directory.
pub cargo_home: Option<PathBuf>,
+ /// Name of the package.
+ pub package_name: &'package str,
/// `true` iff color should be written to `stdout` and `stderr`.
pub color: bool,
/// `true` iff `compile_error`s should be ignored.
@@ -377,7 +389,7 @@ pub(crate) struct Options<'toolchain, 'errs> {
/// Returns `true` iff a no-library target error occurred and `doc_only` was `true`.
fn execute_command(
mut cmd: Command,
- options: &mut Options<'_, '_>,
+ options: &mut Options<'_, '_, '_>,
features: &str,
doc_only: bool,
) -> Result<bool, Box<CargoErr>> {
@@ -479,7 +491,7 @@ impl Clippy {
reason = "want to crash when there is a bug"
)]
pub(crate) fn run(
- options: &mut Options<'_, '_>,
+ options: &mut Options<'_, '_, '_>,
all_targets: bool,
deny_warnings: bool,
features: &str,
@@ -492,25 +504,34 @@ impl Clippy {
if let Some(ref env) = options.cargo_home {
_ = c.env(CARGO_HOME, env);
}
- match options.toolchain {
+ let ignore_msrv = match options.toolchain {
Toolchain::Stable => {
_ = c.arg(PLUS_STABLE);
+ false
}
- Toolchain::Default => {}
+ Toolchain::Default(ignore_msrv) => ignore_msrv,
Toolchain::Msrv(ref msrv) => {
_ = c.arg(msrv);
+ false
}
- }
- _ = c.arg("clippy").arg(DASH_Q);
+ };
+ _ = c
+ .arg("clippy")
+ .arg(DASH_P)
+ .arg(options.package_name)
+ .arg(DASH_Q);
if all_targets {
_ = c.arg("--all-targets");
}
+ if ignore_msrv {
+ _ = c.arg(DASH_DASH_IGNORE_RUST_VERSION);
+ }
_ = c
.arg(DASH_DASH_COLOR)
.arg(if options.color { ALWAYS } else { NEVER })
.arg(DASH_DASH_NO_DEFAULT_FEATURES);
if !features.is_empty() {
- _ = c.arg(DASH_F).arg(features);
+ _ = c.arg(DASH_DASH_FEATURES).arg(features);
}
if deny_warnings {
_ = c.arg(DASH_DASH).arg("-Dwarnings");
@@ -529,14 +550,14 @@ pub(crate) enum TestKind {
/// Only doc tests.
Doc,
}
-/// `cargo t --tests/--doc`.
+/// `cargo test --tests/--doc`.
pub(crate) struct Tests;
impl Tests {
- /// Execute `cargo t`.
+ /// Execute `cargo test`.
///
/// Returns `true` iff only doc tests were run and a no-library error was returned.
pub(crate) fn run(
- options: &mut Options<'_, '_>,
+ options: &mut Options<'_, '_, '_>,
kind: TestKind,
features: &str,
) -> Result<bool, Box<CargoErr>> {
@@ -552,23 +573,31 @@ impl Tests {
if let Some(ref env) = options.cargo_home {
_ = c.env(CARGO_HOME, env);
}
- match options.toolchain {
+ let ignore_msrv = match options.toolchain {
Toolchain::Stable => {
_ = c.arg(PLUS_STABLE);
+ false
}
- Toolchain::Default => {}
+ Toolchain::Default(ignore_msrv) => ignore_msrv,
Toolchain::Msrv(ref msrv) => {
_ = c.arg(msrv);
+ false
}
+ };
+ _ = c
+ .arg("test")
+ .arg(DASH_P)
+ .arg(options.package_name)
+ .arg(DASH_Q);
+ if ignore_msrv {
+ _ = c.arg(DASH_DASH_IGNORE_RUST_VERSION);
}
_ = c
- .arg("t")
- .arg(DASH_Q)
.arg(DASH_DASH_COLOR)
.arg(if options.color { ALWAYS } else { NEVER })
.arg(DASH_DASH_NO_DEFAULT_FEATURES);
if !features.is_empty() {
- _ = c.arg(DASH_F).arg(features);
+ _ = c.arg(DASH_DASH_FEATURES).arg(features);
}
let mut doc_only = false;
match kind {
@@ -616,6 +645,63 @@ impl Tests {
execute_command(c, options, features, doc_only)
}
}
+/// `cargo check`.
+pub(crate) struct Check;
+impl Check {
+ /// Execute `cargo check`.
+ ///
+ /// Returns `false` iff the command ran successfully. Note this can only return `true` if
+ /// [`Options::ignore_compile_errors`] is `true` since an error would be returned instead.
+ #[expect(
+ clippy::panic_in_result_fn,
+ reason = "want to crash when there is a bug"
+ )]
+ pub(crate) fn run(
+ options: &mut Options<'_, '_, '_>,
+ all_targets: bool,
+ features: &str,
+ ) -> Result<(), Box<CargoErr>> {
+ let mut c = Command::new(options.cargo_path.as_path());
+ _ = c.stderr(Stdio::piped()).stdin(Stdio::null());
+ if let Some(ref env) = options.rustup_home {
+ _ = c.env(RUSTUP_HOME, env);
+ }
+ if let Some(ref env) = options.cargo_home {
+ _ = c.env(CARGO_HOME, env);
+ }
+ let ignore_msrv = match options.toolchain {
+ Toolchain::Stable => {
+ _ = c.arg(PLUS_STABLE);
+ false
+ }
+ Toolchain::Default(ignore_msrv) => ignore_msrv,
+ Toolchain::Msrv(ref msrv) => {
+ _ = c.arg(msrv);
+ false
+ }
+ };
+ _ = c
+ .arg("check")
+ .arg(DASH_P)
+ .arg(options.package_name)
+ .arg(DASH_Q);
+ if all_targets {
+ _ = c.arg("--all-targets");
+ }
+ if ignore_msrv {
+ _ = c.arg(DASH_DASH_IGNORE_RUST_VERSION);
+ }
+ _ = c
+ .arg(DASH_DASH_COLOR)
+ .arg(if options.color { ALWAYS } else { NEVER })
+ .arg(DASH_DASH_NO_DEFAULT_FEATURES);
+ if !features.is_empty() {
+ _ = c.arg(DASH_DASH_FEATURES).arg(features);
+ }
+ execute_command(c, options, features, false)
+ .map(|no_library_target| assert!(!no_library_target, "there is a bug in cargo::execute_command since a no-library target error was returned when running Check."))
+ }
+}
#[cfg(test)]
mod tests {
use super::{Command, Toolchain, ToolchainErr, Version};
diff --git a/src/main.rs b/src/main.rs
@@ -42,10 +42,12 @@ enum E {
SetDir(Error, PathBuf),
/// Error reading `Cargo.toml`.
CargoTomlRead(Error, PathBuf),
- /// Error looking for `rust-toolchain.toml`.
- RustToolchainTomlIo(Error, PathBuf),
/// Error related to extracting the necessary data from `Cargo.toml`.
Manifest(Box<ManifestErr>),
+ /// Error looking for `rust-toolchain.toml`.
+ RustToolchainTomlIo(Error, PathBuf),
+ /// Error when `--ignore-msrv` was passed when using the `stable` toolchain.
+ IgnoreMsrvStable,
/// Error from `Msrv::compare_to_other`.
Toolchain(Box<ToolchainErr>),
/// Error from OpenBSD `pledge`.
@@ -104,13 +106,14 @@ impl E {
Self::CargoTomlRead(err, p) => {
writeln!(stderr, "There was an error reading {}: {err}.", p.display())
}
+ Self::Manifest(e) => e.write(stderr),
Self::RustToolchainTomlIo(err, p) => {
writeln!(
stderr,
"There was an error looking for rust-toolchain.toml in {} and its ancestor directories: {err}.", p.display()
)
}
- Self::Manifest(e) => e.write(stderr),
+ Self::IgnoreMsrvStable => writeln!(stderr, "--ignore-msrv was passed when using the stable toolchain."),
Self::Toolchain(e) => e.write(stderr),
#[cfg(target_os = "openbsd")]
Self::Pledge(e) => writeln!(stderr, "pledge(2) erred: {e}."),
@@ -260,20 +263,20 @@ fn main() -> ExitCode {
}
fs::read_to_string(&cur_dir).map_err(|e| E::CargoTomlRead(e, cur_dir.clone())).and_then(|toml| Manifest::from_toml(toml, opts.allow_implied_features, &cur_dir, &opts.ignore_features).map_err(E::Manifest).and_then(|man| {
if opts.default_toolchain || (!rustup::SUPPORTED && opts.rustup_home.is_none()) {
- Ok(Toolchain::Default)
+ Ok(Toolchain::Default(opts.ignore_msrv))
} else {
let mut cargo_toml_path = cur_dir.clone();
_ = cargo_toml_path.pop();
- get_path_of_file(&mut cargo_toml_path, rust_toolchain_toml()).map_err(|e| E::RustToolchainTomlIo(e, cargo_toml_path)).map(|rust_toolchain_exists| if rust_toolchain_exists { Toolchain::Default } else { Toolchain::Stable })
- }.and_then(|toolchain| priv_sep_final(&mut proms, &opts.cargo_path).and_then(|()| man.msrv().map_or(Ok(None), |msrv| if !opts.skip_msrv && (rustup::SUPPORTED || opts.rustup_home.is_some()) {
- msrv.compare_to_other(matches!(toolchain, Toolchain::Default), opts.rustup_home.as_deref(), &opts.cargo_path, opts.cargo_home.as_deref()).map_err(E::Toolchain)
+ get_path_of_file(&mut cargo_toml_path, rust_toolchain_toml()).map_err(|e| E::RustToolchainTomlIo(e, cargo_toml_path)).and_then(|rust_toolchain_exists| if rust_toolchain_exists { Ok(Toolchain::Default(opts.ignore_msrv)) } else if opts.ignore_msrv { Err(E::IgnoreMsrvStable) } else { Ok(Toolchain::Stable) })
+ }.and_then(|toolchain| priv_sep_final(&mut proms, &opts.cargo_path).and_then(|()| man.package().msrv().map_or(Ok(None), |msrv| if !opts.skip_msrv && (rustup::SUPPORTED || opts.rustup_home.is_some()) {
+ msrv.compare_to_other(matches!(toolchain, Toolchain::Default(_)), opts.rustup_home.as_deref(), &opts.cargo_path, opts.cargo_home.as_deref()).map_err(E::Toolchain)
} else {
Ok(None)
}).and_then(|msrv_string| {
let default_feature_does_not_exist = !man.features().contains_default();
man.features().power_set(skip_no_feats).map_err(|_e| E::TooManyFeatures(cur_dir)).and_then(|power_set_opt| power_set_opt.map_or_else(|| Ok(()), |mut power_set| {
let mut non_term_errs = HashSet::new();
- cmd.run(Options { toolchain, rustup_home: opts.rustup_home, cargo_path: opts.cargo_path, cargo_home: opts.cargo_home, color: opts.color, ignore_compile_errors: opts.ignore_compile_errors, default_feature_does_not_exist, non_terminating_errors: &mut non_term_errs, }, msrv_string.as_deref(), &mut power_set, opts.progress).map_err(E::Cargo).and_then(|()| {
+ cmd.run(Options { toolchain, rustup_home: opts.rustup_home, cargo_path: opts.cargo_path, cargo_home: opts.cargo_home, package_name: man.package().name(), color: opts.color, ignore_compile_errors: opts.ignore_compile_errors, default_feature_does_not_exist, non_terminating_errors: &mut non_term_errs, }, msrv_string.as_deref(), &mut power_set, opts.progress).map_err(E::Cargo).and_then(|()| {
if non_term_errs.is_empty() {
Ok(())
} else {
diff --git a/src/manifest.rs b/src/manifest.rs
@@ -81,6 +81,8 @@ impl WorkspaceErr {
}
}
}
+/// `"name"`.
+const NAME: &str = "name";
/// Error returned from extracting `"package"`.
#[cfg_attr(test, derive(Debug))]
pub(crate) enum PackageErr {
@@ -88,6 +90,10 @@ pub(crate) enum PackageErr {
Missing,
/// Variant returned when `"package"` is not a table.
InvalidType,
+ /// Variant returned when `packagen.name` does not exist.
+ MissingName,
+ /// Variant returned when `package.name` is not a string.
+ InvalidNameType,
/// Variant returned when `package.rust-version` is not a string nor table.
InvalidMsrvType,
/// Variant returned when `package.rust-version` is not a valid MSRV.
@@ -131,6 +137,12 @@ impl PackageErr {
"'{PACKAGE}' exists but is not a table in {}.",
file.display()
),
+ Self::MissingName => writeln!(stderr, "'{PACKAGE}.{NAME}' does not exist in {}.", file.display()),
+ Self::InvalidNameType => writeln!(
+ stderr,
+ "'{PACKAGE}.{NAME}' exists but is not a string in {}.",
+ file.display()
+ ),
Self::InvalidMsrvType => writeln!(
stderr,
"'{PACKAGE}.{RUST_VERSION}' exists but is not a string nor table in {}.",
@@ -373,7 +385,7 @@ impl ImpliedFeaturesErr {
DependenciesErr::ImpliedFeature(name, dep_name) => {
writeln!(
stderr,
- "'{name}.{dep_name}' causes an implied feature to be defined in {}, but implied features were forbidden.",
+ "'{name}.{dep_name}' causes an implied feature to be defined in {}, but implied features were forbidden. --allow-implied-features can be passed to allow it.",
file.display()
)
}
@@ -420,7 +432,7 @@ impl ImpliedFeaturesErr {
DependenciesErr::ImpliedFeature(table_name, dep_name) => {
writeln!(
stderr,
- "'{TARGET}.{name}.{table_name}.{dep_name}' causes an implied feature to be defined in {}, but implied features were forbidden.",
+ "'{TARGET}.{name}.{table_name}.{dep_name}' causes an implied feature to be defined in {}, but implied features were forbidden. --allow-implied-features can be passed to allow it.",
file.display()
)
}
@@ -461,7 +473,7 @@ impl ManifestErr {
Self::ImpliedFeatures(e, file) => e.write(stderr, &file),
Self::UndefinedIgnoreFeature(feature, file) => writeln!(
stderr,
- "The feature '{feature}' was requested to be ignored, but it is not a feature in the package file {}. --allow-implied-features may need to be passed if this feature is an implied one.",
+ "The feature '{feature}' was requested to be ignored, but it is not a feature in the package file {}.",
file.display()
),
}
@@ -628,71 +640,66 @@ impl Msrv {
}
}
}
- /// Extracts `"package"` from `toml` before extracting `"rust-version"` from it.
+ /// Extracts `"rust-version"` from `"package"` or `toml` in the case it's defined in a workspace.
#[expect(
clippy::panic_in_result_fn,
reason = "want to crash when there is a bug"
)]
fn extract_from_toml(
toml: &Map<Spanned<Cow<'_, str>>, Spanned<DeValue<'_>>>,
+ package: &Map<Spanned<Cow<'_, str>>, Spanned<DeValue<'_>>>,
cargo_toml: &Path,
) -> Result<Option<Self>, PackageErr> {
- toml.get(PACKAGE)
- .ok_or(PackageErr::Missing)
- .and_then(|pack_span| {
- if let DeValue::Table(ref package) = *pack_span.get_ref() {
- package.get(RUST_VERSION).map_or(Ok(None), |msrv_span| {
- match *msrv_span.get_ref() {
- DeValue::String(ref msrv) => Self::extract_msrv(msrv)
- .map_err(|()| PackageErr::Msrv)
- .map(Some),
- DeValue::Table(ref msrv) => msrv
- .get(WORKSPACE)
- .ok_or(PackageErr::MsrvWorkspaceMissing)
- .and_then(|work| {
- if matches!(*work.get_ref(), DeValue::Boolean(b) if b) {
- package.get(WORKSPACE).map_or_else(
- || if toml.contains_key(WORKSPACE) {
- Self::extract_workspace(toml).map_err(|e| PackageErr::Workspace(e, cargo_toml.to_path_buf())).map(Some)
- } else {
- let mut search_path = cargo_toml.to_path_buf();
- assert!(search_path.pop(), "there is a bug in main. manifest::Manifest::from_toml must be passed the absolute path to the package's Carg.toml.");
- if search_path.pop() {
- Self::get_workspace_toml(search_path).map(Some)
- } else {
- Err(PackageErr::WorkspaceDoesNotExist)
- }
- },
- |path_span| {
- if let DeValue::String(ref workspace_path) = *path_span.get_ref() {
- let mut path = cargo_toml.to_path_buf();
- assert!(path.pop(), "there is a bug in main. manifest::Manifest::from_toml must be passed the absolute path to the package's Carg.toml.");
- path.push(workspace_path.as_ref());
- path.push(super::cargo_toml());
- fs::read_to_string(&path).map_err(|e| PackageErr::WorkspaceRead(e, path.clone())).and_then(|workspace_file| Map::parse(&workspace_file).map_err(|e| PackageErr::WorkspaceToml(e, path.clone())).and_then(|workspace_toml| Self::extract_workspace(workspace_toml.get_ref()).map_err(|e| PackageErr::Workspace(e, path)).map(Some)))
- } else {
- Err(PackageErr::InvalidWorkspaceType)
- }
- },
- )
+ package.get(RUST_VERSION).map_or(Ok(None), |msrv_span| {
+ match *msrv_span.get_ref() {
+ DeValue::String(ref msrv) => Self::extract_msrv(msrv)
+ .map_err(|()| PackageErr::Msrv)
+ .map(Some),
+ DeValue::Table(ref msrv) => msrv
+ .get(WORKSPACE)
+ .ok_or(PackageErr::MsrvWorkspaceMissing)
+ .and_then(|work| {
+ if matches!(*work.get_ref(), DeValue::Boolean(b) if b) {
+ package.get(WORKSPACE).map_or_else(
+ || if toml.contains_key(WORKSPACE) {
+ Self::extract_workspace(toml).map_err(|e| PackageErr::Workspace(e, cargo_toml.to_path_buf())).map(Some)
+ } else {
+ let mut search_path = cargo_toml.to_path_buf();
+ assert!(search_path.pop(), "there is a bug in main. manifest::Manifest::from_toml must be passed the absolute path to the package's Cargo.toml.");
+ if search_path.pop() {
+ Self::get_workspace_toml(search_path).map(Some)
} else {
- Err(PackageErr::MsrvWorkspaceVal)
+ Err(PackageErr::WorkspaceDoesNotExist)
}
- }),
- DeValue::Integer(_)
- | DeValue::Float(_)
- | DeValue::Boolean(_)
- | DeValue::Datetime(_)
- | DeValue::Array(_) => Err(PackageErr::InvalidMsrvType),
+ },
+ |path_span| {
+ if let DeValue::String(ref workspace_path) = *path_span.get_ref() {
+ let mut path = cargo_toml.to_path_buf();
+ assert!(path.pop(), "there is a bug in main. manifest::Manifest::from_toml must be passed the absolute path to the package's Cargo.toml.");
+ path.push(workspace_path.as_ref());
+ path.push(super::cargo_toml());
+ fs::read_to_string(&path).map_err(|e| PackageErr::WorkspaceRead(e, path.clone())).and_then(|workspace_file| Map::parse(&workspace_file).map_err(|e| PackageErr::WorkspaceToml(e, path.clone())).and_then(|workspace_toml| Self::extract_workspace(workspace_toml.get_ref()).map_err(|e| PackageErr::Workspace(e, path)).map(Some)))
+ } else {
+ Err(PackageErr::InvalidWorkspaceType)
+ }
+ },
+ )
+ } else {
+ Err(PackageErr::MsrvWorkspaceVal)
}
- })
- } else {
- Err(PackageErr::InvalidType)
- }
- })
+ }),
+ DeValue::Integer(_)
+ | DeValue::Float(_)
+ | DeValue::Boolean(_)
+ | DeValue::Datetime(_)
+ | DeValue::Array(_) => Err(PackageErr::InvalidMsrvType),
+ }
+ })
}
- /// Returns `Some` containing the MSRV with `'+'` prepended iff the stable or default toolchain is semantically
- /// greater than `self`; otherwise returns `None`.
+ /// Returns `Some` containing the MSRV with `'+'` prepended iff `stable` is semantically greater than `self`
+ /// or the default toolchan is semantically not equivalent to `self`; otherwise returns `None`.
+ ///
+ /// When `stable` is semantically less than the MSRV, an error is returned.
pub(crate) fn compare_to_other(
&self,
default: bool,
@@ -701,7 +708,7 @@ impl Msrv {
cargo_home: Option<&Path>,
) -> Result<Option<String>, Box<ToolchainErr>> {
if default {
- Toolchain::Default
+ Toolchain::Default(false)
} else {
Toolchain::Stable
}
@@ -718,13 +725,31 @@ impl Msrv {
|pat| match pat.cmp(&stable_dflt_version.patch) {
Ordering::Less => Ok(true),
Ordering::Equal => Ok(false),
- Ordering::Greater => Err(Box::new(ToolchainErr::MsrvTooHigh)),
+ Ordering::Greater => {
+ if default {
+ Ok(true)
+ } else {
+ Err(Box::new(ToolchainErr::MsrvTooHigh))
+ }
+ }
},
),
- Ordering::Greater => Err(Box::new(ToolchainErr::MsrvTooHigh)),
+ Ordering::Greater => {
+ if default {
+ Ok(true)
+ } else {
+ Err(Box::new(ToolchainErr::MsrvTooHigh))
+ }
+ }
},
),
- Ordering::Greater => Err(Box::new(ToolchainErr::MsrvTooHigh)),
+ Ordering::Greater => {
+ if default {
+ Ok(true)
+ } else {
+ Err(Box::new(ToolchainErr::MsrvTooHigh))
+ }
+ }
}
.and_then(|get_msrv| {
if get_msrv {
@@ -762,6 +787,53 @@ impl Msrv {
})
}
}
+/// `package` info.
+#[cfg_attr(test, derive(Debug, PartialEq))]
+pub(crate) struct Package {
+ /// `rust-version`.
+ msrv: Option<Msrv>,
+ /// `name`.
+ name: String,
+}
+impl Package {
+ /// MSRV.
+ pub(crate) const fn msrv(&self) -> Option<&Msrv> {
+ self.msrv.as_ref()
+ }
+ /// Name.
+ pub(crate) const fn name(&self) -> &str {
+ self.name.as_str()
+ }
+ /// Extracts `"package"` from `toml`.
+ fn extract_from_toml(
+ toml: &Map<Spanned<Cow<'_, str>>, Spanned<DeValue<'_>>>,
+ cargo_toml: &Path,
+ ) -> Result<Self, PackageErr> {
+ toml.get(PACKAGE)
+ .ok_or(PackageErr::Missing)
+ .and_then(|pack_span| {
+ if let DeValue::Table(ref package) = *pack_span.get_ref() {
+ package
+ .get(NAME)
+ .ok_or(PackageErr::MissingName)
+ .and_then(|name_span| {
+ if let DeValue::String(ref name) = *name_span.get_ref() {
+ Msrv::extract_from_toml(toml, package, cargo_toml).map(|msrv| {
+ Self {
+ msrv,
+ name: name.clone().into_owned(),
+ }
+ })
+ } else {
+ Err(PackageErr::InvalidNameType)
+ }
+ })
+ } else {
+ Err(PackageErr::InvalidType)
+ }
+ })
+ }
+}
/// Returns `true` iff `nodes` is pairwise disconnected.
#[expect(
clippy::arithmetic_side_effects,
@@ -1505,18 +1577,18 @@ impl Features {
PowerSet::new(self, skip_no_feats)
}
}
-/// MSRV and features in `Cargo.toml`.
+/// Package and features in `Cargo.toml`.
#[cfg_attr(test, derive(Debug, PartialEq))]
pub(crate) struct Manifest {
- /// The MSRV.
- msrv: Option<Msrv>,
+ /// The package.
+ package: Package,
/// The features.
features: Features,
}
impl Manifest {
/// Returns the defined MSRV iff there was one defined.
- pub(crate) const fn msrv(&self) -> Option<&Msrv> {
- self.msrv.as_ref()
+ pub(crate) const fn package(&self) -> &Package {
+ &self.package
}
/// Returns the defined features.
///
@@ -1546,9 +1618,9 @@ impl Manifest {
.map_err(|e| Box::new(ManifestErr::Toml(e, cargo_toml.to_path_buf())))
.and_then(|span| {
let cargo = span.get_ref();
- Msrv::extract_from_toml(cargo, cargo_toml)
+ Package::extract_from_toml(cargo, cargo_toml)
.map_err(|e| Box::new(ManifestErr::Package(e, cargo_toml.to_path_buf())))
- .and_then(|msrv| {
+ .and_then(|package| {
Features::extract_from_toml(cargo, allow_implied_features)
.map_err(|e| {
Box::new(ManifestErr::Features(e, cargo_toml.to_path_buf()))
@@ -1619,7 +1691,7 @@ impl Manifest {
!info.1.iter().any(|d| d == ig_feat)
});
});
- Self { msrv, features }
+ Self { package, features }
})
})
})
@@ -1631,14 +1703,16 @@ impl Manifest {
mod tests {
use super::{
DependenciesErr, FeatureDependenciesErr, Features, FeaturesErr, ImpliedFeaturesErr,
- Manifest, ManifestErr, Msrv, NonZeroUsizePlus1, PackageErr, Path, PathBuf, PowerSet,
- TooManyFeaturesErr, WorkspaceErr,
+ Manifest, ManifestErr, Msrv, NonZeroUsizePlus1, Package, PackageErr, Path, PathBuf,
+ PowerSet, TooManyFeaturesErr, WorkspaceErr,
};
impl PartialEq for PackageErr {
fn eq(&self, other: &Self) -> bool {
match *self {
Self::Missing => matches!(*other, Self::Missing),
Self::InvalidType => matches!(*other, Self::InvalidType),
+ Self::MissingName => matches!(*other, Self::MissingName),
+ Self::InvalidNameType => matches!(*other, Self::InvalidNameType),
Self::InvalidMsrvType => matches!(*other, Self::InvalidMsrvType),
Self::Msrv => matches!(*other, Self::Msrv),
Self::MsrvWorkspaceMissing => matches!(*other, Self::MsrvWorkspaceMissing),
@@ -1700,8 +1774,22 @@ mod tests {
)))
);
assert_eq!(
+ Manifest::from_toml("[package]".to_owned(), false, Path::new(""), &[]),
+ Err(Box::new(ManifestErr::Package(
+ PackageErr::MissingName,
+ PathBuf::new()
+ )))
+ );
+ assert_eq!(
+ Manifest::from_toml("[package]\nname=true".to_owned(), false, Path::new(""), &[]),
+ Err(Box::new(ManifestErr::Package(
+ PackageErr::InvalidNameType,
+ PathBuf::new()
+ )))
+ );
+ assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=2".to_owned(),
+ "[package]\nname=\"\"\n\nrust-version=2".to_owned(),
false,
Path::new(""),
&[]
@@ -1713,7 +1801,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\"\"".to_owned(),
+ "[package]\nname=\"\"\nrust-version=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -1725,7 +1813,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\"a\"".to_owned(),
+ "[package]\nname=\"\"\nrust-version=\"a\"".to_owned(),
false,
Path::new(""),
&[]
@@ -1737,7 +1825,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\"1.00.0\"".to_owned(),
+ "[package]\nname=\"\"\nrust-version=\"1.00.0\"".to_owned(),
false,
Path::new(""),
&[]
@@ -1749,7 +1837,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\"1..0\"".to_owned(),
+ "[package]\nname=\"\"\nrust-version=\"1..0\"".to_owned(),
false,
Path::new(""),
&[]
@@ -1761,7 +1849,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\"1.\"".to_owned(),
+ "[package]\nname=\"\"\nrust-version=\"1.\"".to_owned(),
false,
Path::new(""),
&[]
@@ -1773,7 +1861,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\"01.0.0\"".to_owned(),
+ "[package]\nname=\"\"\nrust-version=\"01.0.0\"".to_owned(),
false,
Path::new(""),
&[]
@@ -1785,7 +1873,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\"1.0.0.1\"".to_owned(),
+ "[package]\nname=\"\"\nrust-version=\"1.0.0.1\"".to_owned(),
false,
Path::new(""),
&[]
@@ -1797,7 +1885,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\"111111111111111111111111.2.3\"".to_owned(),
+ "[package]\nname=\"\"\nrust-version=\"111111111111111111111111.2.3\"".to_owned(),
false,
Path::new(""),
&[]
@@ -1809,7 +1897,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\"1.0.0-nightly\"".to_owned(),
+ "[package]\nname=\"\"\nrust-version=\"1.0.0-nightly\"".to_owned(),
false,
Path::new(""),
&[]
@@ -1821,7 +1909,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\"-1.0.0\"".to_owned(),
+ "[package]\nname=\"\"\nrust-version=\"-1.0.0\"".to_owned(),
false,
Path::new(""),
&[]
@@ -1833,7 +1921,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\" 1.0.0\"".to_owned(),
+ "[package]\nname=\"\"\nrust-version=\" 1.0.0\"".to_owned(),
false,
Path::new(""),
&[]
@@ -1845,7 +1933,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\"1.0.0 \"".to_owned(),
+ "[package]\nname=\"\"\nrust-version=\"1.0.0 \"".to_owned(),
false,
Path::new(""),
&[]
@@ -1857,7 +1945,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version={}".to_owned(),
+ "[package]\nname=\"\"\nrust-version={}".to_owned(),
false,
Path::new(""),
&[]
@@ -1869,7 +1957,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version={workspace=2}".to_owned(),
+ "[package]\nname=\"\"\nrust-version={workspace=2}".to_owned(),
false,
Path::new(""),
&[]
@@ -1881,7 +1969,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version={workspace=false}".to_owned(),
+ "[package]\nname=\"\"\nrust-version={workspace=false}".to_owned(),
false,
Path::new(""),
&[]
@@ -1893,7 +1981,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version={workspace=true}\nworkspace=2".to_owned(),
+ "[package]\nname=\"\"\nrust-version={workspace=true}\nworkspace=2".to_owned(),
false,
Path::new(""),
&[]
@@ -1905,7 +1993,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "workspace=2\n[package]\nrust-version={workspace=true}".to_owned(),
+ "workspace=2\n[package]\nname=\"\"\nrust-version={workspace=true}".to_owned(),
false,
Path::new(""),
&[]
@@ -1917,7 +2005,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[workspace]\n[package]\nrust-version={workspace=true}".to_owned(),
+ "[workspace]\n[package]\nname=\"\"\nrust-version={workspace=true}".to_owned(),
false,
Path::new(""),
&[]
@@ -1929,7 +2017,8 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[workspace]\npackage=2\n[package]\nrust-version={workspace=true}".to_owned(),
+ "[workspace]\npackage=2\n[package]\nname=\"\"\nrust-version={workspace=true}"
+ .to_owned(),
false,
Path::new(""),
&[]
@@ -1941,7 +2030,8 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[workspace.package]\n[package]\nrust-version={workspace=true}".to_owned(),
+ "[workspace.package]\n[package]\nname=\"\"\nrust-version={workspace=true}"
+ .to_owned(),
false,
Path::new(""),
&[]
@@ -1953,7 +2043,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[workspace.package]\nrust-version={}\n[package]\nrust-version={workspace=true}"
+ "[workspace.package]\nrust-version={}\n[package]\nname=\"\"\nrust-version={workspace=true}"
.to_owned(),
false,
Path::new(""),
@@ -1966,7 +2056,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[workspace.package]\nrust-version=\"\"\n[package]\nrust-version={workspace=true}"
+ "[workspace.package]\nrust-version=\"\"\n[package]\nname=\"\"\nrust-version={workspace=true}"
.to_owned(),
false,
Path::new(""),
@@ -1979,7 +2069,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "features=2\n[package]".to_owned(),
+ "features=2\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -1991,7 +2081,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[features]\n\"/\"=[]\n[package]".to_owned(),
+ "[features]\n\"/\"=[]\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2003,7 +2093,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[features]\n\"dep:\"=[]\n[package]".to_owned(),
+ "[features]\n\"dep:\"=[]\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2015,7 +2105,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[features]\n\"\"=2\n[package]".to_owned(),
+ "[features]\n\"\"=2\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2029,7 +2119,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[features]\n\"\"=[true]\n[package]".to_owned(),
+ "[features]\n\"\"=[true]\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2043,7 +2133,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[features]\n\"\"=[\"foo\"]\n[package]".to_owned(),
+ "[features]\n\"\"=[\"foo\"]\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2059,7 +2149,7 @@ mod tests {
// Feature dependencies can't be implied features when implied features are forbidden.
assert_eq!(
Manifest::from_toml(
- "[dependencies]\nfoo={optional=true}\n[features]\n\"\"=[\"foo\"]\n[package]"
+ "[dependencies]\nfoo={optional=true}\n[features]\n\"\"=[\"foo\"]\n[package]\nname=\"\""
.to_owned(),
false,
Path::new(""),
@@ -2075,7 +2165,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[features]\n\"\"=[\"\"]\n[package]".to_owned(),
+ "[features]\n\"\"=[\"\"]\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2089,7 +2179,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[features]\n\"\"=[\"a\"]\na=[\"\"]\n[package]".to_owned(),
+ "[features]\n\"\"=[\"a\"]\na=[\"\"]\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2103,7 +2193,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[features]\n\"\"=[\"a\"]\na=[\"b\"]\nb=[\"a\"]\n[package]".to_owned(),
+ "[features]\n\"\"=[\"a\"]\na=[\"b\"]\nb=[\"a\"]\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2117,7 +2207,8 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[features]\n\"\"=[\"a\"]\na=[\"c\",\"b\"]\nb=[\"a\"]\nc=[]\n[package]".to_owned(),
+ "[features]\n\"\"=[\"a\"]\na=[\"c\",\"b\"]\nb=[\"a\"]\nc=[]\n[package]\nname=\"\""
+ .to_owned(),
false,
Path::new(""),
&[]
@@ -2131,7 +2222,8 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[features]\n\"\"=[]\na=[\"c\",\"b\"]\nb=[\"a\"]\nc=[]\n[package]".to_owned(),
+ "[features]\n\"\"=[]\na=[\"c\",\"b\"]\nb=[\"a\"]\nc=[]\n[package]\nname=\"\""
+ .to_owned(),
false,
Path::new(""),
&[]
@@ -2145,7 +2237,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[features]\n\"\"=[\"a\",\"b\"]\na=[\"b\"]\nb=[]\n[package]".to_owned(),
+ "[features]\n\"\"=[\"a\",\"b\"]\na=[\"b\"]\nb=[]\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2160,7 +2252,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[features]\n\"\"=[\"a\",\"a\"]\na=[]\n[package]".to_owned(),
+ "[features]\n\"\"=[\"a\",\"a\"]\na=[]\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2176,7 +2268,7 @@ mod tests {
// Duplicate `"dep:"` feature dependencies error.
assert_eq!(
Manifest::from_toml(
- "[features]\n\"\"=[\"dep:\",\"dep:\"]\na=[]\n[package]".to_owned(),
+ "[features]\n\"\"=[\"dep:\",\"dep:\"]\na=[]\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2190,7 +2282,12 @@ mod tests {
)))
);
assert_eq!(
- Manifest::from_toml("target=2\n[package]".to_owned(), false, Path::new(""), &[]),
+ Manifest::from_toml(
+ "target=2\n[package]\nname=\"\"".to_owned(),
+ false,
+ Path::new(""),
+ &[]
+ ),
Err(Box::new(ManifestErr::ImpliedFeatures(
ImpliedFeaturesErr::TargetType,
PathBuf::new()
@@ -2198,7 +2295,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "dependencies=2\n[package]".to_owned(),
+ "dependencies=2\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2210,7 +2307,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "build-dependencies=2\n[package]".to_owned(),
+ "build-dependencies=2\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2222,7 +2319,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[dependencies]\n\"dep:\"=\"\"\n[package]".to_owned(),
+ "[dependencies]\n\"dep:\"=\"\"\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2237,7 +2334,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[dependencies]\n\"/\"=\"\"\n[package]".to_owned(),
+ "[dependencies]\n\"/\"=\"\"\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2252,7 +2349,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[build-dependencies]\n\"dep:\"=\"\"\n[package]".to_owned(),
+ "[build-dependencies]\n\"dep:\"=\"\"\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2267,7 +2364,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[build-dependencies]\n\"/\"=\"\"\n[package]".to_owned(),
+ "[build-dependencies]\n\"/\"=\"\"\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2282,7 +2379,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[dependencies]\n\"\"=2\n[package]".to_owned(),
+ "[dependencies]\n\"\"=2\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2297,7 +2394,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[build-dependencies]\n\"\"=2\n[package]".to_owned(),
+ "[build-dependencies]\n\"\"=2\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2312,7 +2409,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[dependencies]\n\"\"={optional=2}\n[package]".to_owned(),
+ "[dependencies]\n\"\"={optional=2}\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2327,7 +2424,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[build-dependencies]\n\"\"={optional=2}\n[package]".to_owned(),
+ "[build-dependencies]\n\"\"={optional=2}\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2343,7 +2440,7 @@ mod tests {
// Implied features are disallowed iff `!allow_implied_features`.
assert_eq!(
Manifest::from_toml(
- "[dependencies]\nfoo={optional=true}\n[package]".to_owned(),
+ "[dependencies]\nfoo={optional=true}\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2358,7 +2455,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[target]\n\"\"=2\n[package]".to_owned(),
+ "[target]\n\"\"=2\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2370,7 +2467,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[target.\"\"]\ndependencies=2\n[package]".to_owned(),
+ "[target.\"\"]\ndependencies=2\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2385,7 +2482,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[target.\"\"]\nbuild-dependencies=2\n[package]".to_owned(),
+ "[target.\"\"]\nbuild-dependencies=2\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2400,7 +2497,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[target.\"\".dependencies]\n\"/\"=\"\"\n[package]".to_owned(),
+ "[target.\"\".dependencies]\n\"/\"=\"\"\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2415,7 +2512,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[target.\"\".dependencies]\n\"dep:\"=\"\"\n[package]".to_owned(),
+ "[target.\"\".dependencies]\n\"dep:\"=\"\"\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2430,7 +2527,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[target.\"\".build-dependencies]\n\"/\"=\"\"\n[package]".to_owned(),
+ "[target.\"\".build-dependencies]\n\"/\"=\"\"\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2445,7 +2542,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[target.\"\".build-dependencies]\n\"dep:\"=\"\"\n[package]".to_owned(),
+ "[target.\"\".build-dependencies]\n\"dep:\"=\"\"\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2460,7 +2557,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[target.\"\".dependencies]\n\"\"=false\n[package]".to_owned(),
+ "[target.\"\".dependencies]\n\"\"=false\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2475,7 +2572,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[target.\"\".build-dependencies]\n\"\"=false\n[package]".to_owned(),
+ "[target.\"\".build-dependencies]\n\"\"=false\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2490,7 +2587,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[target.\"\".dependencies]\n\"\"={optional=2}\n[package]".to_owned(),
+ "[target.\"\".dependencies]\n\"\"={optional=2}\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2505,7 +2602,8 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[target.\"\".build-dependencies]\n\"\"={optional=2}\n[package]".to_owned(),
+ "[target.\"\".build-dependencies]\n\"\"={optional=2}\n[package]\nname=\"\""
+ .to_owned(),
false,
Path::new(""),
&[]
@@ -2522,7 +2620,7 @@ mod tests {
// implied features aren't added until after feature extraction.
assert_eq!(
Manifest::from_toml(
- "[features]\n\"\"=[\"foo\"]\n[package]".to_owned(),
+ "[features]\n\"\"=[\"foo\"]\n[package]\nname=\"\"".to_owned(),
true,
Path::new(""),
&[]
@@ -2535,7 +2633,7 @@ mod tests {
// In contrast, above would have erred sooner if `!allow_implied_features`.
assert_eq!(
Manifest::from_toml(
- "[features]\n\"\"=[\"foo\"]\n[package]".to_owned(),
+ "[features]\n\"\"=[\"foo\"]\n[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&[]
@@ -2550,7 +2648,7 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]".to_owned(),
+ "[package]\nname=\"\"".to_owned(),
false,
Path::new(""),
&["a".to_owned()]
@@ -2568,71 +2666,76 @@ mod tests {
// the explict feature `foo` and the implied feature from the dependency `foo`.
assert_eq!(
Manifest::from_toml(
- "[dependencies]\nfoo={optional=true}\n[features]\nfoo=[]\n[package]".to_owned(),
+ "[dependencies]\nfoo={optional=true}\n[features]\nfoo=[]\n[package]\nname=\"\""
+ .to_owned(),
false,
Path::new(""),
&[]
),
Ok(Manifest {
- msrv: None,
+ package: Package {
+ msrv: None,
+ name: String::new(),
+ },
features: Features(vec![("foo".to_owned(), Vec::new())]),
})
);
- // Allow empty `package`.
- assert_eq!(
- Manifest::from_toml("[package]".to_owned(), false, Path::new(""), &[]),
- Ok(Manifest {
- msrv: None,
- features: Features(Vec::new()),
- })
- );
// Allow major-only MSRV.
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\"0\"".to_owned(),
+ "[package]\nname=\"foo\"\nrust-version=\"0\"".to_owned(),
false,
Path::new(""),
&[]
),
Ok(Manifest {
- msrv: Some(Msrv {
- major: 0,
- minor: None,
- patch: None,
- }),
+ package: Package {
+ msrv: Some(Msrv {
+ major: 0,
+ minor: None,
+ patch: None,
+ }),
+ name: "foo".to_owned(),
+ },
features: Features(Vec::new()),
})
);
// Allow escapes.
assert_eq!(
Manifest::from_toml(
- "[\"\\u0070ackage\"]\n\"\\u0072ust-version\"=\"0\\u002E\\u0031\"".to_owned(),
+ "[\"\\u0070ackage\"]\n\"n\\u0061me\"=\"\\u0066oo\"\n\"\\u0072ust-version\"=\"0\\u002E\\u0031\"".to_owned(),
false,
Path::new(""),
&[]
),
Ok(Manifest {
- msrv: Some(Msrv {
- major: 0,
- minor: Some(1),
- patch: None,
- }),
+ package: Package {
+ msrv: Some(Msrv {
+ major: 0,
+ minor: Some(1),
+ patch: None,
+ }),
+ name: "foo".to_owned(),
+ },
features: Features(Vec::new()),
})
);
assert_eq!(
Manifest::from_toml(
- "[package]\nrust-version=\"0.0.0\"".to_owned(),
+ "[package]\nname=\"\"\nrust-version=\"0.0.0\"".to_owned(),
false,
Path::new(""),
&[]
),
Ok(Manifest {
- msrv: Some(Msrv {
- major: 0,
- minor: Some(0),
- patch: Some(0),
- }),
+ package: Package {
+ msrv: Some(Msrv {
+ major: 0,
+ minor: Some(0),
+ patch: Some(0),
+ }),
+ name: String::new(),
+ },
features: Features(Vec::new()),
})
);
@@ -2641,18 +2744,21 @@ mod tests {
// `target.<something>` unless the key is `dependencies` or `build-dependencies`. Don't treat
// `<something>` special in `target.<something>` other than its being a table.
assert_eq!(
- Manifest::from_toml("dev-dependencies=2\n[package]\nfoo=2\nrust-version=\"18446744073709551615.18446744073709551615.18446744073709551615\"\n[foo]\nbar=false\n[target.\"\".foo]\nbar=2\n[target.foo]\nbar=false\n[target.dependencies]\nfoo=2\n[target.build-dependencies]\nfoo=false\n[target.dev-dependencies]\nfoo=true\n".to_owned(), false, Path::new(""), &[]),
+ Manifest::from_toml("dev-dependencies=2\n[package]\nname=\"\"\n\nfoo=2\nrust-version=\"18446744073709551615.18446744073709551615.18446744073709551615\"\n[foo]\nbar=false\n[target.\"\".foo]\nbar=2\n[target.foo]\nbar=false\n[target.dependencies]\nfoo=2\n[target.build-dependencies]\nfoo=false\n[target.dev-dependencies]\nfoo=true\n".to_owned(), false, Path::new(""), &[]),
Ok(Manifest {
-
- msrv: Some(Msrv {
- major: u64::MAX,
- minor: Some(u64::MAX),
- patch: Some(u64::MAX),
- }),
+ package: Package {
+ msrv: Some(Msrv {
+ major: u64::MAX,
+ minor: Some(u64::MAX),
+ patch: Some(u64::MAX),
+ }),
+ name: String::new(),
+ },
features: Features(Vec::new()),
})
);
// [package]
+ // name = ""
//
// ["\u0064ependencies"]
// "\u0000" = "\u0000"
@@ -2702,17 +2808,21 @@ mod tests {
// 6. (c, [])
assert_eq!(
Manifest::from_toml(
- "[\"\\u0064ependencies\"]\n\"\\u0000\"=\"\\u0000\"\na={optional=true}\n[\"build-\\u0064ependencies\"]\n\"\\u0000\"={optional=true}\n[target.\"\".dependencies]\nb={optional=false,foo=2}\nfizz={optional=true,foo=3}\n[features]\ndefault=[\"bar\",\"dep:lk\",\"a/ak\",\"a/ak\"]\nbar=[\"dep\\u003Awuzz\"]\n[dev-dependencies]\nbuzz={optional=true}\n[target.a.dependencies]\nc={optional=true}\nwuzz={optional=true}\n[package]".to_owned(),
+ "[\"\\u0064ependencies\"]\n\"\\u0000\"=\"\\u0000\"\na={optional=true}\n[\"build-\\u0064ependencies\"]\n\"\\u0000\"={optional=true}\n[target.\"\".dependencies]\nb={optional=false,foo=2}\nfizz={optional=true,foo=3}\n[features]\ndefault=[\"bar\",\"dep:lk\",\"a/ak\",\"a/ak\"]\nbar=[\"dep\\u003Awuzz\"]\n[dev-dependencies]\nbuzz={optional=true}\n[target.a.dependencies]\nc={optional=true}\nwuzz={optional=true}\n[package]\nname=\"\"".to_owned(),
true,
Path::new(""),
&[]
),
Ok(Manifest {
- msrv: None,
+ package: Package {
+ msrv: None,
+ name: String::new(),
+ },
features: Features(vec![("bar".to_owned(), Vec::new()), ("default".to_owned(), vec!["bar".to_owned()]), ("a".to_owned(), Vec::new()), ("\0".to_owned(), Vec::new()), ("fizz".to_owned(), Vec::new()), ("c".to_owned(), Vec::new())]),
})
);
// [package]
+ // name = ""
//
// [dependencies]
// foo = { "optional" = true }
@@ -2723,13 +2833,16 @@ mod tests {
// bar = ["dep:foo"]
assert_eq!(
Manifest::from_toml(
- "[package]\n[dependencies]\nfoo={optional=true}\nfizz={optional=true}\n[features]\nfizz=[\"dep:fizz\"]\nbar=[\"dep:foo\"]".to_owned(),
+ "[package]\nname=\"\"\n[dependencies]\nfoo={optional=true}\nfizz={optional=true}\n[features]\nfizz=[\"dep:fizz\"]\nbar=[\"dep:foo\"]".to_owned(),
false,
Path::new(""),
&[]
),
Ok(Manifest {
- msrv: None,
+ package: Package {
+ msrv: None,
+ name: String::new(),
+ },
features: Features(vec![
("bar".to_owned(), Vec::new()),
("fizz".to_owned(), Vec::new())
@@ -2737,6 +2850,7 @@ mod tests {
})
);
// [package]
+ // name = ""
//
// [dependencies]
// bar = { "optional" = true }
@@ -2745,14 +2859,17 @@ mod tests {
// foo = ["bar"]
assert_eq!(
Manifest::from_toml(
- "[package]\n[dependencies]\nbar={optional=true}\n[features]\nfoo=[\"bar\"]"
+ "[package]\nname=\"\"\n[dependencies]\nbar={optional=true}\n[features]\nfoo=[\"bar\"]"
.to_owned(),
true,
Path::new(""),
&[]
),
Ok(Manifest {
- msrv: None,
+ package: Package {
+ msrv: None,
+ name: String::new(),
+ },
features: Features(vec![
("foo".to_owned(), vec!["bar".to_owned()]),
("bar".to_owned(), Vec::new()),
@@ -2761,49 +2878,63 @@ mod tests {
);
assert_eq!(
Manifest::from_toml(
- "[package]\n[features]\na=[]\nb=[\"a\"]".to_owned(),
+ "[package]\nname=\"\"\n[features]\na=[]\nb=[\"a\"]".to_owned(),
false,
Path::new(""),
&["a".to_owned()]
),
Ok(Manifest {
- msrv: None,
+ package: Package {
+ msrv: None,
+ name: String::new(),
+ },
features: Features(vec![]),
})
);
assert_eq!(
Manifest::from_toml(
- "[package]\n[features]\na=[]\nb=[\"a\"]".to_owned(),
+ "[package]\nname=\"\"\n[features]\na=[]\nb=[\"a\"]".to_owned(),
false,
Path::new(""),
&["b".to_owned()]
),
Ok(Manifest {
- msrv: None,
+ package: Package {
+ msrv: None,
+ name: String::new(),
+ },
features: Features(vec![("a".to_owned(), Vec::new())]),
})
);
assert_eq!(
Manifest::from_toml(
- "[package]\n[dependencies]\nc={optional=true}\n[features]\nb=[\"c\"]".to_owned(),
+ "[package]\nname=\"\"\n[dependencies]\nc={optional=true}\n[features]\nb=[\"c\"]"
+ .to_owned(),
true,
Path::new(""),
&["c".to_owned()]
),
Ok(Manifest {
- msrv: None,
+ package: Package {
+ msrv: None,
+ name: String::new(),
+ },
features: Features(vec![]),
})
);
assert_eq!(
Manifest::from_toml(
- "[package]\n[dependencies]\nc={optional=true}\n[features]\nb=[\"c\"]".to_owned(),
+ "[package]\nname=\"\"\n[dependencies]\nc={optional=true}\n[features]\nb=[\"c\"]"
+ .to_owned(),
true,
Path::new(""),
&["b".to_owned()]
),
Ok(Manifest {
- msrv: None,
+ package: Package {
+ msrv: None,
+ name: String::new(),
+ },
features: Features(vec![("c".to_owned(), Vec::new())]),
})
);