mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-01 00:23:56 +08:00 
			
		
		
		
	util: simplify progress syncronization
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
		| @@ -11,7 +11,6 @@ import ( | ||||
| ) | ||||
|  | ||||
| func FromReader(w Writer, name string, rc io.ReadCloser) { | ||||
| 	status := w.Status() | ||||
| 	dgst := digest.FromBytes([]byte(identity.NewID())) | ||||
| 	tm := time.Now() | ||||
|  | ||||
| @@ -21,9 +20,9 @@ func FromReader(w Writer, name string, rc io.ReadCloser) { | ||||
| 		Started: &tm, | ||||
| 	} | ||||
|  | ||||
| 	status <- &client.SolveStatus{ | ||||
| 	w.Write(&client.SolveStatus{ | ||||
| 		Vertexes: []*client.Vertex{&vtx}, | ||||
| 	} | ||||
| 	}) | ||||
|  | ||||
| 	_, err := io.Copy(ioutil.Discard, rc) | ||||
|  | ||||
| @@ -33,8 +32,7 @@ func FromReader(w Writer, name string, rc io.ReadCloser) { | ||||
| 	if err != nil { | ||||
| 		vtx2.Error = err.Error() | ||||
| 	} | ||||
| 	status <- &client.SolveStatus{ | ||||
| 	w.Write(&client.SolveStatus{ | ||||
| 		Vertexes: []*client.Vertex{&vtx2}, | ||||
| 	} | ||||
| 	close(status) | ||||
| 	}) | ||||
| } | ||||
|   | ||||
| @@ -1,101 +1,32 @@ | ||||
| package progress | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
|  | ||||
| 	"github.com/moby/buildkit/client" | ||||
| 	"golang.org/x/sync/errgroup" | ||||
| ) | ||||
|  | ||||
| type MultiWriter struct { | ||||
| 	w     Writer | ||||
| 	eg    *errgroup.Group | ||||
| 	once  sync.Once | ||||
| 	ready chan struct{} | ||||
| } | ||||
|  | ||||
| func (mw *MultiWriter) WithPrefix(pfx string, force bool) Writer { | ||||
| 	in := make(chan *client.SolveStatus) | ||||
| 	out := mw.w.Status() | ||||
| 	p := &prefixed{ | ||||
| 		main: mw.w, | ||||
| 		in:   in, | ||||
| func WithPrefix(w Writer, pfx string, force bool) Writer { | ||||
| 	return &prefixed{ | ||||
| 		main:  w, | ||||
| 		pfx:   pfx, | ||||
| 		force: force, | ||||
| 	} | ||||
| 	mw.eg.Go(func() error { | ||||
| 		mw.once.Do(func() { | ||||
| 			close(mw.ready) | ||||
| 		}) | ||||
| 		for { | ||||
| 			select { | ||||
| 			case v, ok := <-in: | ||||
| 				if ok { | ||||
| 					if force { | ||||
| 						for _, v := range v.Vertexes { | ||||
| 							v.Name = addPrefix(pfx, v.Name) | ||||
| 						} | ||||
| 					} | ||||
| 					out <- v | ||||
| 				} else { | ||||
| 					return nil | ||||
| 				} | ||||
| 			case <-mw.Done(): | ||||
| 				return mw.Err() | ||||
| 			} | ||||
| 		} | ||||
| 	}) | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| func (mw *MultiWriter) Done() <-chan struct{} { | ||||
| 	return mw.w.Done() | ||||
| } | ||||
|  | ||||
| func (mw *MultiWriter) Err() error { | ||||
| 	return mw.w.Err() | ||||
| } | ||||
|  | ||||
| func (mw *MultiWriter) Status() chan *client.SolveStatus { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type prefixed struct { | ||||
| 	main Writer | ||||
| 	in   chan *client.SolveStatus | ||||
| 	main  Writer | ||||
| 	pfx   string | ||||
| 	force bool | ||||
| } | ||||
|  | ||||
| func (p *prefixed) Done() <-chan struct{} { | ||||
| 	return p.main.Done() | ||||
| } | ||||
|  | ||||
| func (p *prefixed) Err() error { | ||||
| 	return p.main.Err() | ||||
| } | ||||
|  | ||||
| func (p *prefixed) Status() chan *client.SolveStatus { | ||||
| 	return p.in | ||||
| } | ||||
|  | ||||
| func NewMultiWriter(pw Writer) *MultiWriter { | ||||
| 	if pw == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	eg, _ := errgroup.WithContext(context.TODO()) | ||||
|  | ||||
| 	ready := make(chan struct{}) | ||||
|  | ||||
| 	go func() { | ||||
| 		<-ready | ||||
| 		eg.Wait() | ||||
| 		close(pw.Status()) | ||||
| 	}() | ||||
|  | ||||
| 	return &MultiWriter{ | ||||
| 		w:     pw, | ||||
| 		eg:    eg, | ||||
| 		ready: ready, | ||||
| func (p *prefixed) Write(v *client.SolveStatus) { | ||||
| 	if p.force { | ||||
| 		for _, v := range v.Vertexes { | ||||
| 			v.Name = addPrefix(p.pfx, v.Name) | ||||
| 		} | ||||
| 	} | ||||
| 	p.main.Write(v) | ||||
| } | ||||
|  | ||||
| func addPrefix(pfx, name string) string { | ||||
|   | ||||
| @@ -9,32 +9,27 @@ import ( | ||||
| 	"github.com/moby/buildkit/util/progress/progressui" | ||||
| ) | ||||
|  | ||||
| type printer struct { | ||||
| type Printer struct { | ||||
| 	status chan *client.SolveStatus | ||||
| 	done   <-chan struct{} | ||||
| 	err    error | ||||
| } | ||||
|  | ||||
| func (p *printer) Done() <-chan struct{} { | ||||
| 	return p.done | ||||
| } | ||||
|  | ||||
| func (p *printer) Err() error { | ||||
| func (p *Printer) Wait() error { | ||||
| 	close(p.status) | ||||
| 	<-p.done | ||||
| 	return p.err | ||||
| } | ||||
|  | ||||
| func (p *printer) Status() chan *client.SolveStatus { | ||||
| 	if p == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return p.status | ||||
| func (p *Printer) Write(s *client.SolveStatus) { | ||||
| 	p.status <- s | ||||
| } | ||||
|  | ||||
| func NewPrinter(ctx context.Context, out console.File, mode string) Writer { | ||||
| func NewPrinter(ctx context.Context, out console.File, mode string) *Printer { | ||||
| 	statusCh := make(chan *client.SolveStatus) | ||||
| 	doneCh := make(chan struct{}) | ||||
|  | ||||
| 	pw := &printer{ | ||||
| 	pw := &Printer{ | ||||
| 		status: statusCh, | ||||
| 		done:   doneCh, | ||||
| 	} | ||||
|   | ||||
| @@ -7,56 +7,45 @@ import ( | ||||
| ) | ||||
|  | ||||
| func ResetTime(in Writer) Writer { | ||||
| 	w := &pw{Writer: in, status: make(chan *client.SolveStatus), tm: time.Now()} | ||||
| 	go func() { | ||||
| 		for { | ||||
| 			select { | ||||
| 			case <-in.Done(): | ||||
| 				return | ||||
| 			case st, ok := <-w.status: | ||||
| 				if !ok { | ||||
| 					close(in.Status()) | ||||
| 					return | ||||
| 				} | ||||
| 				if w.diff == nil { | ||||
| 					for _, v := range st.Vertexes { | ||||
| 						if v.Started != nil { | ||||
| 							d := v.Started.Sub(w.tm) | ||||
| 							w.diff = &d | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				if w.diff != nil { | ||||
| 					for _, v := range st.Vertexes { | ||||
| 						if v.Started != nil { | ||||
| 							d := v.Started.Add(-*w.diff) | ||||
| 							v.Started = &d | ||||
| 						} | ||||
| 						if v.Completed != nil { | ||||
| 							d := v.Completed.Add(-*w.diff) | ||||
| 							v.Completed = &d | ||||
| 						} | ||||
| 					} | ||||
| 					for _, v := range st.Statuses { | ||||
| 						if v.Started != nil { | ||||
| 							d := v.Started.Add(-*w.diff) | ||||
| 							v.Started = &d | ||||
| 						} | ||||
| 						if v.Completed != nil { | ||||
| 							d := v.Completed.Add(-*w.diff) | ||||
| 							v.Completed = &d | ||||
| 						} | ||||
| 						v.Timestamp = v.Timestamp.Add(-*w.diff) | ||||
| 					} | ||||
| 					for _, v := range st.Logs { | ||||
| 						v.Timestamp = v.Timestamp.Add(-*w.diff) | ||||
| 					} | ||||
| 				} | ||||
| 				in.Status() <- st | ||||
| 	return &pw{Writer: in, status: make(chan *client.SolveStatus), tm: time.Now()} | ||||
| } | ||||
|  | ||||
| func (w *pw) Write(st *client.SolveStatus) { | ||||
| 	if w.diff == nil { | ||||
| 		for _, v := range st.Vertexes { | ||||
| 			if v.Started != nil { | ||||
| 				d := v.Started.Sub(w.tm) | ||||
| 				w.diff = &d | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
| 	return w | ||||
| 	} | ||||
| 	if w.diff != nil { | ||||
| 		for _, v := range st.Vertexes { | ||||
| 			if v.Started != nil { | ||||
| 				d := v.Started.Add(-*w.diff) | ||||
| 				v.Started = &d | ||||
| 			} | ||||
| 			if v.Completed != nil { | ||||
| 				d := v.Completed.Add(-*w.diff) | ||||
| 				v.Completed = &d | ||||
| 			} | ||||
| 		} | ||||
| 		for _, v := range st.Statuses { | ||||
| 			if v.Started != nil { | ||||
| 				d := v.Started.Add(-*w.diff) | ||||
| 				v.Started = &d | ||||
| 			} | ||||
| 			if v.Completed != nil { | ||||
| 				d := v.Completed.Add(-*w.diff) | ||||
| 				v.Completed = &d | ||||
| 			} | ||||
| 			v.Timestamp = v.Timestamp.Add(-*w.diff) | ||||
| 		} | ||||
| 		for _, v := range st.Logs { | ||||
| 			v.Timestamp = v.Timestamp.Add(-*w.diff) | ||||
| 		} | ||||
| 	} | ||||
| 	w.Writer.Write(st) | ||||
| } | ||||
|  | ||||
| type pw struct { | ||||
|   | ||||
| @@ -9,13 +9,10 @@ import ( | ||||
| ) | ||||
|  | ||||
| type Writer interface { | ||||
| 	Done() <-chan struct{} | ||||
| 	Err() error | ||||
| 	Status() chan *client.SolveStatus | ||||
| 	Write(*client.SolveStatus) | ||||
| } | ||||
|  | ||||
| func Write(w Writer, name string, f func() error) { | ||||
| 	status := w.Status() | ||||
| 	dgst := digest.FromBytes([]byte(identity.NewID())) | ||||
| 	tm := time.Now() | ||||
|  | ||||
| @@ -25,9 +22,9 @@ func Write(w Writer, name string, f func() error) { | ||||
| 		Started: &tm, | ||||
| 	} | ||||
|  | ||||
| 	status <- &client.SolveStatus{ | ||||
| 	w.Write(&client.SolveStatus{ | ||||
| 		Vertexes: []*client.Vertex{&vtx}, | ||||
| 	} | ||||
| 	}) | ||||
|  | ||||
| 	err := f() | ||||
|  | ||||
| @@ -37,7 +34,21 @@ func Write(w Writer, name string, f func() error) { | ||||
| 	if err != nil { | ||||
| 		vtx2.Error = err.Error() | ||||
| 	} | ||||
| 	status <- &client.SolveStatus{ | ||||
| 	w.Write(&client.SolveStatus{ | ||||
| 		Vertexes: []*client.Vertex{&vtx2}, | ||||
| 	} | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func NewChannel(w Writer) chan *client.SolveStatus { | ||||
| 	ch := make(chan *client.SolveStatus) | ||||
| 	go func() { | ||||
| 		for { | ||||
| 			v, ok := <-ch | ||||
| 			if !ok { | ||||
| 				return | ||||
| 			} | ||||
| 			w.Write(v) | ||||
| 		} | ||||
| 	}() | ||||
| 	return ch | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Tonis Tiigi
					Tonis Tiigi