2015-07-25 08:35:07 +00:00
|
|
|
// Package progressreader provides a Reader with a progress bar that can be
|
|
|
|
// printed out using the streamformatter package.
|
2015-02-24 08:51:46 +00:00
|
|
|
package progressreader
|
|
|
|
|
|
|
|
import (
|
2015-03-31 20:17:25 +00:00
|
|
|
"io"
|
|
|
|
|
2015-03-18 02:18:41 +00:00
|
|
|
"github.com/docker/docker/pkg/jsonmessage"
|
|
|
|
"github.com/docker/docker/pkg/streamformatter"
|
2015-02-24 08:51:46 +00:00
|
|
|
)
|
|
|
|
|
2015-07-25 08:35:07 +00:00
|
|
|
// Config contains the configuration for a Reader with progress bar.
|
2015-02-24 08:51:46 +00:00
|
|
|
type Config struct {
|
|
|
|
In io.ReadCloser // Stream to read from
|
|
|
|
Out io.Writer // Where to send progress bar to
|
2015-03-18 02:18:41 +00:00
|
|
|
Formatter *streamformatter.StreamFormatter
|
2015-07-23 21:19:58 +00:00
|
|
|
Size int64
|
|
|
|
Current int64
|
|
|
|
LastUpdate int64
|
2015-02-24 08:51:46 +00:00
|
|
|
NewLines bool
|
|
|
|
ID string
|
|
|
|
Action string
|
|
|
|
}
|
|
|
|
|
2015-07-25 08:35:07 +00:00
|
|
|
// New creates a new Config.
|
2015-02-24 08:51:46 +00:00
|
|
|
func New(newReader Config) *Config {
|
|
|
|
return &newReader
|
|
|
|
}
|
2015-05-27 15:48:51 +00:00
|
|
|
|
2015-02-24 08:51:46 +00:00
|
|
|
func (config *Config) Read(p []byte) (n int, err error) {
|
|
|
|
read, err := config.In.Read(p)
|
2015-07-23 21:19:58 +00:00
|
|
|
config.Current += int64(read)
|
|
|
|
updateEvery := int64(1024 * 512) //512kB
|
2015-02-24 08:51:46 +00:00
|
|
|
if config.Size > 0 {
|
|
|
|
// Update progress for every 1% read if 1% < 512kB
|
2015-07-23 21:19:58 +00:00
|
|
|
if increment := int64(0.01 * float64(config.Size)); increment < updateEvery {
|
2015-02-24 08:51:46 +00:00
|
|
|
updateEvery = increment
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if config.Current-config.LastUpdate > updateEvery || err != nil {
|
2015-05-27 15:48:51 +00:00
|
|
|
updateProgress(config)
|
2015-02-24 08:51:46 +00:00
|
|
|
config.LastUpdate = config.Current
|
|
|
|
}
|
2015-05-27 15:48:51 +00:00
|
|
|
|
|
|
|
if err != nil && read == 0 {
|
|
|
|
updateProgress(config)
|
|
|
|
if config.NewLines {
|
|
|
|
config.Out.Write(config.Formatter.FormatStatus("", ""))
|
|
|
|
}
|
2015-02-24 08:51:46 +00:00
|
|
|
}
|
|
|
|
return read, err
|
|
|
|
}
|
2015-05-27 15:48:51 +00:00
|
|
|
|
2015-07-25 08:35:07 +00:00
|
|
|
// Close closes the reader (Config).
|
2015-02-24 08:51:46 +00:00
|
|
|
func (config *Config) Close() error {
|
2015-05-27 15:48:51 +00:00
|
|
|
if config.Current < config.Size {
|
|
|
|
//print a full progress bar when closing prematurely
|
|
|
|
config.Current = config.Size
|
|
|
|
updateProgress(config)
|
|
|
|
}
|
2015-02-24 08:51:46 +00:00
|
|
|
return config.In.Close()
|
|
|
|
}
|
2015-05-27 15:48:51 +00:00
|
|
|
|
|
|
|
func updateProgress(config *Config) {
|
|
|
|
progress := jsonmessage.JSONProgress{Current: config.Current, Total: config.Size}
|
|
|
|
fmtMessage := config.Formatter.FormatProgress(config.ID, config.Action, &progress)
|
|
|
|
config.Out.Write(fmtMessage)
|
|
|
|
}
|