aboutsummaryrefslogtreecommitdiffstats
path: root/commands
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2023-01-10 21:36:03 +0100
committerMichael Muré <batolettre@gmail.com>2023-01-11 14:31:22 +0100
commit7df34aa7a40be0d7b759ea3ef42cedf9f25f32b2 (patch)
treea3d1cc77f56814d4ec8838f18cb6768035c1b290 /commands
parent9c50a359704f4edd2f33df6d256e032feae3a576 (diff)
downloadgit-bug-7df34aa7a40be0d7b759ea3ef42cedf9f25f32b2.tar.gz
commands: add a nice terminal progress bar when building the cache
One issue remaining is that writing the cache takes significant time, but I don't know how to reflect that nicely to the user.
Diffstat (limited to 'commands')
-rw-r--r--commands/execenv/env.go63
-rw-r--r--commands/execenv/env_testing.go7
-rw-r--r--commands/webui.go17
3 files changed, 62 insertions, 25 deletions
diff --git a/commands/execenv/env.go b/commands/execenv/env.go
index 4be7c247..d2d1c301 100644
--- a/commands/execenv/env.go
+++ b/commands/execenv/env.go
@@ -7,6 +7,8 @@ import (
"os"
"github.com/spf13/cobra"
+ "github.com/vbauerster/mpb/v8"
+ "github.com/vbauerster/mpb/v8/decor"
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/entities/identity"
@@ -50,6 +52,10 @@ type Out interface {
// Reset clear what has been recorded as written in the output before.
// This only works in test scenario.
Reset()
+
+ // Raw return the underlying io.Writer, or itself if not.
+ // This is useful if something need to access the raw file descriptor.
+ Raw() io.Writer
}
type out struct {
@@ -89,6 +95,10 @@ func (o out) Reset() {
panic("only work with a test env")
}
+func (o out) Raw() io.Writer {
+ return o.Writer
+}
+
// LoadRepo is a pre-run function that load the repository for use in a command
func LoadRepo(env *Env) func(*cobra.Command, []string) error {
return func(cmd *cobra.Command, args []string) error {
@@ -143,18 +153,9 @@ func LoadBackend(env *Env) func(*cobra.Command, []string) error {
var events chan cache.BuildEvent
env.Backend, events = cache.NewRepoCache(env.Repo)
- for event := range events {
- if event.Err != nil {
- return event.Err
- }
- switch event.Event {
- case cache.BuildEventCacheIsBuilt:
- env.Err.Println("Building cache... ")
- case cache.BuildEventStarted:
- env.Err.Printf("[%s] started\n", event.Typename)
- case cache.BuildEventFinished:
- env.Err.Printf("[%s] done\n", event.Typename)
- }
+ err = CacheBuildProgressBar(env, events)
+ if err != nil {
+ return err
}
cleaner := func(env *Env) interrupt.CleanerFunc {
@@ -213,3 +214,41 @@ func CloseBackend(env *Env, runE func(cmd *cobra.Command, args []string) error)
return err
}
}
+
+func CacheBuildProgressBar(env *Env, events chan cache.BuildEvent) error {
+ var progress *mpb.Progress
+ var bars = make(map[string]*mpb.Bar)
+
+ for event := range events {
+ if event.Err != nil {
+ return event.Err
+ }
+
+ if progress == nil {
+ progress = mpb.New(mpb.WithOutput(env.Err.Raw()))
+ }
+
+ switch event.Event {
+ case cache.BuildEventCacheIsBuilt:
+ env.Err.Println("Building cache... ")
+ case cache.BuildEventStarted:
+ bars[event.Typename] = progress.AddBar(-1,
+ mpb.BarRemoveOnComplete(),
+ mpb.PrependDecorators(
+ decor.Name(event.Typename, decor.WCSyncSpace),
+ decor.CountersNoUnit("%d / %d", decor.WCSyncSpace),
+ ),
+ mpb.AppendDecorators(decor.Percentage(decor.WCSyncSpace)),
+ )
+ case cache.BuildEventProgress:
+ bars[event.Typename].SetTotal(event.Total, false)
+ bars[event.Typename].SetCurrent(event.Progress)
+ }
+ }
+
+ if progress != nil {
+ progress.Shutdown()
+ }
+
+ return nil
+}
diff --git a/commands/execenv/env_testing.go b/commands/execenv/env_testing.go
index 34eafc9c..6eb9c69d 100644
--- a/commands/execenv/env_testing.go
+++ b/commands/execenv/env_testing.go
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
+ "io"
"testing"
"github.com/stretchr/testify/require"
@@ -12,6 +13,8 @@ import (
"github.com/MichaelMure/git-bug/repository"
)
+var _ Out = &TestOut{}
+
type TestOut struct {
*bytes.Buffer
}
@@ -37,6 +40,10 @@ func (te *TestOut) PrintJSON(v interface{}) error {
return nil
}
+func (te *TestOut) Raw() io.Writer {
+ return te.Buffer
+}
+
func NewTestEnv(t *testing.T) *Env {
t.Helper()
diff --git a/commands/webui.go b/commands/webui.go
index 0b3b24a6..31313146 100644
--- a/commands/webui.go
+++ b/commands/webui.go
@@ -108,19 +108,10 @@ func runWebUI(env *execenv.Env, opts webUIOptions) error {
mrc := cache.NewMultiRepoCache()
_, events := mrc.RegisterDefaultRepository(env.Repo)
- for event := range events {
- if event.Err != nil {
- env.Err.Printf("Cache building error [%s]: %v\n", event.Typename, event.Err)
- continue
- }
- switch event.Event {
- case cache.BuildEventCacheIsBuilt:
- env.Err.Println("Building cache... ")
- case cache.BuildEventStarted:
- env.Err.Printf("[%s] started\n", event.Typename)
- case cache.BuildEventFinished:
- env.Err.Printf("[%s] done\n", event.Typename)
- }
+
+ err := execenv.CacheBuildProgressBar(env, events)
+ if err != nil {
+ return err
}
var errOut io.Writer