Print the byte unit once in the summary line (closes #17)
check / check (push) Successful in 3m8s

formatBytes already ends in a unit, so the summary line read "9 B
bytes" or "1.0 KiB bytes". The format string in Stats.Print no longer
adds the word "bytes".

Print now takes the io.Writer to print to; its callers pass os.Stderr,
and the new test passes a buffer to read the line for one small and
one large byte count.

Model: opus-5-5
This commit is contained in:
2026-10-06 05:37:37 +00:00
parent d010135618
commit c49c5e63b9
3 changed files with 33 additions and 6 deletions
+2
View File
@@ -25,6 +25,8 @@ today), `.dockerignore`, `.gitea/workflows/check.yml` and
# Completed Steps # Completed Steps
* 2026-10-06: the summary line after `sum`, `check` and `clear` prints
the byte unit once (`1.5 KiB`, not `1.5 KiB bytes`)
* 2026-10-06: lint and test run as phases of the `Dockerfile`, and the * 2026-10-06: lint and test run as phases of the `Dockerfile`, and the
build stage depends on both; `script/lint` and `script/test` each build stage depends on both; `script/lint` and `script/test` each
build their phase with `--no-cache`; `script/cibuild` bootstraps, build their phase with `--no-cache`; `script/cibuild` bootstraps,
+6 -6
View File
@@ -71,13 +71,13 @@ func (s *Stats) Duration() time.Duration {
return time.Since(s.StartTime) return time.Since(s.StartTime)
} }
func (s *Stats) Print(opts *options, operation string) { func (s *Stats) Print(w io.Writer, opts *options, operation string) {
if opts.quiet { if opts.quiet {
return return
} }
fmt.Fprintf(os.Stderr, _, _ = fmt.Fprintf(w,
"\n%s complete: %d files processed, %d skipped, %d failed, %s bytes in %s\n", "\n%s complete: %d files processed, %d skipped, %d failed, %s in %s\n",
operation, operation,
s.FilesProcessed, s.FilesProcessed,
s.FilesSkipped, s.FilesSkipped,
@@ -227,7 +227,7 @@ func runOverPaths(
} }
finishBar(bar) finishBar(bar)
stats.Print(opts, op) stats.Print(os.Stderr, opts, op)
return nil return nil
} }
@@ -481,7 +481,7 @@ func runCheck(opts *options, args []string, cont bool) error {
if perr != nil { if perr != nil {
if !cont { if !cont {
finishBar(bar) finishBar(bar)
stats.Print(opts, "check") stats.Print(os.Stderr, opts, "check")
return perr return perr
} }
@@ -491,7 +491,7 @@ func runCheck(opts *options, args []string, cont bool) error {
} }
finishBar(bar) finishBar(bar)
stats.Print(opts, "check") stats.Print(os.Stderr, opts, "check")
return finalErr return finalErr
} }
+25
View File
@@ -1,6 +1,7 @@
package main package main
import ( import (
"bytes"
"errors" "errors"
"os" "os"
"path/filepath" "path/filepath"
@@ -328,3 +329,27 @@ func TestCheckContinuePastUnreadable(t *testing.T) {
t.Fatalf("expected verification error from runCheck, got %v", err) t.Fatalf("expected verification error from runCheck, got %v", err)
} }
} }
func TestSummaryPrintsByteUnitOnce(t *testing.T) {
t.Parallel()
tests := []struct {
bytesProcessed int64
want string
}{
{9, ", 9 B in "},
{1536, ", 1.5 KiB in "},
}
for _, tt := range tests {
var out bytes.Buffer
stats := newTestStats()
stats.BytesProcessed = tt.bytesProcessed
stats.Print(&out, &options{}, "check")
if !strings.Contains(out.String(), tt.want) {
t.Errorf("summary %q does not contain %q", out.String(), tt.want)
}
}
}