github.com/dlintw/docker@v1.5.0-rc4/utils/progressreader.go (about) 1 package utils 2 3 import ( 4 "io" 5 "time" 6 ) 7 8 // Reader with progress bar 9 type progressReader struct { 10 reader io.ReadCloser // Stream to read from 11 output io.Writer // Where to send progress bar to 12 progress JSONProgress 13 lastUpdate int // How many bytes read at least update 14 ID string 15 action string 16 sf *StreamFormatter 17 newLine bool 18 } 19 20 func (r *progressReader) Read(p []byte) (n int, err error) { 21 read, err := r.reader.Read(p) 22 r.progress.Current += read 23 updateEvery := 1024 * 512 //512kB 24 if r.progress.Total > 0 { 25 // Update progress for every 1% read if 1% < 512kB 26 if increment := int(0.01 * float64(r.progress.Total)); increment < updateEvery { 27 updateEvery = increment 28 } 29 } 30 if r.progress.Current-r.lastUpdate > updateEvery || err != nil { 31 r.output.Write(r.sf.FormatProgress(r.ID, r.action, &r.progress)) 32 r.lastUpdate = r.progress.Current 33 } 34 // Send newline when complete 35 if r.newLine && err != nil && read == 0 { 36 r.output.Write(r.sf.FormatStatus("", "")) 37 } 38 return read, err 39 } 40 func (r *progressReader) Close() error { 41 r.progress.Current = r.progress.Total 42 r.output.Write(r.sf.FormatProgress(r.ID, r.action, &r.progress)) 43 return r.reader.Close() 44 } 45 func ProgressReader(r io.ReadCloser, size int, output io.Writer, sf *StreamFormatter, newline bool, ID, action string) *progressReader { 46 return &progressReader{ 47 reader: r, 48 output: NewWriteFlusher(output), 49 ID: ID, 50 action: action, 51 progress: JSONProgress{Total: size, Start: time.Now().UTC().Unix()}, 52 sf: sf, 53 newLine: newline, 54 } 55 }