aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/pkg/exec.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/pkg/exec.go')
-rw-r--r--internal/pkg/exec.go32
1 files changed, 31 insertions, 1 deletions
diff --git a/internal/pkg/exec.go b/internal/pkg/exec.go
index 7c4133eb..e499ecf1 100644
--- a/internal/pkg/exec.go
+++ b/internal/pkg/exec.go
@@ -2,6 +2,7 @@ package pkg
import (
"bufio"
+ "bytes"
"context"
"errors"
"fmt"
@@ -439,6 +440,34 @@ const (
execWaitDelay = time.Nanosecond
)
+// scanLinesCR is like [bufio.ScanLines], but also treats a bare \r as an
+// end-of-line marker.
+func scanLinesCR(data []byte, atEOF bool) (advance int, token []byte, err error) {
+ if atEOF && len(data) == 0 {
+ return 0, nil, nil
+ }
+ ri, ni := bytes.IndexByte(data, '\r'), bytes.IndexByte(data, '\n')
+
+ if ri >= 0 && (ni < 0 || ri < ni) {
+ if ri+1 == ni {
+ // We have a full \r\n-terminated line.
+ return ri + 2, data[:ri], nil
+ }
+ // We have a bare \r, probably some kind of progress indicator.
+ return ri + 1, data[:ri], nil
+ }
+ if ni >= 0 && (ri < 0 || ni < ri) {
+ // We have a full newline-terminated line.
+ return ni + 1, data[:ni], nil
+ }
+ // If we're at EOF, we have a final, non-terminated line. Return it.
+ if atEOF {
+ return len(data), data, nil
+ }
+ // Request more data.
+ return 0, nil, nil
+}
+
// scanVerbose prefixes program output for a verbose [message.Msg].
func scanVerbose(
msg message.Msg,
@@ -449,6 +478,7 @@ func scanVerbose(
) {
defer close(done)
s := bufio.NewScanner(r)
+ s.Split(scanLinesCR)
s.Buffer(
make([]byte, bufio.MaxScanTokenSize),
bufio.MaxScanTokenSize<<12,
@@ -458,7 +488,7 @@ func scanVerbose(
}
if err := s.Err(); err != nil && !errors.Is(err, os.ErrClosed) {
cancel()
- msg.Verbose("*"+prefix, err)
+ msg.Verbose("*"+prefix, err.Error()+suffix)
}
}