Based on #12874 from Sam Abed <sam.abed@gmail.com>. His original commit was brought up to date by manually porting the changes in pull.go into the new code in pull_v1.go and pull_v2.go. Fixes #8385 Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com> Upstream-commit: 572f008e892b06262963ccb75c631f2f5d6c6fcd Component: engine
73 lines
1.2 KiB
Go
73 lines
1.2 KiB
Go
package progressreader
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"sync"
|
|
|
|
"github.com/docker/docker/vendor/src/github.com/Sirupsen/logrus"
|
|
)
|
|
|
|
type ProgressStatus struct {
|
|
sync.Mutex
|
|
c chan struct{}
|
|
observers []io.Writer
|
|
history bytes.Buffer
|
|
}
|
|
|
|
func NewProgressStatus() *ProgressStatus {
|
|
return &ProgressStatus{
|
|
c: make(chan struct{}),
|
|
observers: []io.Writer{},
|
|
}
|
|
}
|
|
|
|
func (ps *ProgressStatus) Write(p []byte) (n int, err error) {
|
|
ps.Lock()
|
|
defer ps.Unlock()
|
|
ps.history.Write(p)
|
|
for _, w := range ps.observers {
|
|
// copy paste from MultiWriter, replaced return with continue
|
|
n, err = w.Write(p)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if n != len(p) {
|
|
err = io.ErrShortWrite
|
|
continue
|
|
}
|
|
}
|
|
return len(p), nil
|
|
}
|
|
|
|
func (ps *ProgressStatus) AddObserver(w io.Writer) {
|
|
ps.Lock()
|
|
defer ps.Unlock()
|
|
w.Write(ps.history.Bytes())
|
|
ps.observers = append(ps.observers, w)
|
|
}
|
|
|
|
func (ps *ProgressStatus) Done() {
|
|
ps.Lock()
|
|
close(ps.c)
|
|
ps.history.Reset()
|
|
ps.Unlock()
|
|
}
|
|
|
|
func (ps *ProgressStatus) Wait(w io.Writer, msg []byte) error {
|
|
ps.Lock()
|
|
channel := ps.c
|
|
ps.Unlock()
|
|
|
|
if channel == nil {
|
|
// defensive
|
|
logrus.Debugf("Channel is nil ")
|
|
}
|
|
if w != nil {
|
|
w.Write(msg)
|
|
ps.AddObserver(w)
|
|
}
|
|
<-channel
|
|
return nil
|
|
}
|