mirror of
https://github.com/mudler/luet.git
synced 2025-09-20 10:46: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/kyokomi/emoji"
|
||||||
"github.com/mudler/luet/pkg/helpers/terminal"
|
"github.com/mudler/luet/pkg/helpers/terminal"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/pterm/pterm"
|
"github.com/pterm/pterm"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"go.uber.org/zap/zapcore"
|
"go.uber.org/zap/zapcore"
|
||||||
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -48,13 +50,16 @@ type Context struct {
|
|||||||
NoSpinner bool
|
NoSpinner bool
|
||||||
|
|
||||||
s *pterm.SpinnerPrinter
|
s *pterm.SpinnerPrinter
|
||||||
spinnerLock sync.Mutex
|
spinnerLock *sync.Mutex
|
||||||
z *zap.Logger
|
z *zap.Logger
|
||||||
|
AreaPrinter *pterm.AreaPrinter
|
||||||
|
ProgressBar *pterm.ProgressbarPrinter
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContext() *Context {
|
func NewContext() *Context {
|
||||||
return &Context{
|
return &Context{
|
||||||
IsTerminal: terminal.IsTerminal(os.Stdout),
|
spinnerLock: &sync.Mutex{},
|
||||||
|
IsTerminal: terminal.IsTerminal(os.Stdout),
|
||||||
Config: &LuetConfig{
|
Config: &LuetConfig{
|
||||||
ConfigFromHost: true,
|
ConfigFromHost: true,
|
||||||
Logging: LuetLoggingConfig{},
|
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) {
|
func (c *Context) Init() (err error) {
|
||||||
if c.IsTerminal {
|
if c.IsTerminal {
|
||||||
if !c.Config.Logging.Color {
|
if !c.Config.Logging.Color {
|
||||||
|
@@ -38,8 +38,6 @@ type HttpClient struct {
|
|||||||
RepoData RepoData
|
RepoData RepoData
|
||||||
Cache *artifact.ArtifactCache
|
Cache *artifact.ArtifactCache
|
||||||
context *types.Context
|
context *types.Context
|
||||||
|
|
||||||
ProgressBarArea *pterm.AreaPrinter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHttpClient(r RepoData, ctx *types.Context) *HttpClient {
|
func NewHttpClient(r RepoData, ctx *types.Context) *HttpClient {
|
||||||
@@ -126,11 +124,16 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resp := client.Do(req)
|
resp := client.Do(req)
|
||||||
pb := pterm.DefaultProgressbar.WithTotal(int(resp.Size()))
|
|
||||||
if c.ProgressBarArea != nil {
|
// Initialize a progressbar only if we have one in the current context
|
||||||
pb = pb.WithPrintTogether(c.ProgressBarArea)
|
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
|
// start download loop
|
||||||
t := time.NewTicker(500 * time.Millisecond)
|
t := time.NewTicker(500 * time.Millisecond)
|
||||||
defer t.Stop()
|
defer t.Stop()
|
||||||
@@ -140,11 +143,15 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-t.C:
|
case <-t.C:
|
||||||
// bar.Set64(resp.BytesComplete())
|
// update the progress bar
|
||||||
//pb.Increment()
|
if pb != nil {
|
||||||
pb.Increment().Current = int(resp.BytesComplete())
|
pb.Increment().Current = int(resp.BytesComplete())
|
||||||
|
}
|
||||||
case <-resp.Done:
|
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
|
// download is complete
|
||||||
break download_loop
|
break download_loop
|
||||||
}
|
}
|
||||||
@@ -157,7 +164,11 @@ func (c *HttpClient) DownloadFile(p string) (string, error) {
|
|||||||
c.context.Info("Downloaded", p, "of",
|
c.context.Info("Downloaded", p, "of",
|
||||||
fmt.Sprintf("%.2f", (float64(resp.BytesComplete())/1000)/1000), "MB (",
|
fmt.Sprintf("%.2f", (float64(resp.BytesComplete())/1000)/1000), "MB (",
|
||||||
fmt.Sprintf("%.2f", (float64(resp.BytesPerSecond())/1024)/1024), "MiB/s )")
|
fmt.Sprintf("%.2f", (float64(resp.BytesPerSecond())/1024)/1024), "MiB/s )")
|
||||||
pb.Stop()
|
|
||||||
|
if pb != nil {
|
||||||
|
// stop the progressbar if active
|
||||||
|
pb.Stop()
|
||||||
|
}
|
||||||
//bar.Finish()
|
//bar.Finish()
|
||||||
downloaded = true
|
downloaded = true
|
||||||
break
|
break
|
||||||
|
@@ -32,7 +32,6 @@ import (
|
|||||||
"github.com/mudler/luet/pkg/helpers"
|
"github.com/mudler/luet/pkg/helpers"
|
||||||
fileHelper "github.com/mudler/luet/pkg/helpers/file"
|
fileHelper "github.com/mudler/luet/pkg/helpers/file"
|
||||||
"github.com/mudler/luet/pkg/helpers/match"
|
"github.com/mudler/luet/pkg/helpers/match"
|
||||||
"github.com/mudler/luet/pkg/installer/client"
|
|
||||||
pkg "github.com/mudler/luet/pkg/package"
|
pkg "github.com/mudler/luet/pkg/package"
|
||||||
"github.com/mudler/luet/pkg/solver"
|
"github.com/mudler/luet/pkg/solver"
|
||||||
"github.com/pterm/pterm"
|
"github.com/pterm/pterm"
|
||||||
@@ -566,21 +565,30 @@ func (l *LuetInstaller) download(syncedRepos Repositories, toDownload map[string
|
|||||||
|
|
||||||
var wg = new(sync.WaitGroup)
|
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
|
// Download
|
||||||
for i := 0; i < l.Options.Concurrency; i++ {
|
for i := 0; i < l.Options.Concurrency; i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go l.downloadWorker(i, wg, all, p, area)
|
go l.downloadWorker(i, wg, all, ctx)
|
||||||
}
|
}
|
||||||
for _, c := range toDownload {
|
for _, c := range toDownload {
|
||||||
all <- c
|
all <- c
|
||||||
}
|
}
|
||||||
close(all)
|
close(all)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
area.Stop()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -772,7 +780,7 @@ func (l *LuetInstaller) checkFileconflicts(toInstall map[string]ArtifactMatch, c
|
|||||||
|
|
||||||
filesToInstall := []string{}
|
filesToInstall := []string{}
|
||||||
for _, m := range toInstall {
|
for _, m := range toInstall {
|
||||||
a, err := l.downloadPackage(m, nil)
|
a, err := l.downloadPackage(m, l.Options.Context)
|
||||||
if err != nil && !l.Options.Force {
|
if err != nil && !l.Options.Force {
|
||||||
return errors.Wrap(err, "Failed downloading package")
|
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)
|
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)
|
cli := a.Repository.Client(ctx)
|
||||||
|
|
||||||
switch v := cli.(type) {
|
|
||||||
case *client.HttpClient:
|
|
||||||
v.ProgressBarArea = area
|
|
||||||
}
|
|
||||||
|
|
||||||
artifact, err := cli.DownloadArtifact(a.Artifact)
|
artifact, err := cli.DownloadArtifact(a.Artifact)
|
||||||
if err != nil {
|
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 {
|
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 {
|
if err != nil && !l.Options.Force {
|
||||||
return errors.Wrap(err, "Failed downloading package")
|
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})
|
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()
|
defer wg.Done()
|
||||||
|
|
||||||
for p := range c {
|
for p := range c {
|
||||||
// TODO: Keep trace of what was added from the tar, and save it into system
|
// 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 {
|
if err != nil {
|
||||||
l.Options.Context.Error("Failed downloading package "+p.Package.GetName(), err.Error())
|
l.Options.Context.Error("Failed downloading package "+p.Package.GetName(), err.Error())
|
||||||
return errors.Wrap(err, "Failed downloading package "+p.Package.GetName())
|
return errors.Wrap(err, "Failed downloading package "+p.Package.GetName())
|
||||||
} else {
|
} else {
|
||||||
l.Options.Context.Success(":package: Package ", p.Package.HumanReadableString(), "downloaded")
|
l.Options.Context.Success(":package: Package ", p.Package.HumanReadableString(), "downloaded")
|
||||||
}
|
}
|
||||||
pb.Increment()
|
if ctx.ProgressBar != nil {
|
||||||
|
ctx.ProgressBar.Increment()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
Reference in New Issue
Block a user