/
multiwriter.go
80 lines (69 loc) · 1.78 KB
/
multiwriter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package solver
import (
"strings"
"sync"
"github.com/docker/buildx/util/progress"
"github.com/moby/buildkit/client"
digest "github.com/opencontainers/go-digest"
)
// MultiWriter is similar to progress.MultiWriter, but deduplicates writes by
// vertex.
type MultiWriter struct {
w progress.Writer
allClaimedVertices map[digest.Digest]struct{}
claimedVerticesMu sync.Mutex
}
func NewMultiWriter(pw progress.Writer) *MultiWriter {
if pw == nil {
return nil
}
return &MultiWriter{
w: pw,
allClaimedVertices: make(map[digest.Digest]struct{}),
}
}
func (mw *MultiWriter) WithPrefix(pfx string, force bool) progress.Writer {
return &prefixed{
mw: mw,
pfx: pfx,
force: force,
claimedVertices: make(map[digest.Digest]struct{}),
}
}
type prefixed struct {
mw *MultiWriter
pfx string
force bool
claimedVertices map[digest.Digest]struct{}
}
func (p *prefixed) Write(v *client.SolveStatus) {
filtered := &client.SolveStatus{
Vertexes: v.Vertexes,
Statuses: v.Statuses,
}
p.mw.claimedVerticesMu.Lock()
for _, log := range v.Logs {
if _, ourVertex := p.claimedVertices[log.Vertex]; ourVertex {
filtered.Logs = append(filtered.Logs, log)
continue
}
if _, claimed := p.mw.allClaimedVertices[log.Vertex]; !claimed {
p.mw.allClaimedVertices[log.Vertex] = struct{}{}
p.claimedVertices[log.Vertex] = struct{}{}
filtered.Logs = append(filtered.Logs, log)
}
}
p.mw.claimedVerticesMu.Unlock()
if p.force {
for _, v := range filtered.Vertexes {
v.Name = addPrefix(p.pfx, v.Name)
}
}
p.mw.w.Write(filtered)
}
func addPrefix(pfx, name string) string {
if strings.HasPrefix(name, "[") {
return "[" + pfx + " " + name[1:]
}
return "[" + pfx + "] " + name
}