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:
parent
971b9ca29a
commit
55a1b4eff8
7 changed files with 509 additions and 0 deletions
65
progress/bar.go
Normal file
65
progress/bar.go
Normal 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
2
progress/doc.go
Normal file
|
@ -0,0 +1,2 @@
|
|||
// Package progress assists in displaying human readable progress information.
|
||||
package progress
|
8
progress/escape.go
Normal file
8
progress/escape.go
Normal 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
25
progress/humaans.go
Normal 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
60
progress/writer.go
Normal 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
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue