grit://cooking/dogfood← what’s cooking
Thursday, October 29, 2026 · macOS 15.7 (24G214), APFS

Dogfood on scott-mbp: Tool builder on grit-lib

5 repos · 20 commands · 3 broken · 0 slow · 5 filed

As a tool builder I linked grit-lib by path from a scratch cargo project (toolchain 1.99.0) on macOS and exercised open/discover, typed object and ref writing with CAS, threads, blame and status for an editor, kill -9 recovery, memory soak and git interop. The library is fast and its typed errors and validation are good, but I found and filed 5 issues: a status index refresh that silently reverts a concurrent commit's index (#2317), commits/tags with no blank line treated as corrupt (#2320), legacy 100664 tree modes giving phantom changes and a non-canonical index (#2322), write_tree not validating referenced objects (#2323), and blame_file resolving repo paths against the process cwd (#2325). All six 'fixed since last wave' issues re-verified (two only partially testable because they are Windows-specific).

os
macOS 15.7 (24G214), APFS · arm64
machine
scott-mbp (agador.sparticus), Apple M3, 8 cores, 24 GB RAM
versions
grit 0.5.0 on PATH (not used for results) · main 1d054b51 · 2.52.0
repositories5
repofilescommits.gitnotes
rust-lang/cargo3,07823,59687 MBmain benchmark repo; local clones for races and gc
gitbutlerapp/grit2,83512,096170 MBbuilt from here
octocat/Hello-World131 MBnotes and bundle interop
scratch/synthetic-30003,0001,2413 MBrepro_race.sh status-vs-commit repro
scratch/odd-objects (c1, tr1, val, col, evil)431 MBhand-crafted commits/tags/trees, collision and malicious-name trees
commandsgrit vs. system git, wall time
commandrepogritgitgrit/gitresultnotes
grit status (clean)rust-lang/cargo19 ms24 ms0.8×okhyperfine -N; RSS 2.1x but tiny absolute
grit revs --count HEADrust-lang/cargo124 ms100 ms1.2×ok
grit log -n 50rust-lang/cargo3.8 ms4.0 ms0.9×ok
grit blame tests/testsuite/build.rsrust-lang/cargo374 ms224 ms1.7×ok1.7x slower; lib blame_file 304 ms in-process
grit diff HEAD~200 HEADrust-lang/cargo183 ms77 ms2.4×ok2.4x, under the 3x threshold
grit show HEAD~5rust-lang/cargo———ok
grit merge-base HEAD~500 origin/masterrust-lang/cargo———ok
grit fsckrust-lang/cargo870 ms4.15 s0.2×ok4.8x faster than git fsck --no-dangling
grit clone (local path)rust-lang/cargo260 ms285 ms0.9×ok
grit gcrust-lang/cargo1.03 s——ok194,737 objects repacked, 24,299 commits in commit-graph; git fsck/commit-graph verify clean
grit commit (auto-stage) x ~500 while grit status pollsscratch/synthetic-3000———wrong30 of 1240 commits leave a stale index (#2317)
grit log / revs / clone / gc / push on history with a message-less commitscratch/odd-objects———error#2320
grit status / diff / commit on tree with 100664 modescratch/odd-objects———wrong#2322
lib: Repository::discoverrust-lang/cargo7.4 ms——ok
lib: rev_walk().walk(HEAD) all commits (23,596)rust-lang/cargo120 ms132 ms0.9×okgit rev-list HEAD | wc -l
lib: blame_file build.rs (7055 lines)rust-lang/cargo304 ms225 ms1.4×okRSS is whole-process incl. 50 MB from the preceding full walk
lib: status() default optionsrust-lang/cargo19 ms27 ms0.7×oksecond call 14 ms
lib: 8 parallel blame_file on shared Arc<Repository>rust-lang/cargo317 ms1.13 s0.3×okserial lib 1074 ms; git serial loop 1133 ms; results identical
lib: 1000-iteration mixed soak (walk, tree diff, blame, status)rust-lang/cargo28.10 s——okRSS 170 MB after iteration 0, 299 MB at end; reopen-each-iteration 410 MB peak; plateaus
lib: 16 threads x 25 CAS ref updates on one refscratch/s2———ok769 typed ExpectedMismatch retries; a few typed LockHeld after the default lock wait (git has the same 100 ms policy)
worked9
  • ›Typed errors everywhere I looked: ExpectedMismatch, LockHeld with holder pid, InvalidSymrefTarget, NotARepository reasons, ObjectNotFound/UnexpectedObjectKind
  • ›write_commit / Signature / write_tree reject nearly every malformed input (.git aliases, NTFS/HFS names, bad modes, NUL, newline in idents) before anything is written
  • ›Refs: multi-ref atomic transactions, CAS, symrefs and reflog-only updates behave identically on files and reftable and read back correctly with git 2.52
  • ›Shared &Repository across 8-16 threads gave identical results and no deadlocks; library has no printing and no cwd/env reads except the path issue in #2325
  • ›blame_file parity with git on speed, Contents/Worktree sources and non-UTF-8 bytes; fsck 4.8x faster than git on cargo
  • ›gc/commit-graph/midx/notes/bundle/reftable output validated by system git 2.52 (fsck --strict, multi-pack-index verify, bundle verify)
  • ›grit refuses malicious .GIT / zero-width .git aliases on clone and cleans up
  • ›kill -9 during commits never corrupted the repository; stale-lock message names the dead pid
  • ›docs build cleanly and the guide examples are real runnable programs
problems11
  • ›#2317 status index refresh clobbers a concurrent commit's index (filed, high)
  • ›#2320 commit/tag with no blank line before message is 'corrupt' (filed, high); also fsck misses nulInCommit
  • ›#2322 legacy 100664 tree modes: phantom changes and non-canonical index entries git rejects (filed)
  • ›#2323 Objects::write_tree accepts missing / wrong-kind entry objects (filed, api)
  • ›#2325 blame_file resolves repo-relative paths against process cwd (filed, api)
  • ›Not filed: Repository::open(work tree path or .git gitfile) fails with 'not a git repository (or any of the parent directories)' although open() never searches parents; open(.git) silently yields a repo without work tree (documented, minor ergonomics)
  • ›Not filed: 0.4-2% of blame lines attributed to a different valid commit than git (diff tie-breaking)
  • ›Not filed: clone collision warning omits the NFC/NFD group that git lists (cosmetic)
  • ›Not filed: grit leaves stale .lock files after kill -9 and only reports them (git does the same), plus an extra index~pid.lock sidecar file that git does not know
  • ›Not filed: lib tool-builder gaps (no describe / nearest-tag, no recursive tree walk helper on Objects) are intentional scope decisions
  • ›Not filed: CommitRequest exposes several #[doc(hidden)] pub fields and repo.rs has pub #[doc(hidden)] test-injection fns (set_test_inject_index_write_fail); cosmetic API surface
bugs filed5
#2317 #2320 #2322 #2323 #2325already reported: #2142 #1749 #1746 #2187 #2128 #1792
next time
  • ›Re-test #2317 after the fix with the status poller against grit add / switch / merge / stash writers too, and with GIT_OPTIONAL_LOCKS=0 and write_index=false
  • ›Message-less commit/tag: also test fetch/clone from a real server, commit-graph write, bundle, blame and rev-list --objects through such history
  • ›Legacy-mode trees from a real old repo (git/git early history, linux) through clone, switch to an old commit, merge, stash, status
  • ›Hours-long soak with 100 writers + gc/repack under live handles and fault injection (only 40 kill -9 rounds and 6 threads done here)
  • ›Cancel mid-fetch/push/commit via ProgressSink (#2142) against a throttled smart-HTTP server; partial packs and temp files left behind
  • ›Library-written MIDX v2 / bitmaps / reftable read back by git >= 2.50, and grit gc midx default version vs midx.version
  • ›Other &str path APIs for the same cwd dependence (diff file filters, log paths, add) once #2325 is triaged
  • ›Pluggable ObjectStore/RefStore toy backend through porcelain (#2187, #2128 still open) and fsmonitor-driven status through the public API
  • ›git/git full-history blame with -C -C, --ignore-revs-file and rename following; compare more attributions with git