summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
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
commitfa0779f51bb6855acf6bdf5e01a599596a44d1dd (patch)
treeebdd0136a050eefba233daaa22e13c1b551a7762
parentadded select/deselect all (diff)
downloadgitbatch-fa0779f51bb6855acf6bdf5e01a599596a44d1dd.tar.gz
refactor and performance improvements
-rw-r--r--.gitignore1
-rw-r--r--pkg/app/app.go42
-rw-r--r--pkg/git/git-commands.go13
-rw-r--r--pkg/git/model.go (renamed from pkg/git/git.go)74
-rw-r--r--pkg/git/repository.go65
-rw-r--r--pkg/gui/gui-util.go19
-rw-r--r--pkg/gui/gui.go4
-rw-r--r--pkg/gui/keybindings.go3
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
}