rust · one scan · o(1) lookups
Per-file git metadata in Rust.
A Rust port of gitmeta — scan a working tree once, then resolve per-file git metadata (last commit, author, churn, tracked/ignored) in constant time. Optional async via the tokio feature.
MIT licensed · sync core pulls in no async runtime · Rust 1.79+
let Some(cache) = gitmeta::Cache::new("/path/to/repo")? else { return Ok(()); // not a git working tree }; if let Some(info) = cache.lookup("src/main.rs") { println!("{} by {} — {} commits", info.last_commit_time, info.last_commit_author, info.commit_count); }
what you get
Git history, one scan away.
One batch scan up front — git ls-files plus a single git log pass — turns thousands of per-path history questions into constant-time lookups.
One-shot Cache
Batch scan the whole working tree up front, then answer O(1) per-path lookups — no git log -1 -- <path> fan-out.
Rich per-file info
Last-commit time, author, and subject, plus first-seen and the commit count (a churn proxy) for every tracked path.
Tracked / ignored
Ask whether a path is under version control with is_tracked, or excluded by gitignore rules with is_ignored.
Pool
Keeps one Cache per repo, re-validated on HEAD change, handing back an Arc<Cache> — ideal for servers, watchers, and tooling.
Optional async
The tokio feature adds an async API with free cancellation on future-drop; the sync API pulls in no runtime at all.
Graceful "no git data"
Cache::new returns Ok(None) when the path isn't a working tree or git is absent; errors are reserved for real failures. MSRV 1.79+.
usage
Sync by default, async when you want it.
The synchronous Cache covers most callers; flip on the tokio feature for an async constructor that cancels for free when its future is dropped.
// Sync — scan once, then look up let Some(cache) = gitmeta::Cache::new("/path/to/repo")? else { return Ok(()); // no git data }; if let Some(info) = cache.lookup("src/main.rs") { println!("{} commits", info.commit_count); }
// Async — enable the `tokio` feature let Some(cache) = gitmeta::Cache::new_async("/path/to/repo").await? else { return Ok(()); }; // dropping the future kills the in-flight git process let tracked = cache.is_tracked("Cargo.toml");
- Cache::new
- Cache::new_async
- .lookup
- .is_tracked
- .is_ignored
- Pool::get
- has_git_binary
install
Add it to your crate.
The crate is named gitmeta (not the repo name). The sync core needs no async runtime; opt into async with the tokio feature. Requires Rust 1.79+.
cargo add gitmeta
cargo add gitmeta --features tokio
gitmeta-rs is the Rust port of the Go gitmeta library. See the source on GitHub for the full API.