use crate::config::worktrees_dir;
use crate::util::{cmd_output, die, run_cmd};
use std::path::{Path, PathBuf};
use std::process::Command;
pub fn resolve_repo_root(repo_path: &str) -> PathBuf {
let cmd = vec![
"git".to_string(),
"-C".to_string(),
repo_path.to_string(),
"rev-parse".to_string(),
"--show-toplevel".to_string(),
];
let output = cmd_output(&cmd);
match output {
Some(path) if !path.is_empty() => PathBuf::from(path),
_ => die("vvbox requires a git repo (no git root found)"),
}
}
pub fn create_worktree(repo_root: &Path, run_id: &str) -> PathBuf {
let snapshot_path = worktrees_dir().join(run_id);
if snapshot_path.exists() {
let _ = std::fs::remove_dir_all(&snapshot_path);
}
let cmd = vec![
"git".to_string(),
"-C".to_string(),
repo_root.to_string_lossy().to_string(),
"worktree".to_string(),
"add".to_string(),
"--detach".to_string(),
snapshot_path.to_string_lossy().to_string(),
"HEAD".to_string(),
];
let status = run_cmd(&cmd, None, true);
if !status.success() {
die("failed to create git worktree snapshot");
}
snapshot_path
}
pub fn resolve_existing_worktree(path: &str) -> (PathBuf, PathBuf) {
let worktree_path = PathBuf::from(path);
if !worktree_path.exists() {
die("worktree path does not exist");
}
let cmd = vec![
"git".to_string(),
"-C".to_string(),
worktree_path.to_string_lossy().to_string(),
"rev-parse".to_string(),
"--show-toplevel".to_string(),
];
let output = cmd_output(&cmd);
match output {
Some(root) if !root.is_empty() => (PathBuf::from(root), worktree_path),
_ => die("worktree path is not a git repo"),
}
}
pub fn git_status_clean(repo_root: &str) -> bool {
let cmd = vec![
"git".to_string(),
"-C".to_string(),
repo_root.to_string(),
"status".to_string(),
"--porcelain".to_string(),
];
if let Some(out) = cmd_output(&cmd) {
return out.trim().is_empty();
}
false
}
pub fn git_apply_stat(repo_root: &str, patch_path: &Path) -> Option<String> {
let output = Command::new("git")
.arg("-C")
.arg(repo_root)
.arg("apply")
.arg("--stat")
.arg(patch_path)
.output();
if let Ok(out) = output {
if out.status.success() {
return Some(String::from_utf8_lossy(&out.stdout).to_string());
}
}
None
}