diff options
author | Michael Muré <batolettre@gmail.com> | 2023-01-10 21:36:03 +0100 |
---|---|---|
committer | Michael Muré <batolettre@gmail.com> | 2023-01-11 14:31:22 +0100 |
commit | 7df34aa7a40be0d7b759ea3ef42cedf9f25f32b2 (patch) | |
tree | a3d1cc77f56814d4ec8838f18cb6768035c1b290 /commands | |
parent | 9c50a359704f4edd2f33df6d256e032feae3a576 (diff) | |
download | git-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.go | 63 | ||||
-rw-r--r-- | commands/execenv/env_testing.go | 7 | ||||
-rw-r--r-- | commands/webui.go | 17 |
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 |