github.com/akerouanton/docker@v1.11.0-rc3/pkg/progress/progressreader.go (about) 1 package progress 2 3 import ( 4 "io" 5 ) 6 7 // Reader is a Reader with progress bar. 8 type Reader struct { 9 in io.ReadCloser // Stream to read from 10 out Output // Where to send progress bar to 11 size int64 12 current int64 13 lastUpdate int64 14 id string 15 action string 16 } 17 18 // NewProgressReader creates a new ProgressReader. 19 func NewProgressReader(in io.ReadCloser, out Output, size int64, id, action string) *Reader { 20 return &Reader{ 21 in: in, 22 out: out, 23 size: size, 24 id: id, 25 action: action, 26 } 27 } 28 29 func (p *Reader) Read(buf []byte) (n int, err error) { 30 read, err := p.in.Read(buf) 31 p.current += int64(read) 32 updateEvery := int64(1024 * 512) //512kB 33 if p.size > 0 { 34 // Update progress for every 1% read if 1% < 512kB 35 if increment := int64(0.01 * float64(p.size)); increment < updateEvery { 36 updateEvery = increment 37 } 38 } 39 if p.current-p.lastUpdate > updateEvery || err != nil { 40 p.updateProgress(err != nil && read == 0) 41 p.lastUpdate = p.current 42 } 43 44 return read, err 45 } 46 47 // Close closes the progress reader and its underlying reader. 48 func (p *Reader) Close() error { 49 if p.current < p.size { 50 // print a full progress bar when closing prematurely 51 p.current = p.size 52 p.updateProgress(false) 53 } 54 return p.in.Close() 55 } 56 57 func (p *Reader) updateProgress(last bool) { 58 p.out.WriteProgress(Progress{ID: p.id, Action: p.action, Current: p.current, Total: p.size, LastUpdate: last}) 59 }