diff --git a/command/cmd.go b/command/cmd.go index bf7ff5b..6140f21 100644 --- a/command/cmd.go +++ b/command/cmd.go @@ -50,7 +50,6 @@ func (r *Command) RunWith(ctx context.Context) (err error) { } else { r.Reporter.Succeeded(r.Path) } - r.Reporter.End() }() cmd := exec.CommandContext(ctx, r.Path, r.Options...) cmd.Dir = r.Dir diff --git a/command/reporter.go b/command/reporter.go index 7da5166..113d4d6 100644 --- a/command/reporter.go +++ b/command/reporter.go @@ -1,9 +1,7 @@ package command import ( - "fmt" "strings" - "time" ) // @@ -19,15 +17,6 @@ const ( LiveOutput = 1 ) -// -// Rate -const ( - // Rate limit. - Rate = time.Second - // Depth of rate limit queue. - Depth = 100 -) - // // Reporter activity reporter. type Reporter struct { @@ -44,7 +33,7 @@ func (r *Reporter) Run(path string, options Options) { case Error: case Default, LiveOutput: - r.report( + addon.Activity( "[CMD] Running: %s %s", path, strings.Join(options, " ")) @@ -59,7 +48,7 @@ func (r *Reporter) Succeeded(path string) { case Error: case Default, LiveOutput: - r.report("[CMD] %s succeeded.", path) + addon.Activity("[CMD] %s succeeded.", path) } } @@ -70,13 +59,13 @@ func (r *Reporter) Error(path string, err error, output []byte) { case Disabled: case Error, Default: - r.report( + addon.Activity( "[CMD] %s failed: %s.\n%s", path, err.Error(), output) case LiveOutput: - r.report( + addon.Activity( "[CMD] %s failed: %s.", path, err.Error()) @@ -91,36 +80,6 @@ func (r *Reporter) Output(output string) { case Error: case Default: case LiveOutput: - r.report("> %s", output) - } -} - -// -// report activity in task Report.Activity. -// Rate limited. -func (r *Reporter) report(entry string, v ...interface{}) { - if r.queue == nil { - r.queue = make(chan string, Depth) - r.done = make(chan int) - go func() { - for entry := range r.queue { - time.Sleep(Rate) - addon.Activity(entry) - } - r.done <- 1 - }() - } - r.queue <- fmt.Sprintf(entry, v...) -} - -// -// End of reporting. -func (r *Reporter) End() { - if r.queue != nil { - close(r.queue) - <-r.done - close(r.done) - r.queue = nil - r.done = nil + addon.Activity("> %s", output) } } diff --git a/command/writer.go b/command/writer.go index 2aee0bd..03f0e3d 100644 --- a/command/writer.go +++ b/command/writer.go @@ -2,14 +2,20 @@ package command import ( "strings" + "time" ) +// +// Rate limit. +const Rate = time.Second + // // Writer records command output. type Writer struct { reporter Reporter buffer []byte index int + done chan any } // @@ -18,25 +24,50 @@ type Writer struct { func (w *Writer) Write(p []byte) (n int, err error) { w.buffer = append(w.buffer, p...) n = len(p) - batch := string(w.buffer[w.index:]) - end := strings.LastIndex(batch, "\n") - if end != -1 { - output := batch[:end] - w.reporter.Output(output) - w.index += len(output) - w.index++ + if w.done == nil { + w.done = make(chan any) + go w.report() } return } // -// End of writing. -// When verbosity > 0, output is reported in task Report.Activity. -func (w *Writer) End() { +// report in task Report.Activity. +func (w *Writer) report() { + for { + select { + case <-w.done: + goto done + case <-time.After(Rate): + } + batch := string(w.buffer[w.index:]) + end := strings.LastIndex(batch, "\n") + if end != -1 { + output := batch[:end] + w.reporter.Output(output) + w.index += len(output) + w.index++ + } + } +done: batch := string(w.buffer[w.index:]) if len(batch) > 0 { w.reporter.Output(batch) w.index += len(batch) w.index++ } + w.done <- true +} + +// +// End of writing. +// When verbosity > 0, output is reported in task Report.Activity. +func (w *Writer) End() { + if w.done == nil { + return + } + w.done <- true + <-w.done + close(w.done) + w.done = nil }