Compare commits

...
1 Commits
Author SHA1 Message Date
CodeWhale BotandClaude Sonnet 5.5 9015c91b5b fix(tui): find the codewhale binary under Cargo's per-unit build layout
The acceptance harness derived the profile directory from the test
executable's parent. Under Cargo 1.100 test executables live in
<profile>/build/<pkg>/<hash>/out, so the profile resolved to "out" and the
lookup went to target/out/codewhale. Walk up to the nearest deps or build
directory and take its parent as the profile, which holds for both layouts
and for split build directories and explicit --target builds. Adds a unit
test with a fake per-unit path and a separate final target.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 17:33:27 -08:00
+41 -10
View File
@@ -44,16 +44,7 @@ fn resolve(
if let Some(path) = qa.or(cargo) {
return require_file(path);
}
let directory = test_executable
.parent()
.ok_or("test executable has no parent")?;
let directory = if directory.ends_with("deps") {
directory
.parent()
.ok_or("test deps directory has no parent")?
} else {
directory
};
let directory = profile_directory(test_executable)?;
let name = format!("codewhale{}", std::env::consts::EXE_SUFFIX);
let adjacent = directory.join(&name);
if adjacent.is_file() {
@@ -76,6 +67,22 @@ fn resolve(
require_file(target_directory.join(profile).join(&name))
}
fn profile_directory(test_executable: &Path) -> Result<&Path, String> {
let parent = test_executable
.parent()
.ok_or("test executable has no parent")?;
parent
.ancestors()
.find(|ancestor| {
ancestor
.file_name()
.is_some_and(|name| name == "deps" || name == "build")
})
.and_then(Path::parent)
.or(Some(parent))
.ok_or_else(|| "test profile directory is unavailable".to_string())
}
// This synchronous resolver belongs only to Cargo acceptance test binaries.
#[cfg(test)]
fn require_file(path: PathBuf) -> Result<PathBuf, String> {
@@ -200,4 +207,28 @@ mod tests {
assert_eq!(resolve(None, None, &test, &target).unwrap(), canonical);
}
}
#[test]
fn per_unit_build_layout_resolves_the_final_profile_binary() {
let root = tempfile::TempDir::new().unwrap();
let target = root.path().join("target");
let cache = root.path().join("build cache");
for triple in [None, Some("aarch64-unknown-linux-gnu")] {
let profile = match triple {
Some(triple) => target.join(triple).join("debug"),
None => target.join("debug"),
};
let build_profile = match triple {
Some(triple) => cache.join(triple).join("debug"),
None => cache.join("debug"),
};
let unit = build_profile.join("build/codewhale-tui/0123456789abcdef/out");
std::fs::create_dir_all(&unit).unwrap();
std::fs::create_dir_all(&profile).unwrap();
let canonical = profile.join(format!("codewhale{}", std::env::consts::EXE_SUFFIX));
std::fs::write(&canonical, b"canonical").unwrap();
let test = unit.join("integration-hash");
assert_eq!(resolve(None, None, &test, &target).unwrap(), canonical);
}
}
}