use std::error::Error;
use std::io::Read;
use std::process::{Command, Stdio};
use cargo_metadata::Target;
use serde::Deserialize;
use crate::print_command;
#[derive(Deserialize)]
pub struct UnitGraph {
pub version: i32,
pub units: Vec<Unit>,
}
impl UnitGraph {
pub(crate) fn from_cargo(cargo_cmd: &Command, verbose: bool) -> Result<Self, Box<dyn Error>> {
let mut cmd = Command::new(cargo_cmd.get_program());
let mut args = cargo_cmd.get_args();
cmd.args(args.next())
.args(["-Z", "unstable-options", "--unit-graph"])
.args(args)
.envs(cargo_cmd.get_envs().filter_map(|(k, v)| Some((k, v?))))
.stdout(Stdio::piped())
.stderr(Stdio::piped());
if verbose {
print_command(&cmd);
}
let mut proc = cmd.spawn()?;
let stdout = proc.stdout.take().unwrap();
let mut stderr = proc.stderr.take().unwrap();
let result: Self = serde_json::from_reader(stdout).map_err(|err| {
let mut stderr_str = String::new();
let _ = stderr.read_to_string(&mut stderr_str);
let _ = proc.wait();
format!("unable to parse `--unit-graph` json: {err}\nstderr: `{stderr_str}`")
})?;
let _status = proc.wait()?;
if result.version == 1 {
Ok(result)
} else {
Err(format!(
"unknown `cargo --unit-graph` output version {}",
result.version
))?
}
}
}
#[derive(Deserialize)]
pub struct Unit {
pub target: Target,
pub profile: Profile,
}
#[derive(Deserialize)]
pub struct Profile {
pub debuginfo: Option<u32>,
}