a73x

6cc4a83e

Fix patch merge and TUI diff with short commit OIDs

a73x   2026-03-20 20:12

Closes ddfb3488. Use repo.revparse_single() instead of
Oid::from_str() to resolve head commits in patch merge and TUI diff
generation. This correctly resolves short OID prefixes instead of
zero-padding them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

diff --git a/src/patch.rs b/src/patch.rs
index eceee5e..2bed55c 100644
--- a/src/patch.rs
+++ b/src/patch.rs
@@ -145,15 +145,19 @@ pub fn merge(repo: &Repository, id_prefix: &str) -> Result<(), crate::error::Err
        .into());
    }

    // Resolve the head commit and the base branch
    let head_oid = git2::Oid::from_str(&p.head_commit)
        .map_err(|_| git2::Error::from_str("invalid head commit OID in patch"))?;
    let head_commit = repo.find_commit(head_oid)?;
    // Resolve the head commit (supports short OIDs via revparse)
    let head_obj = repo
        .revparse_single(&p.head_commit)
        .map_err(|_| git2::Error::from_str("cannot resolve head commit in patch"))?;
    let head_commit = head_obj
        .into_commit()
        .map_err(|_| git2::Error::from_str("head ref is not a commit"))?;

    let base_ref = format!("refs/heads/{}", p.base_ref);
    let base_oid = repo.refname_to_id(&base_ref)?;

    // Fast-forward: the base must be an ancestor of head
    let head_oid = head_commit.id();
    if repo.graph_descendant_of(head_oid, base_oid)? {
        repo.reference(&base_ref, head_oid, true, "collab: merge patch")?;
    } else if head_oid == base_oid {
diff --git a/src/tui.rs b/src/tui.rs
index 51612da..510defe 100644
--- a/src/tui.rs
+++ b/src/tui.rs
@@ -5,7 +5,7 @@ use std::time::Duration;
use crossterm::event::{self, Event, KeyCode, KeyModifiers};
use crossterm::terminal::{self, EnterAlternateScreen, LeaveAlternateScreen};
use crossterm::ExecutableCommand;
use git2::{DiffFormat, Oid, Repository};
use git2::{DiffFormat, Repository};
use ratatui::prelude::*;
use ratatui::widgets::{Block, Borders, List, ListItem, ListState, Paragraph, Tabs, Wrap};

@@ -153,9 +153,12 @@ impl App {

fn generate_diff(repo: &Repository, patch: &PatchState) -> String {
    let result = (|| -> Result<String, Error> {
        let head_oid = Oid::from_str(&patch.head_commit)
            .map_err(|e| Error::Cmd(format!("bad head OID: {}", e)))?;
        let head_commit = repo.find_commit(head_oid)?;
        let head_obj = repo
            .revparse_single(&patch.head_commit)
            .map_err(|e| Error::Cmd(format!("bad head ref: {}", e)))?;
        let head_commit = head_obj
            .into_commit()
            .map_err(|_| Error::Cmd("head ref is not a commit".to_string()))?;
        let head_tree = head_commit.tree()?;

        let base_ref = format!("refs/heads/{}", patch.base_ref);