diff options
| author | İbrahim Serdar Açıkgöz <serdaracikgoz86@gmail.com> | 2018-11-20 15:08:47 +0300 |
|---|---|---|
| committer | İbrahim Serdar Açıkgöz <serdaracikgoz86@gmail.com> | 2018-11-20 15:08:47 +0300 |
| commit | fa0779f51bb6855acf6bdf5e01a599596a44d1dd (patch) | |
| tree | ebdd0136a050eefba233daaa22e13c1b551a7762 | |
| parent | added select/deselect all (diff) | |
| download | gitbatch-fa0779f51bb6855acf6bdf5e01a599596a44d1dd.tar.gz | |
refactor and performance improvements
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | pkg/app/app.go | 42 | ||||
| -rw-r--r-- | pkg/git/git-commands.go | 13 | ||||
| -rw-r--r-- | pkg/git/model.go (renamed from pkg/git/git.go) | 74 | ||||
| -rw-r--r-- | pkg/git/repository.go | 65 | ||||
| -rw-r--r-- | pkg/gui/gui-util.go | 19 | ||||
| -rw-r--r-- | pkg/gui/gui.go | 4 | ||||
| -rw-r--r-- | pkg/gui/keybindings.go | 3 |
8 files changed, 156 insertions, 65 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8c11484 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +exec.go.test diff --git a/pkg/app/app.go b/pkg/app/app.go index 83231a5..241217f 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -4,6 +4,9 @@ import ( "github.com/isacikgoz/gitbatch/pkg/gui" "github.com/isacikgoz/gitbatch/pkg/git" "io" + "log" + "sync" + "time" ) // App struct @@ -43,12 +46,39 @@ func (app *App) Close() error { func createRepositoryEntities(directories []string) (entities []*git.RepoEntity, err error) { entities = make([]*git.RepoEntity, 0) + + var wg sync.WaitGroup + var mu sync.Mutex + + start := time.Now() for _, dir := range directories { - entity, err := git.InitializeRepository(dir) - if err != nil { - continue - } - entities = append(entities, entity) + // increment wait counter by one because we run a single goroutine + // below + wg.Add(1) + + go func(d string) { + + // decrement the wait counter by one, we call it in a defer so it's + // called at the end of this goroutine + defer wg.Done() + entity, err := git.InitializeRepository(d) + if err != nil { + return + } + + // lock so we don't get a race if multiple go routines try to add + // to the same entities + mu.Lock() + entities = append(entities, entity) + mu.Unlock() + }(dir) } + + // wait until the wait counter is zero, this happens if all goroutines have + // finished + wg.Wait() + + elapsed := time.Since(start) + log.Printf("Finished collecting entities, elapsed time: %s\n", elapsed) return entities, nil -} +}
\ No newline at end of file diff --git a/pkg/git/git-commands.go b/pkg/git/git-commands.go index 9d33bec..a871356 100644 --- a/pkg/git/git-commands.go +++ b/pkg/git/git-commands.go @@ -6,6 +6,7 @@ import ( "github.com/isacikgoz/gitbatch/pkg/utils" ) + // UpstreamDifferenceCount checks how many pushables/pullables there are for the // current branch func UpstreamDifferenceCount(repoPath string) (string, string) { @@ -33,4 +34,16 @@ func CurrentBranchName(repoPath string) (string, error) { } } return utils.TrimTrailingNewline(branchName), nil +} + +func (entity *RepoEntity) IsClean() (bool, error) { + worktree, err := entity.Repository.Worktree() + if err != nil { + return true, nil + } + status, err := worktree.Status() + if err != nil { + return status.IsClean(), nil + } + return false, nil }
\ No newline at end of file diff --git a/pkg/git/git.go b/pkg/git/model.go index db7af8f..d5182c0 100644 --- a/pkg/git/git.go +++ b/pkg/git/model.go @@ -5,38 +5,21 @@ import ( "github.com/isacikgoz/gitbatch/pkg/utils" "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing/object" - "os" "regexp" ) -type RepoEntity struct { - Name string - AbsPath string - Repository git.Repository - Pushables string - Pullables string - Branch string - Marked bool -} +func (entity *RepoEntity) GetRemotes() (remotes []string, err error) { + r := entity.Repository -func InitializeRepository(directory string) (entity *RepoEntity, err error) { - file, err := os.Open(directory) - if err != nil { - return entity, err - } - fileInfo, err := file.Stat() - if err != nil { - return entity, err - } - r, err := git.PlainOpen(directory) - if err != nil { - return entity, err - } - pushable, pullable := UpstreamDifferenceCount(directory) - branch, err := CurrentBranchName(directory) - entity = &RepoEntity{fileInfo.Name(), directory, *r, pushable, pullable, branch, false} - - return entity, nil + if list, err := r.Remotes(); err != nil { + return remotes, err + } else { + for _, r := range list { + remoteString := r.Config().Name + " → " + r.Config().URLs[0] + remotes = append(remotes, remoteString) + } + } + return remotes, nil } func (entity *RepoEntity) GetCommits() (commits []string, err error) { @@ -64,20 +47,6 @@ func (entity *RepoEntity) GetCommits() (commits []string, err error) { return commits, nil } -func (entity *RepoEntity) GetRemotes() (remotes []string, err error) { - r := entity.Repository - - if list, err := r.Remotes(); err != nil { - return remotes, err - } else { - for _, r := range list { - remoteString := r.Config().Name + " → " + r.Config().URLs[0] - remotes = append(remotes, remoteString) - } - } - return remotes, nil -} - func (entity *RepoEntity) GetStatus() (status string) { status = "↑ " + entity.Pushables + " ↓ " + entity.Pullables + " → " + entity.Branch re := regexp.MustCompile(`\r?\n`) @@ -85,12 +54,15 @@ func (entity *RepoEntity) GetStatus() (status string) { return status } -func (entity *RepoEntity) Mark() { - entity.Marked = true -} - -func (entity *RepoEntity) UnMark() { - entity.Marked = false -} - - +func (entity *RepoEntity) GetDisplayString() string{ + if entity.Marked { + green := color.New(color.FgGreen) + return string(green.Sprint(entity.Name)) + } else if !entity.Clean { + orange := color.New(color.FgYellow) + return string(orange.Sprint(entity.Name)) + } else { + white := color.New(color.FgWhite) + return string(white.Sprint(entity.Name)) + } +}
\ No newline at end of file diff --git a/pkg/git/repository.go b/pkg/git/repository.go new file mode 100644 index 0000000..56c0f2f --- /dev/null +++ b/pkg/git/repository.go @@ -0,0 +1,65 @@ +package git + +import ( + "gopkg.in/src-d/go-git.v4" + "os" +) + +type RepoEntity struct { + Name string + AbsPath string + Repository git.Repository + Pushables string + Pullables string + Branch string + Marked bool + Clean bool +} + +func InitializeRepository(directory string) (entity *RepoEntity, err error) { + file, err := os.Open(directory) + if err != nil { + return nil, err + } + fileInfo, err := file.Stat() + if err != nil { + return nil, err + } + r, err := git.PlainOpen(directory) + if err != nil { + return nil, err + } + pushable, pullable := UpstreamDifferenceCount(directory) + branch, err := CurrentBranchName(directory) + + entity = &RepoEntity{fileInfo.Name(), directory, *r, pushable, pullable, branch, false, isClean(r, fileInfo.Name())} + + return entity, nil +} + +func isClean(r *git.Repository, name string) bool { + w, err := r.Worktree() + if err != nil { + return false + } + // TODO: This function is incredibly slow + s, err := w.Status() + if err != nil { + return false + } + return s.IsClean() +} + +func (entity *RepoEntity) Mark() { + entity.Marked = true +} + +func (entity *RepoEntity) UnMark() { + entity.Marked = false +} + +func (entity *RepoEntity) Pull() error { + return nil +} + + diff --git a/pkg/gui/gui-util.go b/pkg/gui/gui-util.go index 50de1d9..d9505dd 100644 --- a/pkg/gui/gui-util.go +++ b/pkg/gui/gui-util.go @@ -2,7 +2,6 @@ package gui import ( "fmt" - "github.com/fatih/color" "github.com/isacikgoz/gitbatch/pkg/utils" "github.com/isacikgoz/gitbatch/pkg/git" "github.com/jroimartin/gocui" @@ -141,11 +140,7 @@ func (gui *Gui) refreshMain(g *gocui.Gui) error { } mainView.Clear() for _, r := range gui.Repositories { - if r.Marked { - fmt.Fprintln(mainView, utils.ColoredString(r.Name, color.FgGreen)) - } else { - fmt.Fprintln(mainView, r.Name) - } + fmt.Fprintln(mainView, r.GetDisplayString()) } return nil } @@ -188,4 +183,16 @@ func (gui *Gui) getScheduleView(g *gocui.Gui) *gocui.View { func (gui *Gui) getStatusView(g *gocui.Gui) *gocui.View { v, _ := g.View("status") return v +} + +func (gui *Gui) execute(g *gocui.Gui, v *gocui.View) error { + for _, r := range gui.Repositories { + if err := r.Pull(); err != nil { + return err + } + r.UnMark() + gui.refreshMain(g) + gui.updateSchedule(g) + } + return nil }
\ No newline at end of file diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 72cf1c6..3ccc203 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -36,7 +36,7 @@ func (gui *Gui) layout(g *gocui.Gui) error { v.SelFgColor = gocui.ColorBlack v.Overwrite = true for _, r := range gui.Repositories { - fmt.Fprintln(v, r.Name) + fmt.Fprintln(v, r.GetDisplayString()) } if _, err = gui.setCurrentViewOnTop(g, "main"); err != nil { @@ -87,7 +87,7 @@ func (gui *Gui) layout(g *gocui.Gui) error { v.BgColor = gocui.ColorWhite v.FgColor = gocui.ColorBlack v.Frame = false - fmt.Fprintln(v, "q: quit ↑ ↓: navigate space: select/deselect a: select all r: clear selection") + fmt.Fprintln(v, "q: quit | ↑ ↓: navigate | space: select/deselect | a: select all | r: clear selection | enter: execute") } return nil } diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 9623719..196fc2e 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -11,6 +11,9 @@ func (gui *Gui) keybindings(g *gocui.Gui) error { if err := g.SetKeybinding("", 'q', gocui.ModNone, gui.quit); err != nil { return err } + if err := g.SetKeybinding("", gocui.KeyEnter, gocui.ModNone, gui.execute); err != nil { + return err + } if err := g.SetKeybinding("main", gocui.KeyArrowDown, gocui.ModNone, gui.cursorDown); err != nil { return err } |
