github.com/pdmccormick/importable-docker-buildx@v0.0.0-20240426161518-e47091289030/util/progress/writer.go (about)

     1  package progress
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/moby/buildkit/client"
     7  	"github.com/moby/buildkit/identity"
     8  	"github.com/opencontainers/go-digest"
     9  )
    10  
    11  type Writer interface {
    12  	Write(*client.SolveStatus)
    13  	WriteBuildRef(string, string)
    14  	ValidateLogSource(digest.Digest, interface{}) bool
    15  	ClearLogSource(interface{})
    16  }
    17  
    18  func Write(w Writer, name string, f func() error) error {
    19  	dgst := digest.FromBytes([]byte(identity.NewID()))
    20  	tm := time.Now()
    21  
    22  	vtx := client.Vertex{
    23  		Digest:  dgst,
    24  		Name:    name,
    25  		Started: &tm,
    26  	}
    27  
    28  	w.Write(&client.SolveStatus{
    29  		Vertexes: []*client.Vertex{&vtx},
    30  	})
    31  
    32  	err := f()
    33  
    34  	tm2 := time.Now()
    35  	vtx2 := vtx
    36  	vtx2.Completed = &tm2
    37  	if err != nil {
    38  		vtx2.Error = err.Error()
    39  	}
    40  	w.Write(&client.SolveStatus{
    41  		Vertexes: []*client.Vertex{&vtx2},
    42  	})
    43  
    44  	return err
    45  }
    46  
    47  func WriteBuildRef(w Writer, target string, ref string) {
    48  	w.WriteBuildRef(target, ref)
    49  }
    50  
    51  func NewChannel(w Writer) (chan *client.SolveStatus, chan struct{}) {
    52  	ch := make(chan *client.SolveStatus)
    53  	done := make(chan struct{})
    54  	go func() {
    55  		for {
    56  			v, ok := <-ch
    57  			if !ok {
    58  				close(done)
    59  				w.ClearLogSource(done)
    60  				return
    61  			}
    62  
    63  			if len(v.Logs) > 0 {
    64  				logs := make([]*client.VertexLog, 0, len(v.Logs))
    65  				for _, l := range v.Logs {
    66  					if w.ValidateLogSource(l.Vertex, done) {
    67  						logs = append(logs, l)
    68  					}
    69  				}
    70  				v.Logs = logs
    71  			}
    72  
    73  			w.Write(v)
    74  		}
    75  	}()
    76  	return ch, done
    77  }
    78  
    79  type tee struct {
    80  	Writer
    81  	ch chan *client.SolveStatus
    82  }
    83  
    84  func (t *tee) Write(v *client.SolveStatus) {
    85  	v2 := *v
    86  	t.ch <- &v2
    87  	t.Writer.Write(v)
    88  }
    89  
    90  func Tee(w Writer, ch chan *client.SolveStatus) Writer {
    91  	if ch == nil {
    92  		return w
    93  	}
    94  	return &tee{
    95  		Writer: w,
    96  		ch:     ch,
    97  	}
    98  }