[03/08] replace graph walking and batching internals with gitoxide-backed history reads#97
[03/08] replace graph walking and batching internals with gitoxide-backed history reads#97mjc wants to merge 23 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR is a major internal refactor that replaces libgit2 revwalk pagination + graph-buffer internals with a gitoxide (gix) backed history cursor that emits aliased commits (with parent aliases and timestamps) in batches, while keeping the renderer’s “reconstructable window” model intact. It also migrates several git queries (tags, stashes, reflogs, file-history status, heatmap inputs) across the same gix boundary and updates tests/benches accordingly.
Changes:
- Replaces revwalk batching with a
gix-backed commit cursor (Batcher/WalkedCommit) and updatesWalker/graph loading to consume aliased walked commits with parent aliases and commit-time metadata. - Reworks graph history/buffer storage (smallvec snapshots + chunked delta-op arenas + checkpoints) and adapts window construction/rendering to the new representation.
- Migrates/supports additional
gix-backed queries and tooling (reflog reads, stash/tag enumeration, heatmap streaming, file-history status lookup caching), plus adds test scaffolding and bench updates.
Reviewed changes
Copilot reviewed 53 out of 54 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/tests/helpers/localisation.rs | Switches temp language path creation to tempfile and adds a language guard to avoid cross-test global state leakage. |
| src/tests/helpers/keymap.rs | Adds language guard usage and removes manual language reset in a localisation-sensitive keymap test. |
| src/tests/helpers/heatmap.rs | Adds tests for new heatmap counting/building behavior and OID prefix lookup. |
| src/tests/git/queries/remotes.rs | Uses shared test-support repo initialization helper. |
| src/tests/git/queries/reflogs.rs | Updates reflog tests to use gix reflog reader and adds coverage for missing reflog and non-commit entries. |
| src/tests/git/queries/diffs.rs | Renames local init helper and centralizes repo seeding behavior. |
| src/tests/git/actions/reverting.rs | Uses shared test-support repo initialization helper. |
| src/tests/git/actions/rebasing.rs | Uses shared test-support repo initialization helper. |
| src/tests/git/actions/merging.rs | Uses shared test-support repo initialization helper. |
| src/tests/git/actions/cherrypicking.rs | Uses shared test-support repo initialization helper. |
| src/tests/git/actions/branching.rs | Uses shared test-support repo initialization helper. |
| src/tests/core/walker.rs | Refactors walker tests to use gix-backed walker behavior, adds new fixtures, and expands coverage for tags/worktrees/stashes/reflogs. |
| src/tests/core/renderers.rs | Updates renderer tests to match new graph-history representation and worktree symbol behavior. |
| src/tests/core/oids.rs | Adds targeted tests for aliasing/prefix lookup and OID round-tripping. |
| src/tests/core/graph_service.rs | Introduces a harness for graph-service tests; updates window/lookup/file-history tests and adds worktree update event coverage. |
| src/tests/core/buffer.rs | Replaces tests to validate new delta/log/checkpoint buffer design and memory characteristics. |
| src/tests/app/state/app.rs | Adds tests for wait_until_graph_complete behavior and adapts file-history row shape changes. |
| src/tests/app/input/navigation.rs | Updates tests for current branch naming and file-history row shape; adds language guard in settings language test. |
| src/tests/app/input/git.rs | Uses shared test-support repo initialization helper. |
| src/tests/app/draw/status.rs | Updates GraphRow construction to match new fields/defaults. |
| src/tests/app/draw/settings.rs | Adds language guard to avoid global localisation flakiness. |
| src/tests/app/draw/search.rs | Updates test row OIDs and removes reliance on a stored short_oid field. |
| src/tests/app/draw/graph.rs | Updates cached history construction to new GraphHistory type and removes short_oid usage. |
| src/main.rs | Adds --exit-when-graph-complete mode and improves CLI repo-path handling while reusing App bootstrapping. |
| src/lib.rs | Exposes new git::gix module and adds git::test_support behind cfg(test). |
| src/helpers/time.rs | Splits timestamp formatting into git2/gix variants and adds UTC date-time formatting support. |
| src/helpers/heatmap.rs | Reworks heatmap computation to gix commit reads and introduces HeatmapCounts for streamed counting. |
| src/helpers/branch_visibility.rs | Adds refname parsing helper to extract local/remote branch names from ref bytes. |
| src/git/test_support.rs | Adds shared test utilities for repos/commits/worktrees/remotes and a language guard for localisation tests. |
| src/git/queries/reflogs.rs | Replaces libgit2 reflog reads with gix-based reflog iteration and commit filtering. |
| src/git/queries/file_history.rs | Moves file-history status lookup toward gix tree/diff reads with thread-local caches. |
| src/git/queries/commits.rs | Migrates tip/tag/stash enumeration to gix, returns visible walk roots, and updates sorted-oid paging to use aliased walked commits. |
| src/git/gix.rs | Adds shared gix helpers (object cache sizing, commit-graph access, branch tip enumeration, error mapping). |
| src/core/walker.rs | Updates the history walker to own a gix::Repository, stream heatmap counts during walking, and consume aliased walked commits with parent aliases. |
| src/core/renderers.rs | Adapts graph rendering to the new history representation and optimizes allocations/lifetimes around symbol rendering. |
| src/core/oids.rs | Replaces OID storage with gix::ObjectId + compact alias mapping and adds prefix lookup support. |
| src/core/layers.rs | Removes per-token String allocations by storing &str symbols and adjusts empty-token handling. |
| src/core/chunk.rs | Makes Chunk Copy to reduce cloning in hot paths. |
| src/core/buffer.rs | Replaces prior im-based snapshot/delta model with smallvec snapshots, chunked delta-op arenas, and checkpointed replay. |
| src/core/batcher.rs | Introduces gix-backed lazy commit cursor with commit-graph acceleration, seen tracking, and aliased WalkedCommit output. |
| src/app/input/worktrees.rs | Updates worktree selection logic to use the new OID alias API. |
| src/app/input/navigation.rs | Updates parent/child navigation and alias lookup to use new OID accessors and avoid borrowing old OID map internals. |
| src/app/input/modals.rs | Replaces SHA-prefix lookup scan with Oids::get_alias_by_prefix. |
| src/app/input/git.rs | Adjusts stash OID access to new Oids::get_oid_by_alias return type. |
| src/app/draw/stashes.rs | Fixes stash commit lookup to match new OID accessor type. |
| src/app/draw/search.rs | Renders SHA prefix directly from oid formatting instead of a stored short_oid field. |
| src/app/draw/graph.rs | Generalizes line alignment lifetime and adapts to updated GraphHistory handling. |
| src/app/app.rs | Adds background-task shutdown, adds wait_until_graph_complete, improves graph worker disconnect handling, and wires Worktrees update events. |
| Cargo.toml | Adds gix/worktree crates, iddqd, smallvec, rustc-hash and related dependencies for new internals. |
| benches/render_graph_projection.rs | Adds helper row constructor and updates benchmarks to match new GraphRow fields. |
| benches/fixtures.rs | Updates benchmark fixtures for new GraphRow fields/defaults. |
| benches/commit_batching.rs | Migrates batching/walker benches to gix-backed batcher APIs and adds scratch reuse. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| fn open_repo(repo: &Repository) -> Result<gix::Repository, git2::Error> { | ||
| let path = repo.workdir().unwrap_or(repo.path()); | ||
| GIX_REPO_CACHE.with(|cache| { | ||
| if let Some(repo) = cache.borrow().get(path).cloned() { | ||
| return Ok(repo); | ||
| } | ||
|
|
||
| let repo = gix::open(path).map_err(gix_error)?; | ||
| cache.borrow_mut().insert(path.to_path_buf(), repo.clone()); | ||
| Ok(repo) | ||
| }) | ||
| } |
There was a problem hiding this comment.
these are fair points, I can do a follow-up PR if desired
| let ids = (tree_id, parent_tree_id); | ||
| COMMIT_TREE_CACHE.with(|cache| { | ||
| cache.borrow_mut().insert(oid, ids); | ||
| }); | ||
| Ok(ids) |
Stacked on
mjc/gitoxide-spike-02-gix-oids.Why this PR exists:
What changed:
git2::Revwalkbatcher with a gix-backed lazy commit cursor.WalkedCommit, carrying:Mutex/lifetime workaround path.Walkerto own agix::Repository.Algorithm difference:
Performance story:
Benchmark Results for this PR
Command shape:
hyperfine --warmup 5 './target/release/guitar /home/mjc/src/linux --exit-when-graph-complete'.CPU: M1 MacBook Pro 16GB
03-graph-walker5.816s27.05x1.82s0.74s43%CPU: 5950x Linux/ZFS
03-graph-walker2.094s47.39x1.59s0.55s102%Memory: 5950x Linux/ZFS
03-graph-walker455.13M1.15GTop 10 heaptrack allocation sites for `03-graph-walker`
289528 calls, 19.55M peak - git__calloc100783 calls, 1.14K peak - git_str_try_grow89663 calls, 1.27M peak - CRYPTO_malloc50812 calls, 5.63M peak - git__reallocarray21137 calls, 518.16K peak - git_pool_malloc17534 calls, 1.61M peak - <>::finish_grow17061 calls, 878.28K peak - guitar::core::walker::Walker::new17056 calls, 0B peak - gix_ref::raw::convert::<>::from15510 calls, 0B peak - inflateInit2_13003 calls, 0B peak - __alloc_dir