From a59b7eb0bf8886a7e17512a8893a6280ccbf8c88 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 10 Mar 2026 14:49:55 -0500 Subject: [PATCH 1/7] refactor: Simplify target_dir logic --- src/cargo.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/cargo.rs b/src/cargo.rs index 0e64334..874bfb3 100644 --- a/src/cargo.rs +++ b/src/cargo.rs @@ -220,16 +220,13 @@ impl fmt::Display for NotFoundError { // Adapted from // https://github.com/rust-lang/cargo/blob/485670b3983b52289a2f353d589c57fae2f60f82/tests/testsuite/support/mod.rs#L507 fn target_dir() -> path::PathBuf { - env::current_exe() - .ok() - .map(|mut path| { - path.pop(); - if path.ends_with("deps") { - path.pop(); - } - path - }) - .expect("this should only be used where a `current_exe` can be set") + let mut path = + env::current_exe().expect("this should only be used where a `current_exe` can be set"); + let _test_bin_name = path.pop(); + if path.ends_with("deps") { + let _deps = path.pop(); + } + path } /// Look up the path to a cargo-built binary within an integration test. From bcb2519a4365c4f548f1b9403dd7f750406dafb6 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 10 Mar 2026 14:51:40 -0500 Subject: [PATCH 2/7] refactor: Improve order of file --- src/cargo.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/cargo.rs b/src/cargo.rs index 874bfb3..3562f20 100644 --- a/src/cargo.rs +++ b/src/cargo.rs @@ -217,18 +217,6 @@ impl fmt::Display for NotFoundError { } } -// Adapted from -// https://github.com/rust-lang/cargo/blob/485670b3983b52289a2f353d589c57fae2f60f82/tests/testsuite/support/mod.rs#L507 -fn target_dir() -> path::PathBuf { - let mut path = - env::current_exe().expect("this should only be used where a `current_exe` can be set"); - let _test_bin_name = path.pop(); - if path.ends_with("deps") { - let _deps = path.pop(); - } - path -} - /// Look up the path to a cargo-built binary within an integration test. /// /// **NOTE:** Prefer [`cargo_bin!`] as this makes assumptions about cargo @@ -247,5 +235,17 @@ fn cargo_bin_str(name: &str) -> path::PathBuf { .unwrap_or_else(|| target_dir().join(format!("{}{}", name, env::consts::EXE_SUFFIX))) } +// Adapted from +// https://github.com/rust-lang/cargo/blob/485670b3983b52289a2f353d589c57fae2f60f82/tests/testsuite/support/mod.rs#L507 +fn target_dir() -> path::PathBuf { + let mut path = + env::current_exe().expect("this should only be used where a `current_exe` can be set"); + let _test_bin_name = path.pop(); + if path.ends_with("deps") { + let _deps = path.pop(); + } + path +} + /// The current process' target triplet. const CURRENT_TARGET: &str = include_str!(concat!(env!("OUT_DIR"), "/current_target.txt")); From a966b36e56a06fead7688666ac20600f9a72bf6e Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 10 Mar 2026 14:52:34 -0500 Subject: [PATCH 3/7] refactor: Pull out all of the legacy logic --- src/cargo.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cargo.rs b/src/cargo.rs index 3562f20..2fceec3 100644 --- a/src/cargo.rs +++ b/src/cargo.rs @@ -232,7 +232,11 @@ fn cargo_bin_str(name: &str) -> path::PathBuf { let env_var = format!("CARGO_BIN_EXE_{name}"); env::var_os(env_var) .map(|p| p.into()) - .unwrap_or_else(|| target_dir().join(format!("{}{}", name, env::consts::EXE_SUFFIX))) + .unwrap_or_else(|| legacy_cargo_bin(name)) +} + +fn legacy_cargo_bin(name: &str) -> path::PathBuf { + target_dir().join(format!("{}{}", name, env::consts::EXE_SUFFIX)) } // Adapted from From 4f4f0f1759ada46b3b1519cc08df1461eb0c55ea Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 10 Mar 2026 14:54:41 -0500 Subject: [PATCH 4/7] refactor: Make legacy bin path fallable --- src/cargo.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/cargo.rs b/src/cargo.rs index 2fceec3..e1dc782 100644 --- a/src/cargo.rs +++ b/src/cargo.rs @@ -232,23 +232,25 @@ fn cargo_bin_str(name: &str) -> path::PathBuf { let env_var = format!("CARGO_BIN_EXE_{name}"); env::var_os(env_var) .map(|p| p.into()) - .unwrap_or_else(|| legacy_cargo_bin(name)) + .or_else(|| legacy_cargo_bin(name)) + .expect("`CARGO_BIN_EXE_*` is not set") } -fn legacy_cargo_bin(name: &str) -> path::PathBuf { - target_dir().join(format!("{}{}", name, env::consts::EXE_SUFFIX)) +fn legacy_cargo_bin(name: &str) -> Option { + let target_dir = target_dir()?; + let bin_path = target_dir.join(format!("{}{}", name, env::consts::EXE_SUFFIX)); + Some(bin_path) } // Adapted from // https://github.com/rust-lang/cargo/blob/485670b3983b52289a2f353d589c57fae2f60f82/tests/testsuite/support/mod.rs#L507 -fn target_dir() -> path::PathBuf { - let mut path = - env::current_exe().expect("this should only be used where a `current_exe` can be set"); +fn target_dir() -> Option { + let mut path = env::current_exe().ok()?; let _test_bin_name = path.pop(); if path.ends_with("deps") { let _deps = path.pop(); } - path + Some(path) } /// The current process' target triplet. From 4c9ab64f87048a31517b28292f8f81fbc8d89ba3 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 10 Mar 2026 14:56:02 -0500 Subject: [PATCH 5/7] refactor: Pull out the panic --- src/cargo.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cargo.rs b/src/cargo.rs index e1dc782..99c1252 100644 --- a/src/cargo.rs +++ b/src/cargo.rs @@ -233,7 +233,11 @@ fn cargo_bin_str(name: &str) -> path::PathBuf { env::var_os(env_var) .map(|p| p.into()) .or_else(|| legacy_cargo_bin(name)) - .expect("`CARGO_BIN_EXE_*` is not set") + .unwrap_or_else(|| missing_cargo_bin()) +} + +fn missing_cargo_bin() -> ! { + panic!("`CARGO_BIN_EXE_*` is not set") } fn legacy_cargo_bin(name: &str) -> Option { From 656f70ff4d62773663c1d27639ef519898f3a05e Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 10 Mar 2026 14:57:06 -0500 Subject: [PATCH 6/7] refactor: Pull out the env prefix --- src/cargo.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cargo.rs b/src/cargo.rs index 99c1252..2b3eeb9 100644 --- a/src/cargo.rs +++ b/src/cargo.rs @@ -229,13 +229,15 @@ pub fn cargo_bin>(name: S) -> path::PathBuf { } fn cargo_bin_str(name: &str) -> path::PathBuf { - let env_var = format!("CARGO_BIN_EXE_{name}"); + let env_var = format!("{CARGO_BIN_EXE_}{name}"); env::var_os(env_var) .map(|p| p.into()) .or_else(|| legacy_cargo_bin(name)) .unwrap_or_else(|| missing_cargo_bin()) } +const CARGO_BIN_EXE_: &str = "CARGO_BIN_EXE_"; + fn missing_cargo_bin() -> ! { panic!("`CARGO_BIN_EXE_*` is not set") } From 90a660de0bf677ae1011a844f6265b59046fe15b Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 10 Mar 2026 15:05:46 -0500 Subject: [PATCH 7/7] fix: Improve the quality of the panic message --- src/cargo.rs | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/cargo.rs b/src/cargo.rs index 2b3eeb9..ba1119f 100644 --- a/src/cargo.rs +++ b/src/cargo.rs @@ -233,13 +233,33 @@ fn cargo_bin_str(name: &str) -> path::PathBuf { env::var_os(env_var) .map(|p| p.into()) .or_else(|| legacy_cargo_bin(name)) - .unwrap_or_else(|| missing_cargo_bin()) + .unwrap_or_else(|| missing_cargo_bin(name)) } const CARGO_BIN_EXE_: &str = "CARGO_BIN_EXE_"; -fn missing_cargo_bin() -> ! { - panic!("`CARGO_BIN_EXE_*` is not set") +fn missing_cargo_bin(name: &str) -> ! { + let possible_names: Vec<_> = env::vars_os() + .filter_map(|(k, _)| k.into_string().ok()) + .filter_map(|k| k.strip_prefix(CARGO_BIN_EXE_).map(|s| s.to_owned())) + .collect(); + if possible_names.is_empty() { + panic!("`CARGO_BIN_EXE_{name}` is unset +help: if this is running within a unit test, move it to an integration test to gain access to `CARGO_BIN_EXE_{name}`") + } else { + let mut names = String::new(); + for (i, name) in possible_names.iter().enumerate() { + use std::fmt::Write as _; + if i != 0 { + let _ = write!(&mut names, ", "); + } + let _ = write!(&mut names, "\"{name}\""); + } + panic!( + "`CARGO_BIN_EXE_{name}` is unset +help: available binary names are {names}" + ) + } } fn legacy_cargo_bin(name: &str) -> Option {