mirror of
https://github.com/mudler/luet.git
synced 2025-09-18 16:32:16 +00:00
Show progressbar only if terminal is big enough
Fixes #259
The bug is caused by
4c725e56bf/progressbar_printer.go (L190)
which is not taking into account when barCurrentLength is <=0.
As a workaround display it only if the terminal width is big enough.
Now the context drives this kind of runtime state, so we keep everything
tight and we inject only that into the workers
This commit is contained in:
@@ -28,9 +28,11 @@ import (
|
||||
|
||||
"github.com/kyokomi/emoji"
|
||||
"github.com/mudler/luet/pkg/helpers/terminal"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pterm/pterm"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -48,13 +50,16 @@ type Context struct {
|
||||
NoSpinner bool
|
||||
|
||||
s *pterm.SpinnerPrinter
|
||||
spinnerLock sync.Mutex
|
||||
spinnerLock *sync.Mutex
|
||||
z *zap.Logger
|
||||
AreaPrinter *pterm.AreaPrinter
|
||||
ProgressBar *pterm.ProgressbarPrinter
|
||||
}
|
||||
|
||||
func NewContext() *Context {
|
||||
return &Context{
|
||||
IsTerminal: terminal.IsTerminal(os.Stdout),
|
||||
spinnerLock: &sync.Mutex{},
|
||||
IsTerminal: terminal.IsTerminal(os.Stdout),
|
||||
Config: &LuetConfig{
|
||||
ConfigFromHost: true,
|
||||
Logging: LuetLoggingConfig{},
|
||||
@@ -68,6 +73,35 @@ func NewContext() *Context {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Context) Copy() *Context {
|
||||
|
||||
configCopy := *c.Config
|
||||
configCopy.System = *c.Config.GetSystem()
|
||||
configCopy.General = *c.Config.GetGeneral()
|
||||
configCopy.Logging = *c.Config.GetLogging()
|
||||
|
||||
ctx := *c
|
||||
ctxCopy := &ctx
|
||||
ctxCopy.Config = &configCopy
|
||||
|
||||
return ctxCopy
|
||||
}
|
||||
|
||||
// GetTerminalSize returns the width and the height of the active terminal.
|
||||
func (c *Context) GetTerminalSize() (width, height int, err error) {
|
||||
w, h, err := term.GetSize(int(os.Stdout.Fd()))
|
||||
if w <= 0 {
|
||||
w = 0
|
||||
}
|
||||
if h <= 0 {
|
||||
h = 0
|
||||
}
|
||||
if err != nil {
|
||||
err = errors.New("size not detectable")
|
||||
}
|
||||
return w, h, err
|
||||
}
|
||||
|
||||
func (c *Context) Init() (err error) {
|
||||
if c.IsTerminal {
|
||||
if !c.Config.Logging.Color {
|
||||
|
@@ -38,8 +38,6 @@ type HttpClient struct {
|
||||
RepoData RepoData
|
||||
Cache *artifact.ArtifactCache
|
||||
context *types.Context
|
||||
|
||||
ProgressBarArea *pterm.AreaPrinter
|
||||
}
|
||||
|
||||
func NewHttpClient(r RepoData, ctx *types.Context) *HttpClient {
|
||||
@@ -126,11 +124,16 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
|
||||
}
|
||||
|
||||
resp := client.Do(req)
|
||||
pb := pterm.DefaultProgressbar.WithTotal(int(resp.Size()))
|
||||
if c.ProgressBarArea != nil {
|
||||
pb = pb.WithPrintTogether(c.ProgressBarArea)
|
||||
|
||||
// Initialize a progressbar only if we have one in the current context
|
||||
var pb *pterm.ProgressbarPrinter
|
||||
if c.context.ProgressBar != nil {
|
||||
pb = pterm.DefaultProgressbar.WithTotal(int(resp.Size()))
|
||||
if c.context.AreaPrinter != nil {
|
||||
pb = pb.WithPrintTogether(c.context.AreaPrinter)
|
||||
}
|
||||
pb, _ = pb.WithTitle(filepath.Base(resp.Request.HTTPRequest.URL.RequestURI())).Start()
|
||||
}
|
||||
pb, _ = pb.WithTitle(filepath.Base(resp.Request.HTTPRequest.URL.RequestURI())).Start()
|
||||
// start download loop
|
||||
t := time.NewTicker(500 * time.Millisecond)
|
||||
defer t.Stop()
|
||||
@@ -140,11 +143,15 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
|
||||
for {
|
||||
select {
|
||||
case <-t.C:
|
||||
// bar.Set64(resp.BytesComplete())
|
||||
//pb.Increment()
|
||||
pb.Increment().Current = int(resp.BytesComplete())
|
||||
// update the progress bar
|
||||
if pb != nil {
|
||||
pb.Increment().Current = int(resp.BytesComplete())
|
||||
}
|
||||
case <-resp.Done:
|
||||
pb.Increment().Current = int(resp.BytesComplete())
|
||||
// update the progress bar
|
||||
if pb != nil {
|
||||
pb.Increment().Current = int(resp.BytesComplete())
|
||||
}
|
||||
// download is complete
|
||||
break download_loop
|
||||
}
|
||||
@@ -157,7 +164,11 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
|
||||
c.context.Info("Downloaded", p, "of",
|
||||
fmt.Sprintf("%.2f", (float64(resp.BytesComplete())/1000)/1000), "MB (",
|
||||
fmt.Sprintf("%.2f", (float64(resp.BytesPerSecond())/1024)/1024), "MiB/s )")
|
||||
pb.Stop()
|
||||
|
||||
if pb != nil {
|
||||
// stop the progressbar if active
|
||||
pb.Stop()
|
||||
}
|
||||
//bar.Finish()
|
||||
downloaded = true
|
||||
break
|
||||
|
@@ -32,7 +32,6 @@ import (
|
||||
"github.com/mudler/luet/pkg/helpers"
|
||||
fileHelper "github.com/mudler/luet/pkg/helpers/file"
|
||||
"github.com/mudler/luet/pkg/helpers/match"
|
||||
"github.com/mudler/luet/pkg/installer/client"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
"github.com/mudler/luet/pkg/solver"
|
||||
"github.com/pterm/pterm"
|
||||
@@ -566,21 +565,30 @@ func (l *LuetInstaller) download(syncedRepos Repositories, toDownload map[string
|
||||
|
||||
var wg = new(sync.WaitGroup)
|
||||
|
||||
area, _ := pterm.DefaultArea.Start()
|
||||
ctx := l.Options.Context.Copy()
|
||||
|
||||
p, _ := pterm.DefaultProgressbar.WithPrintTogether(area).WithTotal(len(toDownload)).WithTitle("Downloading packages").Start()
|
||||
// Check if the terminal is big enough to display a progress bar
|
||||
// https://github.com/pterm/pterm/blob/4c725e56bfd9eb38e1c7b9dec187b50b93baa8bd/progressbar_printer.go#L190
|
||||
w, _, err := ctx.GetTerminalSize()
|
||||
if ctx.IsTerminal && err == nil && w > 100 {
|
||||
area, _ := pterm.DefaultArea.Start()
|
||||
p, _ := pterm.DefaultProgressbar.WithPrintTogether(area).WithTotal(len(toDownload)).WithTitle("Downloading packages").Start()
|
||||
|
||||
ctx.AreaPrinter = area
|
||||
ctx.ProgressBar = p
|
||||
defer area.Stop()
|
||||
}
|
||||
|
||||
// Download
|
||||
for i := 0; i < l.Options.Concurrency; i++ {
|
||||
wg.Add(1)
|
||||
go l.downloadWorker(i, wg, all, p, area)
|
||||
go l.downloadWorker(i, wg, all, ctx)
|
||||
}
|
||||
for _, c := range toDownload {
|
||||
all <- c
|
||||
}
|
||||
close(all)
|
||||
wg.Wait()
|
||||
area.Stop()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -772,7 +780,7 @@ func (l *LuetInstaller) checkFileconflicts(toInstall map[string]ArtifactMatch, c
|
||||
|
||||
filesToInstall := []string{}
|
||||
for _, m := range toInstall {
|
||||
a, err := l.downloadPackage(m, nil)
|
||||
a, err := l.downloadPackage(m, l.Options.Context)
|
||||
if err != nil && !l.Options.Force {
|
||||
return errors.Wrap(err, "Failed downloading package")
|
||||
}
|
||||
@@ -867,14 +875,9 @@ func (l *LuetInstaller) install(o Option, syncedRepos Repositories, toInstall ma
|
||||
return s.ExecuteFinalizers(l.Options.Context, toFinalize)
|
||||
}
|
||||
|
||||
func (l *LuetInstaller) downloadPackage(a ArtifactMatch, area *pterm.AreaPrinter) (*artifact.PackageArtifact, error) {
|
||||
func (l *LuetInstaller) downloadPackage(a ArtifactMatch, ctx *types.Context) (*artifact.PackageArtifact, error) {
|
||||
|
||||
cli := a.Repository.Client(l.Options.Context)
|
||||
|
||||
switch v := cli.(type) {
|
||||
case *client.HttpClient:
|
||||
v.ProgressBarArea = area
|
||||
}
|
||||
cli := a.Repository.Client(ctx)
|
||||
|
||||
artifact, err := cli.DownloadArtifact(a.Artifact)
|
||||
if err != nil {
|
||||
@@ -890,7 +893,7 @@ func (l *LuetInstaller) downloadPackage(a ArtifactMatch, area *pterm.AreaPrinter
|
||||
|
||||
func (l *LuetInstaller) installPackage(m ArtifactMatch, s *System) error {
|
||||
|
||||
a, err := l.downloadPackage(m, nil)
|
||||
a, err := l.downloadPackage(m, l.Options.Context)
|
||||
if err != nil && !l.Options.Force {
|
||||
return errors.Wrap(err, "Failed downloading package")
|
||||
}
|
||||
@@ -910,20 +913,21 @@ func (l *LuetInstaller) installPackage(m ArtifactMatch, s *System) error {
|
||||
return s.Database.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: m.Package.GetFingerPrint(), Files: files})
|
||||
}
|
||||
|
||||
func (l *LuetInstaller) downloadWorker(i int, wg *sync.WaitGroup, c <-chan ArtifactMatch, pb *pterm.ProgressbarPrinter, area *pterm.AreaPrinter) error {
|
||||
func (l *LuetInstaller) downloadWorker(i int, wg *sync.WaitGroup, c <-chan ArtifactMatch, ctx *types.Context) error {
|
||||
defer wg.Done()
|
||||
|
||||
for p := range c {
|
||||
// TODO: Keep trace of what was added from the tar, and save it into system
|
||||
_, err := l.downloadPackage(p, area)
|
||||
_, err := l.downloadPackage(p, ctx)
|
||||
if err != nil {
|
||||
l.Options.Context.Error("Failed downloading package "+p.Package.GetName(), err.Error())
|
||||
return errors.Wrap(err, "Failed downloading package "+p.Package.GetName())
|
||||
} else {
|
||||
l.Options.Context.Success(":package: Package ", p.Package.HumanReadableString(), "downloaded")
|
||||
}
|
||||
pb.Increment()
|
||||
|
||||
if ctx.ProgressBar != nil {
|
||||
ctx.ProgressBar.Increment()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
Reference in New Issue
Block a user