progressreader.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // Package progressreader provides a Reader with a progress bar that can be
  2. // printed out using the streamformatter package.
  3. package progressreader
  4. import (
  5. "io"
  6. "github.com/docker/docker/pkg/jsonmessage"
  7. "github.com/docker/docker/pkg/streamformatter"
  8. )
  9. // Config contains the configuration for a Reader with progress bar.
  10. type Config struct {
  11. In io.ReadCloser // Stream to read from
  12. Out io.Writer // Where to send progress bar to
  13. Formatter *streamformatter.StreamFormatter
  14. Size int
  15. Current int
  16. LastUpdate int
  17. NewLines bool
  18. ID string
  19. Action string
  20. }
  21. // New creates a new Config.
  22. func New(newReader Config) *Config {
  23. return &newReader
  24. }
  25. func (config *Config) Read(p []byte) (n int, err error) {
  26. read, err := config.In.Read(p)
  27. config.Current += read
  28. updateEvery := 1024 * 512 //512kB
  29. if config.Size > 0 {
  30. // Update progress for every 1% read if 1% < 512kB
  31. if increment := int(0.01 * float64(config.Size)); increment < updateEvery {
  32. updateEvery = increment
  33. }
  34. }
  35. if config.Current-config.LastUpdate > updateEvery || err != nil {
  36. updateProgress(config)
  37. config.LastUpdate = config.Current
  38. }
  39. if err != nil && read == 0 {
  40. updateProgress(config)
  41. if config.NewLines {
  42. config.Out.Write(config.Formatter.FormatStatus("", ""))
  43. }
  44. }
  45. return read, err
  46. }
  47. // Close closes the reader (Config).
  48. func (config *Config) Close() error {
  49. if config.Current < config.Size {
  50. //print a full progress bar when closing prematurely
  51. config.Current = config.Size
  52. updateProgress(config)
  53. }
  54. return config.In.Close()
  55. }
  56. func updateProgress(config *Config) {
  57. progress := jsonmessage.JSONProgress{Current: config.Current, Total: config.Size}
  58. fmtMessage := config.Formatter.FormatProgress(config.ID, config.Action, &progress)
  59. config.Out.Write(fmtMessage)
  60. }