diff --git a/README.md b/README.md index 98058178..ee625e37 100644 --- a/README.md +++ b/README.md @@ -316,12 +316,14 @@ Perform commands on a specified (inclusive) range of Rust versions. ```console $ cargo hack check --version-range 1.46..=1.47 -info: running `cargo +1.46 check` on cargo-hack (1/2) +info: running `rustup run 1.46 cargo check` on cargo-hack (1/2) ... -info: running `cargo +1.47 check` on cargo-hack (2/2) +info: running `rustup run 1.47 cargo check` on cargo-hack (2/2) ... ``` +(We use `rustup run cargo` instead of `cargo +` to work around a [rustup bug](https://github.com/rust-lang/rustup/issues/3036).) + This might be useful for catching issues like [termcolor#35], [regex#685], [rust-clippy#6324]. diff --git a/src/main.rs b/src/main.rs index 789e2b73..c53d7a63 100644 --- a/src/main.rs +++ b/src/main.rs @@ -71,7 +71,9 @@ fn try_main() -> Result<()> { progress.total += total * cx.target.len(); } } - let line = cmd!("cargo"); + // Do not use `cargo +` due to a rustup bug: https://github.com/rust-lang/rustup/issues/3036 + let mut line = cmd!("rustup"); + line.leading_arg("run"); // First, generate the lockfile using the oldest cargo specified. // https://github.com/taiki-e/cargo-hack/issues/105 @@ -80,11 +82,12 @@ fn try_main() -> Result<()> { // (This does not work around the underlying cargo bug: https://github.com/rust-lang/cargo/issues/10623) let mut regenerate_lockfile_on_51_or_up = false; for cargo_version in range { - let toolchain = format!("+1.{cargo_version}"); + let toolchain = format!("1.{cargo_version}"); rustup::install_toolchain(&toolchain, &cx.target, true)?; if generate_lockfile || regenerate_lockfile_on_51_or_up && *cargo_version >= 51 { let mut line = line.clone(); line.leading_arg(&toolchain); + line.leading_arg("cargo"); line.arg("generate-lockfile"); if let Some(pid) = cx.current_package() { let package = cx.packages(pid); @@ -112,6 +115,7 @@ fn try_main() -> Result<()> { let mut line = line.clone(); line.leading_arg(&toolchain); + line.leading_arg("cargo"); line.apply_context(cx); exec_on_packages( cx, diff --git a/src/metadata.rs b/src/metadata.rs index 928c7780..4a8c5cf8 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -53,7 +53,7 @@ impl Metadata { restore: &restore::Manager, ) -> Result { let stable_cargo_version = - cargo::version(cmd!("cargo", "+stable")).map(|v| v.minor).unwrap_or(0); + cargo::version(cmd!("rustup", "run", "stable", "cargo")).map(|v| v.minor).unwrap_or(0); let mut cmd; let json = if stable_cargo_version > cargo_version { @@ -79,7 +79,7 @@ impl Metadata { // Try with stable cargo because if workspace member has // a dependency that requires newer cargo features, `cargo metadata` // with older cargo may fail. - cmd = cmd!("cargo", "+stable", "metadata", "--format-version=1"); + cmd = cmd!("rustup", "run", "stable", "cargo", "metadata", "--format-version=1"); if let Some(manifest_path) = &args.manifest_path { cmd.arg("--manifest-path"); cmd.arg(manifest_path); diff --git a/src/rustup.rs b/src/rustup.rs index 1624b9c0..ec467b3e 100644 --- a/src/rustup.rs +++ b/src/rustup.rs @@ -43,7 +43,7 @@ pub(crate) fn version_range(range: VersionRange, cx: &Context) -> Result Command { cmd } -fn test_toolchain() -> String { - if let Some(toolchain) = test_version() { - format!("+1.{toolchain} ") - } else { - String::new() - } -} - fn test_version() -> Option { static TEST_VERSION: OnceLock> = OnceLock::new(); *TEST_VERSION.get_or_init(|| { @@ -145,10 +137,12 @@ struct AssertOutputInner { } fn replace_command(lines: &str) -> String { - if lines.contains("cargo +") || lines.contains(&format!("cargo{EXE_SUFFIX} +")) { + if lines.contains("rustup run") { lines.to_owned() + } else if let Some(minor) = test_version() { + lines.replace("cargo ", &format!("rustup run 1.{minor} cargo ")) } else { - lines.replace("cargo ", &format!("cargo {}", test_toolchain())) + lines.to_owned() } } fn line_separated(lines: &str) -> impl Iterator { diff --git a/tests/test.rs b/tests/test.rs index f9cac600..44f07089 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1315,13 +1315,12 @@ fn default_feature_behavior() { .stdout_not_contains("has default feature!"); } -#[cfg_attr(windows, ignore)] // rustup bug: https://github.com/rust-lang/rustup/issues/3036 #[test] fn version_range() { cargo_hack(["check", "--version-range", "1.63..=1.64"]).assert_success("real").stderr_contains( " - running `cargo +1.63 check` on real (1/2) - running `cargo +1.64 check` on real (2/2) + running `rustup run 1.63 cargo check` on real (1/2) + running `rustup run 1.64 cargo check` on real (2/2) ", ); @@ -1330,8 +1329,8 @@ fn version_range() { .stderr_contains( " warning: using `..` for inclusive range is deprecated; consider using `1.63..=1.64` - running `cargo +1.63 check` on real (1/2) - running `cargo +1.64 check` on real (2/2) + running `rustup run 1.63 cargo check` on real (1/2) + running `rustup run 1.64 cargo check` on real (2/2) ", ); @@ -1339,8 +1338,8 @@ fn version_range() { .assert_success("real") .stderr_contains(format!( " - running `cargo +1.63 check --target {TARGET}` on real (1/2) - running `cargo +1.64 check --target {TARGET}` on real (2/2) + running `rustup run 1.63 cargo check --target {TARGET}` on real (1/2) + running `rustup run 1.64 cargo check --target {TARGET}` on real (2/2) ", )); @@ -1348,31 +1347,23 @@ fn version_range() { .assert_success("rust-version") .stderr_contains( " - running `cargo +1.64 check` on real (1/1) + running `rustup run 1.64 cargo check` on real (1/1) ", ); } -#[cfg_attr(windows, ignore)] // rustup bug: https://github.com/rust-lang/rustup/issues/3036 #[test] fn rust_version() { cargo_hack(["check", "--rust-version"]).assert_success("rust-version").stderr_contains( " - running `cargo +1.64 check` on real (1/1) - ", + running `rustup run 1.64 cargo check` on real (1/1) + ", ); } -#[cfg_attr(windows, ignore)] // rustup bug: https://github.com/rust-lang/rustup/issues/3036 #[test] fn multi_target() { - let target_suffix = if cfg!(target_os = "linux") && cfg!(target_env = "gnu") { - "-unknown-linux-gnu" - } else if cfg!(target_os = "macos") { - "-apple-darwin" - } else { - unimplemented!() - }; + let target_suffix = String::from("-") + TARGET.split_once('-').unwrap().1; cargo_hack([ "check", @@ -1384,8 +1375,8 @@ fn multi_target() { .assert_success("real") .stderr_contains(format!( " - running `cargo +1.63 check --target aarch64{target_suffix}` on real (1/2) - running `cargo +1.64 check --target aarch64{target_suffix}` on real (2/2) + running `rustup run 1.63 cargo check --target aarch64{target_suffix}` on real (1/2) + running `rustup run 1.64 cargo check --target aarch64{target_suffix}` on real (2/2) " )); @@ -1401,9 +1392,9 @@ fn multi_target() { .assert_success("real") .stderr_contains(format!( " - running `cargo +1.63 check --target aarch64{target_suffix}` on real (1/3) - running `cargo +1.63 check --target x86_64{target_suffix}` on real (2/3) - running `cargo +1.64 check --target aarch64{target_suffix} --target x86_64{target_suffix}` on real (3/3) + running `rustup run 1.63 cargo check --target aarch64{target_suffix}` on real (1/3) + running `rustup run 1.63 cargo check --target x86_64{target_suffix}` on real (2/3) + running `rustup run 1.64 cargo check --target aarch64{target_suffix} --target x86_64{target_suffix}` on real (3/3) ", )); @@ -1419,13 +1410,12 @@ fn multi_target() { .assert_success("real") .stderr_contains(format!( " - running `cargo +1.63 check --target x86_64{target_suffix}` on real (1/2) - running `cargo +1.64 check --target x86_64{target_suffix}` on real (2/2) + running `rustup run 1.63 cargo check --target x86_64{target_suffix}` on real (1/2) + running `rustup run 1.64 cargo check --target x86_64{target_suffix}` on real (2/2) ", )); } -#[cfg_attr(windows, ignore)] // rustup bug: https://github.com/rust-lang/rustup/issues/3036 #[test] fn version_range_failure() { // zero step