use std::path::PathBuf;
use std::process::Command;
use crate::utils::output;
pub fn get_git_root() -> Option<PathBuf> {
let output = Command::new("git")
.args(["rev-parse", "--show-toplevel"])
.output()
.ok()?;
if output.status.success() {
let path_str = String::from_utf8_lossy(&output.stdout);
Some(PathBuf::from(path_str.trim()))
} else {
None
}
}
pub fn is_git_repo() -> bool {
Command::new("git")
.args(["rev-parse", "--is-inside-work-tree"])
.output()
.is_ok()
}
pub fn get_git_status(auto_add: bool) -> Vec<String> {
let status_output = Command::new("git")
.args([
"status",
"-s",
&format!("--untracked-files={}", if auto_add { "all" } else { "no" }),
])
.output()
.expect("Failed to get git status");
output::print_verbose(&format!(
"Run 'git status -s --untracked-files={}'",
if auto_add { "all" } else { "no" }
));
let status_str = String::from_utf8_lossy(&status_output.stdout);
status_str.lines().map(|s| s.to_string()).collect()
}
pub fn git_add_all() {
let add_output = Command::new("git")
.args(["add", "."])
.output()
.expect("Failed to execute git add");
if !add_output.status.success() {
eprintln!("Error: Failed to add changes to git");
panic!("git add failed");
}
output::print_verbose("Run 'git add .'");
}
pub fn get_staged_name_status() -> String {
let diff_output = Command::new("git")
.args(["diff", "--cached", "--name-status"])
.output()
.expect("Failed to get git diff --cached --name-status");
output::print_verbose("Run 'git diff --cached --name-status'");
String::from_utf8_lossy(&diff_output.stdout).to_string()
}
pub fn get_staged_diff() -> String {
let full_diff_output = Command::new("git")
.args(["diff", "--cached", "--diff-filter=AM"])
.output()
.expect("Failed to get git diff --cached --diff-filter=AM");
output::print_verbose("Run 'git diff --cached --diff-filter=AM'");
String::from_utf8_lossy(&full_diff_output.stdout).to_string()
}
pub fn get_staged_numstat() -> String {
let numstat_output = Command::new("git")
.args(["diff", "--cached", "--numstat"])
.output()
.expect("Failed to get git diff --cached --numstat");
output::print_verbose("Run 'git diff --cached --numstat'");
String::from_utf8_lossy(&numstat_output.stdout).to_string()
}
pub fn get_staged_diff_for_files(files: &[String]) -> String {
let mut args = vec!["diff", "--cached", "--diff-filter=AM", "--"];
let file_refs: Vec<&str> = files.iter().map(|s| s.as_str()).collect();
args.extend(file_refs);
let diff_output = Command::new("git")
.args(&args)
.output()
.expect("Failed to get git diff for specific files");
output::print_verbose(&format!(
"Run 'git diff --cached --diff-filter=AM -- {:?}'",
files
));
String::from_utf8_lossy(&diff_output.stdout).to_string()
}
pub fn get_last_commit_name_status() -> String {
let show_status_output = Command::new("git")
.args(["show", "--pretty=format:", "--name-status", "HEAD"])
.output()
.expect("Failed to get git show --name-status");
output::print_verbose("Run 'git show --pretty=format: --name-status HEAD'");
String::from_utf8_lossy(&show_status_output.stdout).to_string()
}
pub fn get_last_commit_diff() -> String {
let show_diff_output = Command::new("git")
.args(["show", "--pretty=format:", "--diff-filter=AM", "HEAD"])
.output()
.expect("Failed to get git show --diff-filter=AM");
output::print_verbose("Run 'git show --pretty=format: --diff-filter=AM HEAD'");
String::from_utf8_lossy(&show_diff_output.stdout).to_string()
}
pub fn get_last_commit_numstat() -> String {
let show_numstat_output = Command::new("git")
.args(["show", "--pretty=format:", "--numstat", "HEAD"])
.output()
.expect("Failed to get git show --numstat");
output::print_verbose("Run 'git show --pretty=format: --numstat HEAD'");
String::from_utf8_lossy(&show_numstat_output.stdout).to_string()
}
pub fn get_last_commit_diff_for_files(files: &[String]) -> String {
let mut args = vec!["show", "--pretty=format:", "--diff-filter=AM", "HEAD", "--"];
let file_refs: Vec<&str> = files.iter().map(|s| s.as_str()).collect();
args.extend(file_refs);
let show_diff_output = Command::new("git")
.args(&args)
.output()
.expect("Failed to get git show for specific files");
output::print_verbose(&format!(
"Run 'git show --pretty=format: --diff-filter=AM HEAD -- {:?}'",
files
));
String::from_utf8_lossy(&show_diff_output.stdout).to_string()
}
pub fn git_commit(subject: &str, message: &str, overwrite: bool) -> bool {
let mut commit_args = vec!["commit"];
if overwrite {
commit_args.push("--amend");
}
commit_args.extend(["-m", subject, "-m", message]);
output::print_verbose("Run 'git commit -m <subject> -m <message>'");
let commit_output = Command::new("git")
.args(&commit_args)
.output()
.expect("Failed to execute git commit");
commit_output.status.success()
}