mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
vendor: update buildkit and dockerd
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
24
vendor/github.com/moby/buildkit/util/entitlements/entitlements.go
generated
vendored
24
vendor/github.com/moby/buildkit/util/entitlements/entitlements.go
generated
vendored
@ -1,26 +1,19 @@
|
||||
package entitlements
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Entitlement string
|
||||
|
||||
const (
|
||||
EntitlementSecurityConfined Entitlement = "security.confined"
|
||||
EntitlementSecurityUnconfined Entitlement = "security.unconfined" // unimplemented
|
||||
EntitlementNetworkHost Entitlement = "network.host"
|
||||
EntitlementNetworkNone Entitlement = "network.none"
|
||||
EntitlementSecurityInsecure Entitlement = "security.insecure"
|
||||
EntitlementNetworkHost Entitlement = "network.host"
|
||||
)
|
||||
|
||||
var all = map[Entitlement]struct{}{
|
||||
EntitlementSecurityConfined: {},
|
||||
EntitlementSecurityUnconfined: {},
|
||||
EntitlementNetworkHost: {},
|
||||
EntitlementNetworkNone: {},
|
||||
}
|
||||
|
||||
var defaults = map[Entitlement]struct{}{
|
||||
EntitlementSecurityConfined: {},
|
||||
EntitlementNetworkNone: {},
|
||||
EntitlementSecurityInsecure: {},
|
||||
EntitlementNetworkHost: {},
|
||||
}
|
||||
|
||||
func Parse(s string) (Entitlement, error) {
|
||||
@ -56,9 +49,6 @@ func WhiteList(allowed, supported []Entitlement) (Set, error) {
|
||||
m[e] = struct{}{}
|
||||
}
|
||||
|
||||
for e := range defaults {
|
||||
m[e] = struct{}{}
|
||||
}
|
||||
return Set(m), nil
|
||||
}
|
||||
|
||||
|
67
vendor/github.com/moby/buildkit/util/entitlements/security_linux.go
generated
vendored
Normal file
67
vendor/github.com/moby/buildkit/util/entitlements/security_linux.go
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
package entitlements
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/oci"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
// WithInsecureSpec sets spec with All capability.
|
||||
func WithInsecureSpec() oci.SpecOpts {
|
||||
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
|
||||
addCaps := []string{
|
||||
"CAP_FSETID",
|
||||
"CAP_KILL",
|
||||
"CAP_FOWNER",
|
||||
"CAP_MKNOD",
|
||||
"CAP_CHOWN",
|
||||
"CAP_DAC_OVERRIDE",
|
||||
"CAP_NET_RAW",
|
||||
"CAP_SETGID",
|
||||
"CAP_SETUID",
|
||||
"CAP_SETPCAP",
|
||||
"CAP_SETFCAP",
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
"CAP_SYS_CHROOT",
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_MAC_ADMIN",
|
||||
"CAP_MAC_OVERRIDE",
|
||||
"CAP_DAC_READ_SEARCH",
|
||||
"CAP_SYS_PTRACE",
|
||||
"CAP_SYS_MODULE",
|
||||
"CAP_SYSLOG",
|
||||
"CAP_SYS_RAWIO",
|
||||
"CAP_SYS_ADMIN",
|
||||
"CAP_LINUX_IMMUTABLE",
|
||||
"CAP_SYS_BOOT",
|
||||
"CAP_SYS_NICE",
|
||||
"CAP_SYS_PACCT",
|
||||
"CAP_SYS_TTY_CONFIG",
|
||||
"CAP_SYS_TIME",
|
||||
"CAP_WAKE_ALARM",
|
||||
"CAP_AUDIT_READ",
|
||||
"CAP_AUDIT_CONTROL",
|
||||
"CAP_SYS_RESOURCE",
|
||||
"CAP_BLOCK_SUSPEND",
|
||||
"CAP_IPC_LOCK",
|
||||
"CAP_IPC_OWNER",
|
||||
"CAP_LEASE",
|
||||
"CAP_NET_ADMIN",
|
||||
"CAP_NET_BROADCAST",
|
||||
}
|
||||
for _, cap := range addCaps {
|
||||
s.Process.Capabilities.Bounding = append(s.Process.Capabilities.Bounding, cap)
|
||||
s.Process.Capabilities.Ambient = append(s.Process.Capabilities.Ambient, cap)
|
||||
s.Process.Capabilities.Effective = append(s.Process.Capabilities.Effective, cap)
|
||||
s.Process.Capabilities.Inheritable = append(s.Process.Capabilities.Inheritable, cap)
|
||||
s.Process.Capabilities.Permitted = append(s.Process.Capabilities.Permitted, cap)
|
||||
}
|
||||
s.Linux.ReadonlyPaths = []string{}
|
||||
s.Linux.MaskedPaths = []string{}
|
||||
s.Process.ApparmorProfile = ""
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
226
vendor/github.com/moby/buildkit/util/progress/progressui/display.go
generated
vendored
226
vendor/github.com/moby/buildkit/util/progress/progressui/display.go
generated
vendored
@ -5,10 +5,14 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/jaguilar/vt100"
|
||||
"github.com/moby/buildkit/client"
|
||||
"github.com/morikuni/aec"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
@ -27,14 +31,26 @@ func DisplaySolveStatus(ctx context.Context, phase string, c console.Console, w
|
||||
disp.phase = "Building"
|
||||
}
|
||||
|
||||
t := newTrace(w)
|
||||
t := newTrace(w, modeConsole)
|
||||
|
||||
tickerTimeout := 150 * time.Millisecond
|
||||
displayTimeout := 100 * time.Millisecond
|
||||
|
||||
if v := os.Getenv("TTY_DISPLAY_RATE"); v != "" {
|
||||
if r, err := strconv.ParseInt(v, 10, 64); err == nil {
|
||||
tickerTimeout = time.Duration(r) * time.Millisecond
|
||||
displayTimeout = time.Duration(r) * time.Millisecond
|
||||
}
|
||||
}
|
||||
|
||||
var done bool
|
||||
ticker := time.NewTicker(100 * time.Millisecond)
|
||||
ticker := time.NewTicker(tickerTimeout)
|
||||
defer ticker.Stop()
|
||||
|
||||
displayLimiter := rate.NewLimiter(rate.Every(70*time.Millisecond), 1)
|
||||
displayLimiter := rate.NewLimiter(rate.Every(displayTimeout), 1)
|
||||
|
||||
var height int
|
||||
width, _ := disp.getSize()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
@ -42,34 +58,43 @@ func DisplaySolveStatus(ctx context.Context, phase string, c console.Console, w
|
||||
case <-ticker.C:
|
||||
case ss, ok := <-ch:
|
||||
if ok {
|
||||
t.update(ss)
|
||||
t.update(ss, width)
|
||||
} else {
|
||||
done = true
|
||||
}
|
||||
}
|
||||
|
||||
if modeConsole {
|
||||
width, height = disp.getSize()
|
||||
if done {
|
||||
disp.print(t.displayInfo(), true)
|
||||
disp.print(t.displayInfo(), width, height, true)
|
||||
t.printErrorLogs(c)
|
||||
return nil
|
||||
} else if displayLimiter.Allow() {
|
||||
disp.print(t.displayInfo(), false)
|
||||
ticker.Stop()
|
||||
ticker = time.NewTicker(tickerTimeout)
|
||||
disp.print(t.displayInfo(), width, height, false)
|
||||
}
|
||||
} else {
|
||||
if done || displayLimiter.Allow() {
|
||||
printer.print(t)
|
||||
if done {
|
||||
t.printErrorLogs(w)
|
||||
return nil
|
||||
}
|
||||
ticker.Stop()
|
||||
ticker = time.NewTicker(tickerTimeout)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const termHeight = 6
|
||||
const termPad = 10
|
||||
|
||||
type displayInfo struct {
|
||||
startTime time.Time
|
||||
jobs []job
|
||||
jobs []*job
|
||||
countTotal int
|
||||
countCompleted int
|
||||
}
|
||||
@ -81,6 +106,8 @@ type job struct {
|
||||
status string
|
||||
hasError bool
|
||||
isCanceled bool
|
||||
vertex *vertex
|
||||
showTerm bool
|
||||
}
|
||||
|
||||
type trace struct {
|
||||
@ -90,6 +117,7 @@ type trace struct {
|
||||
byDigest map[digest.Digest]*vertex
|
||||
nextIndex int
|
||||
updates map[digest.Digest]struct{}
|
||||
modeConsole bool
|
||||
}
|
||||
|
||||
type vertex struct {
|
||||
@ -107,6 +135,13 @@ type vertex struct {
|
||||
lastBlockTime *time.Time
|
||||
count int
|
||||
statusUpdates map[string]struct{}
|
||||
|
||||
jobs []*job
|
||||
jobCached bool
|
||||
|
||||
term *vt100.VT100
|
||||
termBytes int
|
||||
termCount int
|
||||
}
|
||||
|
||||
func (v *vertex) update(c int) {
|
||||
@ -121,11 +156,12 @@ type status struct {
|
||||
*client.VertexStatus
|
||||
}
|
||||
|
||||
func newTrace(w io.Writer) *trace {
|
||||
func newTrace(w io.Writer, modeConsole bool) *trace {
|
||||
return &trace{
|
||||
byDigest: make(map[digest.Digest]*vertex),
|
||||
updates: make(map[digest.Digest]struct{}),
|
||||
w: w,
|
||||
byDigest: make(map[digest.Digest]*vertex),
|
||||
updates: make(map[digest.Digest]struct{}),
|
||||
w: w,
|
||||
modeConsole: modeConsole,
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,41 +176,37 @@ func (t *trace) triggerVertexEvent(v *client.Vertex) {
|
||||
old = *v
|
||||
}
|
||||
|
||||
var ev []string
|
||||
changed := false
|
||||
if v.Digest != old.Digest {
|
||||
ev = append(ev, fmt.Sprintf("%13s %s", "digest:", v.Digest))
|
||||
changed = true
|
||||
}
|
||||
if v.Name != old.Name {
|
||||
ev = append(ev, fmt.Sprintf("%13s %q", "name:", v.Name))
|
||||
changed = true
|
||||
}
|
||||
if v.Started != old.Started {
|
||||
if v.Started != nil && old.Started == nil || !v.Started.Equal(*old.Started) {
|
||||
ev = append(ev, fmt.Sprintf("%13s %v", "started:", v.Started))
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
if v.Completed != old.Completed && v.Completed != nil {
|
||||
ev = append(ev, fmt.Sprintf("%13s %v", "completed:", v.Completed))
|
||||
if v.Started != nil {
|
||||
ev = append(ev, fmt.Sprintf("%13s %v", "duration:", v.Completed.Sub(*v.Started)))
|
||||
}
|
||||
changed = true
|
||||
}
|
||||
if v.Cached != old.Cached {
|
||||
ev = append(ev, fmt.Sprintf("%13s %v", "cached:", v.Cached))
|
||||
changed = true
|
||||
}
|
||||
if v.Error != old.Error {
|
||||
ev = append(ev, fmt.Sprintf("%13s %q", "error:", v.Error))
|
||||
changed = true
|
||||
}
|
||||
|
||||
if len(ev) > 0 {
|
||||
vtx.events = append(vtx.events, ev...)
|
||||
vtx.update(len(ev))
|
||||
if changed {
|
||||
vtx.update(1)
|
||||
t.updates[v.Digest] = struct{}{}
|
||||
}
|
||||
|
||||
t.byDigest[v.Digest].prev = v
|
||||
}
|
||||
|
||||
func (t *trace) update(s *client.SolveStatus) {
|
||||
func (t *trace) update(s *client.SolveStatus, termWidth int) {
|
||||
for _, v := range s.Vertexes {
|
||||
prev, ok := t.byDigest[v.Digest]
|
||||
if !ok {
|
||||
@ -184,6 +216,9 @@ func (t *trace) update(s *client.SolveStatus) {
|
||||
statusUpdates: make(map[string]struct{}),
|
||||
index: t.nextIndex,
|
||||
}
|
||||
if t.modeConsole {
|
||||
t.byDigest[v.Digest].term = vt100.NewVT100(termHeight, termWidth-termPad)
|
||||
}
|
||||
}
|
||||
t.triggerVertexEvent(v)
|
||||
if v.Started != nil && (prev == nil || prev.Started == nil) {
|
||||
@ -193,12 +228,14 @@ func (t *trace) update(s *client.SolveStatus) {
|
||||
t.vertexes = append(t.vertexes, t.byDigest[v.Digest])
|
||||
}
|
||||
t.byDigest[v.Digest].Vertex = v
|
||||
t.byDigest[v.Digest].jobCached = false
|
||||
}
|
||||
for _, s := range s.Statuses {
|
||||
v, ok := t.byDigest[s.Vertex]
|
||||
if !ok {
|
||||
continue // shouldn't happen
|
||||
}
|
||||
v.jobCached = false
|
||||
prev, ok := v.byID[s.ID]
|
||||
if !ok {
|
||||
v.byID[s.ID] = &status{VertexStatus: s}
|
||||
@ -216,6 +253,14 @@ func (t *trace) update(s *client.SolveStatus) {
|
||||
if !ok {
|
||||
continue // shouldn't happen
|
||||
}
|
||||
v.jobCached = false
|
||||
if v.term != nil {
|
||||
if v.term.Width != termWidth {
|
||||
v.term.Resize(termHeight, termWidth-termPad)
|
||||
}
|
||||
v.termBytes += len(l.Data)
|
||||
v.term.Write(l.Data) // error unhandled on purpose. don't trust vt100
|
||||
}
|
||||
i := 0
|
||||
complete := split(l.Data, byte('\n'), func(dt []byte) {
|
||||
if v.logsPartial && len(v.logs) != 0 && i == 0 {
|
||||
@ -262,10 +307,16 @@ func (t *trace) displayInfo() (d displayInfo) {
|
||||
}
|
||||
|
||||
for _, v := range t.vertexes {
|
||||
j := job{
|
||||
if v.jobCached {
|
||||
d.jobs = append(d.jobs, v.jobs...)
|
||||
continue
|
||||
}
|
||||
var jobs []*job
|
||||
j := &job{
|
||||
startTime: addTime(v.Started, t.localTimeDiff),
|
||||
completedTime: addTime(v.Completed, t.localTimeDiff),
|
||||
name: strings.Replace(v.Name, "\t", " ", -1),
|
||||
vertex: v,
|
||||
}
|
||||
if v.Error != "" {
|
||||
if strings.HasSuffix(v.Error, context.Canceled.Error()) {
|
||||
@ -280,9 +331,9 @@ func (t *trace) displayInfo() (d displayInfo) {
|
||||
j.name = "CACHED " + j.name
|
||||
}
|
||||
j.name = v.indent + j.name
|
||||
d.jobs = append(d.jobs, j)
|
||||
jobs = append(jobs, j)
|
||||
for _, s := range v.statuses {
|
||||
j := job{
|
||||
j := &job{
|
||||
startTime: addTime(s.Started, t.localTimeDiff),
|
||||
completedTime: addTime(s.Completed, t.localTimeDiff),
|
||||
name: v.indent + "=> " + s.ID,
|
||||
@ -292,8 +343,11 @@ func (t *trace) displayInfo() (d displayInfo) {
|
||||
} else if s.Current != 0 {
|
||||
j.status = fmt.Sprintf("%.2f", units.Bytes(s.Current))
|
||||
}
|
||||
d.jobs = append(d.jobs, j)
|
||||
jobs = append(jobs, j)
|
||||
}
|
||||
d.jobs = append(d.jobs, jobs...)
|
||||
v.jobs = jobs
|
||||
v.jobCached = true
|
||||
}
|
||||
|
||||
return d
|
||||
@ -332,20 +386,56 @@ type display struct {
|
||||
repeated bool
|
||||
}
|
||||
|
||||
func (disp *display) print(d displayInfo, all bool) {
|
||||
// this output is inspired by Buck
|
||||
func (disp *display) getSize() (int, int) {
|
||||
width := 80
|
||||
height := 10
|
||||
size, err := disp.c.Size()
|
||||
if err == nil && size.Width > 0 && size.Height > 0 {
|
||||
width = int(size.Width)
|
||||
height = int(size.Height)
|
||||
if disp.c != nil {
|
||||
size, err := disp.c.Size()
|
||||
if err == nil && size.Width > 0 && size.Height > 0 {
|
||||
width = int(size.Width)
|
||||
height = int(size.Height)
|
||||
}
|
||||
}
|
||||
return width, height
|
||||
}
|
||||
|
||||
func setupTerminals(jobs []*job, height int, all bool) []*job {
|
||||
var candidates []*job
|
||||
numInUse := 0
|
||||
for _, j := range jobs {
|
||||
if j.vertex != nil && j.vertex.termBytes > 0 && j.completedTime == nil {
|
||||
candidates = append(candidates, j)
|
||||
}
|
||||
if j.completedTime == nil {
|
||||
numInUse++
|
||||
}
|
||||
}
|
||||
sort.Slice(candidates, func(i, j int) bool {
|
||||
idxI := candidates[i].vertex.termBytes + candidates[i].vertex.termCount*50
|
||||
idxJ := candidates[j].vertex.termBytes + candidates[j].vertex.termCount*50
|
||||
return idxI > idxJ
|
||||
})
|
||||
|
||||
numFree := height - 2 - numInUse
|
||||
numToHide := 0
|
||||
termLimit := termHeight + 3
|
||||
|
||||
for i := 0; numFree > termLimit && i < len(candidates); i++ {
|
||||
candidates[i].showTerm = true
|
||||
numToHide += candidates[i].vertex.term.UsedHeight()
|
||||
numFree -= termLimit
|
||||
}
|
||||
|
||||
if !all {
|
||||
d.jobs = wrapHeight(d.jobs, height-2)
|
||||
jobs = wrapHeight(jobs, height-2-numToHide)
|
||||
}
|
||||
|
||||
return jobs
|
||||
}
|
||||
|
||||
func (disp *display) print(d displayInfo, width, height int, all bool) {
|
||||
// this output is inspired by Buck
|
||||
d.jobs = setupTerminals(d.jobs, height, all)
|
||||
b := aec.EmptyBuilder
|
||||
for i := 0; i <= disp.lineCount; i++ {
|
||||
b = b.Up(1)
|
||||
@ -395,11 +485,12 @@ func (disp *display) print(d displayInfo, all bool) {
|
||||
if left < 12 { // too small screen to show progress
|
||||
continue
|
||||
}
|
||||
if len(j.name) > left {
|
||||
j.name = j.name[:left]
|
||||
name := j.name
|
||||
if len(name) > left {
|
||||
name = name[:left]
|
||||
}
|
||||
|
||||
out := pfx + j.name
|
||||
out := pfx + name
|
||||
if showStatus {
|
||||
out += " " + status
|
||||
}
|
||||
@ -416,17 +507,68 @@ func (disp *display) print(d displayInfo, all bool) {
|
||||
}
|
||||
fmt.Fprint(disp.c, out)
|
||||
lineCount++
|
||||
if j.showTerm {
|
||||
term := j.vertex.term
|
||||
term.Resize(termHeight, width-termPad)
|
||||
for _, l := range term.Content {
|
||||
if !isEmpty(l) {
|
||||
out := aec.Apply(fmt.Sprintf(" => => # %s\n", string(l)), aec.Faint)
|
||||
fmt.Fprint(disp.c, out)
|
||||
lineCount++
|
||||
}
|
||||
}
|
||||
j.vertex.termCount++
|
||||
j.showTerm = false
|
||||
}
|
||||
}
|
||||
// override previous content
|
||||
if diff := disp.lineCount - lineCount; diff > 0 {
|
||||
for i := 0; i < diff; i++ {
|
||||
fmt.Fprintln(disp.c, strings.Repeat(" ", width))
|
||||
}
|
||||
fmt.Fprint(disp.c, aec.EmptyBuilder.Up(uint(diff)).Column(0).ANSI)
|
||||
}
|
||||
disp.lineCount = lineCount
|
||||
}
|
||||
|
||||
func isEmpty(l []rune) bool {
|
||||
for _, r := range l {
|
||||
if r != ' ' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func align(l, r string, w int) string {
|
||||
return fmt.Sprintf("%-[2]*[1]s %[3]s", l, w-len(r)-1, r)
|
||||
}
|
||||
|
||||
func wrapHeight(j []job, limit int) []job {
|
||||
func wrapHeight(j []*job, limit int) []*job {
|
||||
var wrapped []*job
|
||||
wrapped = append(wrapped, j...)
|
||||
if len(j) > limit {
|
||||
j = j[len(j)-limit:]
|
||||
wrapped = wrapped[len(j)-limit:]
|
||||
|
||||
// wrap things around if incomplete jobs were cut
|
||||
var invisible []*job
|
||||
for _, j := range j[:len(j)-limit] {
|
||||
if j.completedTime == nil {
|
||||
invisible = append(invisible, j)
|
||||
}
|
||||
}
|
||||
|
||||
if l := len(invisible); l > 0 {
|
||||
rewrapped := make([]*job, 0, len(wrapped))
|
||||
for _, j := range wrapped {
|
||||
if j.completedTime == nil || l <= 0 {
|
||||
rewrapped = append(rewrapped, j)
|
||||
}
|
||||
l--
|
||||
}
|
||||
freespace := len(wrapped) - len(rewrapped)
|
||||
wrapped = append(invisible[len(invisible)-freespace:], rewrapped...)
|
||||
}
|
||||
}
|
||||
return j
|
||||
return wrapped
|
||||
}
|
||||
|
63
vendor/github.com/moby/buildkit/util/progress/progressui/printer.go
generated
vendored
63
vendor/github.com/moby/buildkit/util/progress/progressui/printer.go
generated
vendored
@ -1,8 +1,12 @@
|
||||
package progressui
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
@ -20,9 +24,10 @@ type lastStatus struct {
|
||||
}
|
||||
|
||||
type textMux struct {
|
||||
w io.Writer
|
||||
current digest.Digest
|
||||
last map[string]lastStatus
|
||||
w io.Writer
|
||||
current digest.Digest
|
||||
last map[string]lastStatus
|
||||
notFirst bool
|
||||
}
|
||||
|
||||
func (p *textMux) printVtx(t *trace, dgst digest.Digest) {
|
||||
@ -43,10 +48,22 @@ func (p *textMux) printVtx(t *trace, dgst digest.Digest) {
|
||||
}
|
||||
old.logsOffset = 0
|
||||
old.count = 0
|
||||
fmt.Fprintf(p.w, "#%d ...\n", v.index)
|
||||
fmt.Fprintf(p.w, "#%d ...\n", old.index)
|
||||
}
|
||||
|
||||
if p.notFirst {
|
||||
fmt.Fprintln(p.w, "")
|
||||
} else {
|
||||
p.notFirst = true
|
||||
}
|
||||
|
||||
if os.Getenv("PROGRESS_NO_TRUNC") == "1" {
|
||||
fmt.Fprintf(p.w, "#%d %s\n", v.index, v.Name)
|
||||
fmt.Fprintf(p.w, "#%d %s\n", v.index, v.Digest)
|
||||
} else {
|
||||
fmt.Fprintf(p.w, "#%d %s\n", v.index, limitString(v.Name, 72))
|
||||
}
|
||||
|
||||
fmt.Fprintf(p.w, "\n#%d %s\n", v.index, limitString(v.Name, 72))
|
||||
}
|
||||
|
||||
if len(v.events) != 0 {
|
||||
@ -127,18 +144,46 @@ func (p *textMux) printVtx(t *trace, dgst digest.Digest) {
|
||||
}
|
||||
|
||||
p.current = dgst
|
||||
|
||||
if v.Completed != nil {
|
||||
p.current = ""
|
||||
v.count = 0
|
||||
fmt.Fprintf(p.w, "\n")
|
||||
|
||||
if v.Error != "" {
|
||||
if v.logsPartial {
|
||||
fmt.Fprintln(p.w, "")
|
||||
}
|
||||
if strings.HasSuffix(v.Error, context.Canceled.Error()) {
|
||||
fmt.Fprintf(p.w, "#%d CANCELED\n", v.index)
|
||||
} else {
|
||||
fmt.Fprintf(p.w, "#%d ERROR: %s\n", v.index, v.Error)
|
||||
}
|
||||
} else if v.Cached {
|
||||
fmt.Fprintf(p.w, "#%d CACHED\n", v.index)
|
||||
} else {
|
||||
tm := ""
|
||||
if v.Started != nil {
|
||||
tm = fmt.Sprintf(" %.1fs", v.Completed.Sub(*v.Started).Seconds())
|
||||
}
|
||||
fmt.Fprintf(p.w, "#%d DONE%s\n", v.index, tm)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
delete(t.updates, dgst)
|
||||
}
|
||||
|
||||
func (p *textMux) print(t *trace) {
|
||||
func sortCompleted(t *trace, m map[digest.Digest]struct{}) []digest.Digest {
|
||||
out := make([]digest.Digest, 0, len(m))
|
||||
for k := range m {
|
||||
out = append(out, k)
|
||||
}
|
||||
sort.Slice(out, func(i, j int) bool {
|
||||
return t.byDigest[out[i]].Completed.Before(*t.byDigest[out[j]].Completed)
|
||||
})
|
||||
return out
|
||||
}
|
||||
|
||||
func (p *textMux) print(t *trace) {
|
||||
completed := map[digest.Digest]struct{}{}
|
||||
rest := map[digest.Digest]struct{}{}
|
||||
|
||||
@ -161,7 +206,7 @@ func (p *textMux) print(t *trace) {
|
||||
p.printVtx(t, current)
|
||||
}
|
||||
|
||||
for dgst := range completed {
|
||||
for _, dgst := range sortCompleted(t, completed) {
|
||||
if dgst != current {
|
||||
p.printVtx(t, dgst)
|
||||
}
|
||||
|
Reference in New Issue
Block a user