eazygit 0.5.1

A fast TUI for Git with staging, conflicts, rebase, and palette-first UX
Documentation
//! History operations: cherry_pick, revert, reset, log_brief, log_stats.

use anyhow::{bail, Result};
use std::process::Command;
use super::GitCli;

impl GitCli {
    /// Cherry-pick a commit hash.
    pub fn cherry_pick(&self, repo_path: &str, hash: &str) -> Result<()> {
        let output = Command::new("git")
            .args(["-C", repo_path, "cherry-pick", hash])
            .output()?;
        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            if stderr.contains("your local changes would be overwritten") {
                bail!("Cannot cherry-pick: uncommitted changes would be overwritten. Commit or stash first.");
            }
            bail!("git cherry-pick failed: {}", stderr);
        }
        Ok(())
    }

    /// Revert a commit hash.
    pub fn revert(&self, repo_path: &str, hash: &str) -> Result<()> {
        let output = Command::new("git")
            .args(["-C", repo_path, "revert", hash])
            .output()?;
        if !output.status.success() {
            bail!("git revert failed: {}", String::from_utf8_lossy(&output.stderr));
        }
        Ok(())
    }

    /// Reset to a target with a mode (soft/mixed/hard).
    pub fn reset(&self, repo_path: &str, mode: &str, target: &str) -> Result<()> {
        let output = Command::new("git")
            .args(["-C", repo_path, "reset", mode, target])
            .output()?;
        if !output.status.success() {
            bail!("git reset failed: {}", String::from_utf8_lossy(&output.stderr));
        }
        Ok(())
    }

    /// Log brief (oneline, decorate, graph).
    pub fn log_brief(&self, repo_path: &str, limit: usize) -> Result<String> {
        let output = Command::new("git")
            .args(["-C", repo_path, "log", "--oneline", "--decorate", "--graph", "--date=relative", "-n", &limit.to_string()])
            .output()?;
        if !output.status.success() {
            bail!("git log failed: {}", String::from_utf8_lossy(&output.stderr));
        }
        Ok(String::from_utf8_lossy(&output.stdout).into_owned())
    }

    /// Log with stats.
    pub fn log_stats(&self, repo_path: &str, limit: usize) -> Result<String> {
        let output = Command::new("git")
            .args(["-C", repo_path, "log", "--stat", "-n", &limit.to_string()])
            .output()?;
        if !output.status.success() {
            bail!("git log --stat failed: {}", String::from_utf8_lossy(&output.stderr));
        }
        Ok(String::from_utf8_lossy(&output.stdout).into_owned())
    }
}