Skip to content

Commit de6a7df

Browse files
committed
Buffer partial writes and only emit complete lines in logLineWriter
1 parent 32b7be7 commit de6a7df

File tree

1 file changed

+30
-6
lines changed

1 file changed

+30
-6
lines changed

internal/update/update.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package update
22

33
import (
4+
"bytes"
45
"context"
56
"encoding/json"
67
"fmt"
@@ -123,7 +124,9 @@ func updateHomebrew(ctx context.Context, sink output.Sink) error {
123124
w := newLogLineWriter(sink, "brew")
124125
cmd.Stdout = w
125126
cmd.Stderr = w
126-
return cmd.Run()
127+
err := cmd.Run()
128+
w.Flush()
129+
return err
127130
}
128131

129132
func updateNPM(ctx context.Context, sink output.Sink, projectDir string) error {
@@ -137,27 +140,48 @@ func updateNPM(ctx context.Context, sink output.Sink, projectDir string) error {
137140
w := newLogLineWriter(sink, "npm")
138141
cmd.Stdout = w
139142
cmd.Stderr = w
140-
return cmd.Run()
143+
err := cmd.Run()
144+
w.Flush()
145+
return err
141146
}
142147

143-
// logLineWriter adapts an output.Sink into an io.Writer, emitting each line as a LogLineEvent.
148+
// logLineWriter adapts an output.Sink into an io.Writer, emitting each
149+
// complete line as a LogLineEvent. Partial writes are buffered until a
150+
// newline arrives.
144151
type logLineWriter struct {
145152
sink output.Sink
146153
source string
154+
buf []byte
147155
}
148156

149157
func newLogLineWriter(sink output.Sink, source string) *logLineWriter {
150158
return &logLineWriter{sink: sink, source: source}
151159
}
152160

153161
func (w *logLineWriter) Write(p []byte) (int, error) {
154-
line := strings.TrimRight(string(p), "\n")
155-
if line != "" {
156-
output.EmitLogLine(w.sink, w.source, line)
162+
w.buf = append(w.buf, p...)
163+
for {
164+
i := bytes.IndexByte(w.buf, '\n')
165+
if i < 0 {
166+
break
167+
}
168+
line := string(w.buf[:i])
169+
w.buf = w.buf[i+1:]
170+
if line != "" {
171+
output.EmitLogLine(w.sink, w.source, line)
172+
}
157173
}
158174
return len(p), nil
159175
}
160176

177+
// Flush emits any remaining buffered content that didn't end with a newline.
178+
func (w *logLineWriter) Flush() {
179+
if len(w.buf) > 0 {
180+
output.EmitLogLine(w.sink, w.source, string(w.buf))
181+
w.buf = nil
182+
}
183+
}
184+
161185
func updateBinary(ctx context.Context, tag string) error {
162186
ver := normalizeVersion(tag)
163187
assetName := buildAssetName(ver, goruntime.GOOS, goruntime.GOARCH)

0 commit comments

Comments
 (0)