mirror of
https://github.com/containers/skopeo.git
synced 2025-09-24 03:17:17 +00:00
... to work around some of the "unexpected EOF" failures. Signed-off-by: Miloslav Trmač <mitr@redhat.com>
260 lines
5.5 KiB
Go
260 lines
5.5 KiB
Go
package mpb
|
|
|
|
import (
|
|
"io"
|
|
|
|
"github.com/acarl005/stripansi"
|
|
"github.com/mattn/go-runewidth"
|
|
"github.com/vbauerster/mpb/v8/decor"
|
|
"github.com/vbauerster/mpb/v8/internal"
|
|
)
|
|
|
|
const (
|
|
iLbound = iota
|
|
iRbound
|
|
iFiller
|
|
iRefiller
|
|
iPadding
|
|
components
|
|
)
|
|
|
|
// BarStyleComposer interface.
|
|
type BarStyleComposer interface {
|
|
BarFillerBuilder
|
|
Lbound(string) BarStyleComposer
|
|
Rbound(string) BarStyleComposer
|
|
Filler(string) BarStyleComposer
|
|
Refiller(string) BarStyleComposer
|
|
Padding(string) BarStyleComposer
|
|
TipOnComplete(string) BarStyleComposer
|
|
Tip(frames ...string) BarStyleComposer
|
|
Reverse() BarStyleComposer
|
|
}
|
|
|
|
type bFiller struct {
|
|
rev bool
|
|
components [components]*component
|
|
tip struct {
|
|
count uint
|
|
frames []*component
|
|
onComplete *component
|
|
}
|
|
}
|
|
|
|
type component struct {
|
|
width int
|
|
bytes []byte
|
|
}
|
|
|
|
type barStyle struct {
|
|
lbound string
|
|
rbound string
|
|
filler string
|
|
refiller string
|
|
padding string
|
|
tipOnComplete string
|
|
tipFrames []string
|
|
rev bool
|
|
}
|
|
|
|
// BarStyle constructs default bar style which can be altered via
|
|
// BarStyleComposer interface.
|
|
func BarStyle() BarStyleComposer {
|
|
return &barStyle{
|
|
lbound: "[",
|
|
rbound: "]",
|
|
filler: "=",
|
|
refiller: "+",
|
|
padding: "-",
|
|
tipFrames: []string{">"},
|
|
}
|
|
}
|
|
|
|
func (s *barStyle) Lbound(bound string) BarStyleComposer {
|
|
s.lbound = bound
|
|
return s
|
|
}
|
|
|
|
func (s *barStyle) Rbound(bound string) BarStyleComposer {
|
|
s.rbound = bound
|
|
return s
|
|
}
|
|
|
|
func (s *barStyle) Filler(filler string) BarStyleComposer {
|
|
s.filler = filler
|
|
return s
|
|
}
|
|
|
|
func (s *barStyle) Refiller(refiller string) BarStyleComposer {
|
|
s.refiller = refiller
|
|
return s
|
|
}
|
|
|
|
func (s *barStyle) Padding(padding string) BarStyleComposer {
|
|
s.padding = padding
|
|
return s
|
|
}
|
|
|
|
func (s *barStyle) TipOnComplete(tip string) BarStyleComposer {
|
|
s.tipOnComplete = tip
|
|
return s
|
|
}
|
|
|
|
func (s *barStyle) Tip(frames ...string) BarStyleComposer {
|
|
if len(frames) != 0 {
|
|
s.tipFrames = append(s.tipFrames[:0], frames...)
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (s *barStyle) Reverse() BarStyleComposer {
|
|
s.rev = true
|
|
return s
|
|
}
|
|
|
|
func (s *barStyle) Build() BarFiller {
|
|
bf := &bFiller{rev: s.rev}
|
|
bf.components[iLbound] = &component{
|
|
width: runewidth.StringWidth(stripansi.Strip(s.lbound)),
|
|
bytes: []byte(s.lbound),
|
|
}
|
|
bf.components[iRbound] = &component{
|
|
width: runewidth.StringWidth(stripansi.Strip(s.rbound)),
|
|
bytes: []byte(s.rbound),
|
|
}
|
|
bf.components[iFiller] = &component{
|
|
width: runewidth.StringWidth(stripansi.Strip(s.filler)),
|
|
bytes: []byte(s.filler),
|
|
}
|
|
bf.components[iRefiller] = &component{
|
|
width: runewidth.StringWidth(stripansi.Strip(s.refiller)),
|
|
bytes: []byte(s.refiller),
|
|
}
|
|
bf.components[iPadding] = &component{
|
|
width: runewidth.StringWidth(stripansi.Strip(s.padding)),
|
|
bytes: []byte(s.padding),
|
|
}
|
|
bf.tip.onComplete = &component{
|
|
width: runewidth.StringWidth(stripansi.Strip(s.tipOnComplete)),
|
|
bytes: []byte(s.tipOnComplete),
|
|
}
|
|
bf.tip.frames = make([]*component, len(s.tipFrames))
|
|
for i, t := range s.tipFrames {
|
|
bf.tip.frames[i] = &component{
|
|
width: runewidth.StringWidth(stripansi.Strip(t)),
|
|
bytes: []byte(t),
|
|
}
|
|
}
|
|
return bf
|
|
}
|
|
|
|
func (s *bFiller) Fill(w io.Writer, stat decor.Statistics) (err error) {
|
|
width := internal.CheckRequestedWidth(stat.RequestedWidth, stat.AvailableWidth)
|
|
// don't count brackets as progress
|
|
width -= (s.components[iLbound].width + s.components[iRbound].width)
|
|
if width < 0 {
|
|
return nil
|
|
}
|
|
|
|
_, err = w.Write(s.components[iLbound].bytes)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if width == 0 {
|
|
_, err = w.Write(s.components[iRbound].bytes)
|
|
return err
|
|
}
|
|
|
|
var filling [][]byte
|
|
var padding [][]byte
|
|
var tip *component
|
|
var filled int
|
|
var refWidth int
|
|
curWidth := int(internal.PercentageRound(stat.Total, stat.Current, uint(width)))
|
|
|
|
if stat.Completed {
|
|
tip = s.tip.onComplete
|
|
} else {
|
|
tip = s.tip.frames[s.tip.count%uint(len(s.tip.frames))]
|
|
}
|
|
|
|
if curWidth > 0 {
|
|
filling = append(filling, tip.bytes)
|
|
filled += tip.width
|
|
s.tip.count++
|
|
}
|
|
|
|
if stat.Refill > 0 {
|
|
refWidth = int(internal.PercentageRound(stat.Total, stat.Refill, uint(width)))
|
|
curWidth -= refWidth
|
|
refWidth += curWidth
|
|
}
|
|
|
|
for filled < curWidth {
|
|
if curWidth-filled >= s.components[iFiller].width {
|
|
filling = append(filling, s.components[iFiller].bytes)
|
|
if s.components[iFiller].width == 0 {
|
|
break
|
|
}
|
|
filled += s.components[iFiller].width
|
|
} else {
|
|
filling = append(filling, []byte("…"))
|
|
filled++
|
|
}
|
|
}
|
|
|
|
for filled < refWidth {
|
|
if refWidth-filled >= s.components[iRefiller].width {
|
|
filling = append(filling, s.components[iRefiller].bytes)
|
|
if s.components[iRefiller].width == 0 {
|
|
break
|
|
}
|
|
filled += s.components[iRefiller].width
|
|
} else {
|
|
filling = append(filling, []byte("…"))
|
|
filled++
|
|
}
|
|
}
|
|
|
|
padWidth := width - filled
|
|
for padWidth > 0 {
|
|
if padWidth >= s.components[iPadding].width {
|
|
padding = append(padding, s.components[iPadding].bytes)
|
|
if s.components[iPadding].width == 0 {
|
|
break
|
|
}
|
|
padWidth -= s.components[iPadding].width
|
|
} else {
|
|
padding = append(padding, []byte("…"))
|
|
padWidth--
|
|
}
|
|
}
|
|
|
|
if s.rev {
|
|
filling, padding = padding, filling
|
|
}
|
|
err = flush(w, filling, padding)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = w.Write(s.components[iRbound].bytes)
|
|
return err
|
|
}
|
|
|
|
func flush(w io.Writer, filling, padding [][]byte) error {
|
|
for i := len(filling) - 1; i >= 0; i-- {
|
|
_, err := w.Write(filling[i])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for i := 0; i < len(padding); i++ {
|
|
_, err := w.Write(padding[i])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|