commit 7f69f27c3f9ee888b7f88ca90dbfbcdbe392203b
parent 530efb82f6712d7b55c168b8a7382da4cf06f4ab
Author: Zack Newman <zack@philomathiclife.com>
Date: Sat, 10 Jan 2026 20:49:43 -0700
support more 'targets'
Diffstat:
| M | Cargo.toml | | | 20 | +++++++++++++++----- |
| M | LICENSE-MIT | | | 2 | +- |
| M | README.md | | | 270 | +++++++++++++++++++++++++++++++++++++++++++++++++------------------------------ |
| M | src/args.rs | | | 2632 | +++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------- |
| M | src/cargo.rs | | | 254 | +++++++++++++++++++++++++++++++++++++++++-------------------------------------- |
| M | src/main.rs | | | 22 | ++++------------------ |
| M | src/rustup.rs | | | 1150 | +++++-------------------------------------------------------------------------- |
7 files changed, 2150 insertions(+), 2200 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -1,7 +1,7 @@
[package]
authors = ["Zack Newman <zack@philomathiclife.com>"]
categories = ["command-line-utilities", "development-tools::testing", "rust-patterns"]
-description = "Continuous integration for Clippy, unit tests, and doc tests for all possible features."
+description = "Continuous integration using cargo for Clippy and tests for all possible features."
documentation = "https://crates.io/crates/ci-cargo"
edition = "2024"
keywords = ["cargo", "ci", "features", "msrv", "rust"]
@@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
name = "ci-cargo"
readme = "README.md"
repository = "https://git.philomathiclife.com/repos/ci-cargo/"
-rust-version = "1.88.0"
+rust-version = "1.91.1"
version = "0.1.0"
[lints.rust]
@@ -168,6 +168,7 @@ min_ident_chars = "allow"
missing_trait_methods = "allow"
pathbuf_init_then_push = "allow"
pub_with_shorthand = "allow"
+question_mark_used = "allow"
ref_patterns = "allow"
redundant_pub_crate = "allow"
return_and_then = "allow"
@@ -188,14 +189,23 @@ unseparated_literal_suffix = "allow"
[package.metadata.docs.rs]
default-target = "x86_64-unknown-linux-gnu"
targets = [
- "aarch64-apple-darwin"
+ "aarch64-apple-darwin",
+ "aarch64-pc-windows-msvc",
+ "aarch64-unknown-linux-gnu",
+ "i686-pc-windows-msvc",
+ "i686-unknown-linux-gnu",
+ "x86_64-pc-windows-gnu",
+ "x86_64-pc-windows-msvc",
+ "x86_64-unknown-freebsd",
+ "x86_64-unknown-linux-musl",
+ "x86_64-unknown-netbsd"
]
[dependencies]
-toml = { version = "0.9.7", default-features = false, features = ["parse"] }
+toml = { version = "0.9.11", default-features = false, features = ["parse"] }
[target.'cfg(target_os = "openbsd")'.dependencies]
-priv_sep = { version = "3.0.0-alpha.2.1", default-features = false }
+priv_sep = { version = "3.0.0-alpha.4.0", default-features = false, features = ["std"] }
[profile.release]
codegen-units = 1
diff --git a/LICENSE-MIT b/LICENSE-MIT
@@ -1,4 +1,4 @@
-Copyright © 2025 Zack Newman
+Copyright © 2026 Zack Newman
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
diff --git a/README.md b/README.md
@@ -5,7 +5,7 @@ CI app for Rust code
[<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 `check`,
-`clippy`, `test --tests`, and `test --doc` for all possible combinations of features defined in `Cargo.toml`.
+`clippy`, and `test` 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
@@ -37,20 +37,20 @@ easily cause a crate to not be tested with certain combinations of features. Ins
with each possible combination of features, this handles it automatically. Additionally it automatically ensures the
build works on both the stable or default toolchain _and_ the stated MSRV (if one is defined).
+## Usage
+
+`ci-cargo [COMMAND] [OPTIONS] [COMMAND] [OPTIONS] [COMMAND] [OPTIONS]`
+
## Commands
-* `<none>`: `cargo clippy` and `cargo test` are invoked for each combination of features.
+* `check`: `cargo check`.
+* `clippy`: `cargo clippy`.
* `help`: Prints help message.
+* `test`: `cargo test`.
* `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
+## Global Options
-* `--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`.
@@ -58,7 +58,6 @@ build works on both the stable or default toolchain _and_ the stated MSRV (if on
* `--color`: `--color always` is passed to the above commands; otherwise without this option, `--color never` is
passed.
* `--default-toolchain`: `cargo` is used instead of `cargo +stable`.
-* `--deny-warnings`: `cargo clippy -- --Dwarnings` is invoked for each combination of features.
* `--dir <PATH>`: Changes the working directory to the passed path before executing. Without this, the current
directory and all ancestor directories are searched for `Cargo.toml` before changing the working directory to its
location.
@@ -71,22 +70,55 @@ build works on both the stable or default toolchain _and_ the stated MSRV (if on
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`.
* `--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.
* `--summary`: Writes the toolchain(s) used and the combinations of features run on to `stdout` on success.
-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` 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.
+## Check Options
+
+* `--all-targets`: `--all-targets` is passed.
+* `--benches`: `--benches` is passed.
+* `--bins`: `--bins` is passed.
+* `--examples`: `--examples` is passed.
+* `--lib`: `--lib` is passed.
+* `--tests`: `--tests` is passed.
+
+## Clippy Options
+
+* `--all-targets`: `--all-targets` is passed.
+* `--benches`: `--benches` is passed.
+* `--bins`: `--bins` is passed.
+* `--deny-warnings`: `-- -Dwarnings` is passed.
+* `--examples`: `--examples` is passed.
+* `--lib`: `--lib` is passed.
+* `--tests`: `--tests` is passed.
+
+## Test Options
+
+* `--all-targets`: `cargo test --all-targets` _and_ `cargo test --doc` are run. Note if one wants _just_ the
+ behavior of `cargo test --all-targets`, then one must pass `cargo test --benches --bins --examples --lib --tests`
+ instead.
+* `--benches`: `--benches` is passed.
+* `--bins`: `--bins` is passed.
+* `--doc`: `--doc` is passed.
+* `--examples`: `--examples` is passed.
+* `--ignored`: `-- --ignored` is passed.
+* `--include-ignored`: `-- --include-ignored` is passed.
+* `--lib`: `--lib` is passed.
+* `--tests`: `--tests` is passed.
+
+The following conditions must be met:
+
+* `help` and `version` mustn't be combined with other commands or options.
+* Any unique and non-empty combination of `check`, `clippy`, and `test` can be used.
+* Command-specific options must be unique for a given command.
+* Global options are allowed after any command but must be unique.
+* Command-specific options must follow the command.
+* `test` options `--ignored` and `--include-ignored` are mutually exclusive.
+* `--all-targets` mustn't be combined with other targets (e.g., `--lib`).
+* `test` option `--doc` mustn't be combined with other targets (e.g., `--tests`).
+* `--ignore-msrv` is not allowed if the stable toolchain is used.
## `ci-cargo` in action
@@ -103,7 +135,7 @@ license = "MIT OR Apache-2.0"
name = "example"
readme = "README.md"
repository = "https://example.com/"
-rust-version = "1.89.0"
+rust-version = "1.90.0"
version = "0.1.0"
[lints.rust]
@@ -171,80 +203,116 @@ default = ["foo"]
foo = []
bar = ["fizz"]
fizz = []
-[zack@laptop example]$ ci-cargo --all-targets --include-ignored --progress --summary
-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
+[zack@laptop example]$ ci-cargo clippy --all-targets test --all-targets --include-ignored --progress --summary
+Package: example. Toolchain (1/2): cargo +stable. Features (1/32, 5 skipped): buzz,fizz,foo. Command (1/3): clippy. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (1/32, 5 skipped): buzz,fizz,foo. Command (2/3): test --all-targets. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (1/32, 5 skipped): buzz,fizz,foo. Command (3/3): test --doc. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (2/32, 6 skipped): fizz,foo. Command (1/3): clippy. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (2/32, 6 skipped): fizz,foo. Command (2/3): test --all-targets. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (2/32, 6 skipped): fizz,foo. Command (3/3): test --doc. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (3/32, 10 skipped): bar,buzz,foo. Command (1/3): clippy. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (3/32, 10 skipped): bar,buzz,foo. Command (2/3): test --all-targets. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (3/32, 10 skipped): bar,buzz,foo. Command (3/3): test --doc. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (4/32, 10 skipped): buzz,foo. Command (1/3): clippy. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (4/32, 10 skipped): buzz,foo. Command (2/3): test --all-targets. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (4/32, 10 skipped): buzz,foo. Command (3/3): test --doc. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (5/32, 10 skipped): bar,foo. Command (1/3): clippy. Time running: 0 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (5/32, 10 skipped): bar,foo. Command (2/3): test --all-targets. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (5/32, 10 skipped): bar,foo. Command (3/3): test --doc. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (6/32, 10 skipped): foo. Command (1/3): clippy. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (6/32, 10 skipped): foo. Command (2/3): test --all-targets. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (6/32, 10 skipped): foo. Command (3/3): test --doc. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (7/32, 11 skipped): buzz,default,fizz. Command (1/3): clippy. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (7/32, 11 skipped): buzz,default,fizz. Command (2/3): test --all-targets. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (7/32, 11 skipped): buzz,default,fizz. Command (3/3): test --doc. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (8/32, 12 skipped): default,fizz. Command (1/3): clippy. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (8/32, 12 skipped): default,fizz. Command (2/3): test --all-targets. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (8/32, 12 skipped): default,fizz. Command (3/3): test --doc. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (9/32, 13 skipped): buzz,fizz. Command (1/3): clippy. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (9/32, 13 skipped): buzz,fizz. Command (2/3): test --all-targets. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (9/32, 13 skipped): buzz,fizz. Command (3/3): test --doc. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (10/32, 14 skipped): fizz. Command (1/3): clippy. Time running: 1 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (10/32, 14 skipped): fizz. Command (2/3): test --all-targets. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (10/32, 14 skipped): fizz. Command (3/3): test --doc. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (11/32, 14 skipped): bar,buzz,default. Command (1/3): clippy. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (11/32, 14 skipped): bar,buzz,default. Command (2/3): test --all-targets. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (11/32, 14 skipped): bar,buzz,default. Command (3/3): test --doc. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (12/32, 14 skipped): buzz,default. Command (1/3): clippy. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (12/32, 14 skipped): buzz,default. Command (2/3): test --all-targets. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (12/32, 14 skipped): buzz,default. Command (3/3): test --doc. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (13/32, 14 skipped): bar,default. Command (1/3): clippy. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (13/32, 14 skipped): bar,default. Command (2/3): test --all-targets. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (13/32, 14 skipped): bar,default. Command (3/3): test --doc. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (14/32, 14 skipped): default. Command (1/3): clippy. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (14/32, 14 skipped): default. Command (2/3): test --all-targets. Time running: 2 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (14/32, 14 skipped): default. Command (3/3): test --doc. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (15/32, 14 skipped): bar,buzz. Command (1/3): clippy. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (15/32, 14 skipped): bar,buzz. Command (2/3): test --all-targets. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (15/32, 14 skipped): bar,buzz. Command (3/3): test --doc. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (16/32, 14 skipped): buzz. Command (1/3): clippy. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (16/32, 14 skipped): buzz. Command (2/3): test --all-targets. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (16/32, 14 skipped): buzz. Command (3/3): test --doc. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (17/32, 14 skipped): bar. Command (1/3): clippy. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (17/32, 14 skipped): bar. Command (2/3): test --all-targets. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (17/32, 14 skipped): bar. Command (3/3): test --doc. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (18/32, 14 skipped): <none>. Command (1/3): clippy. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (18/32, 14 skipped): <none>. Command (2/3): test --all-targets. Time running: 3 s.
+Package: example. Toolchain (1/2): cargo +stable. Features (18/32, 14 skipped): <none>. Command (3/3): test --doc. Time running: 3 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (1/32, 5 skipped): buzz,fizz,foo. Command (1/3): clippy. Time running: 3 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (1/32, 5 skipped): buzz,fizz,foo. Command (2/3): test --all-targets. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (1/32, 5 skipped): buzz,fizz,foo. Command (3/3): test --doc. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (2/32, 6 skipped): fizz,foo. Command (1/3): clippy. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (2/32, 6 skipped): fizz,foo. Command (2/3): test --all-targets. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (2/32, 6 skipped): fizz,foo. Command (3/3): test --doc. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (3/32, 10 skipped): bar,buzz,foo. Command (1/3): clippy. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (3/32, 10 skipped): bar,buzz,foo. Command (2/3): test --all-targets. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (3/32, 10 skipped): bar,buzz,foo. Command (3/3): test --doc. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (4/32, 10 skipped): buzz,foo. Command (1/3): clippy. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (4/32, 10 skipped): buzz,foo. Command (2/3): test --all-targets. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (4/32, 10 skipped): buzz,foo. Command (3/3): test --doc. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (5/32, 10 skipped): bar,foo. Command (1/3): clippy. Time running: 4 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (5/32, 10 skipped): bar,foo. Command (2/3): test --all-targets. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (5/32, 10 skipped): bar,foo. Command (3/3): test --doc. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (6/32, 10 skipped): foo. Command (1/3): clippy. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (6/32, 10 skipped): foo. Command (2/3): test --all-targets. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (6/32, 10 skipped): foo. Command (3/3): test --doc. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (7/32, 11 skipped): buzz,default,fizz. Command (1/3): clippy. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (7/32, 11 skipped): buzz,default,fizz. Command (2/3): test --all-targets. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (7/32, 11 skipped): buzz,default,fizz. Command (3/3): test --doc. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (8/32, 12 skipped): default,fizz. Command (1/3): clippy. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (8/32, 12 skipped): default,fizz. Command (2/3): test --all-targets. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (8/32, 12 skipped): default,fizz. Command (3/3): test --doc. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (9/32, 13 skipped): buzz,fizz. Command (1/3): clippy. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (9/32, 13 skipped): buzz,fizz. Command (2/3): test --all-targets. Time running: 5 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (9/32, 13 skipped): buzz,fizz. Command (3/3): test --doc. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (10/32, 14 skipped): fizz. Command (1/3): clippy. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (10/32, 14 skipped): fizz. Command (2/3): test --all-targets. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (10/32, 14 skipped): fizz. Command (3/3): test --doc. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (11/32, 14 skipped): bar,buzz,default. Command (1/3): clippy. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (11/32, 14 skipped): bar,buzz,default. Command (2/3): test --all-targets. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (11/32, 14 skipped): bar,buzz,default. Command (3/3): test --doc. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (12/32, 14 skipped): buzz,default. Command (1/3): clippy. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (12/32, 14 skipped): buzz,default. Command (2/3): test --all-targets. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (12/32, 14 skipped): buzz,default. Command (3/3): test --doc. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (13/32, 14 skipped): bar,default. Command (1/3): clippy. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (13/32, 14 skipped): bar,default. Command (2/3): test --all-targets. Time running: 6 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (13/32, 14 skipped): bar,default. Command (3/3): test --doc. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (14/32, 14 skipped): default. Command (1/3): clippy. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (14/32, 14 skipped): default. Command (2/3): test --all-targets. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (14/32, 14 skipped): default. Command (3/3): test --doc. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (15/32, 14 skipped): bar,buzz. Command (1/3): clippy. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (15/32, 14 skipped): bar,buzz. Command (2/3): test --all-targets. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (15/32, 14 skipped): bar,buzz. Command (3/3): test --doc. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (16/32, 14 skipped): buzz. Command (1/3): clippy. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (16/32, 14 skipped): buzz. Command (2/3): test --all-targets. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (16/32, 14 skipped): buzz. Command (3/3): test --doc. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (17/32, 14 skipped): bar. Command (1/3): clippy. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (17/32, 14 skipped): bar. Command (2/3): test --all-targets. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (17/32, 14 skipped): bar. Command (3/3): test --doc. Time running: 7 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (18/32, 14 skipped): <none>. Command (1/3): clippy. Time running: 8 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (18/32, 14 skipped): <none>. Command (2/3): test --all-targets. Time running: 8 s.
+Package: example. Toolchain (2/2): cargo +1.90.0. Features (18/32, 14 skipped): <none>. Command (3/3): test --doc. Time running: 8 s.
+Toolchains used: cargo +stable and cargo +1.90.0
Features used:
buzz,fizz,foo
fizz,foo
@@ -265,11 +333,11 @@ buzz
bar
<none>
[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 test --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 doc-tests
-doc-tests is an unknown argument. See ci-cargo help for more information.
+[zack@laptop example]$ ci-cargo --summary clippy
+A command was not passed as the first argument. See ci-cargo help for more information.
```
## Limitations
@@ -325,8 +393,8 @@ at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you,
as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
-Before any PR is sent, `ci-cargo --all-targets --include-ignored` should be run on itself. Additionally
-`cargo +nightly doc` should be run to ensure documentation can be built.
+Before any PR is sent, `ci-cargo clippy --all-targets test --benches --bins --examples --tests --include-ignored`
+should be run on itself. Additionally `cargo +nightly doc` should be run to ensure documentation can be built.
### Status
diff --git a/src/args.rs b/src/args.rs
@@ -1,5 +1,5 @@
use super::{
- cargo::{CargoErr, Check, Clippy, Options, TestKind, Tests, Toolchain},
+ cargo::{CargoErr, Check, Clippy, Options, Test, Toolchain},
manifest::PowerSet,
};
use core::{
@@ -15,49 +15,71 @@ use std::{
/// Help message.
pub(crate) const HELP_MSG: &str = "Continuous integration of all features using cargo
-Usage: ci-cargo [COMMAND] [OPTIONS]
+Usage: ci-cargo [COMMAND] [OPTIONS] [COMMAND] [OPTIONS] [COMMAND] [OPTIONS]
Commands:
- <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
+ check cargo check
+ clippy cargo clippy
+ help This message
+ test cargo test
+ version Prints version info
-Options:
- --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
- --color --color always is passed to each command; otherwise --color never is
- --default-toolchain cargo is invoked as is (i.e., cargo +stable is never used)
- --deny-warnings -Dwarnings is passed to cargo clippy
- --dir <PATH> Set the working directory
- --ignore-compile-errors compile_error!s are ignored
- --ignore-features <feats> Ignore the provided comma-separated features
- --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
- --summary Writes the toolchain(s) and combinations of features used to stdout on success
+Global Options:
+ --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
+ --color --color always is passed to each command; otherwise --color never is
+ --default-toolchain cargo is invoked as is (i.e., cargo +stable is never used)
+ --dir <PATH> Set the working directory
+ --ignore-compile-errors compile_error!s are ignored
+ --ignore-features <feats> Ignore the provided comma-separated features
+ --ignore-msrv --ignore-rust-version is passed to each command for the default toolchain
+ --progress Writes the progress to stdout
+ --rustup-home <PATH> Set the storage directory used by rustup
+ --skip-msrv cargo +<MSRV> is not used
+ --summary Writes the toolchain(s) and combinations of features used to stdout on success
-Any unique sequence of the above options are allowed so long as the following
-conditions are met:
+Check Options:
+ --all-targets --all-targets is passed
+ --benches --benches is passed
+ --bins --bins is passed
+ --examples --examples is passed
+ --lib --lib is passed
+ --tests --tests is 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
+Clippy Options:
+ --all-targets --all-targets is passed
+ --benches --benches is passed
+ --bins --bins is passed
+ --deny-warnings -- -Dwarnings is passed
+ --examples --examples is passed
+ --lib --lib is passed
+ --tests --tests is passed
+
+Test Options:
+ --all-targets cargo test --all-targets and cargo test --doc are run
+ --benches --benches is passed
+ --bins --bins is passed
+ --doc --doc is passed
+ --examples --examples is passed
+ --ignored -- --ignored is passed
+ --include-ignored -- --include-ignored is passed
+ --lib --lib is passed
+ --tests --tests is passed
+
+The following conditions must be met:
+
+* the help and version commands mustn't be combined with other commands or options
+* any unique combination of check, clippy, and test can be used
+* command-specific options must be unique for a given command
+* global options are allowed after any command but must be unique
+* command-specific options must follow the command
+* the test options --ignored and --include-ignored are mutually exclusive
+* --all-targets mustn't be combined with other targets (e.g., --lib)
+* the test option --doc mustn't be combined with other targets
* --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:
+cargo +stable will be used to run the command(s) if all of the following conditions are met:
* --default-toolchain was not passed
* rust-toolchain.toml does not exist in the package directory nor its ancestor directories
@@ -67,7 +89,7 @@ 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 not
+* 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
@@ -83,14 +105,16 @@ const VERSION: &str = "version";
const CHECK: &str = "check";
/// `"clippy"`.
const CLIPPY: &str = "clippy";
-/// `"tests"`.
-const TESTS: &str = "tests";
-/// `"doc-tests"`.
-const DOC_TESTS: &str = "doc-tests";
+/// `"test"`.
+const TEST: &str = "test";
/// `"--all-targets"`.
const ALL_TARGETS: &str = "--all-targets";
/// `"--allow-implied-features"`.
const ALLOW_IMPLIED_FEATURES: &str = "--allow-implied-features";
+/// `"--benches"`.
+const BENCHES: &str = "--benches";
+/// `"--bins"`.
+const BINS: &str = "--bins";
/// `"--cargo-home"`.
const CARGO_HOME: &str = "--cargo-home";
/// `"--cargo-path"`.
@@ -103,6 +127,10 @@ const DEFAULT_TOOLCHAIN: &str = "--default-toolchain";
const DENY_WARNINGS: &str = "--deny-warnings";
/// `"--dir"`.
const DIR: &str = "--dir";
+/// `"--doc"`.
+const DOC: &str = "--doc";
+/// `"--examples"`.
+const EXAMPLES: &str = "--examples";
/// `"--ignore-compile-errors"`.
const IGNORE_COMPILE_ERRORS: &str = "--ignore-compile-errors";
/// `"--ignore-features"`.
@@ -113,6 +141,8 @@ const IGNORE_MSRV: &str = "--ignore-msrv";
const IGNORED: &str = "--ignored";
/// `"--include-ignored"`.
const INCLUDE_IGNORED: &str = "--include-ignored";
+/// `"--lib"`.
+const LIB: &str = "--lib";
/// `"--progress"`.
const PROGRESS: &str = "--progress";
/// `"--rustup-home"`.
@@ -121,11 +151,31 @@ const RUSTUP_HOME: &str = "--rustup-home";
const SKIP_MSRV: &str = "--skip-msrv";
/// `"--summary"`.
const SUMMARY: &str = "--summary";
+/// `"--tests"`.
+const TESTS: &str = "--tests";
+/// `"cargo"`.
+const CARGO: &str = "cargo";
+/// `"test --doc"`.
+const TEST_DOC: &str = "test --doc";
+/// `"test --all-targets"`.
+const TEST_ALL_TARGETS: &str = "test --all-targets";
+/// `"1"`.
+const ONE: &str = "1";
+/// `"2"`.
+const TWO: &str = "2";
+/// `"3"`.
+const THREE: &str = "3";
+/// `"4"`.
+const FOUR: &str = "4";
+/// `"cargo "`.
+const CARGO_SPACE: &str = "cargo ";
/// Error returned when parsing arguments passed to the application.
#[cfg_attr(test, derive(Debug, PartialEq))]
pub(crate) enum ArgsErr {
/// Error when no arguments exist.
NoArgs,
+ /// Error when no command was passed.
+ NoCommand,
/// Error when an unknown argument is passed. The contained [`OsString`] is the value of the unknown command
/// or option.
UnknownArg(OsString),
@@ -143,13 +193,11 @@ pub(crate) enum ArgsErr {
MissingCargoHome,
/// Error when `--rustup-home` is passed with no file path to the storage directory `rustup` uses.
MissingRustupHome,
- /// Error when `--all-targets` is passed for `tests` or `doc-tests`.
- AllTargetsTests,
- /// 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.
+ /// Error when `--all-targets` is passed with other targets.
+ AllTargets,
+ /// Error when `--doc` is passed with other targets with the `test` command.
+ Doc,
+ /// Error when `--ignored` and `--include-ignored` are passed with the `test` command.
IgnoredIncludeIgnored,
/// Error when `--ignore-features` was not passed any features.
///
@@ -168,6 +216,10 @@ impl ArgsErr {
stderr,
"No arguments exist including the name of the process itself.{FINAL_SENTENCE}"
),
+ Self::NoCommand => writeln!(
+ stderr,
+ "A command was not passed as the first argument.{FINAL_SENTENCE}"
+ ),
Self::UnknownArg(arg) => {
writeln!(
stderr,
@@ -218,22 +270,16 @@ impl ArgsErr {
"{RUSTUP_HOME} was passed without a path to the rustup storage directory.{FINAL_SENTENCE}"
)
}
- Self::AllTargetsTests => {
- writeln!(
- stderr,
- "{ALL_TARGETS} was passed with {TESTS} or {DOC_TESTS}.{FINAL_SENTENCE}"
- )
- }
- Self::DenyWarningsCheckTests => {
+ Self::AllTargets => {
writeln!(
stderr,
- "{DENY_WARNINGS} was passed with {CHECK}, {TESTS}, or {DOC_TESTS}.{FINAL_SENTENCE}"
+ "{ALL_TARGETS} was passed with other targets.{FINAL_SENTENCE}"
)
}
- Self::IgnoredCheckClippyDoc => {
+ Self::Doc => {
writeln!(
stderr,
- "{IGNORED} or {INCLUDE_IGNORED} was passed with {CHECK}, {CLIPPY}, or {DOC_TESTS}.{FINAL_SENTENCE}"
+ "{DOC} was passed with other targets.{FINAL_SENTENCE}"
)
}
Self::IgnoredIncludeIgnored => {
@@ -316,11 +362,12 @@ impl Default for Opts {
}
}
}
-/// Controls if `cargo test --tests -- --ignored` or `cargo test --tests --include-ignored` should be run.
+/// Controls if `cargo test -- --ignored` or `cargo test --include-ignored` should be run.
#[cfg_attr(test, derive(Debug, PartialEq))]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub(crate) enum Ignored {
/// Don't run any `ignore` tests.
+ #[default]
None,
/// Only run `ignore` tests.
Only,
@@ -374,7 +421,7 @@ impl Display for NonZeroUsizePlus1 {
// SAFETY:
// 2^n is even for all n != 0. When n = 0, 2^n = 1. This means we can always increment the last
// digit without carrying.
- // We only mutate the last digit which is guaranteed to be valid ASCII; thuse we can increment
+ // We only mutate the last digit which is guaranteed to be valid ASCII; thus we can increment
// the `u8` since digits are consecutive in ASCII.
*unsafe { val.as_bytes_mut() }.index_mut(idx) += 1;
write!(f, "{val}")
@@ -414,14 +461,14 @@ struct Progress<'package, 'toolchain> {
stdout: Option<StdoutLock<'static>>,
}
impl<'package> Progress<'package, '_> {
- /// Returns `Self` based on running both clippy and tests.
- fn all(
+ /// Returns `Self` based on running check.
+ fn check(
package: &'package str,
toolchain: Toolchain<'_>,
use_msrv: bool,
features_total: NonZeroUsizePlus1,
) -> Self {
- Self::inner_new(package, "clippy", "2", toolchain, use_msrv, features_total)
+ Self::inner_new(package, CHECK, ONE, toolchain, use_msrv, features_total)
}
/// Returns `Self` based on running clippy.
fn clippy(
@@ -430,48 +477,79 @@ impl<'package> Progress<'package, '_> {
use_msrv: bool,
features_total: NonZeroUsizePlus1,
) -> Self {
- Self::inner_new(package, "clippy", "1", toolchain, use_msrv, features_total)
+ Self::inner_new(package, CLIPPY, ONE, toolchain, use_msrv, features_total)
}
- /// Returns `Self` based on running tests --tests.
- fn tests(
+ /// Returns `Self` based on running test.
+ fn test(
package: &'package str,
toolchain: Toolchain<'_>,
use_msrv: bool,
features_total: NonZeroUsizePlus1,
+ all_targets: bool,
) -> Self {
- Self::inner_new(
- package,
- "test --tests",
- "1",
- toolchain,
- use_msrv,
- features_total,
- )
+ if all_targets {
+ Self::inner_new(
+ package,
+ TEST_ALL_TARGETS,
+ TWO,
+ toolchain,
+ use_msrv,
+ features_total,
+ )
+ } else {
+ Self::inner_new(package, TEST, ONE, toolchain, use_msrv, features_total)
+ }
}
- /// Returns `Self` based on running tests --doc.
- fn doc_tests(
+ /// Returns `Self` based on running both check and clippy.
+ fn check_clippy(
package: &'package str,
toolchain: Toolchain<'_>,
use_msrv: bool,
features_total: NonZeroUsizePlus1,
) -> Self {
- Self::inner_new(
- package,
- "test --doc",
- "1",
- toolchain,
- use_msrv,
- features_total,
- )
+ Self::inner_new(package, CHECK, TWO, toolchain, use_msrv, features_total)
}
- /// Returns `Self` based on running check.
- fn check(
+ /// Returns `Self` based on running both check and test.
+ fn check_test(
+ package: &'package str,
+ toolchain: Toolchain<'_>,
+ use_msrv: bool,
+ features_total: NonZeroUsizePlus1,
+ test_all_targets: bool,
+ ) -> Self {
+ if test_all_targets {
+ Self::inner_new(package, CHECK, THREE, toolchain, use_msrv, features_total)
+ } else {
+ Self::inner_new(package, CHECK, TWO, toolchain, use_msrv, features_total)
+ }
+ }
+ /// Returns `Self` based on running both clippy and test.
+ fn clippy_test(
+ package: &'package str,
+ toolchain: Toolchain<'_>,
+ use_msrv: bool,
+ features_total: NonZeroUsizePlus1,
+ test_all_targets: bool,
+ ) -> Self {
+ if test_all_targets {
+ Self::inner_new(package, CLIPPY, THREE, toolchain, use_msrv, features_total)
+ } else {
+ Self::inner_new(package, CLIPPY, TWO, toolchain, use_msrv, features_total)
+ }
+ }
+ /// Returns `Self` based on running check, clippy, and test.
+ fn check_clippy_test(
package: &'package str,
toolchain: Toolchain<'_>,
use_msrv: bool,
features_total: NonZeroUsizePlus1,
+ test_all_targets: bool,
) -> Self {
- Self::inner_new(package, "check", "1", toolchain, use_msrv, features_total)
+ if test_all_targets {
+ Self::inner_new(package, CHECK, FOUR, toolchain, use_msrv, features_total)
+ } else {
+ Self::inner_new(package, CHECK, THREE, toolchain, use_msrv, features_total)
+ }
}
/// Returns `Self` based on the passed arguments.
fn inner_new(
@@ -483,17 +561,17 @@ impl<'package> Progress<'package, '_> {
features_total: NonZeroUsizePlus1,
) -> Self {
let (cargo_cmd, toolchain) = if matches!(tool, Toolchain::Stable) {
- ("cargo ", "+stable")
+ (CARGO_SPACE, "+stable")
} else {
- ("cargo", "")
+ (CARGO, "")
};
Self {
package,
- toolchain_counter: "1",
- toolchain_total: if use_msrv { "2" } else { "1" },
+ toolchain_counter: ONE,
+ toolchain_total: if use_msrv { TWO } else { ONE },
cargo_cmd,
toolchain,
- cmd_counter: "1",
+ cmd_counter: ONE,
cmd_total,
cmd,
features_total: features_total.to_string(),
@@ -520,35 +598,132 @@ impl<'package> Progress<'package, '_> {
}
}
}
+/// Target selection.
+#[cfg_attr(test, derive(Debug, PartialEq))]
+#[derive(Clone, Copy)]
+pub(crate) enum Target {
+ /// `--benches`.
+ Benches,
+ /// `--bins`.
+ Bins,
+ /// `--examples`.
+ Examples,
+ /// `--lib`.
+ Lib,
+ /// `--tests`.
+ Tests,
+}
+impl Target {
+ /// Transfoms `self` into a `u8`.
+ const fn to_u8(self) -> u8 {
+ match self {
+ Self::Benches => 1,
+ Self::Bins => 2,
+ Self::Examples => 4,
+ Self::Lib => 8,
+ Self::Tests => 16,
+ }
+ }
+ /// Returns `self` as an `OsString`.
+ fn to_os_string(self) -> OsString {
+ match match self {
+ Self::Benches => BENCHES,
+ Self::Bins => BINS,
+ Self::Examples => EXAMPLES,
+ Self::Lib => LIB,
+ Self::Tests => TESTS,
+ }
+ .parse()
+ {
+ Ok(val) => val,
+ Err(e) => match e {},
+ }
+ }
+}
+/// Combination of targets to select.
+#[cfg_attr(test, derive(Debug, PartialEq))]
+#[derive(Clone, Copy, Default)]
+pub(crate) struct Targets(u8);
+impl Targets {
+ /// Returns `Self` only containing `target`.
+ const fn new(target: Target) -> Self {
+ Self(target.to_u8())
+ }
+ /// Adds `target` to `self` returning `true` iff `target` wasn't added before.
+ const fn add(&mut self, target: Target) -> bool {
+ let this = self.0 | target.to_u8();
+ if this == self.0 {
+ false
+ } else {
+ self.0 = this;
+ true
+ }
+ }
+ /// Returns `true` iff `self` contains `target`.
+ pub(super) const fn contains(self, target: Target) -> bool {
+ let val = target.to_u8();
+ self.0 & val == val
+ }
+}
+/// Test targets to select.
+#[cfg_attr(test, derive(Debug, PartialEq))]
+#[derive(Clone, Copy)]
+pub(crate) enum CheckClippyTargets {
+ /// Use the default targets.
+ Default,
+ /// `--all-targets`.
+ All,
+ /// All targets.
+ Targets(Targets),
+}
+/// Test targets to select.
+#[cfg_attr(test, derive(Debug, PartialEq))]
+#[derive(Clone, Copy)]
+pub(crate) enum TestTargets {
+ /// Use the default targets.
+ Default,
+ /// `--all-targets`.
+ ///
+ /// This causes all non-`doc` targets to be run and the `--doc` target/mode to be run as well.
+ All,
+ /// Non-`doc` targets.
+ Targets(Targets),
+ /// `--doc`.
+ Doc,
+}
/// `cargo` command(s) we should run.
#[cfg_attr(test, derive(Debug, PartialEq))]
+#[derive(Clone, Copy)]
pub(crate) enum Cmd {
- /// 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
- /// the `Ignored` represents if `--ignored` or `--include-ignored` were
- /// passed.
- All(bool, bool, Ignored),
- /// `cargo clippy`.
- ///
- /// 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 test --tests`.
- Tests(Ignored),
- /// `cargo test --doc`.
- DocTests,
/// `cargo check`.
+ Check(CheckClippyTargets),
+ /// `cargo clippy`.
///
- /// The contained `bool` is `true` iff `--all-targets` was passed,
- Check(bool),
+ /// The contained `bool` is `true` iff `--deny-warnings` was passed.
+ Clippy(CheckClippyTargets, bool),
+ /// `cargo test`.
+ Test(TestTargets, Ignored),
+ /// [`Self::Check`] and [`Self::Clippy`].
+ CheckClippy(CheckClippyTargets, CheckClippyTargets, bool),
+ /// [`Self::Check`] and [`Self::Test`].
+ CheckTest(CheckClippyTargets, TestTargets, Ignored),
+ /// [`Self::Clippy`] and [`Self::Test`].
+ ClippyTest(CheckClippyTargets, bool, TestTargets, Ignored),
+ /// [`Self::Check`], [`Self::Clippy`], and [`Self::Test`].
+ CheckClippyTest(
+ CheckClippyTargets,
+ CheckClippyTargets,
+ bool,
+ TestTargets,
+ Ignored,
+ ),
}
impl Cmd {
/// 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.
+ #[expect(clippy::too_many_lines, reason = "long match expression")]
pub(crate) fn run<'a>(
self,
options: Options<'a, '_, '_>,
@@ -557,9 +732,9 @@ impl Cmd {
progress: bool,
) -> Result<(), Box<CargoErr>> {
match self {
- Self::All(all_targets, deny_warning, ignored_tests) => Self::run_all(
+ Self::Check(targets) => Self::run_check(
progress.then(|| {
- Progress::all(
+ Progress::check(
options.package_name,
options.toolchain,
msrv.is_some(),
@@ -568,12 +743,10 @@ impl Cmd {
}),
msrv,
options,
- all_targets,
- deny_warning,
- ignored_tests,
+ targets,
power_set,
),
- Self::Clippy(all_targets, deny_warnings) => Self::run_clippy(
+ Self::Clippy(targets, deny_warnings) => Self::run_clippy(
progress.then(|| {
Progress::clippy(
options.package_name,
@@ -584,140 +757,241 @@ impl Cmd {
}),
msrv,
options,
- all_targets,
+ targets,
deny_warnings,
power_set,
),
- Self::Tests(ignored_tests) => Self::run_unit_tests(
- progress.then(|| {
- Progress::tests(
- options.package_name,
- options.toolchain,
- msrv.is_some(),
- power_set.len(),
+ Self::Test(targets, ignored) => {
+ if matches!(targets, TestTargets::All) {
+ Self::run_test_all_targets(
+ progress.then(|| {
+ Progress::test(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ true,
+ )
+ }),
+ msrv,
+ options,
+ ignored,
+ power_set,
)
- }),
- msrv,
- options,
- ignored_tests,
- power_set,
- ),
- Self::DocTests => Self::run_doc_tests(
- progress.then(|| {
- Progress::doc_tests(
- options.package_name,
- options.toolchain,
- msrv.is_some(),
- power_set.len(),
+ } else {
+ Self::run_test(
+ progress.then(|| {
+ Progress::test(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ false,
+ )
+ }),
+ msrv,
+ options,
+ targets,
+ ignored,
+ power_set,
)
- }),
- 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(),
+ }
+ }
+ Self::CheckClippy(check_targets, clippy_targets, deny_warnings) => {
+ Self::run_check_clippy(
+ progress.then(|| {
+ Progress::check_clippy(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ )
+ }),
+ msrv,
+ options,
+ check_targets,
+ (clippy_targets, deny_warnings),
+ power_set,
+ )
+ }
+ Self::CheckTest(check_targets, test_targets, ignored) => {
+ if matches!(test_targets, TestTargets::All) {
+ Self::run_check_test_all_targets(
+ progress.then(|| {
+ Progress::check_test(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ true,
+ )
+ }),
+ msrv,
+ options,
+ check_targets,
+ ignored,
+ power_set,
)
- }),
- msrv,
- options,
- all_targets,
- power_set,
- ),
+ } else {
+ Self::run_check_test(
+ progress.then(|| {
+ Progress::check_test(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ false,
+ )
+ }),
+ msrv,
+ options,
+ check_targets,
+ (test_targets, ignored),
+ power_set,
+ )
+ }
+ }
+ Self::ClippyTest(clippy_targets, deny_warnings, test_targets, ignored) => {
+ if matches!(test_targets, TestTargets::All) {
+ Self::run_clippy_test_all_targets(
+ progress.then(|| {
+ Progress::clippy_test(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ true,
+ )
+ }),
+ msrv,
+ options,
+ (clippy_targets, deny_warnings),
+ ignored,
+ power_set,
+ )
+ } else {
+ Self::run_clippy_test(
+ progress.then(|| {
+ Progress::clippy_test(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ false,
+ )
+ }),
+ msrv,
+ options,
+ (clippy_targets, deny_warnings),
+ (test_targets, ignored),
+ power_set,
+ )
+ }
+ }
+ Self::CheckClippyTest(
+ check_targets,
+ clippy_targets,
+ deny_warnings,
+ test_targets,
+ ignored,
+ ) => {
+ if matches!(test_targets, TestTargets::All) {
+ Self::run_check_clippy_test_all_targets(
+ progress.then(|| {
+ Progress::check_clippy_test(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ true,
+ )
+ }),
+ msrv,
+ options,
+ check_targets,
+ (clippy_targets, deny_warnings),
+ ignored,
+ power_set,
+ )
+ } else {
+ Self::run_check_clippy_test(
+ progress.then(|| {
+ Progress::check_clippy_test(
+ options.package_name,
+ options.toolchain,
+ msrv.is_some(),
+ power_set.len(),
+ false,
+ )
+ }),
+ msrv,
+ options,
+ check_targets,
+ (clippy_targets, deny_warnings),
+ (test_targets, ignored),
+ power_set,
+ )
+ }
+ }
}
}
- /// Runs `cargo clippy` and `cargo test` for all features in `power_set`.
+ /// 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.
- #[expect(clippy::else_if_without_else, reason = "don't want an empty else")]
- fn run_all<'a>(
+ fn run_check<'a>(
mut progress: Option<Progress<'_, 'a>>,
msrv: Option<&'a str>,
mut options: Options<'a, '_, '_>,
- all_targets: bool,
- deny_warnings: bool,
- ignored_tests: Ignored,
+ targets: CheckClippyTargets,
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.cmd_counter = "1";
- prog.cmd = "clippy";
- prog.write_to_stdout(set, feat_counter, skip_count);
- if let Err(e) = Clippy::run(&mut options, all_targets, deny_warnings, set) {
- return Err(e);
- }
- // Note we run tests even if a `compile_error` occurred since it may not occur for tests.
- prog.cmd_counter = "2";
- 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);
- }
- // 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();
+ /// Runs the commands for each feature combination.
+ fn run_loop<'a>(
+ progress: &mut Option<Progress<'_, 'a>>,
+ options: &mut Options<'a, '_, '_>,
+ targets: CheckClippyTargets,
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ let mut feat_counter = 1usize;
+ // We have two loops instead of one to avoid repeated and unnecessary if branches. This does
+ // cause some bloat though.
+ if let Some(ref mut prog) = *progress {
while let Some((set, skip_count)) = power_set.next_set_with_skip_count() {
- prog.cmd_counter = "1";
- prog.cmd = "clippy";
- prog.write_to_stdout(set, feat_counter, skip_count);
- if let Err(e) = Clippy::run(&mut options, all_targets, deny_warnings, set) {
- return Err(e);
- }
- // Note we run tests even if a `compile_error` occurred since it may not occur for tests.
- prog.cmd_counter = "2";
- prog.cmd = "test";
+ prog.cmd_counter = ONE;
+ prog.cmd = CHECK;
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);
- }
+ Check::run(options, targets, set)?;
// 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) = Clippy::run(&mut options, all_targets, deny_warnings, set) {
- return Err(e);
- // Note we run tests even if a `compile_error` occurred since it may not occur for tests.
- } else if let Err(e) = Tests::run(&mut options, TestKind::All(ignored_tests), set) {
- return Err(e);
+ } else {
+ while let Some(set) = power_set.next_set() {
+ Check::run(options, targets, set)?;
+ // 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);
}
}
+ Ok(())
+ }
+ run_loop(&mut progress, &mut options, targets, power_set).and_then(|()| {
if let Some(msrv_val) = msrv {
+ if let Some(ref mut prog) = progress {
+ prog.toolchain_counter = TWO;
+ prog.cargo_cmd = CARGO_SPACE;
+ prog.toolchain = msrv_val;
+ }
options.toolchain = Toolchain::Msrv(msrv_val);
power_set.reset();
- while let Some(set) = power_set.next_set() {
- if let Err(e) = Clippy::run(&mut options, all_targets, deny_warnings, set) {
- return Err(e);
- // Note we run tests even if a `compile_error` occurred since it may not occur for tests.
- } else if let Err(e) =
- Tests::run(&mut options, TestKind::All(ignored_tests), set)
- {
- return Err(e);
- }
- }
+ run_loop(&mut progress, &mut options, targets, power_set)
+ } else {
+ Ok(())
}
- }
- Ok(())
+ })
}
/// Runs `cargo clippy` for all features in `power_set`.
///
@@ -727,258 +1001,880 @@ impl Cmd {
mut progress: Option<Progress<'_, 'a>>,
msrv: Option<&'a str>,
mut options: Options<'a, '_, '_>,
- all_targets: bool,
+ targets: CheckClippyTargets,
deny_warnings: 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) = Clippy::run(&mut options, all_targets, deny_warnings, 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();
+ /// Runs the commands for each feature combination.
+ fn run_loop<'a>(
+ progress: &mut Option<Progress<'_, 'a>>,
+ options: &mut Options<'a, '_, '_>,
+ targets: CheckClippyTargets,
+ deny_warnings: bool,
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ let mut feat_counter = 1usize;
+ // We have two loops instead of one to avoid repeated and unnecessary if branches. This does
+ // cause some bloat though.
+ if let Some(ref mut prog) = *progress {
while let Some((set, skip_count)) = power_set.next_set_with_skip_count() {
+ prog.cmd_counter = ONE;
+ prog.cmd = CLIPPY;
prog.write_to_stdout(set, feat_counter, skip_count);
- if let Err(e) = Clippy::run(&mut options, all_targets, deny_warnings, set) {
- return Err(e);
- }
+ Clippy::run(options, targets, deny_warnings, set)?;
// 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) = Clippy::run(&mut options, all_targets, deny_warnings, set) {
- return Err(e);
+ } else {
+ while let Some(set) = power_set.next_set() {
+ Clippy::run(options, targets, deny_warnings, set)?;
+ // 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);
}
}
+ Ok(())
+ }
+ run_loop(
+ &mut progress,
+ &mut options,
+ targets,
+ deny_warnings,
+ power_set,
+ )
+ .and_then(|()| {
if let Some(msrv_val) = msrv {
+ if let Some(ref mut prog) = progress {
+ prog.toolchain_counter = TWO;
+ prog.cargo_cmd = CARGO_SPACE;
+ prog.toolchain = msrv_val;
+ }
options.toolchain = Toolchain::Msrv(msrv_val);
power_set.reset();
- while let Some(set) = power_set.next_set() {
- if let Err(e) = Clippy::run(&mut options, all_targets, deny_warnings, set) {
- return Err(e);
- }
- }
+ run_loop(
+ &mut progress,
+ &mut options,
+ targets,
+ deny_warnings,
+ power_set,
+ )
+ } else {
+ Ok(())
}
- }
- Ok(())
+ })
}
- /// Runs `cargo test --tests` for all features in `power_set`.
+ /// Runs `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.
- fn run_unit_tests<'a>(
+ fn run_test<'a>(
mut progress: Option<Progress<'_, 'a>>,
msrv: Option<&'a str>,
mut options: Options<'a, '_, '_>,
- ignored_tests: Ignored,
+ targets: TestTargets,
+ ignored: Ignored,
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) = Tests::run(&mut options, TestKind::Unit(ignored_tests), 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();
+ /// Runs the commands for each feature combination.
+ fn run_loop<'a>(
+ progress: &mut Option<Progress<'_, 'a>>,
+ options: &mut Options<'a, '_, '_>,
+ targets: TestTargets,
+ ignored: Ignored,
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ let mut feat_counter = 1usize;
+ // We have two loops instead of one to avoid repeated and unnecessary if branches. This does
+ // cause some bloat though.
+ if let Some(ref mut prog) = *progress {
while let Some((set, skip_count)) = power_set.next_set_with_skip_count() {
+ prog.cmd_counter = ONE;
+ prog.cmd = TEST;
prog.write_to_stdout(set, feat_counter, skip_count);
- if let Err(e) = Tests::run(&mut options, TestKind::Unit(ignored_tests), set) {
- return Err(e);
- }
+ Test::run(options, targets, ignored, set)?;
// 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) = Tests::run(&mut options, TestKind::Unit(ignored_tests), set) {
- return Err(e);
+ } else {
+ while let Some(set) = power_set.next_set() {
+ Test::run(options, targets, ignored, set)?;
+ // 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);
}
}
+ Ok(())
+ }
+ run_loop(&mut progress, &mut options, targets, ignored, power_set).and_then(|()| {
if let Some(msrv_val) = msrv {
+ if let Some(ref mut prog) = progress {
+ prog.toolchain_counter = TWO;
+ prog.cargo_cmd = CARGO_SPACE;
+ prog.toolchain = msrv_val;
+ }
options.toolchain = Toolchain::Msrv(msrv_val);
power_set.reset();
- while let Some(set) = power_set.next_set() {
- if let Err(e) = Tests::run(&mut options, TestKind::Unit(ignored_tests), set) {
- return Err(e);
- }
- }
+ run_loop(&mut progress, &mut options, targets, ignored, power_set)
+ } else {
+ Ok(())
}
- }
- Ok(())
+ })
}
- /// Runs `cargo test --doc` for all features in `power_set`.
+ /// Runs `cargo test --all-targets` and `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>(
+ fn run_test_all_targets<'a>(
mut progress: Option<Progress<'_, 'a>>,
msrv: Option<&'a str>,
mut options: Options<'a, '_, '_>,
+ ignored: Ignored,
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);
- match Tests::run(&mut options, TestKind::Doc, set) {
- Ok(no_library_target) => {
- if no_library_target {
- return Ok(());
- }
- }
- Err(e) => 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();
+ /// Runs the commands for each feature combination.
+ fn run_loop<'a>(
+ progress: &mut Option<Progress<'_, 'a>>,
+ options: &mut Options<'a, '_, '_>,
+ ignored: Ignored,
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ let mut feat_counter = 1usize;
+ // We have two loops instead of one to avoid repeated and unnecessary if branches. This does
+ // cause some bloat though.
+ if let Some(ref mut prog) = *progress {
while let Some((set, skip_count)) = power_set.next_set_with_skip_count() {
+ prog.cmd_counter = ONE;
+ prog.cmd = TEST_ALL_TARGETS;
prog.write_to_stdout(set, feat_counter, skip_count);
- // If there is no library target, then we would have been informed above.
- if let Err(e) = Tests::run(&mut options, TestKind::Doc, set) {
- return Err(e);
- }
+ Test::run(options, TestTargets::All, ignored, set).and_then(|()| {
+ prog.cmd_counter = TWO;
+ prog.cmd = TEST_DOC;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Test::run(options, TestTargets::Doc, ignored, set)
+ })?;
// 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() {
- match Tests::run(&mut options, TestKind::Doc, set) {
- Ok(no_library_target) => {
- if no_library_target {
- // We don't want to continue invoking `cargo test --doc` once we know this is not a
- // library target.
- return Ok(());
- }
- }
- Err(e) => return Err(e),
+ } else {
+ while let Some(set) = power_set.next_set() {
+ Test::run(options, TestTargets::All, ignored, set)
+ .and_then(|()| Test::run(options, TestTargets::Doc, ignored, set))?;
+ // 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);
}
}
+ Ok(())
+ }
+ run_loop(&mut progress, &mut options, ignored, power_set).and_then(|()| {
if let Some(msrv_val) = msrv {
+ if let Some(ref mut prog) = progress {
+ prog.toolchain_counter = TWO;
+ prog.cargo_cmd = CARGO_SPACE;
+ prog.toolchain = msrv_val;
+ }
options.toolchain = Toolchain::Msrv(msrv_val);
power_set.reset();
- while let Some(set) = power_set.next_set() {
- // If there is no library target, then we would have been informed above.
- if let Err(e) = Tests::run(&mut options, TestKind::Doc, set) {
- return Err(e);
- }
- }
+ run_loop(&mut progress, &mut options, ignored, power_set)
+ } else {
+ Ok(())
}
- }
- Ok(())
+ })
}
- /// Runs `cargo check` for all features in `power_set`.
+ /// Runs `cargo check` and `cargo clippy` 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>(
+ fn run_check_clippy<'a>(
mut progress: Option<Progress<'_, 'a>>,
msrv: Option<&'a str>,
mut options: Options<'a, '_, '_>,
- all_targets: bool,
+ check_targets: CheckClippyTargets,
+ clippy_info: (CheckClippyTargets, 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();
+ /// Runs the commands for each feature combination.
+ fn run_loop<'a>(
+ progress: &mut Option<Progress<'_, 'a>>,
+ options: &mut Options<'a, '_, '_>,
+ check_targets: CheckClippyTargets,
+ (clippy_targets, deny_warnings): (CheckClippyTargets, bool),
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ let mut feat_counter = 1usize;
+ // We have two loops instead of one to avoid repeated and unnecessary if branches. This does
+ // cause some bloat though.
+ if let Some(ref mut prog) = *progress {
while let Some((set, skip_count)) = power_set.next_set_with_skip_count() {
+ prog.cmd_counter = ONE;
+ prog.cmd = CHECK;
prog.write_to_stdout(set, feat_counter, skip_count);
- if let Err(e) = Check::run(&mut options, all_targets, set) {
- return Err(e);
- }
+ Check::run(options, check_targets, set).and_then(|()| {
+ prog.cmd_counter = TWO;
+ prog.cmd = CLIPPY;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Clippy::run(options, clippy_targets, deny_warnings, set)
+ })?;
// 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);
+ } else {
+ while let Some(set) = power_set.next_set() {
+ Check::run(options, check_targets, set)
+ .and_then(|()| Clippy::run(options, clippy_targets, deny_warnings, set))?;
+ // 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);
}
}
+ Ok(())
+ }
+ run_loop(
+ &mut progress,
+ &mut options,
+ check_targets,
+ clippy_info,
+ power_set,
+ )
+ .and_then(|()| {
if let Some(msrv_val) = msrv {
+ if let Some(ref mut prog) = progress {
+ prog.toolchain_counter = TWO;
+ prog.cargo_cmd = CARGO_SPACE;
+ prog.toolchain = msrv_val;
+ }
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);
- }
- }
+ run_loop(
+ &mut progress,
+ &mut options,
+ check_targets,
+ clippy_info,
+ power_set,
+ )
+ } else {
+ Ok(())
}
+ })
+ }
+ /// Runs `cargo check` 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.
+ fn run_check_test<'a>(
+ mut progress: Option<Progress<'_, 'a>>,
+ msrv: Option<&'a str>,
+ mut options: Options<'a, '_, '_>,
+ check_targets: CheckClippyTargets,
+ test_info: (TestTargets, Ignored),
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ /// Runs the commands for each feature combination.
+ fn run_loop<'a>(
+ progress: &mut Option<Progress<'_, 'a>>,
+ options: &mut Options<'a, '_, '_>,
+ check_targets: CheckClippyTargets,
+ (test_targets, ignored): (TestTargets, Ignored),
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ let mut feat_counter = 1usize;
+ // We have two loops instead of one to avoid repeated and unnecessary if branches. This does
+ // cause some bloat though.
+ if let Some(ref mut prog) = *progress {
+ while let Some((set, skip_count)) = power_set.next_set_with_skip_count() {
+ prog.cmd_counter = ONE;
+ prog.cmd = CHECK;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Check::run(options, check_targets, set).and_then(|()| {
+ prog.cmd_counter = TWO;
+ prog.cmd = TEST;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Test::run(options, test_targets, ignored, set)
+ })?;
+ // 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() {
+ Check::run(options, check_targets, set)
+ .and_then(|()| Test::run(options, test_targets, ignored, set))?;
+ // 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);
+ }
+ }
+ Ok(())
+ }
+ run_loop(
+ &mut progress,
+ &mut options,
+ check_targets,
+ test_info,
+ power_set,
+ )
+ .and_then(|()| {
+ if let Some(msrv_val) = msrv {
+ if let Some(ref mut prog) = progress {
+ prog.toolchain_counter = TWO;
+ prog.cargo_cmd = CARGO_SPACE;
+ prog.toolchain = msrv_val;
+ }
+ options.toolchain = Toolchain::Msrv(msrv_val);
+ power_set.reset();
+ run_loop(
+ &mut progress,
+ &mut options,
+ check_targets,
+ test_info,
+ power_set,
+ )
+ } else {
+ Ok(())
+ }
+ })
+ }
+ /// Runs `cargo check`, `cargo test --all-targets`, and `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_check_test_all_targets<'a>(
+ mut progress: Option<Progress<'_, 'a>>,
+ msrv: Option<&'a str>,
+ mut options: Options<'a, '_, '_>,
+ check_targets: CheckClippyTargets,
+ ignored: Ignored,
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ /// Runs the commands for each feature combination.
+ fn run_loop<'a>(
+ progress: &mut Option<Progress<'_, 'a>>,
+ options: &mut Options<'a, '_, '_>,
+ check_targets: CheckClippyTargets,
+ ignored: Ignored,
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ let mut feat_counter = 1usize;
+ // We have two loops instead of one to avoid repeated and unnecessary if branches. This does
+ // cause some bloat though.
+ if let Some(ref mut prog) = *progress {
+ while let Some((set, skip_count)) = power_set.next_set_with_skip_count() {
+ prog.cmd_counter = ONE;
+ prog.cmd = CHECK;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Check::run(options, check_targets, set).and_then(|()| {
+ prog.cmd_counter = TWO;
+ prog.cmd = TEST_ALL_TARGETS;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Test::run(options, TestTargets::All, ignored, set).and_then(|()| {
+ prog.cmd_counter = THREE;
+ prog.cmd = TEST_DOC;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Test::run(options, TestTargets::Doc, ignored, set)
+ })
+ })?;
+ // 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() {
+ Check::run(options, check_targets, set).and_then(|()| {
+ Test::run(options, TestTargets::All, ignored, set)
+ .and_then(|()| Test::run(options, TestTargets::Doc, ignored, set))
+ })?;
+ // 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);
+ }
+ }
+ Ok(())
+ }
+ run_loop(
+ &mut progress,
+ &mut options,
+ check_targets,
+ ignored,
+ power_set,
+ )
+ .and_then(|()| {
+ if let Some(msrv_val) = msrv {
+ if let Some(ref mut prog) = progress {
+ prog.toolchain_counter = TWO;
+ prog.cargo_cmd = CARGO_SPACE;
+ prog.toolchain = msrv_val;
+ }
+ options.toolchain = Toolchain::Msrv(msrv_val);
+ power_set.reset();
+ run_loop(
+ &mut progress,
+ &mut options,
+ check_targets,
+ ignored,
+ power_set,
+ )
+ } else {
+ Ok(())
+ }
+ })
+ }
+ /// 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.
+ fn run_clippy_test<'a>(
+ mut progress: Option<Progress<'_, 'a>>,
+ msrv: Option<&'a str>,
+ mut options: Options<'a, '_, '_>,
+ clippy_info: (CheckClippyTargets, bool),
+ test_info: (TestTargets, Ignored),
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ /// Runs the commands for each feature combination.
+ fn run_loop<'a>(
+ progress: &mut Option<Progress<'_, 'a>>,
+ options: &mut Options<'a, '_, '_>,
+ (clippy_targets, deny_warnings): (CheckClippyTargets, bool),
+ (test_targets, ignored): (TestTargets, Ignored),
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ let mut feat_counter = 1usize;
+ // We have two loops instead of one to avoid repeated and unnecessary if branches. This does
+ // cause some bloat though.
+ if let Some(ref mut prog) = *progress {
+ while let Some((set, skip_count)) = power_set.next_set_with_skip_count() {
+ prog.cmd_counter = ONE;
+ prog.cmd = CLIPPY;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Clippy::run(options, clippy_targets, deny_warnings, set).and_then(|()| {
+ prog.cmd_counter = TWO;
+ prog.cmd = TEST;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Test::run(options, test_targets, ignored, set)
+ })?;
+ // 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() {
+ Clippy::run(options, clippy_targets, deny_warnings, set)
+ .and_then(|()| Test::run(options, test_targets, ignored, set))?;
+ // 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);
+ }
+ }
+ Ok(())
+ }
+ run_loop(
+ &mut progress,
+ &mut options,
+ clippy_info,
+ test_info,
+ power_set,
+ )
+ .and_then(|()| {
+ if let Some(msrv_val) = msrv {
+ if let Some(ref mut prog) = progress {
+ prog.toolchain_counter = TWO;
+ prog.cargo_cmd = CARGO_SPACE;
+ prog.toolchain = msrv_val;
+ }
+ options.toolchain = Toolchain::Msrv(msrv_val);
+ power_set.reset();
+ run_loop(
+ &mut progress,
+ &mut options,
+ clippy_info,
+ test_info,
+ power_set,
+ )
+ } else {
+ Ok(())
+ }
+ })
+ }
+ /// Runs `cargo clippy`, `cargo test --all-targets`, and `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_clippy_test_all_targets<'a>(
+ mut progress: Option<Progress<'_, 'a>>,
+ msrv: Option<&'a str>,
+ mut options: Options<'a, '_, '_>,
+ clippy_info: (CheckClippyTargets, bool),
+ ignored: Ignored,
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ /// Runs the commands for each feature combination.
+ fn run_loop<'a>(
+ progress: &mut Option<Progress<'_, 'a>>,
+ options: &mut Options<'a, '_, '_>,
+ (clippy_targets, deny_warnings): (CheckClippyTargets, bool),
+ ignored: Ignored,
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ let mut feat_counter = 1usize;
+ // We have two loops instead of one to avoid repeated and unnecessary if branches. This does
+ // cause some bloat though.
+ if let Some(ref mut prog) = *progress {
+ while let Some((set, skip_count)) = power_set.next_set_with_skip_count() {
+ prog.cmd_counter = ONE;
+ prog.cmd = CLIPPY;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Clippy::run(options, clippy_targets, deny_warnings, set).and_then(|()| {
+ prog.cmd_counter = TWO;
+ prog.cmd = TEST_ALL_TARGETS;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Test::run(options, TestTargets::All, ignored, set).and_then(|()| {
+ prog.cmd_counter = THREE;
+ prog.cmd = TEST_DOC;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Test::run(options, TestTargets::Doc, ignored, set)
+ })
+ })?;
+ // 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() {
+ Clippy::run(options, clippy_targets, deny_warnings, set).and_then(|()| {
+ Test::run(options, TestTargets::All, ignored, set)
+ .and_then(|()| Test::run(options, TestTargets::Doc, ignored, set))
+ })?;
+ // 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);
+ }
+ }
+ Ok(())
}
- Ok(())
+ run_loop(&mut progress, &mut options, clippy_info, ignored, power_set).and_then(|()| {
+ if let Some(msrv_val) = msrv {
+ if let Some(ref mut prog) = progress {
+ prog.toolchain_counter = TWO;
+ prog.cargo_cmd = CARGO_SPACE;
+ prog.toolchain = msrv_val;
+ }
+ options.toolchain = Toolchain::Msrv(msrv_val);
+ power_set.reset();
+ run_loop(&mut progress, &mut options, clippy_info, ignored, power_set)
+ } else {
+ Ok(())
+ }
+ })
+ }
+ /// Runs `cargo check`, `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.
+ fn run_check_clippy_test<'a>(
+ mut progress: Option<Progress<'_, 'a>>,
+ msrv: Option<&'a str>,
+ mut options: Options<'a, '_, '_>,
+ check_targets: CheckClippyTargets,
+ clippy_info: (CheckClippyTargets, bool),
+ test_info: (TestTargets, Ignored),
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ /// Runs the commands for each feature combination.
+ fn run_loop<'a>(
+ progress: &mut Option<Progress<'_, 'a>>,
+ options: &mut Options<'a, '_, '_>,
+ check_targets: CheckClippyTargets,
+ (clippy_targets, deny_warnings): (CheckClippyTargets, bool),
+ (test_targets, ignored): (TestTargets, Ignored),
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ let mut feat_counter = 1usize;
+ // We have two loops instead of one to avoid repeated and unnecessary if branches. This does
+ // cause some bloat though.
+ if let Some(ref mut prog) = *progress {
+ while let Some((set, skip_count)) = power_set.next_set_with_skip_count() {
+ prog.cmd_counter = ONE;
+ prog.cmd = CHECK;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Check::run(options, check_targets, set).and_then(|()| {
+ prog.cmd_counter = TWO;
+ prog.cmd = CLIPPY;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Clippy::run(options, clippy_targets, deny_warnings, set).and_then(|()| {
+ prog.cmd_counter = THREE;
+ prog.cmd = TEST;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Test::run(options, test_targets, ignored, set)
+ })
+ })?;
+ // 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() {
+ Check::run(options, check_targets, set).and_then(|()| {
+ Clippy::run(options, clippy_targets, deny_warnings, set)
+ .and_then(|()| Test::run(options, test_targets, ignored, set))
+ })?;
+ // 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);
+ }
+ }
+ Ok(())
+ }
+ run_loop(
+ &mut progress,
+ &mut options,
+ check_targets,
+ clippy_info,
+ test_info,
+ power_set,
+ )
+ .and_then(|()| {
+ if let Some(msrv_val) = msrv {
+ if let Some(ref mut prog) = progress {
+ prog.toolchain_counter = TWO;
+ prog.cargo_cmd = CARGO_SPACE;
+ prog.toolchain = msrv_val;
+ }
+ options.toolchain = Toolchain::Msrv(msrv_val);
+ power_set.reset();
+ run_loop(
+ &mut progress,
+ &mut options,
+ check_targets,
+ clippy_info,
+ test_info,
+ power_set,
+ )
+ } else {
+ Ok(())
+ }
+ })
+ }
+ /// Runs `cargo check`, `cargo clippy`, `cargo test --all-targets`, and `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_check_clippy_test_all_targets<'a>(
+ mut progress: Option<Progress<'_, 'a>>,
+ msrv: Option<&'a str>,
+ mut options: Options<'a, '_, '_>,
+ check_targets: CheckClippyTargets,
+ clippy_info: (CheckClippyTargets, bool),
+ ignored: Ignored,
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ /// Runs the commands for each feature combination.
+ fn run_loop<'a>(
+ progress: &mut Option<Progress<'_, 'a>>,
+ options: &mut Options<'a, '_, '_>,
+ check_targets: CheckClippyTargets,
+ (clippy_targets, deny_warnings): (CheckClippyTargets, bool),
+ ignored: Ignored,
+ power_set: &mut PowerSet<'_>,
+ ) -> Result<(), Box<CargoErr>> {
+ let mut feat_counter = 1usize;
+ // We have two loops instead of one to avoid repeated and unnecessary if branches. This does
+ // cause some bloat though.
+ if let Some(ref mut prog) = *progress {
+ while let Some((set, skip_count)) = power_set.next_set_with_skip_count() {
+ prog.cmd_counter = ONE;
+ prog.cmd = CHECK;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Check::run(options, check_targets, set).and_then(|()| {
+ prog.cmd_counter = TWO;
+ prog.cmd = CLIPPY;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Clippy::run(options, clippy_targets, deny_warnings, set).and_then(|()| {
+ prog.cmd_counter = THREE;
+ prog.cmd = TEST_ALL_TARGETS;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Test::run(options, TestTargets::All, ignored, set).and_then(|()| {
+ prog.cmd_counter = FOUR;
+ prog.cmd = TEST_DOC;
+ prog.write_to_stdout(set, feat_counter, skip_count);
+ Test::run(options, TestTargets::Doc, ignored, set)
+ })
+ })
+ })?;
+ // 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() {
+ Check::run(options, check_targets, set).and_then(|()| {
+ Clippy::run(options, clippy_targets, deny_warnings, set).and_then(|()| {
+ Test::run(options, TestTargets::All, ignored, set)
+ .and_then(|()| Test::run(options, TestTargets::Doc, ignored, set))
+ })
+ })?;
+ // 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);
+ }
+ }
+ Ok(())
+ }
+ run_loop(
+ &mut progress,
+ &mut options,
+ check_targets,
+ clippy_info,
+ ignored,
+ power_set,
+ )
+ .and_then(|()| {
+ if let Some(msrv_val) = msrv {
+ if let Some(ref mut prog) = progress {
+ prog.toolchain_counter = TWO;
+ prog.cargo_cmd = CARGO_SPACE;
+ prog.toolchain = msrv_val;
+ }
+ options.toolchain = Toolchain::Msrv(msrv_val);
+ power_set.reset();
+ run_loop(
+ &mut progress,
+ &mut options,
+ check_targets,
+ clippy_info,
+ ignored,
+ power_set,
+ )
+ } else {
+ Ok(())
+ }
+ })
}
}
-/// `ci-cargo` command to run.
-#[cfg_attr(test, derive(Debug, PartialEq))]
-pub(crate) enum MetaCmd {
- /// Write help to stdout.
- Help,
- /// Write version info to stdout.
- Version,
- /// Execute `cargo` command(s).
- Cargo(Cmd, Opts),
+/// `cargo` command passed.
+enum CargoCmd<'a> {
+ /// check.
+ Check(&'a mut CheckClippyTargets),
+ /// clippy.
+ Clippy(&'a mut (CheckClippyTargets, bool)),
+ /// test.
+ Test(&'a mut (TestTargets, Ignored)),
+}
+impl CargoCmd<'_> {
+ /// Adds the `--all-targets` target to `self`.
+ fn add_all_targets(&mut self) -> Result<(), ArgsErr> {
+ match *self {
+ Self::Check(ref mut check_targets) => match **check_targets {
+ CheckClippyTargets::Default => {
+ **check_targets = CheckClippyTargets::All;
+ Ok(())
+ }
+ CheckClippyTargets::All => {
+ Err(ArgsErr::DuplicateOption(match ALL_TARGETS.parse() {
+ Ok(arg) => arg,
+ Err(e) => match e {},
+ }))
+ }
+ CheckClippyTargets::Targets(_) => Err(ArgsErr::AllTargets),
+ },
+ Self::Clippy(&mut (ref mut clippy_targets, _)) => match *clippy_targets {
+ CheckClippyTargets::Default => {
+ *clippy_targets = CheckClippyTargets::All;
+ Ok(())
+ }
+ CheckClippyTargets::All => {
+ Err(ArgsErr::DuplicateOption(match ALL_TARGETS.parse() {
+ Ok(arg) => arg,
+ Err(e) => match e {},
+ }))
+ }
+ CheckClippyTargets::Targets(_) => Err(ArgsErr::AllTargets),
+ },
+ Self::Test(&mut (ref mut test_targets, _)) => match *test_targets {
+ TestTargets::Default => {
+ *test_targets = TestTargets::All;
+ Ok(())
+ }
+ TestTargets::All => Err(ArgsErr::DuplicateOption(match ALL_TARGETS.parse() {
+ Ok(arg) => arg,
+ Err(e) => match e {},
+ })),
+ TestTargets::Targets(_) | TestTargets::Doc => Err(ArgsErr::AllTargets),
+ },
+ }
+ }
+ /// Adds the `target` to `self`.
+ fn add_target(&mut self, target: Target) -> Result<(), ArgsErr> {
+ match *self {
+ Self::Check(ref mut check_targets) => match **check_targets {
+ CheckClippyTargets::Default => {
+ **check_targets = CheckClippyTargets::Targets(Targets::new(target));
+ Ok(())
+ }
+ CheckClippyTargets::All => Err(ArgsErr::AllTargets),
+ CheckClippyTargets::Targets(ref mut targets) => {
+ if targets.add(target) {
+ Ok(())
+ } else {
+ Err(ArgsErr::DuplicateOption(target.to_os_string()))
+ }
+ }
+ },
+ Self::Clippy(&mut (ref mut clippy_targets, _)) => match *clippy_targets {
+ CheckClippyTargets::Default => {
+ *clippy_targets = CheckClippyTargets::Targets(Targets::new(target));
+ Ok(())
+ }
+ CheckClippyTargets::All => Err(ArgsErr::AllTargets),
+ CheckClippyTargets::Targets(ref mut targets) => {
+ if targets.add(target) {
+ Ok(())
+ } else {
+ Err(ArgsErr::DuplicateOption(target.to_os_string()))
+ }
+ }
+ },
+ Self::Test(&mut (ref mut test_targets, _)) => match *test_targets {
+ TestTargets::Default => {
+ *test_targets = TestTargets::Targets(Targets::new(target));
+ Ok(())
+ }
+ TestTargets::All => Err(ArgsErr::AllTargets),
+ TestTargets::Targets(ref mut targets) => {
+ if targets.add(target) {
+ Ok(())
+ } else {
+ Err(ArgsErr::DuplicateOption(target.to_os_string()))
+ }
+ }
+ TestTargets::Doc => Err(ArgsErr::Doc),
+ },
+ }
+ }
}
/// Helper to store options from the command line.
#[expect(
@@ -987,8 +1883,6 @@ pub(crate) enum MetaCmd {
)]
#[derive(Default)]
struct ArgOpts {
- /// `--all-targets`.
- all_targets: bool,
/// `--allow-implied-features`.
allow_implied_features: bool,
/// `--cargo-home` along with the path.
@@ -999,8 +1893,6 @@ struct ArgOpts {
color: bool,
/// `--default-toolchain`.
default_toolchain: bool,
- /// `--deny-warnings`.
- deny_warnings: bool,
/// `--dir` along with the path.
dir: Option<PathBuf>,
/// `--ignore-compile-errors`.
@@ -1009,10 +1901,6 @@ struct ArgOpts {
ignore_msrv: bool,
/// `--ignore-features` along with the features to ignore.
ignore_features: Vec<String>,
- /// `--ignored`.
- ignored: bool,
- /// `--include-ignored`.
- include_ignored: bool,
/// `--progress`.
progress: bool,
/// `--rustup-home` along with the path.
@@ -1022,20 +1910,6 @@ struct ArgOpts {
/// `--summary`.
summary: bool,
}
-impl ArgOpts {
- /// Returns `Ignored` based on [`Self::ignored`] and [`Self::include_ignored`].
- const fn ignored(&self) -> Ignored {
- if self.ignored {
- Ignored::Only
- } else if self.include_ignored {
- Ignored::Include
- } else {
- Ignored::None
- }
- }
-}
-/// `"cargo"`.
-const CARGO: &str = "cargo";
/// Returns `"cargo"`.
fn cargo_path() -> PathBuf {
CARGO.to_owned().into()
@@ -1059,104 +1933,125 @@ impl From<ArgOpts> for Opts {
}
}
}
+/// `ci-cargo` command to run.
+#[cfg_attr(test, derive(Debug, PartialEq))]
+pub(crate) enum MetaCmd {
+ /// Run the `cargo` command(s).
+ Cargo(Cmd, Opts),
+ /// Write help message to stdout.
+ Help,
+ /// Write version info to stdout.
+ Version,
+}
impl MetaCmd {
- /// Recursively extracts options from `args`.
+ /// Extracts options from `args`.
///
- /// This must only be called from [`Self::from_args`].
+ /// This must only be called from [`Self::from_args`]. `cmd` is the current command command-specific
+ /// options apply to.
+ ///
+ /// Returns the next `CargoCmd`.
#[expect(unsafe_code, reason = "comment justifies correctness")]
#[expect(
clippy::arithmetic_side_effects,
reason = "comment justifies correctness"
)]
- #[expect(clippy::else_if_without_else, reason = "more concise")]
#[expect(
clippy::too_many_lines,
reason = "expected since we need to extract all the passed options"
)]
fn extract_options<T: Iterator<Item = OsString>>(
+ cmd: &mut CargoCmd<'_>,
opts: &mut ArgOpts,
- arg: Option<OsString>,
mut args: T,
- ) -> Result<(), ArgsErr> {
- arg.map_or_else(
- || Ok(()),
- |val| {
- if let Some(val_str) = val.to_str() {
- match val_str {
- ALL_TARGETS => {
- if opts.all_targets {
- return Err(ArgsErr::DuplicateOption(val));
- }
- opts.all_targets = true;
- }
- ALLOW_IMPLIED_FEATURES => {
- if opts.allow_implied_features {
- return Err(ArgsErr::DuplicateOption(val));
- }
+ ) -> Result<Option<OsString>, ArgsErr> {
+ while let Some(arg) = args.next() {
+ if let Some(arg_str) = arg.to_str() {
+ match arg_str {
+ ALL_TARGETS => cmd.add_all_targets(),
+ ALLOW_IMPLIED_FEATURES => {
+ if opts.allow_implied_features {
+ Err(ArgsErr::DuplicateOption(arg))
+ } else {
opts.allow_implied_features = true;
+ Ok(())
}
- CARGO_HOME => {
- if opts.cargo_home.is_some() {
- return Err(ArgsErr::DuplicateOption(val));
- } else if let Some(path) = args.next() {
- opts.cargo_home = Some(path.into());
- } else {
- return Err(ArgsErr::MissingCargoHome);
- }
- }
- CARGO_PATH => {
- if opts.cargo_path.is_some() {
- return Err(ArgsErr::DuplicateOption(val));
- } else if let Some(p) = args.next() {
- // This won't overflow since `p.len() + 6 < usize::MAX` since
- // `p.len() <= isize::MAX`, `usize::MAX >= u16::MAX`, and
- // `i16::MAX + 6 < u16::MAX`.
- let mut path = PathBuf::with_capacity(CARGO.len() + 1 + p.len());
- path.push(p);
- path.push(CARGO);
- opts.cargo_path = Some(path);
- } else {
- return Err(ArgsErr::MissingCargoPath);
- }
- }
- COLOR => {
- if opts.color {
- return Err(ArgsErr::DuplicateOption(val));
- }
+ }
+ BENCHES => cmd.add_target(Target::Benches),
+ BINS => cmd.add_target(Target::Bins),
+ CARGO_HOME => args.next().map_or(Err(ArgsErr::MissingCargoHome), |path| {
+ opts.cargo_home
+ .replace(path.into())
+ .map_or(Ok(()), |_| Err(ArgsErr::DuplicateOption(arg)))
+ }),
+ CARGO_PATH => args.next().map_or(Err(ArgsErr::MissingCargoPath), |p| {
+ // This won't overflow since `p.len() + 6 < usize::MAX` since
+ // `p.len() <= isize::MAX`, `usize::MAX >= u16::MAX`, and
+ // `i16::MAX + 6 < u16::MAX`.
+ let mut path = PathBuf::with_capacity(CARGO.len() + 1 + p.len());
+ path.push(p);
+ path.push(CARGO);
+ opts.cargo_path
+ .replace(path)
+ .map_or(Ok(()), |_| Err(ArgsErr::DuplicateOption(arg)))
+ }),
+ COLOR => {
+ if opts.color {
+ Err(ArgsErr::DuplicateOption(arg))
+ } else {
opts.color = true;
+ Ok(())
}
- DEFAULT_TOOLCHAIN => {
- if opts.default_toolchain {
- return Err(ArgsErr::DuplicateOption(val));
- }
+ }
+ DEFAULT_TOOLCHAIN => {
+ if opts.default_toolchain {
+ Err(ArgsErr::DuplicateOption(arg))
+ } else {
opts.default_toolchain = true;
+ Ok(())
}
- DENY_WARNINGS => {
- if opts.deny_warnings {
- return Err(ArgsErr::DuplicateOption(val));
- }
- opts.deny_warnings = true;
- }
- DIR => {
- if opts.dir.is_some() {
- return Err(ArgsErr::DuplicateOption(val));
- } else if let Some(path) = args.next() {
- opts.dir = Some(path.into());
+ }
+ DENY_WARNINGS => match *cmd {
+ CargoCmd::Clippy(&mut (_, ref mut deny_warnings)) => {
+ if *deny_warnings {
+ Err(ArgsErr::DuplicateOption(arg))
} else {
- return Err(ArgsErr::MissingDirPath);
+ *deny_warnings = true;
+ Ok(())
}
}
- IGNORE_COMPILE_ERRORS => {
- if opts.ignore_compile_errors {
- return Err(ArgsErr::DuplicateOption(val));
+ CargoCmd::Check(_) | CargoCmd::Test(_) => Err(ArgsErr::UnknownArg(arg)),
+ },
+ DIR => args.next().map_or(Err(ArgsErr::MissingDirPath), |path| {
+ opts.dir
+ .replace(path.into())
+ .map_or(Ok(()), |_| Err(ArgsErr::DuplicateOption(arg)))
+ }),
+ DOC => match *cmd {
+ CargoCmd::Test(&mut (ref mut test_targets, _)) => match *test_targets {
+ TestTargets::Default => {
+ *test_targets = TestTargets::Doc;
+ Ok(())
}
+ TestTargets::All | TestTargets::Targets(_) => Err(ArgsErr::Doc),
+ TestTargets::Doc => Err(ArgsErr::DuplicateOption(arg)),
+ },
+ CargoCmd::Check(_) | CargoCmd::Clippy(_) => Err(ArgsErr::UnknownArg(arg)),
+ },
+ EXAMPLES => cmd.add_target(Target::Examples),
+ IGNORE_COMPILE_ERRORS => {
+ if opts.ignore_compile_errors {
+ Err(ArgsErr::DuplicateOption(arg))
+ } else {
opts.ignore_compile_errors = true;
+ Ok(())
}
- IGNORE_FEATURES => {
- if opts.ignore_features.is_empty() {
- if let Some(feats_os) = args.next() {
+ }
+ IGNORE_FEATURES => {
+ if opts.ignore_features.is_empty() {
+ args.next()
+ .map_or(Err(ArgsErr::MissingIgnoredFeatures), |feats_os| {
if let Some(feats) = feats_os.to_str() {
- if feats
+ feats
.as_bytes()
.split(|b| *b == b',')
.try_fold((), |(), feat| {
@@ -1178,199 +2073,196 @@ impl MetaCmd {
Ok(())
}
})
- .is_err()
- {
- return Err(ArgsErr::DuplicateIgnoredFeatures(
- feats_os,
- ));
- }
+ .map_err(|()| {
+ ArgsErr::DuplicateIgnoredFeatures(feats_os)
+ })
} else {
- return Err(ArgsErr::UnknownArg(val));
+ Err(ArgsErr::UnknownArg(feats_os))
}
- } else {
- return Err(ArgsErr::MissingIgnoredFeatures);
- }
- } else {
- return Err(ArgsErr::DuplicateOption(val));
- }
+ })
+ } else {
+ Err(ArgsErr::DuplicateOption(arg))
}
- IGNORE_MSRV => {
- if opts.ignore_msrv {
- return Err(ArgsErr::DuplicateOption(val));
- }
+ }
+ IGNORE_MSRV => {
+ if opts.ignore_msrv {
+ Err(ArgsErr::DuplicateOption(arg))
+ } else {
opts.ignore_msrv = true;
+ Ok(())
}
- IGNORED => {
- if opts.ignored {
- return Err(ArgsErr::DuplicateOption(val));
- } else if opts.include_ignored {
- return Err(ArgsErr::IgnoredIncludeIgnored);
- }
- opts.ignored = true;
- }
- INCLUDE_IGNORED => {
- if opts.include_ignored {
- return Err(ArgsErr::DuplicateOption(val));
- } else if opts.ignored {
- return Err(ArgsErr::IgnoredIncludeIgnored);
+ }
+ IGNORED => match *cmd {
+ CargoCmd::Test(&mut (_, ref mut ignored)) => match *ignored {
+ Ignored::None => {
+ *ignored = Ignored::Only;
+ Ok(())
}
- opts.include_ignored = true;
- }
- PROGRESS => {
- if opts.progress {
- return Err(ArgsErr::DuplicateOption(val));
+ Ignored::Only => Err(ArgsErr::DuplicateOption(arg)),
+ Ignored::Include => Err(ArgsErr::IgnoredIncludeIgnored),
+ },
+ CargoCmd::Check(_) | CargoCmd::Clippy(_) => Err(ArgsErr::UnknownArg(arg)),
+ },
+ INCLUDE_IGNORED => match *cmd {
+ CargoCmd::Test(&mut (_, ref mut ignored)) => match *ignored {
+ Ignored::None => {
+ *ignored = Ignored::Include;
+ Ok(())
}
+ Ignored::Only => Err(ArgsErr::IgnoredIncludeIgnored),
+ Ignored::Include => Err(ArgsErr::DuplicateOption(arg)),
+ },
+ CargoCmd::Check(_) | CargoCmd::Clippy(_) => Err(ArgsErr::UnknownArg(arg)),
+ },
+ LIB => cmd.add_target(Target::Lib),
+ PROGRESS => {
+ if opts.progress {
+ Err(ArgsErr::DuplicateOption(arg))
+ } else {
opts.progress = true;
+ Ok(())
}
- RUSTUP_HOME => {
- if opts.rustup_home.is_some() {
- return Err(ArgsErr::DuplicateOption(val));
- } else if let Some(path) = args.next() {
- opts.rustup_home = Some(path.into());
- } else {
- return Err(ArgsErr::MissingRustupHome);
- }
- }
- SKIP_MSRV => {
- if opts.skip_msrv {
- return Err(ArgsErr::DuplicateOption(val));
- }
+ }
+ RUSTUP_HOME => args.next().map_or(Err(ArgsErr::MissingRustupHome), |path| {
+ opts.rustup_home
+ .replace(path.into())
+ .map_or(Ok(()), |_| Err(ArgsErr::DuplicateOption(arg)))
+ }),
+ SKIP_MSRV => {
+ if opts.skip_msrv {
+ Err(ArgsErr::DuplicateOption(arg))
+ } else {
opts.skip_msrv = true;
+ Ok(())
}
- SUMMARY => {
- if opts.summary {
- return Err(ArgsErr::DuplicateOption(val));
- }
+ }
+ SUMMARY => {
+ if opts.summary {
+ Err(ArgsErr::DuplicateOption(arg))
+ } else {
opts.summary = true;
+ Ok(())
}
- _ => return Err(ArgsErr::UnknownArg(val)),
}
- Self::extract_options(opts, args.next(), args)
- } else {
- Err(ArgsErr::UnknownArg(val))
+ TESTS => cmd.add_target(Target::Tests),
+ _ => return Ok(Some(arg)),
}
- },
- )
+ } else {
+ Err(ArgsErr::UnknownArg(arg))
+ }?;
+ }
+ Ok(None)
}
/// Returns data we need by reading the supplied CLI arguments.
- #[expect(
- clippy::too_many_lines,
- reason = "expected even if we extract options separately"
- )]
+ #[expect(clippy::unreachable, reason = "want to crash when there is a bug")]
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(
- || {
- Ok(Self::Cargo(
- Cmd::All(false, false, Ignored::None),
- Opts::default(),
- ))
- },
- |arg| {
- if let Some(arg_str) = arg.to_str() {
- match arg_str {
- HELP => {
- if args.next().is_none() {
- Ok(Self::Help)
- } else {
- Err(ArgsErr::HelpWithArgs)
- }
- }
- VERSION => {
- if args.next().is_none() {
- Ok(Self::Version)
- } else {
- Err(ArgsErr::VersionWithArgs)
+ args.next().ok_or(ArgsErr::NoCommand).and_then(|fst_cmd| {
+ if let Some(fst_cmd_str) = fst_cmd.to_str() {
+ let mut opts = ArgOpts::default();
+ let mut check_targets = None;
+ let mut clippy_info: Option<(CheckClippyTargets, bool)> = None;
+ let mut test_info: Option<(TestTargets, Ignored)> = None;
+ let mut cargo_cmd = match fst_cmd_str {
+ CHECK => CargoCmd::Check(check_targets.insert(CheckClippyTargets::Default)),
+ CLIPPY => CargoCmd::Clippy(
+ clippy_info.insert((CheckClippyTargets::Default, false)),
+ ),
+ HELP => {
+ return args
+ .next()
+ .map_or_else(|| Ok(Self::Help), |_| Err(ArgsErr::HelpWithArgs));
+ }
+ TEST => {
+ CargoCmd::Test(test_info.insert((TestTargets::Default, Ignored::None)))
+ }
+ VERSION => {
+ return args.next().map_or_else(
+ || Ok(Self::Version),
+ |_| Err(ArgsErr::VersionWithArgs),
+ );
+ }
+ _ => return Err(ArgsErr::NoCommand),
+ };
+ while let Some(arg) =
+ Self::extract_options(&mut cargo_cmd, &mut opts, &mut args)?
+ {
+ match arg.to_str().unwrap_or_else(|| {
+ unreachable!("there is a bug in args::MetaCmd::extract_options")
+ }) {
+ CHECK => {
+ if check_targets.is_some() {
+ return Err(ArgsErr::DuplicateOption(arg));
}
+ cargo_cmd = CargoCmd::Check(
+ check_targets.insert(CheckClippyTargets::Default),
+ );
}
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::IgnoredCheckClippyDoc)
- } else {
- Ok(Self::Cargo(
- Cmd::Clippy(opts.all_targets, opts.deny_warnings),
- opts.into(),
- ))
- }
- },
- )
- }
- 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::DenyWarningsCheckTests)
- } else {
- let ignored = opts.ignored();
- Ok(Self::Cargo(Cmd::Tests(ignored), opts.into()))
- }
- },
- )
- }
- 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::DenyWarningsCheckTests)
- } else if opts.ignored || opts.include_ignored {
- 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(),
- ))
- }
- },
- )
+ if clippy_info.is_some() {
+ return Err(ArgsErr::DuplicateOption(arg));
+ }
+ cargo_cmd = CargoCmd::Clippy(
+ clippy_info.insert((CheckClippyTargets::Default, false)),
+ );
}
- _ => {
- let mut opts = ArgOpts::default();
- Self::extract_options(&mut opts, Some(arg), &mut args).map(|()| {
- Self::Cargo(
- Cmd::All(
- opts.all_targets,
- opts.deny_warnings,
- opts.ignored(),
- ),
- opts.into(),
- )
- })
+ TEST => {
+ if test_info.is_some() {
+ return Err(ArgsErr::DuplicateOption(arg));
+ }
+ cargo_cmd = CargoCmd::Test(
+ test_info.insert((TestTargets::Default, Ignored::None)),
+ );
}
+ _ => return Err(ArgsErr::UnknownArg(arg)),
}
+ }
+ if let Some(check) = check_targets {
+ Ok(Self::Cargo(
+ clippy_info.map_or_else(
+ || {
+ test_info.map_or(Cmd::Check(check), |test| {
+ Cmd::CheckTest(check, test.0, test.1)
+ })
+ },
+ |clippy| {
+ test_info.map_or(
+ Cmd::CheckClippy(check, clippy.0, clippy.1),
+ |test| {
+ Cmd::CheckClippyTest(
+ check, clippy.0, clippy.1, test.0, test.1,
+ )
+ },
+ )
+ },
+ ),
+ opts.into(),
+ ))
+ } else if let Some(clippy) = clippy_info {
+ Ok(Self::Cargo(
+ test_info.map_or(Cmd::Clippy(clippy.0, clippy.1), |test| {
+ Cmd::ClippyTest(clippy.0, clippy.1, test.0, test.1)
+ }),
+ opts.into(),
+ ))
+ } else if let Some(test) = test_info {
+ Ok(Self::Cargo(Cmd::Test(test.0, test.1), opts.into()))
} else {
- Err(ArgsErr::UnknownArg(arg))
+ Err(ArgsErr::NoCommand)
}
- },
- )
+ } else {
+ Err(ArgsErr::UnknownArg(fst_cmd))
+ }
+ })
})
}
}
#[cfg(test)]
mod tests {
- use super::{ArgsErr, Cmd, Ignored, MetaCmd, NonZeroUsizePlus1, Opts, OsString, PathBuf};
+ use super::{
+ ArgsErr, CheckClippyTargets, Cmd, Ignored, MetaCmd, NonZeroUsizePlus1, Opts, OsString,
+ PathBuf, Target, Targets, TestTargets,
+ };
use core::iter;
#[cfg(unix)]
use std::os::unix::ffi::OsStringExt as _;
@@ -1382,35 +2274,13 @@ mod tests {
#[test]
fn arg_parsing() {
assert_eq!(MetaCmd::from_args(iter::empty()), Err(ArgsErr::NoArgs));
- // We always ignore the first argument.
assert_eq!(
MetaCmd::from_args(iter::once(OsString::new())),
- Ok(MetaCmd::Cargo(
- Cmd::All(false, false, Ignored::None),
- Opts {
- exec_dir: None,
- rustup_home: None,
- cargo_path: "cargo".to_owned().into(),
- cargo_home: None,
- color: false,
- 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(), OsString::new()].into_iter()),
- Err(ArgsErr::UnknownArg(OsString::new()))
+ Err(ArgsErr::NoCommand)
);
assert_eq!(
MetaCmd::from_args([OsString::new(), OsString::new()].into_iter()),
- Err(ArgsErr::UnknownArg(OsString::new()))
+ Err(ArgsErr::NoCommand)
);
// Invalid UTF-8 errors gracefully.
#[cfg(unix)]
@@ -1421,12 +2291,12 @@ mod tests {
// Whitespace is not ignored.
assert_eq!(
MetaCmd::from_args([OsString::new(), " clippy".to_owned().into()].into_iter()),
- Err(ArgsErr::UnknownArg(" clippy".to_owned().into()))
+ Err(ArgsErr::NoCommand)
);
// We parse in a case-sensitive way.
assert_eq!(
MetaCmd::from_args([OsString::new(), "Clippy".to_owned().into()].into_iter()),
- Err(ArgsErr::UnknownArg("Clippy".to_owned().into()))
+ Err(ArgsErr::NoCommand)
);
// We require options to be after the command (if one was passed).
assert_eq!(
@@ -1437,167 +2307,118 @@ mod tests {
"clippy".to_owned().into()
]
.into_iter()
- ),
- Err(ArgsErr::UnknownArg("clippy".to_owned().into()))
- );
- // `ArgsErr::DuplicateOption` has higher priority than disallowed option errors.
- assert_eq!(
- MetaCmd::from_args(
- [
- OsString::new(),
- "tests".to_owned().into(),
- "--deny-warnings".to_owned().into(),
- "--deny-warnings".to_owned().into()
- ]
- .into_iter()
- ),
- Err(ArgsErr::DuplicateOption(
- "--deny-warnings".to_owned().into()
- ))
- );
- assert_eq!(
- MetaCmd::from_args(
- [
- OsString::new(),
- "help".to_owned().into(),
- "--summary".to_owned().into()
- ]
- .into_iter()
- ),
- Err(ArgsErr::HelpWithArgs)
- );
- assert_eq!(
- MetaCmd::from_args(
- [
- OsString::new(),
- "version".to_owned().into(),
- "foo".to_owned().into()
- ]
- .into_iter()
- ),
- Err(ArgsErr::VersionWithArgs)
- );
- assert_eq!(
- MetaCmd::from_args([OsString::new(), "--cargo-path".to_owned().into()].into_iter()),
- Err(ArgsErr::MissingCargoPath)
- );
- assert_eq!(
- MetaCmd::from_args([OsString::new(), "--cargo-home".to_owned().into()].into_iter()),
- Err(ArgsErr::MissingCargoHome)
- );
- assert_eq!(
- MetaCmd::from_args([OsString::new(), "--rustup-home".to_owned().into()].into_iter()),
- Err(ArgsErr::MissingRustupHome)
+ ),
+ Err(ArgsErr::NoCommand)
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
- "tests".to_owned().into(),
- "--all-targets".to_owned().into()
+ "help".to_owned().into(),
+ "--summary".to_owned().into()
]
.into_iter()
),
- Err(ArgsErr::AllTargetsTests)
+ Err(ArgsErr::HelpWithArgs)
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
- "doc-tests".to_owned().into(),
- "--all-targets".to_owned().into()
+ "version".to_owned().into(),
+ "foo".to_owned().into()
]
.into_iter()
),
- Err(ArgsErr::AllTargetsTests)
+ Err(ArgsErr::VersionWithArgs)
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
- "tests".to_owned().into(),
- "--deny-warnings".to_owned().into()
+ "check".to_owned().into(),
+ "--cargo-path".to_owned().into()
]
.into_iter()
),
- Err(ArgsErr::DenyWarningsCheckTests)
+ Err(ArgsErr::MissingCargoPath)
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
- "doc-tests".to_owned().into(),
- "--deny-warnings".to_owned().into()
+ "check".to_owned().into(),
+ "--cargo-home".to_owned().into()
]
.into_iter()
),
- Err(ArgsErr::DenyWarningsCheckTests)
+ Err(ArgsErr::MissingCargoHome)
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
"check".to_owned().into(),
- "--deny-warnings".to_owned().into()
+ "--rustup-home".to_owned().into()
]
.into_iter()
),
- Err(ArgsErr::DenyWarningsCheckTests)
+ Err(ArgsErr::MissingRustupHome)
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
- "clippy".to_owned().into(),
- "--ignored".to_owned().into()
+ "test".to_owned().into(),
+ "--deny-warnings".to_owned().into()
]
.into_iter()
),
- Err(ArgsErr::IgnoredCheckClippyDoc)
+ Err(ArgsErr::UnknownArg("--deny-warnings".to_owned().into()))
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
- "doc-tests".to_owned().into(),
- "--ignored".to_owned().into()
+ "check".to_owned().into(),
+ "--deny-warnings".to_owned().into()
]
.into_iter()
),
- Err(ArgsErr::IgnoredCheckClippyDoc)
+ Err(ArgsErr::UnknownArg("--deny-warnings".to_owned().into()))
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
- "check".to_owned().into(),
+ "clippy".to_owned().into(),
"--ignored".to_owned().into()
]
.into_iter()
),
- Err(ArgsErr::IgnoredCheckClippyDoc)
+ Err(ArgsErr::UnknownArg("--ignored".to_owned().into()))
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
- "clippy".to_owned().into(),
- "--include-ignored".to_owned().into()
+ "check".to_owned().into(),
+ "--ignored".to_owned().into()
]
.into_iter()
),
- Err(ArgsErr::IgnoredCheckClippyDoc)
+ Err(ArgsErr::UnknownArg("--ignored".to_owned().into()))
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
- "doc-tests".to_owned().into(),
+ "clippy".to_owned().into(),
"--include-ignored".to_owned().into()
]
.into_iter()
),
- Err(ArgsErr::IgnoredCheckClippyDoc)
+ Err(ArgsErr::UnknownArg("--include-ignored".to_owned().into()))
);
assert_eq!(
MetaCmd::from_args(
@@ -1608,13 +2429,13 @@ mod tests {
]
.into_iter()
),
- Err(ArgsErr::IgnoredCheckClippyDoc)
+ Err(ArgsErr::UnknownArg("--include-ignored".to_owned().into()))
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
- "tests".to_owned().into(),
+ "test".to_owned().into(),
"--ignored".to_owned().into(),
"--include-ignored".to_owned().into()
]
@@ -1626,23 +2447,18 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
- "--ignored".to_owned().into(),
- "--include-ignored".to_owned().into()
+ "test".to_owned().into(),
+ "--ignore-features".to_owned().into(),
]
.into_iter()
),
- Err(ArgsErr::IgnoredIncludeIgnored)
- );
- assert_eq!(
- MetaCmd::from_args(
- [OsString::new(), "--ignore-features".to_owned().into(),].into_iter()
- ),
Err(ArgsErr::MissingIgnoredFeatures)
);
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
+ "clippy".to_owned().into(),
"--ignore-features".to_owned().into(),
",".to_owned().into(),
]
@@ -1654,6 +2470,7 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
+ "check".to_owned().into(),
"--ignore-features".to_owned().into(),
"a,,a".to_owned().into(),
]
@@ -1665,6 +2482,7 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
+ "check".to_owned().into(),
"--ignore-features".to_owned().into(),
",a,b,".to_owned().into(),
]
@@ -1676,6 +2494,7 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
+ "clippy".to_owned().into(),
"--ignore-features".to_owned().into(),
",a,,b".to_owned().into(),
]
@@ -1687,6 +2506,7 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
+ "clippy".to_owned().into(),
"--ignore-features".to_owned().into(),
"a,b,,".to_owned().into(),
]
@@ -1694,53 +2514,105 @@ mod tests {
),
Err(ArgsErr::DuplicateIgnoredFeatures("a,b,,".to_owned().into()))
);
- // When paths are passed, no attempt is made to interpret them. `cargo` is unconditionally pushed
- // to the path. Similarly features to ignored are not handled special.
+ // `--all-targets` can't be combined with other targets.
assert_eq!(
MetaCmd::from_args(
[
OsString::new(),
+ "clippy".to_owned().into(),
+ "--lib".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(),
- "--deny-warnings".to_owned().into(),
- "--dir".to_owned().into(),
+ ]
+ .into_iter()
+ ),
+ Err(ArgsErr::AllTargets)
+ );
+ assert_eq!(
+ MetaCmd::from_args(
+ [
OsString::new(),
- "--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(),
+ "check".to_owned().into(),
+ "--lib".to_owned().into(),
+ "--all-targets".to_owned().into(),
+ ]
+ .into_iter()
+ ),
+ Err(ArgsErr::AllTargets)
+ );
+ assert_eq!(
+ MetaCmd::from_args(
+ [
OsString::new(),
- "--progress".to_owned().into(),
- "--skip-msrv".to_owned().into(),
- "--summary".to_owned().into(),
+ "check".to_owned().into(),
+ "--all-targets".to_owned().into(),
+ "test".to_owned().into(),
+ "--doc".to_owned().into(),
+ "--all-targets".to_owned().into(),
]
.into_iter()
),
- Ok(MetaCmd::Cargo(
- Cmd::All(true, true, Ignored::None),
- 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!["--include-ignored".to_owned()],
- }
- ))
+ Err(ArgsErr::AllTargets)
+ );
+ // `--doc` can't be combined with other targets.
+ assert_eq!(
+ MetaCmd::from_args(
+ [
+ OsString::new(),
+ "test".to_owned().into(),
+ "--all-targets".to_owned().into(),
+ "--doc".to_owned().into(),
+ ]
+ .into_iter()
+ ),
+ Err(ArgsErr::Doc)
+ );
+ assert_eq!(
+ MetaCmd::from_args(
+ [
+ OsString::new(),
+ "test".to_owned().into(),
+ "--doc".to_owned().into(),
+ "--lib".to_owned().into(),
+ ]
+ .into_iter()
+ ),
+ Err(ArgsErr::Doc)
+ );
+ assert_eq!(
+ MetaCmd::from_args(
+ [
+ OsString::new(),
+ "clippy".to_owned().into(),
+ "--doc".to_owned().into(),
+ ]
+ .into_iter()
+ ),
+ Err(ArgsErr::UnknownArg("--doc".to_owned().into()))
+ );
+ assert_eq!(
+ MetaCmd::from_args(
+ [
+ OsString::new(),
+ "check".to_owned().into(),
+ "--color".to_owned().into(),
+ "clippy".to_owned().into(),
+ "--color".to_owned().into(),
+ ]
+ .into_iter()
+ ),
+ Err(ArgsErr::DuplicateOption("--color".to_owned().into()))
+ );
+ assert_eq!(
+ MetaCmd::from_args(
+ [
+ OsString::new(),
+ "test".to_owned().into(),
+ "--ignored".to_owned().into(),
+ "--ignored".to_owned().into(),
+ ]
+ .into_iter()
+ ),
+ Err(ArgsErr::DuplicateOption("--ignored".to_owned().into()))
);
assert_eq!(
MetaCmd::from_args(
@@ -1771,7 +2643,7 @@ mod tests {
.into_iter()
),
Ok(MetaCmd::Cargo(
- Cmd::Clippy(true, true,),
+ Cmd::Clippy(CheckClippyTargets::All, true,),
Opts {
exec_dir: Some(PathBuf::new()),
rustup_home: Some("a".to_owned().into()),
@@ -1800,7 +2672,7 @@ mod tests {
.into_iter()
),
Ok(MetaCmd::Cargo(
- Cmd::Clippy(true, true,),
+ Cmd::Clippy(CheckClippyTargets::All, true,),
Opts {
exec_dir: None,
rustup_home: None,
@@ -1822,7 +2694,7 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
- "tests".to_owned().into(),
+ "test".to_owned().into(),
"--allow-implied-features".to_owned().into(),
"--cargo-home".to_owned().into(),
"--ignored".to_owned().into(),
@@ -1846,7 +2718,7 @@ mod tests {
.into_iter()
),
Ok(MetaCmd::Cargo(
- Cmd::Tests(Ignored::Only),
+ Cmd::Test(TestTargets::Default, Ignored::Only),
Opts {
exec_dir: Some(PathBuf::new()),
rustup_home: Some(PathBuf::new()),
@@ -1865,9 +2737,9 @@ mod tests {
))
);
assert_eq!(
- MetaCmd::from_args([OsString::new(), "tests".to_owned().into(),].into_iter()),
+ MetaCmd::from_args([OsString::new(), "test".to_owned().into(),].into_iter()),
Ok(MetaCmd::Cargo(
- Cmd::Tests(Ignored::None),
+ Cmd::Test(TestTargets::Default, Ignored::None),
Opts {
exec_dir: None,
rustup_home: None,
@@ -1889,79 +2761,13 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
- "tests".to_owned().into(),
+ "test".to_owned().into(),
"--include-ignored".to_owned().into()
]
.into_iter()
),
Ok(MetaCmd::Cargo(
- Cmd::Tests(Ignored::Include),
- 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,
- ignore_features: Vec::new(),
- }
- ))
- );
- assert_eq!(
- MetaCmd::from_args(
- [
- OsString::new(),
- "doc-tests".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::DocTests,
- 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(), "doc-tests".to_owned().into(),].into_iter()),
- Ok(MetaCmd::Cargo(
- Cmd::DocTests,
+ Cmd::Test(TestTargets::Default, Ignored::Include),
Opts {
exec_dir: None,
rustup_home: None,
@@ -2007,7 +2813,7 @@ mod tests {
.into_iter()
),
Ok(MetaCmd::Cargo(
- Cmd::Check(true),
+ Cmd::Check(CheckClippyTargets::All),
Opts {
exec_dir: Some(PathBuf::new()),
rustup_home: Some(PathBuf::new()),
@@ -2028,7 +2834,7 @@ mod tests {
assert_eq!(
MetaCmd::from_args([OsString::new(), "check".to_owned().into(),].into_iter()),
Ok(MetaCmd::Cargo(
- Cmd::Check(false),
+ Cmd::Check(CheckClippyTargets::Default),
Opts {
exec_dir: None,
rustup_home: None,
@@ -2050,13 +2856,14 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
+ "check".to_owned().into(),
"--ignore-features".to_owned().into(),
"a,,b".to_owned().into(),
]
.into_iter()
),
Ok(MetaCmd::Cargo(
- Cmd::All(false, false, Ignored::None),
+ Cmd::Check(CheckClippyTargets::Default),
Opts {
exec_dir: None,
rustup_home: None,
@@ -2078,13 +2885,14 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
+ "check".to_owned().into(),
"--ignore-features".to_owned().into(),
"a,b,".to_owned().into(),
]
.into_iter()
),
Ok(MetaCmd::Cargo(
- Cmd::All(false, false, Ignored::None),
+ Cmd::Check(CheckClippyTargets::Default),
Opts {
exec_dir: None,
rustup_home: None,
@@ -2106,13 +2914,14 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
+ "check".to_owned().into(),
"--ignore-features".to_owned().into(),
"a,b".to_owned().into(),
]
.into_iter()
),
Ok(MetaCmd::Cargo(
- Cmd::All(false, false, Ignored::None),
+ Cmd::Check(CheckClippyTargets::Default),
Opts {
exec_dir: None,
rustup_home: None,
@@ -2135,13 +2944,14 @@ mod tests {
MetaCmd::from_args(
[
OsString::new(),
+ "check".to_owned().into(),
"--ignore-features".to_owned().into(),
"a , , b, ".to_owned().into(),
]
.into_iter()
),
Ok(MetaCmd::Cargo(
- Cmd::All(false, false, Ignored::None),
+ Cmd::Check(CheckClippyTargets::Default),
Opts {
exec_dir: None,
rustup_home: None,
@@ -2172,6 +2982,78 @@ mod tests {
MetaCmd::from_args([OsString::new(), "version".to_owned().into(),].into_iter()),
Ok(MetaCmd::Version)
);
+ let mut check_targets = Targets::new(Target::Examples);
+ assert!(check_targets.add(Target::Tests));
+ assert!(!check_targets.add(Target::Examples));
+ let mut test_targets = Targets::new(Target::Benches);
+ assert!(test_targets.add(Target::Bins));
+ assert!(!test_targets.add(Target::Bins));
+ assert!(test_targets.add(Target::Examples));
+ assert!(test_targets.add(Target::Lib));
+ assert!(test_targets.add(Target::Tests));
+ assert_eq!(
+ MetaCmd::from_args(
+ [
+ OsString::new(),
+ "clippy".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(),
+ "--deny-warnings".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(),
+ "a".to_owned().into(),
+ "test".to_owned().into(),
+ "--benches".to_owned().into(),
+ "--bins".to_owned().into(),
+ "--examples".to_owned().into(),
+ "--include-ignored".to_owned().into(),
+ "--lib".to_owned().into(),
+ "--tests".to_owned().into(),
+ "--progress".to_owned().into(),
+ "--skip-msrv".to_owned().into(),
+ "check".to_owned().into(),
+ "--tests".to_owned().into(),
+ "--examples".to_owned().into(),
+ "--summary".to_owned().into(),
+ ]
+ .into_iter()
+ ),
+ Ok(MetaCmd::Cargo(
+ Cmd::CheckClippyTest(
+ CheckClippyTargets::Targets(check_targets),
+ CheckClippyTargets::All,
+ true,
+ TestTargets::Targets(test_targets),
+ Ignored::Include,
+ ),
+ Opts {
+ exec_dir: Some(PathBuf::new()),
+ rustup_home: Some("a".to_owned().into()),
+ 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![String::new(), "a".to_owned()],
+ }
+ ))
+ );
}
#[test]
fn non_zero_usize_plus_1() {
diff --git a/src/cargo.rs b/src/cargo.rs
@@ -1,4 +1,7 @@
-use super::{args::Ignored, manifest};
+use super::{
+ args::{CheckClippyTargets, Ignored, Target, TestTargets},
+ manifest,
+};
use std::{
collections::HashSet,
io::{Error, StderrLock, Write as _},
@@ -343,6 +346,18 @@ impl Toolchain<'_> {
}
}
}
+/// `"--all-targets"`.
+const DASH_DASH_ALL_TARGETS: &str = "--all-targets";
+/// `"--benches"`.
+const DASH_DASH_BENCHES: &str = "--benches";
+/// `"--bins"`.
+const DASH_DASH_BINS: &str = "--bins";
+/// `"--examples"`.
+const DASH_DASH_EXAMPLES: &str = "--examples";
+/// `"--lib"`.
+const DASH_DASH_LIB: &str = "--lib";
+/// `"--tests"`.
+const DASH_DASH_TESTS: &str = "--tests";
/// `"-p"`.
const DASH_P: &str = "-p";
/// `"-q"`.
@@ -363,7 +378,7 @@ const DASH_DASH: &str = "--";
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`].
+/// Common options to pass to [`Clippy::run`] and [`Test::run`].
pub(crate) struct Options<'toolchain, 'package, 'errs> {
/// The `cargo` toolchain to use.
pub toolchain: Toolchain<'toolchain>,
@@ -385,14 +400,11 @@ pub(crate) struct Options<'toolchain, 'package, 'errs> {
pub non_terminating_errors: &'errs mut HashSet<String>,
}
/// Executes `cmd`.
-///
-/// Returns `true` iff a no-library target error occurred and `doc_only` was `true`.
fn execute_command(
mut cmd: Command,
options: &mut Options<'_, '_, '_>,
features: &str,
- doc_only: bool,
-) -> Result<bool, Box<CargoErr>> {
+) -> Result<(), Box<CargoErr>> {
match cmd.stdout(Stdio::piped()).output() {
Ok(output) => {
if let Some(code) = output.status.code() {
@@ -406,13 +418,11 @@ fn execute_command(
},
);
}
- Ok(false)
+ Ok(())
}
101i32 => {
/// `"compile_error!"` as a byte string.
const COMPILE_ERROR: &[u8; 14] = b"compile_error!";
- /// `"no library targets found in package"` as a byte string.
- const NO_LIB_TARG: &[u8; 35] = b"no library targets found in package";
if output
.stderr
.windows(COMPILE_ERROR.len())
@@ -426,7 +436,7 @@ fn execute_command(
{
Err(Box::new(CargoErr::CompileErrNoFeatures(cmd)))
} else {
- Ok(false)
+ Ok(())
}
} else if let Ok(err) = String::from_utf8(output.stderr) {
if let Ok(stdout) = String::from_utf8(output.stdout) {
@@ -437,13 +447,6 @@ fn execute_command(
} else {
Err(Box::new(CargoErr::StderrNotUtf8(cmd)))
}
- } else if doc_only
- && output
- .stderr
- .windows(NO_LIB_TARG.len())
- .any(|window| window == NO_LIB_TARG)
- {
- Ok(true)
} else if let Ok(err) = String::from_utf8(output.stderr) {
if let Ok(stdout) = String::from_utf8(output.stdout) {
Err(Box::new(CargoErr::CommandErr(cmd, err, stdout)))
@@ -479,21 +482,13 @@ fn execute_command(
Err(e) => Err(Box::new(CargoErr::CommandFail(cmd, e))),
}
}
-/// `cargo clippy`.
-pub(crate) struct Clippy;
-impl Clippy {
- /// Execute `cargo clippy`.
- ///
- /// 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"
- )]
+/// `cargo check`.
+pub(crate) struct Check;
+impl Check {
+ /// Execute `cargo check`.
pub(crate) fn run(
options: &mut Options<'_, '_, '_>,
- all_targets: bool,
- deny_warnings: bool,
+ targets: CheckClippyTargets,
features: &str,
) -> Result<(), Box<CargoErr>> {
let mut c = Command::new(options.cargo_path.as_path());
@@ -516,12 +511,32 @@ impl Clippy {
}
};
_ = c
- .arg("clippy")
+ .arg("check")
.arg(DASH_P)
.arg(options.package_name)
.arg(DASH_Q);
- if all_targets {
- _ = c.arg("--all-targets");
+ match targets {
+ CheckClippyTargets::Default => {}
+ CheckClippyTargets::All => {
+ _ = c.arg(DASH_DASH_ALL_TARGETS);
+ }
+ CheckClippyTargets::Targets(tar) => {
+ if tar.contains(Target::Benches) {
+ _ = c.arg(DASH_DASH_BENCHES);
+ }
+ if tar.contains(Target::Bins) {
+ _ = c.arg(DASH_DASH_BINS);
+ }
+ if tar.contains(Target::Examples) {
+ _ = c.arg(DASH_DASH_EXAMPLES);
+ }
+ if tar.contains(Target::Lib) {
+ _ = c.arg(DASH_DASH_LIB);
+ }
+ if tar.contains(Target::Tests) {
+ _ = c.arg(DASH_DASH_TESTS);
+ }
+ }
}
if ignore_msrv {
_ = c.arg(DASH_DASH_IGNORE_RUST_VERSION);
@@ -533,38 +548,19 @@ impl Clippy {
if !features.is_empty() {
_ = c.arg(DASH_DASH_FEATURES).arg(features);
}
- if deny_warnings {
- _ = c.arg(DASH_DASH).arg("-Dwarnings");
- }
- 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 Clippy."))
+ execute_command(c, options, features)
}
}
-/// What kind of test to run.
-#[derive(Clone, Copy)]
-pub(crate) enum TestKind {
- /// Both unit/integration and doc tests.
- All(Ignored),
- /// Only unit/integeration and doc tests.
- Unit(Ignored),
- /// Only doc tests.
- Doc,
-}
-/// `cargo test --tests/--doc`.
-pub(crate) struct Tests;
-impl Tests {
- /// Execute `cargo test`.
- ///
- /// Returns `true` iff only doc tests were run and a no-library error was returned.
+/// `cargo clippy`.
+pub(crate) struct Clippy;
+impl Clippy {
+ /// Execute `cargo clippy`.
pub(crate) fn run(
options: &mut Options<'_, '_, '_>,
- kind: TestKind,
+ targets: CheckClippyTargets,
+ deny_warnings: bool,
features: &str,
- ) -> Result<bool, Box<CargoErr>> {
- /// `"--ignored"`.
- const DASH_DASH_IGNORED: &str = "--ignored";
- /// `"--include-ignored"`.
- const DASH_DASH_INCLUDE_IGNORED: &str = "--include-ignored";
+ ) -> 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 {
@@ -585,10 +581,33 @@ impl Tests {
}
};
_ = c
- .arg("test")
+ .arg("clippy")
.arg(DASH_P)
.arg(options.package_name)
.arg(DASH_Q);
+ match targets {
+ CheckClippyTargets::Default => {}
+ CheckClippyTargets::All => {
+ _ = c.arg(DASH_DASH_ALL_TARGETS);
+ }
+ CheckClippyTargets::Targets(tar) => {
+ if tar.contains(Target::Benches) {
+ _ = c.arg(DASH_DASH_BENCHES);
+ }
+ if tar.contains(Target::Bins) {
+ _ = c.arg(DASH_DASH_BINS);
+ }
+ if tar.contains(Target::Examples) {
+ _ = c.arg(DASH_DASH_EXAMPLES);
+ }
+ if tar.contains(Target::Lib) {
+ _ = c.arg(DASH_DASH_LIB);
+ }
+ if tar.contains(Target::Tests) {
+ _ = c.arg(DASH_DASH_TESTS);
+ }
+ }
+ }
if ignore_msrv {
_ = c.arg(DASH_DASH_IGNORE_RUST_VERSION);
}
@@ -599,68 +618,26 @@ impl Tests {
if !features.is_empty() {
_ = c.arg(DASH_DASH_FEATURES).arg(features);
}
- let mut doc_only = false;
- match kind {
- TestKind::All(ignore) => {
- _ = c.arg(DASH_DASH).arg(DASH_DASH_COLOR).arg(if options.color {
- ALWAYS
- } else {
- NEVER
- });
- match ignore {
- Ignored::None => {}
- Ignored::Only => {
- _ = c.arg(DASH_DASH_IGNORED);
- }
- Ignored::Include => {
- _ = c.arg(DASH_DASH_INCLUDE_IGNORED);
- }
- }
- }
- TestKind::Unit(ignore) => {
- _ = c
- .arg("--tests")
- .arg(DASH_DASH)
- .arg(DASH_DASH_COLOR)
- .arg(if options.color { ALWAYS } else { NEVER });
- match ignore {
- Ignored::None => {}
- Ignored::Only => {
- _ = c.arg(DASH_DASH_IGNORED);
- }
- Ignored::Include => {
- _ = c.arg(DASH_DASH_INCLUDE_IGNORED);
- }
- }
- }
- TestKind::Doc => {
- doc_only = true;
- _ = c
- .arg("--doc")
- .arg(DASH_DASH)
- .arg(DASH_DASH_COLOR)
- .arg(if options.color { ALWAYS } else { NEVER });
- }
+ if deny_warnings {
+ _ = c.arg(DASH_DASH).arg("-Dwarnings");
}
- execute_command(c, options, features, doc_only)
+ execute_command(c, options, features)
}
}
-/// `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"
- )]
+/// `cargo test`.
+pub(crate) struct Test;
+impl Test {
+ /// Execute `cargo test`.
pub(crate) fn run(
options: &mut Options<'_, '_, '_>,
- all_targets: bool,
+ targets: TestTargets,
+ ignored: Ignored,
features: &str,
) -> Result<(), Box<CargoErr>> {
+ /// `"--ignored"`.
+ const DASH_DASH_IGNORED: &str = "--ignored";
+ /// `"--include-ignored"`.
+ const DASH_DASH_INCLUDE_IGNORED: &str = "--include-ignored";
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 {
@@ -681,12 +658,35 @@ impl Check {
}
};
_ = c
- .arg("check")
+ .arg("test")
.arg(DASH_P)
.arg(options.package_name)
.arg(DASH_Q);
- if all_targets {
- _ = c.arg("--all-targets");
+ match targets {
+ TestTargets::Default => {}
+ TestTargets::All => {
+ _ = c.arg(DASH_DASH_ALL_TARGETS);
+ }
+ TestTargets::Targets(tar) => {
+ if tar.contains(Target::Benches) {
+ _ = c.arg(DASH_DASH_BENCHES);
+ }
+ if tar.contains(Target::Bins) {
+ _ = c.arg(DASH_DASH_BINS);
+ }
+ if tar.contains(Target::Examples) {
+ _ = c.arg(DASH_DASH_EXAMPLES);
+ }
+ if tar.contains(Target::Lib) {
+ _ = c.arg(DASH_DASH_LIB);
+ }
+ if tar.contains(Target::Tests) {
+ _ = c.arg(DASH_DASH_TESTS);
+ }
+ }
+ TestTargets::Doc => {
+ _ = c.arg("--doc");
+ }
}
if ignore_msrv {
_ = c.arg(DASH_DASH_IGNORE_RUST_VERSION);
@@ -698,8 +698,20 @@ impl Check {
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."))
+ _ = c
+ .arg(DASH_DASH)
+ .arg(DASH_DASH_COLOR)
+ .arg(if options.color { ALWAYS } else { NEVER });
+ match ignored {
+ Ignored::None => {}
+ Ignored::Only => {
+ _ = c.arg(DASH_DASH_IGNORED);
+ }
+ Ignored::Include => {
+ _ = c.arg(DASH_DASH_INCLUDE_IGNORED);
+ }
+ }
+ execute_command(c, options, features)
}
}
#[cfg(test)]
diff --git a/src/main.rs b/src/main.rs
@@ -8,8 +8,6 @@ mod cargo;
mod manifest;
/// Contains a `const bool` that is `true` iff `rustup` is supported by the platform.
mod rustup;
-#[cfg(target_os = "openbsd")]
-use alloc::ffi::CString;
use args::{ArgsErr, HELP_MSG, MetaCmd};
use cargo::{CargoErr, Options, Toolchain, ToolchainErr};
#[cfg(target_os = "openbsd")]
@@ -56,9 +54,6 @@ enum E {
/// Error from OpenBSD `unveil`.
#[cfg(target_os = "openbsd")]
Unveil(Errno),
- /// Error on OpenBSD when the `Path` for `cargo` can't be converted into a `CString`.
- #[cfg(target_os = "openbsd")]
- CargoPathCStr,
/// Variant returned where there are too many features to generate the power set on.
TooManyFeatures(PathBuf),
/// Unable to write non-terminating messages to stderr.
@@ -119,11 +114,6 @@ impl E {
Self::Pledge(e) => writeln!(stderr, "pledge(2) erred: {e}."),
#[cfg(target_os = "openbsd")]
Self::Unveil(e) => writeln!(stderr, "unveil(2) erred: {e}."),
- #[cfg(target_os = "openbsd")]
- Self::CargoPathCStr => writeln!(
- stderr,
- "unable to convert the path passed for --cargo-path into a C string."
- ),
Self::TooManyFeatures(p) => writeln!(stderr, "There are too many features defined in {}. The max number of features allowed is the number of bits that make up a pointer.", p.display()),
Self::StdErr => Ok(()),
Self::Help(err) => writeln!(
@@ -192,9 +182,7 @@ fn priv_sep_final(proms: &mut Promises, cargo_path: &Path) -> Result<(), E> {
.map_err(E::Unveil)
.and_then(|()| {
if cargo_path.is_absolute() {
- CString::new(cargo_path.as_os_str().as_encoded_bytes())
- .map_err(|_e| E::CargoPathCStr)
- .and_then(|path_c| Permissions::EXECUTE.unveil(&path_c).map_err(E::Unveil))
+ Permissions::EXECUTE.unveil(cargo_path).map_err(E::Unveil)
} else {
Permissions::EXECUTE.unveil(ROOT).map_err(E::Unveil)
}
@@ -225,7 +213,7 @@ fn get_path_of_file(cur_dir: &mut PathBuf, file: &Path) -> Result<bool, Error> {
})
}
/// Current version of this crate.
-const VERSION: &str = "ci-cargo 0.1.0\n";
+const VERSION: &str = concat!("ci-cargo ", env!("CARGO_PKG_VERSION"));
#[expect(
clippy::arithmetic_side_effects,
reason = "comment justifies correctness"
@@ -234,7 +222,7 @@ fn main() -> ExitCode {
priv_init().and_then(|mut proms| MetaCmd::from_args(env::args_os()).map_err(E::Args).and_then(|meta_cmd| {
match meta_cmd {
MetaCmd::Help => io::stdout().lock().write_all(HELP_MSG.as_bytes()).map_err(E::Help),
- MetaCmd::Version => io::stdout().lock().write_all(VERSION.as_bytes()).map_err(E::Version),
+ MetaCmd::Version => writeln!(io::stdout().lock(), "{VERSION}").map_err(E::Version),
MetaCmd::Cargo(cmd, mut opts) => opts.exec_dir.map_or_else(
|| env::current_dir().map_err(E::CurDir).and_then(|mut path| {
let search_start = path.clone();
@@ -301,9 +289,7 @@ fn main() -> ExitCode {
writeln!(stdout, "Features used:").and_then(|()| {
power_set.reset();
while let Some(features) = power_set.next_set() {
- if let Err(e) = writeln!(stdout, "{}", if features.is_empty() { "<none>" } else { features }) {
- return Err(e);
- }
+ writeln!(stdout, "{}", if features.is_empty() { "<none>" } else { features })?;
}
Ok(())
})
diff --git a/src/rustup.rs b/src/rustup.rs
@@ -1,844 +1,8 @@
/// `rustup` is supported by the target per <https://rust-lang.github.io/rustup-components-history/>.
-/// Last checked on 2025-10-06T20:57Z.
+/// Last checked on 2025-11-13T18:49Z.
#[cfg(any(
all(
- target_arch = "aarch64",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "gnu",
- target_abi = "llvm",
- target_endian = "little",
- ),
- all(
- target_arch = "wasm32",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "fuchsia",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "wasm32",
- target_vendor = "unknown",
- target_os = "emscripten",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "msvc",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "apple",
- target_os = "ios",
- target_env = "",
- target_abi = "sim",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "gnu",
- target_abi = "llvm",
- target_endian = "little",
- ),
- all(
- target_arch = "riscv64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "x32",
- target_endian = "little",
- ),
- all(
- target_arch = "riscv32",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "redox",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "loongarch64",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "uefi",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "eabihf",
- ),
- all(
- target_arch = "x86",
- target_vendor = "unknown",
- target_os = "uefi",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "nvptx64",
- target_vendor = "nvidia",
- target_os = "cuda",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "wasm32",
- target_vendor = "unknown",
- target_os = "unknown",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "musl",
- target_abi = "eabi",
- target_endian = "little",
- ),
- all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "eabi",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "msvc",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "ohos",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "fortanix",
- target_os = "unknown",
- target_env = "sgx",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "fuchsia",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "musl",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "freebsd",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "mips64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "abi64",
- ),
- all(
- target_arch = "x86",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "musl",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "softfloat",
- target_endian = "little",
- ),
- all(
- target_arch = "x86",
- target_vendor = "apple",
- target_os = "macos",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "illumos",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "powerpc64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "apple",
- target_os = "macos",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "apple",
- target_os = "ios",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "riscv64",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "msvc",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "android",
- target_env = "",
- target_abi = "eabi",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "android",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "powerpc64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "musl",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "ohos",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "mips64r6",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "abi64",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "apple",
- target_os = "ios",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "uefi",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "gnu",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "eabihf",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "netbsd",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86",
- target_vendor = "unknown",
- target_os = "freebsd",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "apple",
- target_os = "ios",
- target_env = "",
- target_abi = "macabi",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "apple",
- target_os = "macos",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "apple",
- target_os = "ios",
- target_env = "",
- target_abi = "macabi",
- target_endian = "little",
- ),
- all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "eabi",
- ),
- all(
- target_arch = "wasm32",
- target_vendor = "unknown",
- target_os = "wasi",
- target_env = "p2",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "mips",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- ),
- all(
- target_arch = "mips32r6",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- ),
- all(
- target_arch = "sparc64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- target_endian = "big",
- ),
- all(
- target_arch = "riscv64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "musl",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "loongarch64",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "softfloat",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "loongarch64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "musl",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "gnu",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "wasm32",
- target_vendor = "unknown",
- target_os = "wasi",
- target_env = "p1",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "s390x",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- target_endian = "big",
- ),
- all(
- target_arch = "x86",
- target_vendor = "unknown",
- target_os = "android",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "arm64ec",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "msvc",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "pc",
- target_os = "solaris",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "musl",
- target_abi = "eabihf",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "musl",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "android",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "gnu",
- target_abi = "llvm",
- target_endian = "little",
- ),
- all(
- target_arch = "sparc64",
- target_vendor = "sun",
- target_os = "solaris",
- target_env = "",
- target_abi = "",
- target_endian = "big",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "ohos",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "loongarch64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "powerpc",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- target_endian = "big",
- ),
-))]
-pub(crate) const SUPPORTED: bool = true;
-/// `rustup` is _not_ supported by the target per <https://rust-lang.github.io/rustup-components-history/>.
-/// Last checked on 2025-10-06T20:57Z.
-#[cfg(not(any(
- all(
- target_arch = "aarch64",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "gnu",
- target_abi = "llvm",
- target_endian = "little",
- ),
- all(
- target_arch = "wasm32",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "fuchsia",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "wasm32",
- target_vendor = "unknown",
- target_os = "emscripten",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "msvc",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "apple",
- target_os = "ios",
- target_env = "",
- target_abi = "sim",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "gnu",
- target_abi = "llvm",
- target_endian = "little",
- ),
- all(
- target_arch = "riscv64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "x32",
- target_endian = "little",
- ),
- all(
- target_arch = "riscv32",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "redox",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "loongarch64",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "uefi",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "eabihf",
- ),
- all(
- target_arch = "x86",
- target_vendor = "unknown",
- target_os = "uefi",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "nvptx64",
- target_vendor = "nvidia",
- target_os = "cuda",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "wasm32",
- target_vendor = "unknown",
- target_os = "unknown",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "musl",
- target_abi = "eabi",
- target_endian = "little",
- ),
- all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "eabi",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "msvc",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "ohos",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "fortanix",
- target_os = "unknown",
- target_env = "sgx",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "fuchsia",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "musl",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "freebsd",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "mips64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "abi64",
- ),
- all(
- target_arch = "x86",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "musl",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "softfloat",
- target_endian = "little",
- ),
- all(
- target_arch = "x86",
+ any(target_arch = "aarch64", target_arch = "x86_64"),
target_vendor = "apple",
target_os = "macos",
target_env = "",
@@ -846,42 +10,11 @@ pub(crate) const SUPPORTED: bool = true;
target_endian = "little",
),
all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "illumos",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "powerpc64",
- target_vendor = "unknown",
- target_os = "linux",
+ any(target_arch = "aarch64", target_arch = "x86_64"),
+ target_vendor = "pc",
+ target_os = "windows",
target_env = "gnu",
- target_abi = "",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "apple",
- target_os = "macos",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "apple",
- target_os = "ios",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "riscv64",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "",
+ target_abi = "llvm",
target_endian = "little",
),
all(
@@ -893,26 +26,15 @@ pub(crate) const SUPPORTED: bool = true;
target_endian = "little",
),
all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "android",
- target_env = "",
- target_abi = "eabi",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "android",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "powerpc64",
+ any(
+ target_arch = "aarch64",
+ target_arch = "loongarch64",
+ target_arch = "powerpc64",
+ target_arch = "x86_64"
+ ),
target_vendor = "unknown",
target_os = "linux",
- target_env = "musl",
+ any(target_env = "gnu", target_env = "musl"),
target_abi = "",
target_endian = "little",
),
@@ -920,83 +42,69 @@ pub(crate) const SUPPORTED: bool = true;
target_arch = "arm",
target_vendor = "unknown",
target_os = "linux",
- target_env = "ohos",
- target_abi = "",
+ target_env = "gnu",
+ any(target_abi = "eabi", target_abi = "eabihf"),
target_endian = "little",
),
all(
- target_arch = "x86",
+ any(
+ target_arch = "powerpc",
+ target_arch = "powerpc64",
+ target_arch = "s390x"
+ ),
target_vendor = "unknown",
target_os = "linux",
target_env = "gnu",
target_abi = "",
- target_endian = "little",
+ target_endian = "big",
),
all(
- target_arch = "mips64r6",
+ any(target_arch = "riscv64", target_arch = "x86"),
target_vendor = "unknown",
target_os = "linux",
target_env = "gnu",
- target_abi = "abi64",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "apple",
- target_os = "ios",
- target_env = "",
target_abi = "",
target_endian = "little",
),
all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "uefi",
+ target_arch = "sparc64",
+ target_vendor = "sun",
+ target_os = "solaris",
target_env = "",
target_abi = "",
- target_endian = "little",
+ target_endian = "big",
),
all(
- target_arch = "x86",
+ any(target_arch = "x86", target_arch = "x86_64"),
target_vendor = "pc",
target_os = "windows",
- target_env = "gnu",
+ any(target_env = "gnu", target_env = "msvc"),
target_abi = "",
target_endian = "little",
),
all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "eabihf",
- target_endian = "little",
- ),
- all(
target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "netbsd",
+ target_vendor = "pc",
+ target_os = "solaris",
target_env = "",
target_abi = "",
target_endian = "little",
),
all(
- target_arch = "x86",
+ target_arch = "x86_64",
target_vendor = "unknown",
- target_os = "freebsd",
+ any(target_os = "freebsd", target_os = "illumos", target_os = "netbsd"),
target_env = "",
target_abi = "",
target_endian = "little",
),
+))]
+pub(crate) const SUPPORTED: bool = true;
+/// `rustup` is not supported by the target per <https://rust-lang.github.io/rustup-components-history/>.
+/// Last checked on 2025-11-13T18:49Z.
+#[cfg(not(any(
all(
- target_arch = "x86_64",
- target_vendor = "apple",
- target_os = "ios",
- target_env = "",
- target_abi = "macabi",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
+ any(target_arch = "aarch64", target_arch = "x86_64"),
target_vendor = "apple",
target_os = "macos",
target_env = "",
@@ -1004,119 +112,75 @@ pub(crate) const SUPPORTED: bool = true;
target_endian = "little",
),
all(
- target_arch = "aarch64",
- target_vendor = "apple",
- target_os = "ios",
- target_env = "",
- target_abi = "macabi",
+ any(target_arch = "aarch64", target_arch = "x86_64"),
+ target_vendor = "pc",
+ target_os = "windows",
+ target_env = "gnu",
+ target_abi = "llvm",
target_endian = "little",
),
all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "eabi",
- ),
- all(
- target_arch = "wasm32",
- target_vendor = "unknown",
- target_os = "wasi",
- target_env = "p2",
+ target_arch = "aarch64",
+ target_vendor = "pc",
+ target_os = "windows",
+ target_env = "msvc",
target_abi = "",
target_endian = "little",
),
all(
- target_arch = "mips",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- ),
- all(
- target_arch = "mips32r6",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- ),
- all(
- target_arch = "sparc64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- target_endian = "big",
- ),
- all(
- target_arch = "riscv64",
+ any(
+ target_arch = "aarch64",
+ target_arch = "loongarch64",
+ target_arch = "powerpc64",
+ target_arch = "x86_64"
+ ),
target_vendor = "unknown",
target_os = "linux",
- target_env = "musl",
+ any(target_env = "gnu", target_env = "musl"),
target_abi = "",
target_endian = "little",
),
all(
- target_arch = "loongarch64",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "softfloat",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
+ target_arch = "arm",
target_vendor = "unknown",
target_os = "linux",
target_env = "gnu",
- target_abi = "",
+ any(target_abi = "eabi", target_abi = "eabihf"),
target_endian = "little",
),
all(
- target_arch = "loongarch64",
+ any(
+ target_arch = "powerpc",
+ target_arch = "powerpc64",
+ target_arch = "s390x"
+ ),
target_vendor = "unknown",
target_os = "linux",
- target_env = "musl",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "pc",
- target_os = "windows",
target_env = "gnu",
target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "wasm32",
- target_vendor = "unknown",
- target_os = "wasi",
- target_env = "p1",
- target_abi = "",
- target_endian = "little",
+ target_endian = "big",
),
all(
- target_arch = "s390x",
+ any(target_arch = "riscv64", target_arch = "x86"),
target_vendor = "unknown",
target_os = "linux",
target_env = "gnu",
target_abi = "",
- target_endian = "big",
+ target_endian = "little",
),
all(
- target_arch = "x86",
- target_vendor = "unknown",
- target_os = "android",
+ target_arch = "sparc64",
+ target_vendor = "sun",
+ target_os = "solaris",
target_env = "",
target_abi = "",
- target_endian = "little",
+ target_endian = "big",
),
all(
- target_arch = "arm64ec",
+ any(target_arch = "x86", target_arch = "x86_64"),
target_vendor = "pc",
target_os = "windows",
- target_env = "msvc",
+ any(target_env = "gnu", target_env = "msvc"),
target_abi = "",
target_endian = "little",
),
@@ -1129,84 +193,12 @@ pub(crate) const SUPPORTED: bool = true;
target_endian = "little",
),
all(
- target_arch = "arm",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "musl",
- target_abi = "eabihf",
- target_endian = "little",
- ),
- all(
- target_arch = "aarch64",
- target_vendor = "unknown",
- target_os = "none",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "musl",
- target_abi = "",
- target_endian = "little",
- ),
- all(
target_arch = "x86_64",
target_vendor = "unknown",
- target_os = "android",
- target_env = "",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86",
- target_vendor = "pc",
- target_os = "windows",
- target_env = "gnu",
- target_abi = "llvm",
- target_endian = "little",
- ),
- all(
- target_arch = "sparc64",
- target_vendor = "sun",
- target_os = "solaris",
+ any(target_os = "freebsd", target_os = "illumos", target_os = "netbsd"),
target_env = "",
target_abi = "",
- target_endian = "big",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "ohos",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "x86_64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- target_endian = "little",
- ),
- all(
- target_arch = "loongarch64",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
target_endian = "little",
),
- all(
- target_arch = "powerpc",
- target_vendor = "unknown",
- target_os = "linux",
- target_env = "gnu",
- target_abi = "",
- target_endian = "big",
- ),
)))]
pub(crate) const SUPPORTED: bool = false;