ic_testkit/artifacts/
workspace.rs1use std::{
2 io,
3 path::{Path, PathBuf},
4 process::Command,
5};
6
7pub fn workspace_root_for(crate_manifest_dir: impl AsRef<Path>) -> io::Result<PathBuf> {
17 let manifest = crate_manifest_dir
18 .as_ref()
19 .canonicalize()?
20 .join("Cargo.toml");
21 let cargo = std::env::var_os("CARGO").unwrap_or_else(|| "cargo".into());
22 let output = Command::new(cargo)
23 .env("RUSTUP_AUTO_INSTALL", "0")
24 .args([
25 "--offline",
26 "locate-project",
27 "--workspace",
28 "--message-format=json",
29 ])
30 .arg("--manifest-path")
31 .arg(manifest)
32 .output()?;
33 if !output.status.success() {
34 return Err(io::Error::new(
35 io::ErrorKind::InvalidInput,
36 format!(
37 "Cargo workspace discovery failed ({}): {}",
38 output.status,
39 String::from_utf8_lossy(&output.stderr).trim()
40 ),
41 ));
42 }
43 let response: serde_json::Value = serde_json::from_slice(&output.stdout)
44 .map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))?;
45 let manifest = response
46 .get("root")
47 .and_then(serde_json::Value::as_str)
48 .map(Path::new)
49 .filter(|path| {
50 path.is_absolute() && path.file_name() == Some(std::ffi::OsStr::new("Cargo.toml"))
51 })
52 .ok_or_else(|| {
53 io::Error::new(
54 io::ErrorKind::InvalidData,
55 "Cargo returned no absolute workspace manifest",
56 )
57 })?;
58 manifest.parent().map(Path::to_owned).ok_or_else(|| {
59 io::Error::new(
60 io::ErrorKind::InvalidData,
61 "Cargo workspace manifest has no parent",
62 )
63 })
64}
65
66#[must_use]
68pub fn test_target_dir(workspace_root: &Path, name: &str) -> PathBuf {
69 workspace_root.join("target").join(name)
70}