use assert_cmd::assert::OutputAssertExt;
use regex::Regex;
use std::path::{Path, PathBuf};
use std::process::Command;
pub const PRIMARY_BRANCH: &str = "master";
pub const TEST_EMAIL: &str = "test@example.com";
pub const TEST_NAME: &str = "Test User";
pub const README_CONTENT: &str = "Test repo";
pub struct GitCommand {
}
#[allow(dead_code)]
impl GitCommand {
pub fn init(repo_dir: &Path) {
Command::new("git")
.args(["init", "--initial-branch", PRIMARY_BRANCH])
.current_dir(repo_dir)
.output()
.expect("Failed to initialize git repository");
Command::new("git")
.args(["config", "user.email", TEST_EMAIL])
.current_dir(repo_dir)
.output()
.expect("Failed to configure git email");
Command::new("git")
.args(["config", "user.name", TEST_NAME])
.current_dir(repo_dir)
.output()
.expect("Failed to configure git name");
std::fs::write(repo_dir.join("README.md"), README_CONTENT).expect("Failed to create README");
Command::new("git")
.args(["add", "README.md"])
.current_dir(repo_dir)
.output()
.expect("Failed to add README to git");
Command::new("git")
.args(["commit", "-m", "Initial commit"])
.current_dir(repo_dir)
.output()
.expect("Failed to commit initial changes");
}
pub fn create_branch(repo_dir: &Path, branch_name: &str) {
Command::new("git")
.args(["branch", branch_name])
.current_dir(repo_dir)
.output()
.expect(&format!("Failed to create branch {}", branch_name));
}
pub fn is_on_branch(repo_dir: &Path, expected_branch_name: &str) -> bool {
let output = Command::new("git")
.args(["branch", "--show-current"])
.current_dir(repo_dir)
.output()
.expect("Failed to get current branch");
let actual_branch_name = String::from_utf8(output.stdout)
.expect("Branch name should be valid UTF-8")
.trim()
.to_string();
actual_branch_name == expected_branch_name
}
pub fn create_worktree(repo_dir: &Path, branch_name: &str, worktree_dir: &Path) {
Command::new("git")
.args(["worktree", "add", "-b", branch_name, &worktree_dir.to_str().expect("worktree path should be representable as a string")])
.current_dir(repo_dir)
.assert()
.success();
()
}
pub fn worktree_exists(repository_dir_buf: &PathBuf, worktree_dir_buf: &PathBuf) -> bool {
let output = Command::new("git")
.args(["worktree", "list", "--porcelain"])
.current_dir(repository_dir_buf)
.output()
.expect("Failed to list worktrees");
if !output.status.success() {
return false;
}
let worktree_list = String::from_utf8_lossy(&output.stdout);
let lines: Vec<&str> = worktree_list.lines().collect();
let re = Regex::new(r"worktree (.+)").unwrap();
let mut i = 0;
while i < lines.len() {
if let Some(captures) = re.captures(lines[i]) {
let path_str = captures.get(1).unwrap().as_str();
if worktree_dir_buf == &PathBuf::from(path_str) {
return true;
}
}
i += 1;
}
false
}
pub fn branch_exists(repo_dir: &Path, branch_name: &str) -> bool {
let output = Command::new("git")
.args(["branch", "-l", branch_name])
.current_dir(repo_dir)
.output()
.expect("Failed to list branches");
if !output.status.success() {
return false;
}
let branch_list = String::from_utf8_lossy(&output.stdout);
let lines: Vec<&str> = branch_list.lines().collect();
let re = Regex::new(r"^\s*\+\s*(.+)$").unwrap();
let mut i = 0;
while i < lines.len() {
if let Some(captures) = re.captures(lines[i]) {
let actual_branch_name = captures.get(1).unwrap().as_str().trim();
if actual_branch_name == branch_name {
return true;
}
}
i += 1;
}
false
}
}