cmd/dist: implement fetch prototype

With the rename of fetch to fetch-object, we now introduce the `fetch`
command. It will fetch all of the resources required for an image into
the content store. We'll still need to follow this up with metadata
registration but this is a good start.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
Stephen J Day 2017-03-02 14:41:51 -08:00
parent 971b9ca29a
commit 55a1b4eff8
7 changed files with 509 additions and 0 deletions

65
progress/bar.go Normal file
View file

@ -0,0 +1,65 @@
package progress
import (
"bytes"
"fmt"
)
// TODO(stevvooe): We may want to support more interesting parameterization of
// the bar. For now, it is very simple.
// Bar provides a very simple progress bar implementation.
//
// Use with fmt.Printf and "r" to format the progress bar. A "-" flag makes it
// progress from right to left.
type Bar float64
var _ fmt.Formatter = Bar(1.0)
func (h Bar) Format(state fmt.State, r rune) {
switch r {
case 'r':
default:
panic(fmt.Sprintf("%v: unexpected format character", float64(h)))
}
if h > 1.0 {
h = 1.0
}
if h < 0.0 {
h = 0.0
}
if state.Flag('-') {
h = 1.0 - h
}
width, ok := state.Width()
if !ok {
// default width of 40
width = 40
}
var pad int
extra := len([]byte(green)) + len([]byte(reset))
p := make([]byte, width+extra)
p[0], p[len(p)-1] = '|', '|'
pad += 2
positive := int(Bar(width-pad) * h)
negative := width - pad - positive
n := 1
n += copy(p[n:], []byte(green))
n += copy(p[n:], bytes.Repeat([]byte("+"), positive))
n += copy(p[n:], []byte(reset))
if negative > 0 {
n += copy(p[n:len(p)-1], bytes.Repeat([]byte("-"), negative))
}
state.Write(p)
}

2
progress/doc.go Normal file
View file

@ -0,0 +1,2 @@
// Package progress assists in displaying human readable progress information.
package progress

8
progress/escape.go Normal file
View file

@ -0,0 +1,8 @@
package progress
const (
escape = "\x1b"
reset = escape + "[0m"
red = escape + "[31m"
green = escape + "[32m"
)

25
progress/humaans.go Normal file
View file

@ -0,0 +1,25 @@
package progress
import (
"fmt"
"time"
units "github.com/docker/go-units"
)
// Bytes converts a regular int64 to human readable type.
type Bytes int64
func (b Bytes) String() string {
return units.CustomSize("%02.1f %s", float64(b), 1024.0, []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"})
}
type BytesPerSecond int64
func NewBytesPerSecond(n int64, duration time.Duration) BytesPerSecond {
return BytesPerSecond(float64(n) / duration.Seconds())
}
func (bps BytesPerSecond) String() string {
return fmt.Sprintf("%v/s", Bytes(bps))
}

60
progress/writer.go Normal file
View file

@ -0,0 +1,60 @@
package progress
import (
"bytes"
"fmt"
"io"
)
// Writer buffers writes until flush, at which time the last screen is cleared
// and the current buffer contents are written. This is useful for
// implementing progress displays, such as those implemented in docker and
// git.
type Writer struct {
buf bytes.Buffer
w io.Writer
lines int
}
func NewWriter(w io.Writer) *Writer {
return &Writer{
w: w,
}
}
func (w *Writer) Write(p []byte) (n int, err error) {
return w.buf.Write(p)
}
// Flush should be called when refreshing the current display.
func (w *Writer) Flush() error {
if w.buf.Len() == 0 {
return nil
}
if err := w.clear(); err != nil {
return err
}
w.lines = bytes.Count(w.buf.Bytes(), []byte("\n"))
if _, err := w.w.Write(w.buf.Bytes()); err != nil {
return err
}
w.buf.Reset()
return nil
}
// TODO(stevvooe): The following are system specific. Break these out if we
// decide to build this package further.
func (w *Writer) clear() error {
for i := 0; i < w.lines; i++ {
if _, err := fmt.Fprintf(w.w, "\x1b[0A\x1b[2K\r"); err != nil {
return err
}
}
return nil
}