kitgit

tirbofish/kitgit · commit

91ca4e1b8da75e5070d27dcae2807dc784bcb423

blame history

Verified

Thribhu K <4tkbytes@pm.me> · 2026-07-28 15:06

view full diff

diff --git a/src/git/blame.rs b/src/git/blame.rs
new file mode 100644
index 0000000..1b55286
--- /dev/null
+++ b/src/git/blame.rs
@@ -0,0 +1,134 @@
+//! Blame and path history helpers (git2).
+
+use anyhow::{anyhow, Result};
+use git2::{BlameOptions, Commit, Oid, Repository as G2Repo, Sort};
+use std::collections::HashMap;
+use std::path::Path;
+
+use super::repo::{read_blob, resolve_ref, CommitInfo};
+
+/// One displayed line in a blame view.
+#[derive(Debug, Clone)]
+pub struct BlameLine {
+    pub line_no: usize,
+    pub content: String,
+    pub commit_id: String,
+    pub short_id: String,
+    pub author: String,
+    pub time: i64,
+    pub summary: String,
+    /// First line of a contiguous blame hunk (same final commit).
+    pub hunk_start: bool,
+}
+
+/// Commits that introduced a change to `path` (blob OID differs from parent), newest first.
+pub fn list_commits_for_path(
+    repo: &G2Repo,
+    reference: &str,
+    path: &str,
+    limit: usize,
+) -> Result<Vec<CommitInfo>> {
+    let oid = resolve_ref(repo, reference)?;
+    let mut revwalk = repo.revwalk()?;
+    revwalk.push(oid)?;
+    revwalk.set_sorting(Sort::TIME)?;
+    let mut out = Vec::new();
+    for id in revwalk {
+        let id = id?;
+        let c = repo.find_commit(id)?;
+        if !path_changed_in_commit(&c, path)? {
+            continue;
+        }
+        let author = c.author();
+        out.push(CommitInfo {
+            id: id.to_string(),

Large diffs are not rendered by default. Showing the first 50 of 604 lines. Show full diff