From 2ccf69f64ccba0c526ba68d20bbfed2fb863122d Mon Sep 17 00:00:00 2001 From: DualFroz Date: Wed, 8 Jul 2026 16:14:43 +0200 Subject: [PATCH] fix: pass -E to git so the multi-identity author filter matches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OwnEmailMatcher::author_regex() emits an extended-regex alternation (|), but scan_repo_own_commits ran `git log --author=` without -E. git defaults --author to *basic* regex, where | is a literal, so the pattern matched nothing for anyone with two or more identities — silently zeroing streak, heatmap, digest and the hour/day patterns (measured 0 -> 141 own commits across the workspace after the fix). Add -E here and in the new has_own_commit helper. --- src/stats/mod.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/stats/mod.rs b/src/stats/mod.rs index ceb31d0..eb9720b 100644 --- a/src/stats/mod.rs +++ b/src/stats/mod.rs @@ -99,7 +99,10 @@ pub fn scan_repo_own_commits(path: &std::path::Path, matcher: &OwnEmailMatcher) let Some(regex) = matcher.author_regex() else { return vec![] }; let out = std::process::Command::new("git") .arg("-C").arg(path) - .args(["log", "--branches", "-i", &format!("--author={regex}")]) + // `-E`: `author_regex()` emits an extended-regex alternation (`a|b`); + // git's `--author` defaults to *basic* regex, where `|` is a literal + // and the pattern silently matches nothing — so this must be explicit. + .args(["log", "--branches", "-E", "-i", &format!("--author={regex}")]) .args(["--date=format-local:%Y-%m-%dT%H", "--pretty=format:%ae\x1f%ad"]) .output(); let Ok(out) = out else { return vec![] }; @@ -113,6 +116,28 @@ pub fn scan_repo_own_commits(path: &std::path::Path, matcher: &OwnEmailMatcher) }).collect() } +/// Whether you've ever committed to the repo at `path`. A workspace clone +/// you've never touched — a vendored/reference fork like an upstream +/// `pterodactyl` — returns `Some(false)`; that's the signal used to mark and +/// optionally hide such repos. Uses the same git-side `--author` filter as +/// the stats scan with `--max-count=1`, so repos where you *do* have commits +/// short-circuit on the first match and only a true zero-match clone walks +/// its full history. `None` when no identity is configured (can't tell — the +/// caller then treats the repo as yours). +pub fn has_own_commit(path: &std::path::Path, matcher: &OwnEmailMatcher) -> Option { + let regex = matcher.author_regex()?; + let out = std::process::Command::new("git") + .arg("-C").arg(path) + // `-E` for the same reason as `scan_repo_own_commits`: the regex is an + // extended-regex alternation that git's default basic-regex `--author` + // would treat as a literal `|` and never match. + .args(["log", "--branches", "-E", "-i", &format!("--author={regex}"), "--max-count=1", "--format=%H"]) + .output() + .ok()?; + // `--format=%H` prints "\n" on a match, nothing at all on none. + Some(out.stdout.iter().any(|b| !b.is_ascii_whitespace())) +} + /// Scans every repo and merges the result into one date-sorted list. pub fn scan_workspace_own_commits( repos: &[crate::status::RepoSummary], matcher: &OwnEmailMatcher,