progress: nothing printed at phase start on non-TTY, bogus isatty, warnings race the spinner #13
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Three defects in
progress.go, all small, all in the same file.1. Non-TTY prints nothing until the first item completes.
newProgressreturns immediately without printing when stderr is not a TTY (progress.go:54-58); the first plain line only appears fromincrement()(progress.go:102-106). README §Progress requires that each phase's display be "rendered the moment the phase starts — a scan must never look hung." Under cron,teeor CI, stderr is a pipe. If the walk's first directory read blocks for minutes on a busy pool, the log is completely silent — precisely the failure the requirement exists to prevent. The hash phase can emit nothing at all if its first read is slow.2.
stderrIsTTYtreats any character device as a terminal.progress.go:26-33testsfi.Mode()&os.ModeCharDevice != 0./dev/nulland/dev/zeroare character devices, sosfdupes scan ... 2>/dev/nulltakes the full ANSI redraw path and runs the library's 100ms spinner goroutine, writing escape sequences into the void.3. Warnings race the spinner's background renderer.
warnf(progress.go:109-119) callsp.bar.Clear()and then writes toos.Stderrfrom the main goroutine. For the indeterminate (-1) bars,progressbar.NewOptions64starts an internal goroutine that renders toos.Stderrevery 100ms with no synchronization againstwarnf. The walk phase is both a spinner bar and the phase that emits per-path warnings (scan.go:234) — and those warnings are what tell the operator which records are about to be deleted, so garbling them matters. Theprogressdoc comment atprogress.go:41-42already claims single-goroutine ownership of stderr; today that is not true.Definition of done
newProgressemits one zero-state plain line immediately on the non-TTY path, before any work begins.stderrIsTTYuses a real terminal test.github.com/mattn/go-isattyandgolang.org/x/termare both already in the module graph as indirect dependencies ofprogressbar; promote whichever is used to a direct dependency and update README §Constraints, which currently lists the permitted third-party dependencies.OptionSetSpinnerChangeInterval(0), so the spinner advances only onAdd) or warnings are routed through the bar's own writer — either way stderr has one writer, matching the doc comment.increment(); a pipe, a regular file and/dev/nullall report not-a-TTY; interleaved warnings and increments each land on their own line.make checkgreen.