diff --git a/NEWS.md b/NEWS.md index 646847c4..9a53fefd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,7 @@ ## Unreleased +- New: `--target-dir` sets the Cargo target directory for check, build, and test commands ([#407](https://github.com/sourcefrog/cargo-mutants/issues/407)). - New: `#[mutants::exclude_re("pattern")]` attribute to exclude specific mutations by regex, without disabling all mutations on the function. The attribute can be placed on functions, `impl` blocks, `trait` blocks, modules, files, and on expressions that can carry an attribute (such as `match`, struct literals, call expressions, method calls, and unary expressions). Multiple patterns can be applied. Also supported within `cfg_attr`. Requires the [mutants](https://crates.io/crates/mutants) crate version `0.0.5` or later. - Fixed: `#[mutants::skip]` (and `#[cfg_attr(..., mutants::skip)]`) is now honoured when placed on `const` and `static` items, including associated constants in `impl` and `trait` blocks. Previously the attribute was silently ignored on these items and operator mutants inside the initializer expression were still generated ([#508](https://github.com/sourcefrog/cargo-mutants/issues/508)). diff --git a/book/src/cargo-args.md b/book/src/cargo-args.md index 6f36e1f3..f7ff1042 100644 --- a/book/src/cargo-args.md +++ b/book/src/cargo-args.md @@ -27,6 +27,20 @@ no_default_features = true When both command line and config options are specified, the command line flags take precedence for boolean options (`all_features` and `no_default_features`), while features from both sources are combined. +## Target directory + +Use `--target-dir` to set the Cargo target directory for every check, build, and test invocation: + +```shell +cargo mutants --target-dir target/mutants +``` + +The path is passed to Cargo unchanged. The equivalent configuration-file form is: + +```toml +additional_cargo_args = ["--target-dir=target/mutants"] +``` + ## Arguments to all `cargo` commands To pass more arguments to every Cargo invocation, use `--cargo-arg`, or the `additional_cargo_args` configuration key. diff --git a/src/cargo.rs b/src/cargo.rs index 909dd881..ed8eb925 100644 --- a/src/cargo.rs +++ b/src/cargo.rs @@ -135,6 +135,9 @@ fn cargo_argv(packages: &PackageSelection, phase: Phase, options: &Options) -> V } } } + if let Some(target_dir) = &options.target_dir { + cargo_args.push(format!("--target-dir={target_dir}")); + } cargo_args.push("--verbose".to_string()); match packages { PackageSelection::All => { @@ -365,6 +368,41 @@ mod test { ); } + #[test] + fn target_dir_is_passed_to_all_cargo_commands() { + let options = Options::from_arg_strs(["mutants", "--target-dir", "target/mutants"]); + + assert_eq!( + cargo_argv(&PackageSelection::All, Phase::Check, &options)[1..], + [ + "check", + "--tests", + "--target-dir=target/mutants", + "--verbose", + "--workspace", + ] + ); + assert_eq!( + cargo_argv(&PackageSelection::All, Phase::Build, &options)[1..], + [ + "test", + "--no-run", + "--target-dir=target/mutants", + "--verbose", + "--workspace", + ] + ); + assert_eq!( + cargo_argv(&PackageSelection::All, Phase::Test, &options)[1..], + [ + "test", + "--target-dir=target/mutants", + "--verbose", + "--workspace", + ] + ); + } + #[test] fn nextest_gets_special_cargo_profile_option() { let args = Args::try_parse_from( diff --git a/src/main.rs b/src/main.rs index 42cdfd61..1047651b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -148,6 +148,10 @@ pub struct Args { #[arg(long, help_heading = "Build")] profile: Option, + /// Directory for all generated Cargo artifacts. + #[arg(long, help_heading = "Build", value_name = "DIRECTORY")] + target_dir: Option, + // Config ============================================================ /// Read configuration from this file instead of .cargo/mutants.toml. #[arg( diff --git a/src/options.rs b/src/options.rs index b983fb98..b80fbfb2 100644 --- a/src/options.rs +++ b/src/options.rs @@ -122,6 +122,9 @@ pub struct Options { /// Cargo profile. pub profile: Option, + /// Directory for Cargo build artifacts. + pub target_dir: Option, + /// Additional arguments for every cargo invocation. pub additional_cargo_args: Vec, @@ -384,6 +387,7 @@ impl Options { test_package, test_timeout: args.timeout.map(Duration::from_secs_f64), test_timeout_multiplier: args.timeout_multiplier.or(config.timeout_multiplier), + target_dir: args.target_dir.clone(), }; if let Some(jobs) = options.jobs && jobs > 8