Skip to content

Commit 7a1fe79

Browse files
lex0cclaude
andcommitted
Extract shortSHA helper; fix remaining unguarded SHA slices
format.go had three SHA[:12] callsites (TopCommits CSV, text, and wide text variants) plus the new Top-commits per-dev block that carried an inline len check. Consolidated into a single shortSHA helper and applied it at all four sites so a dataset with short commit IDs no longer crashes the CLI formatter in any path. Behaviour unchanged for well-formed SHAs (length ≥ 12). The inline comment from the Top-commits block moves onto the helper's godoc so the rationale is close to the definition rather than duplicated at each use. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent fe29198 commit 7a1fe79

1 file changed

Lines changed: 17 additions & 15 deletions

File tree

internal/stats/format.go

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,19 @@ import (
99
"text/tabwriter"
1010
)
1111

12+
// shortSHA returns the first 12 bytes of a commit SHA, clamping safely
13+
// when the input is shorter. LoadJSONL does not validate SHA length,
14+
// so hand-built fixtures (e.g. "c1") and any future ingest path that
15+
// emits abbreviated SHAs would otherwise panic on a fixed `sha[:12]`.
16+
// Twelve mirrors the display convention used across CLI and HTML
17+
// surfaces in this package.
18+
func shortSHA(sha string) string {
19+
if len(sha) > 12 {
20+
return sha[:12]
21+
}
22+
return sha
23+
}
24+
1225
// specLabel turns a DevProfile.Specialization (Herfindahl) value into a
1326
// short human-readable classification. Thresholds live in stats.go as
1427
// named constants so templates can reuse the same values.
@@ -399,7 +412,7 @@ func (f *Formatter) PrintTopCommits(commits []BigCommit) error {
399412
rows := make([][]string, len(commits))
400413
for i, c := range commits {
401414
rows[i] = []string{
402-
c.SHA[:12], c.AuthorName, c.AuthorEmail, c.Date,
415+
shortSHA(c.SHA), c.AuthorName, c.AuthorEmail, c.Date,
403416
fmt.Sprintf("%d", c.Additions), fmt.Sprintf("%d", c.Deletions),
404417
fmt.Sprintf("%d", c.LinesChanged), fmt.Sprintf("%d", c.FilesChanged),
405418
c.Message,
@@ -420,14 +433,14 @@ func (f *Formatter) PrintTopCommits(commits []BigCommit) error {
420433
fmt.Fprintf(tw, "---\t------\t----\t-----\t-----\t-------\n")
421434
for _, c := range commits {
422435
fmt.Fprintf(tw, "%s\t%s\t%s\t%d\t%d\t%s\n",
423-
c.SHA[:12], c.AuthorName, c.Date, c.LinesChanged, c.FilesChanged, c.Message)
436+
shortSHA(c.SHA), c.AuthorName, c.Date, c.LinesChanged, c.FilesChanged, c.Message)
424437
}
425438
} else {
426439
fmt.Fprintf(tw, "SHA\tAUTHOR\tDATE\tADDITIONS\tDELETIONS\tLINES\tFILES\n")
427440
fmt.Fprintf(tw, "---\t------\t----\t---------\t---------\t-----\t-----\n")
428441
for _, c := range commits {
429442
fmt.Fprintf(tw, "%s\t%s\t%s\t%d\t%d\t%d\t%d\n",
430-
c.SHA[:12], c.AuthorName, c.Date, c.Additions, c.Deletions, c.LinesChanged, c.FilesChanged)
443+
shortSHA(c.SHA), c.AuthorName, c.Date, c.Additions, c.Deletions, c.LinesChanged, c.FilesChanged)
431444
}
432445
}
433446
return tw.Flush()
@@ -524,19 +537,8 @@ func (f *Formatter) PrintProfiles(profiles []DevProfile) error {
524537
fmt.Fprintln(f.w)
525538
fmt.Fprintln(f.w, " Top commits:")
526539
for _, tc := range p.TopCommits {
527-
// Defensive slice: LoadJSONL does not validate SHA
528-
// length, so hand-built fixtures (e.g. "c1") or a
529-
// future ingest path that emits abbreviated SHAs
530-
// would panic on a fixed tc.SHA[:12]. The other SHA
531-
// slice sites in this file (TopCommits / LatestCommits)
532-
// carry the same latent risk and are left as-is so
533-
// this change stays scoped to the new Top-commits block.
534-
sha := tc.SHA
535-
if len(sha) > 12 {
536-
sha = sha[:12]
537-
}
538540
fmt.Fprintf(f.w, " %s %s %6d lines %3d files %s\n",
539-
sha, tc.Date, tc.LinesChanged, tc.FilesChanged, tc.Message)
541+
shortSHA(tc.SHA), tc.Date, tc.LinesChanged, tc.FilesChanged, tc.Message)
540542
}
541543
if p.TopCommitsHidden > 0 {
542544
fmt.Fprintf(f.w, " ... (+%d more commits not shown)\n", p.TopCommitsHidden)

0 commit comments

Comments
 (0)