securegit 0.8.5

Zero-trust git replacement with 12 built-in security scanners, LLM redteam bridge, universal undo, durable backups, and a 50-tool MCP server
Documentation
use crate::ops::utils::{format_timestamp, short_oid};
use anyhow::Result;
use git2::{Commit, Repository};
use std::path::Path;

pub fn execute(path: &Path, object: &str, stat_only: bool) -> Result<()> {
    let repo = crate::ops::open_repo(path)?;
    let obj = repo.revparse_single(object)?;

    // If it's an annotated tag, show tag info first
    if obj.kind() == Some(git2::ObjectType::Tag) {
        let tag = obj.peel(git2::ObjectType::Tag)?;
        let tag = tag
            .as_tag()
            .ok_or_else(|| anyhow::anyhow!("expected tag object"))?;
        println!("tag {}", tag.name().unwrap_or(""));
        if let Some(tagger) = tag.tagger() {
            println!(
                "Tagger: {} <{}>",
                tagger.name().unwrap_or(""),
                tagger.email().unwrap_or("")
            );
        }
        if let Some(msg) = tag.message() {
            println!();
            for line in msg.lines() {
                println!("    {}", line);
            }
        }
        println!();
    }

    let commit = obj.peel_to_commit()?;
    show_commit(&repo, &commit, stat_only)?;

    Ok(())
}

pub fn execute_compact(path: &Path, object: &str) -> Result<String> {
    use crate::cli::compact::CompactDiffFormatter;

    let repo = crate::ops::open_repo(path)?;
    let obj = repo.revparse_single(object)?;
    let commit = obj.peel_to_commit()?;

    let short_id = short_oid(&commit.id());
    let summary = commit.summary().unwrap_or("");
    let author = commit.author();
    let author_name = author.name().unwrap_or("");
    let time = commit.time();
    let timestamp = format_timestamp(time.seconds(), time.offset_minutes());

    let mut output = format!(
        "{} {} ({}) <{}>\n",
        short_id, summary, timestamp, author_name
    );

    // Diff against first parent (or empty tree for root commit)
    let parent_tree = commit.parent(0).ok().and_then(|p| p.tree().ok());
    let tree = commit.tree()?;
    let diff = repo.diff_tree_to_tree(parent_tree.as_ref(), Some(&tree), None)?;

    // Stat summary
    let stats = diff.stats()?;
    let stat_buf = stats.to_buf(git2::DiffStatsFormat::SHORT, 80)?;
    output.push_str(stat_buf.as_str().unwrap_or(""));

    // Compact diff via formatter
    let formatter = std::cell::RefCell::new(CompactDiffFormatter::new());

    diff.print(git2::DiffFormat::Patch, |_delta, _hunk, line| {
        let mut fmt = formatter.borrow_mut();
        let content = std::str::from_utf8(line.content()).unwrap_or("");
        match line.origin() {
            'F' => {
                if let Some(path) = _delta
                    .new_file()
                    .path()
                    .or_else(|| _delta.old_file().path())
                {
                    fmt.begin_file(&path.display().to_string());
                }
            }
            'H' => {
                fmt.begin_hunk(content);
            }
            '+' | '-' | ' ' => {
                fmt.add_line(line.origin(), content);
            }
            _ => {}
        }
        true
    })?;

    let compact_diff = formatter.into_inner().finish();
    output.push_str(&compact_diff);

    Ok(output.trim_end().to_string())
}

fn show_commit(repo: &Repository, commit: &Commit, stat_only: bool) -> Result<()> {
    println!("commit {}", commit.id());

    if commit.parent_count() > 1 {
        let parents: Vec<String> = (0..commit.parent_count())
            .filter_map(|i| commit.parent_id(i).ok())
            .map(|id| short_oid(&id))
            .collect();
        println!("Merge: {}", parents.join(" "));
    }

    let author = commit.author();
    println!(
        "Author: {} <{}>",
        author.name().unwrap_or(""),
        author.email().unwrap_or("")
    );

    let time = commit.time();
    println!(
        "Date:   {}",
        format_timestamp(time.seconds(), time.offset_minutes())
    );
    println!();

    if let Some(msg) = commit.message() {
        for line in msg.lines() {
            println!("    {}", line);
        }
        println!();
    }

    // Diff against first parent (or empty tree for root commit)
    let parent_tree = commit.parent(0).ok().and_then(|p| p.tree().ok());
    let tree = commit.tree()?;
    let diff = repo.diff_tree_to_tree(parent_tree.as_ref(), Some(&tree), None)?;

    if stat_only {
        let stats = diff.stats()?;
        let buf = stats.to_buf(git2::DiffStatsFormat::FULL, 80)?;
        print!("{}", buf.as_str().unwrap_or(""));
    } else {
        diff.print(git2::DiffFormat::Patch, |_delta, _hunk, line| {
            let prefix = match line.origin() {
                '+' => "+",
                '-' => "-",
                ' ' => " ",
                _ => "",
            };
            print!(
                "{}{}",
                prefix,
                std::str::from_utf8(line.content()).unwrap_or("")
            );
            true
        })?;
    }

    Ok(())
}