use anyhow::{bail, Result};
use std::process::Command;
use crate::git::cli::GitCli;
impl GitCli {
pub fn stash_list(&self, repo_path: &str) -> Result<Vec<crate::app::state::StashEntry>> {
let output = Command::new("git")
.args([
"-C", repo_path,
"stash", "list",
"--format=%gd|%h|%gs|%cr"
])
.output()?;
if !output.status.success() {
bail!(
"git stash list failed: {}",
String::from_utf8_lossy(&output.stderr)
);
}
let text = String::from_utf8_lossy(&output.stdout);
let mut stashes = Vec::new();
for line in text.lines() {
let parts: Vec<&str> = line.splitn(4, '|').collect();
if parts.len() == 4 {
stashes.push(crate::app::state::StashEntry {
name: parts[0].to_string(),
message: parts[2].to_string(),
});
}
}
Ok(stashes)
}
pub fn stash_apply(&self, repo_path: &str, selector: &str, drop: bool) -> Result<()> {
let output = if drop {
Command::new("git")
.args(["-C", repo_path, "stash", "pop", selector])
.output()?
} else {
Command::new("git")
.args(["-C", repo_path, "stash", "apply", selector])
.output()?
};
if !output.status.success() {
bail!(
"git stash apply/pop failed: {}",
String::from_utf8_lossy(&output.stderr)
);
}
Ok(())
}
pub fn stash_push(&self, repo_path: &str, message: &str) -> Result<()> {
let output = if message.is_empty() {
Command::new("git")
.args(["-C", repo_path, "stash", "push"])
.output()?
} else {
Command::new("git")
.args(["-C", repo_path, "stash", "push", "-m", message])
.output()?
};
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
if stderr.contains("No local changes to save") {
bail!("No local changes to save");
}
bail!(
"git stash push failed: {}",
stderr
);
}
Ok(())
}
pub fn stash_drop(&self, repo_path: &str, selector: &str) -> Result<()> {
let output = Command::new("git")
.args(["-C", repo_path, "stash", "drop", selector])
.output()?;
if !output.status.success() {
bail!(
"git stash drop failed: {}",
String::from_utf8_lossy(&output.stderr)
);
}
Ok(())
}
}