use std::ffi::OsString;
use std::path::{Path, PathBuf};
use std::process::Command;
use super::outcome::PostInstallScanOutcome;
#[must_use]
pub fn build_import_command(exe: &Path, max_prs: u32) -> (PathBuf, Vec<OsString>) {
let argv: Vec<OsString> = vec![
"import-reviews".into(),
"--max-prs".into(),
max_prs.to_string().into(),
];
(exe.to_path_buf(), argv)
}
pub fn resolve_self_binary() -> Result<PathBuf, String> {
if let Ok(exe) = std::env::current_exe() {
let canon = exe.canonicalize().unwrap_or(exe);
return Ok(canon);
}
which::which("difflore").map_err(|e| format!("could not locate `difflore` on PATH: {e}"))
}
pub fn run_import(exe: &Path, cwd: &Path, max_prs: u32) -> PostInstallScanOutcome {
let (program, argv) = build_import_command(exe, max_prs);
let mut cmd = Command::new(&program);
cmd.args(&argv).current_dir(cwd);
cmd.env(difflore_core::cloud::capture::DIFFLORE_CAPTURE_ENV, "false");
let status = match cmd.status() {
Ok(s) => s,
Err(e) => {
return PostInstallScanOutcome::ImportFailed {
error: format!("failed to spawn `difflore import-reviews`: {e}"),
};
}
};
if status.success() {
return PostInstallScanOutcome::ImportedReviews {
pr_count: max_prs,
rule_count: 0,
};
}
PostInstallScanOutcome::ImportFailed {
error: format!("`difflore import-reviews` exited with {status}"),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn import_argv_matches_documented_public_cli() {
let exe = Path::new("/opt/difflore/bin/difflore");
let (program, argv) = build_import_command(exe, 5);
assert_eq!(program, exe);
assert_eq!(
argv,
vec![
OsString::from("import-reviews"),
OsString::from("--max-prs"),
OsString::from("5"),
]
);
}
#[test]
fn import_argv_honours_custom_max_prs() {
let (_, argv) = build_import_command(Path::new("difflore"), 25);
assert!(argv.iter().any(|a| a == "25"));
}
}