use crate::manager::{PackageError, PackageManager, RunOutcome, Runner};
pub const PREFIX: &str = "cargo:";
pub struct Cargo;
impl Cargo {
fn crate_name(spec: &str) -> &str {
spec.split_once('@').map_or(spec, |(name, _)| name)
}
}
impl PackageManager for Cargo {
fn name(&self) -> &'static str {
"cargo"
}
fn is_available(&self) -> bool {
which::which("cargo").is_ok()
}
fn exists(&self, runner: &dyn Runner, pkg: &str) -> Result<bool, PackageError> {
let RunOutcome { status, .. } = runner.run("cargo", &["info", pkg])?;
Ok(status == 0)
}
fn is_installed(&self, runner: &dyn Runner, pkg: &str) -> Result<bool, PackageError> {
let RunOutcome {
status,
stdout,
stderr,
} = runner.run("cargo", &["install", "--list"])?;
if status != 0 {
return Err(PackageError::ExitFailure { status, stderr });
}
let name = Self::crate_name(pkg);
Ok(stdout
.lines()
.filter(|line| !line.starts_with(char::is_whitespace))
.any(|line| line.split_whitespace().next() == Some(name)))
}
fn install(&self, runner: &dyn Runner, packages: &[String]) -> Result<(), PackageError> {
let mut args = vec!["install", "--locked"];
args.extend(packages.iter().map(String::as_str));
let RunOutcome { status, stderr, .. } = runner.run("cargo", &args)?;
if status != 0 {
return Err(PackageError::ExitFailure { status, stderr });
}
Ok(())
}
}