Skip to content

Commit ebef4a4

Browse files
dmcgowanthaJeztah
authored andcommitted
Split streamformatter from jsonmessage
Signed-off-by: Derek McGowan <[email protected]>
1 parent 5a144c4 commit ebef4a4

2 files changed

Lines changed: 68 additions & 13 deletions

File tree

pkg/streamformatter/streamformatter.go

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ import (
55
"encoding/json"
66
"fmt"
77
"io"
8+
"strings"
89
"sync"
10+
"time"
911

10-
"github.com/docker/docker/pkg/jsonmessage"
1112
"github.com/docker/docker/pkg/progress"
13+
"github.com/docker/go-units"
1214
"github.com/moby/moby/api/types/jsonstream"
1315
)
1416

@@ -18,12 +20,12 @@ import (
1820
//
1921
// It is a reduced set of [jsonmessage.JSONMessage].
2022
type jsonMessage struct {
21-
Stream string `json:"stream,omitempty"`
22-
Status string `json:"status,omitempty"`
23-
Progress *jsonmessage.JSONProgress `json:"progressDetail,omitempty"` // TODO(thaJeztah): can this be a [jsonstream.Progress]?
24-
ID string `json:"id,omitempty"`
25-
Error *jsonstream.Error `json:"errorDetail,omitempty"`
26-
Aux *json.RawMessage `json:"aux,omitempty"` // Aux contains out-of-band data, such as digests for push signing and image id after building.
23+
Stream string `json:"stream,omitempty"`
24+
Status string `json:"status,omitempty"`
25+
Progress *jsonstream.Progress `json:"progressDetail,omitempty"`
26+
ID string `json:"id,omitempty"`
27+
Error *jsonstream.Error `json:"errorDetail,omitempty"`
28+
Aux *json.RawMessage `json:"aux,omitempty"` // Aux contains out-of-band data, such as digests for push signing and image id after building.
2729

2830
// ErrorMessage contains errors encountered during the operation.
2931
//
@@ -81,7 +83,7 @@ func (sf *jsonProgressFormatter) formatProgress(id, action string, progress *jso
8183
}
8284
b, err := json.Marshal(&jsonMessage{
8385
Status: action,
84-
Progress: &jsonmessage.JSONProgress{Progress: *progress},
86+
Progress: progress,
8587
ID: id,
8688
Aux: auxJSON,
8789
})
@@ -97,12 +99,68 @@ func (sf *rawProgressFormatter) formatStatus(id, format string, a ...interface{}
9799
return []byte(fmt.Sprintf(format, a...) + streamNewline)
98100
}
99101

102+
func rawProgressString(p *jsonstream.Progress) string {
103+
if p == nil || (p.Current <= 0 && p.Total <= 0) {
104+
return ""
105+
}
106+
if p.Total <= 0 {
107+
switch p.Units {
108+
case "":
109+
return fmt.Sprintf("%8v", units.HumanSize(float64(p.Current)))
110+
default:
111+
return fmt.Sprintf("%d %s", p.Current, p.Units)
112+
}
113+
}
114+
115+
percentage := int(float64(p.Current)/float64(p.Total)*100) / 2
116+
if percentage > 50 {
117+
percentage = 50
118+
}
119+
120+
numSpaces := 0
121+
if 50-percentage > 0 {
122+
numSpaces = 50 - percentage
123+
}
124+
pbBox := fmt.Sprintf("[%s>%s] ", strings.Repeat("=", percentage), strings.Repeat(" ", numSpaces))
125+
126+
var numbersBox string
127+
switch {
128+
case p.HideCounts:
129+
case p.Units == "": // no units, use bytes
130+
current := units.HumanSize(float64(p.Current))
131+
total := units.HumanSize(float64(p.Total))
132+
133+
numbersBox = fmt.Sprintf("%8v/%v", current, total)
134+
135+
if p.Current > p.Total {
136+
// remove total display if the reported current is wonky.
137+
numbersBox = fmt.Sprintf("%8v", current)
138+
}
139+
default:
140+
numbersBox = fmt.Sprintf("%d/%d %s", p.Current, p.Total, p.Units)
141+
142+
if p.Current > p.Total {
143+
// remove total display if the reported current is wonky.
144+
numbersBox = fmt.Sprintf("%d %s", p.Current, p.Units)
145+
}
146+
}
147+
148+
var timeLeftBox string
149+
if p.Current > 0 && p.Start > 0 && percentage < 50 {
150+
fromStart := time.Since(time.Unix(p.Start, 0))
151+
perEntry := fromStart / time.Duration(p.Current)
152+
left := time.Duration(p.Total-p.Current) * perEntry
153+
timeLeftBox = " " + left.Round(time.Second).String()
154+
}
155+
return pbBox + numbersBox + timeLeftBox
156+
}
157+
100158
func (sf *rawProgressFormatter) formatProgress(id, action string, progress *jsonstream.Progress, aux interface{}) []byte {
101159
if progress == nil {
102160
progress = &jsonstream.Progress{}
103161
}
104162
endl := "\r"
105-
out := (&jsonmessage.JSONProgress{Progress: *progress}).String()
163+
out := rawProgressString(progress)
106164
if out == "" {
107165
endl += "\n"
108166
}

pkg/streamformatter/streamformatter_test.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ import (
77
"strings"
88
"testing"
99

10-
"github.com/docker/docker/pkg/jsonmessage"
1110
"github.com/google/go-cmp/cmp"
12-
"github.com/google/go-cmp/cmp/cmpopts"
1311
"github.com/moby/moby/api/types/jsonstream"
1412
"gotest.tools/v3/assert"
1513
is "gotest.tools/v3/assert/cmp"
@@ -72,7 +70,7 @@ func TestJsonProgressFormatterFormatProgress(t *testing.T) {
7270
ID: "id",
7371
Status: "action",
7472
Aux: &rawAux,
75-
Progress: &jsonmessage.JSONProgress{Progress: *jsonProgress},
73+
Progress: jsonProgress,
7674
}
7775
assert.DeepEqual(t, msg, expected, cmpJSONMessageOpt())
7876
}
@@ -82,7 +80,6 @@ func cmpJSONMessageOpt() cmp.Option {
8280
return path.String() == "ProgressMessage"
8381
}
8482
return cmp.Options{
85-
cmpopts.IgnoreUnexported(jsonmessage.JSONProgress{}),
8683
// Ignore deprecated property that is a derivative of Progress
8784
cmp.FilterPath(progressMessagePath, cmp.Ignore()),
8885
}

0 commit comments

Comments
 (0)