Skip to content
gitmeta-rs

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+

main.rs
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 cargo add gitmeta
async 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.