use std::path::Path;
use std::process::Command;
use anyhow::{bail, Context, Result};
use super::{crate_from_path, parse_llvm_cov_json, CoverageReport};
pub fn tool_available() -> bool {
Command::new("cargo")
.args(["llvm-cov", "--version"])
.output()
.map(|o| o.status.success())
.unwrap_or(false)
}
pub const INSTALL_HINT: &str = "cargo-llvm-cov not found. Install it with:\n \
rustup component add llvm-tools-preview\n \
cargo install cargo-llvm-cov";
pub fn run(repo: &str, repo_root: &Path, extra_args: &[String]) -> Result<CoverageReport> {
if !tool_available() {
bail!("{INSTALL_HINT}");
}
let root = repo_root.to_string_lossy().to_string();
let mut cmd = Command::new("cargo");
cmd.arg("llvm-cov")
.arg("--json")
.current_dir(repo_root);
for a in extra_args {
cmd.arg(a);
}
let out = cmd
.output()
.with_context(|| format!("spawn `cargo llvm-cov --json` in {root}"))?;
if !out.status.success() {
bail!(
"cargo llvm-cov failed ({}):\n{}",
out.status,
String::from_utf8_lossy(&out.stderr)
);
}
let json = String::from_utf8(out.stdout).context("llvm-cov JSON is not UTF-8")?;
parse_llvm_cov_json(&json, repo, &root, crate_from_path(repo))
.with_context(|| "parse cargo llvm-cov --json export")
}