summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIbrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>2018-11-22 01:08:00 +0300
committerIbrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>2018-11-22 01:08:00 +0300
commit8252d2f2f19e1b2cad43b472bfdb4308cd3df649 (patch)
tree5767e1d5ffa997284ca764c9f9cc5e4f531dfd09
parentre-arrangement (diff)
downloadgitbatch-8252d2f2f19e1b2cad43b472bfdb4308cd3df649.tar.gz
refactoring and added initial implementation of fetc & pull mechanisms
-rw-r--r--main.go1
-rw-r--r--pkg/app/app.go49
-rw-r--r--pkg/git/load.go41
-rw-r--r--pkg/git/model.go9
-rw-r--r--pkg/git/repository.go37
-rw-r--r--pkg/gui/gui-util.go16
-rw-r--r--pkg/gui/gui.go65
-rw-r--r--pkg/gui/keybindings.go2
-rw-r--r--pkg/gui/pullview.go29
-rw-r--r--pkg/gui/scheduleview.go2
10 files changed, 186 insertions, 65 deletions
diff --git a/main.go b/main.go
index 81ee897..4a716d3 100644
--- a/main.go
+++ b/main.go
@@ -24,6 +24,7 @@ func main() {
if err != nil {
log.Fatal(err)
}
+
app.Gui.Run()
defer app.Close()
diff --git a/pkg/app/app.go b/pkg/app/app.go
index f97d657..c3575a4 100644
--- a/pkg/app/app.go
+++ b/pkg/app/app.go
@@ -2,9 +2,7 @@ package app
import (
"github.com/isacikgoz/gitbatch/pkg/gui"
- "github.com/isacikgoz/gitbatch/pkg/git"
"io"
- "sync"
)
// App struct
@@ -19,12 +17,13 @@ func Setup(directories []string) (*App, error) {
closers: []io.Closer{},
}
- entities, err := createRepositoryEntities(directories)
- if err != nil {
- return app, err
- }
+ var err error
+ // entities, err := createRepositoryEntities(directories)
+ // if err != nil {
+ // return app, err
+ // }
- app.Gui, err = gui.NewGui(entities)
+ app.Gui, err = gui.NewGui(directories)
if err != nil {
return app, err
}
@@ -40,40 +39,4 @@ func (app *App) Close() error {
}
}
return nil
-}
-
-func createRepositoryEntities(directories []string) (entities []*git.RepoEntity, err error) {
- entities = make([]*git.RepoEntity, 0)
-
- var wg sync.WaitGroup
- var mu sync.Mutex
-
- for _, dir := range directories {
- // 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()
-
- return entities, nil
} \ No newline at end of file
diff --git a/pkg/git/load.go b/pkg/git/load.go
new file mode 100644
index 0000000..5d62dcf
--- /dev/null
+++ b/pkg/git/load.go
@@ -0,0 +1,41 @@
+package git
+
+import (
+ "sync"
+)
+
+func LoadRepositoryEntities(directories []string) (entities []*RepoEntity, err error) {
+ entities = make([]*RepoEntity, 0)
+
+ var wg sync.WaitGroup
+ var mu sync.Mutex
+
+ for _, dir := range directories {
+ // 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 := 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()
+
+ return entities, nil
+} \ No newline at end of file
diff --git a/pkg/git/model.go b/pkg/git/model.go
index d5182c0..2c02eda 100644
--- a/pkg/git/model.go
+++ b/pkg/git/model.go
@@ -11,6 +11,15 @@ import (
func (entity *RepoEntity) GetRemotes() (remotes []string, err error) {
r := entity.Repository
+ remotes, err = getRemotes(&r)
+ if err !=nil {
+ return nil ,err
+ }
+ return remotes, nil
+}
+
+func getRemotes(r *git.Repository) (remotes []string, err error) {
+
if list, err := r.Remotes(); err != nil {
return remotes, err
} else {
diff --git a/pkg/git/repository.go b/pkg/git/repository.go
index a825830..93cdbc9 100644
--- a/pkg/git/repository.go
+++ b/pkg/git/repository.go
@@ -2,6 +2,7 @@ package git
import (
"gopkg.in/src-d/go-git.v4"
+ "gopkg.in/src-d/go-git.v4/plumbing"
"os"
"time"
)
@@ -13,6 +14,7 @@ type RepoEntity struct {
Pushables string
Pullables string
Branch string
+ Remote string
Marked bool
Clean bool
}
@@ -32,8 +34,8 @@ func InitializeRepository(directory string) (entity *RepoEntity, err error) {
}
pushable, pullable := UpstreamDifferenceCount(directory)
branch, err := CurrentBranchName(directory)
-
- entity = &RepoEntity{fileInfo.Name(), directory, *r, pushable, pullable, branch, false, isClean(r, fileInfo.Name())}
+ remotes, err := getRemotes(r)
+ entity = &RepoEntity{fileInfo.Name(), directory, *r, pushable, pullable, branch, remotes[0], false, isClean(r, fileInfo.Name())}
return entity, nil
}
@@ -55,12 +57,41 @@ func (entity *RepoEntity) Mark() {
entity.Marked = true
}
-func (entity *RepoEntity) UnMark() {
+func (entity *RepoEntity) Unmark() {
entity.Marked = false
}
func (entity *RepoEntity) Pull() error {
+ w, err := entity.Repository.Worktree()
+ if err != nil {
+ return err
+ }
+ ref := plumbing.NewBranchReferenceName(entity.Branch)
+ err = w.Pull(&git.PullOptions{
+ RemoteName: entity.Remote,
+ ReferenceName: ref,
+ })
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (entity *RepoEntity) PullTest() error {
time.Sleep(5 * time.Second)
+
+ return nil
+}
+
+func (entity *RepoEntity) Fetch() error {
+ err := entity.Repository.Fetch(&git.FetchOptions{
+ RemoteName: entity.Remote,
+ })
+ if err != nil {
+ return err
+ }
+
return nil
}
diff --git a/pkg/gui/gui-util.go b/pkg/gui/gui-util.go
index cb41430..d842eb8 100644
--- a/pkg/gui/gui-util.go
+++ b/pkg/gui/gui-util.go
@@ -34,7 +34,7 @@ func (gui *Gui) cursorDown(g *gocui.Gui, v *gocui.View) error {
cx, cy := v.Cursor()
ox, oy := v.Origin()
- ly := len(gui.Repositories) -1
+ ly := len(gui.State.Repositories) -1
// if we are at the end we just return
if cy+oy == ly {
@@ -83,7 +83,7 @@ func (gui *Gui) getSelectedRepository(g *gocui.Gui, v *gocui.View) (*git.RepoEnt
return r, err
}
- for _, sr := range gui.Repositories {
+ for _, sr := range gui.State.Repositories {
if l == sr.Name {
return sr, nil
}
@@ -102,7 +102,7 @@ func (gui *Gui) markRepository(g *gocui.Gui, v *gocui.View) error {
if r.Marked != true {
r.Mark()
} else {
- r.UnMark()
+ r.Unmark()
}
gui.refreshMain(g)
gui.updateSchedule(g)
@@ -112,7 +112,7 @@ func (gui *Gui) markRepository(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) markAllRepositories(g *gocui.Gui, v *gocui.View) error {
- for _, r := range gui.Repositories {
+ for _, r := range gui.State.Repositories {
r.Mark()
}
if err := gui.refreshMain(g); err !=nil {
@@ -123,8 +123,8 @@ func (gui *Gui) markAllRepositories(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) unMarkAllRepositories(g *gocui.Gui, v *gocui.View) error {
- for _, r := range gui.Repositories {
- r.UnMark()
+ for _, r := range gui.State.Repositories {
+ r.Unmark()
}
if err := gui.refreshMain(g); err !=nil {
return err
@@ -140,7 +140,7 @@ func (gui *Gui) refreshMain(g *gocui.Gui) error {
return err
}
mainView.Clear()
- for _, r := range gui.Repositories {
+ for _, r := range gui.State.Repositories {
fmt.Fprintln(mainView, r.GetDisplayString())
}
return nil
@@ -170,7 +170,7 @@ func (gui *Gui) getMarkedEntities() (rs []*git.RepoEntity, err error) {
var wg sync.WaitGroup
var mu sync.Mutex
- for _, r := range gui.Repositories {
+ for _, r := range gui.State.Repositories {
wg.Add(1)
go func(repo *git.RepoEntity){
defer wg.Done()
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index 1c29ce3..55c6c18 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -4,19 +4,44 @@ import (
"github.com/isacikgoz/gitbatch/pkg/git"
"github.com/jroimartin/gocui"
"fmt"
+ "time"
+ "os"
+ "os/exec"
+ "io/ioutil"
+ "log"
)
+// SentinelErrors are the errors that have special meaning and need to be checked
+// by calling functions. The less of these, the better
+type SentinelErrors struct {
+ ErrSubProcess error
+}
+
// Gui wraps the gocui Gui object which handles rendering and events
type Gui struct {
g *gocui.Gui
- Repositories []*git.RepoEntity
+ SubProcess *exec.Cmd
+ State guiState
+ Errors SentinelErrors
+}
+
+type guiState struct {
+ Repositories []*git.RepoEntity
+ Directories []string
}
// NewGui builds a new gui handler
-func NewGui(entities []*git.RepoEntity) (*Gui, error) {
+func NewGui(directoies []string) (*Gui, error) {
+ rs, err := git.LoadRepositoryEntities(directoies)
+ if err != nil {
+ return nil, err
+ }
+ initialState := guiState{
+ Repositories: rs,
+ }
gui := &Gui{
- Repositories: entities,
+ State: initialState,
}
return gui, nil
@@ -43,6 +68,38 @@ func (gui *Gui) Run() error {
return nil
}
+// RunWithSubprocesses loops, instantiating a new gocui.Gui with each iteration
+// if the error returned from a run is a ErrSubProcess, it runs the subprocess
+// otherwise it handles the error, possibly by quitting the application
+func (gui *Gui) RunWithSubprocesses() {
+ for {
+ if err := gui.Run(); err != nil {
+ if err == gocui.ErrQuit {
+ break
+ } else if err == gui.Errors.ErrSubProcess {
+ gui.SubProcess.Stdin = os.Stdin
+ gui.SubProcess.Stdout = os.Stdout
+ gui.SubProcess.Stderr = os.Stderr
+ gui.SubProcess.Run()
+ gui.SubProcess.Stdout = ioutil.Discard
+ gui.SubProcess.Stderr = ioutil.Discard
+ gui.SubProcess.Stdin = nil
+ gui.SubProcess = nil
+ } else {
+ log.Fatal(err)
+ }
+ }
+ }
+}
+
+func (gui *Gui) goEvery(g *gocui.Gui, interval time.Duration, function func(*gocui.Gui) error) {
+ go func() {
+ for range time.Tick(interval) {
+ function(g)
+ }
+ }()
+}
+
func (gui *Gui) layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
@@ -55,7 +112,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
v.SelBgColor = gocui.ColorWhite
v.SelFgColor = gocui.ColorBlack
v.Overwrite = true
- for _, r := range gui.Repositories {
+ for _, r := range gui.State.Repositories {
fmt.Fprintln(v, r.GetDisplayString())
}
diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go
index 2b46138..5f2164e 100644
--- a/pkg/gui/keybindings.go
+++ b/pkg/gui/keybindings.go
@@ -8,7 +8,7 @@ func (gui *Gui) keybindings(g *gocui.Gui) error {
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, gui.quit); err != nil {
return err
}
- if err := g.SetKeybinding("", 'q', gocui.ModNone, gui.quit); err != nil {
+ if err := g.SetKeybinding("main", 'q', gocui.ModNone, gui.quit); err != nil {
return err
}
if err := g.SetKeybinding("main", gocui.KeyEnter, gocui.ModNone, gui.openPullView); err != nil {
diff --git a/pkg/gui/pullview.go b/pkg/gui/pullview.go
index 14e2a9c..90e3797 100644
--- a/pkg/gui/pullview.go
+++ b/pkg/gui/pullview.go
@@ -1,7 +1,6 @@
package gui
import (
- // "github./com/isacikgoz/gitbatch/pkg/git"
"github.com/jroimartin/gocui"
"fmt"
)
@@ -21,7 +20,6 @@ func (gui *Gui) openPullView(g *gocui.Gui, v *gocui.View) error {
line := r.Name + " : " + r.GetActiveRemote() + "/" + r.Branch + " → " + r.GetActiveBranch()
fmt.Fprintln(v, line)
}
-
}
gui.updateKeyBindingsViewForPullView(g)
if _, err := g.SetCurrentView("pull"); err != nil {
@@ -44,10 +42,17 @@ func (gui *Gui) closePullView(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) executePull(g *gocui.Gui, v *gocui.View) error {
- go gui.updateKeyBindingsViewForExecution(g)
- mrs, _ := gui.getMarkedEntities()
+ gui.updateKeyBindingsViewForExecution(g)
+ mrs, _ := gui.getMarkedEntities()
+
+ gui.updateKeyBindingsViewForExecution(g)
for _, mr := range mrs {
+
+ go gui.counter(g)
+
+ // here we will be waiting
mr.Pull()
+ mr.Unmark()
}
gui.refreshMain(g)
@@ -83,4 +88,18 @@ func (gui *Gui) updateKeyBindingsViewForExecution(g *gocui.Gui) error {
v.Frame = false
fmt.Fprintln(v, " PULLING REPOSITORIES")
return nil
-} \ No newline at end of file
+}
+
+func (gui *Gui) counter(g *gocui.Gui) {
+
+ v, err := g.View("pull")
+ if err != nil {
+ return
+ }
+
+ g.Update(func(g *gocui.Gui) error {
+ v.Clear()
+ fmt.Fprintln(v, "Pulling...")
+ return nil
+ })
+}
diff --git a/pkg/gui/scheduleview.go b/pkg/gui/scheduleview.go
index 7c7a1f2..7a8a1d3 100644
--- a/pkg/gui/scheduleview.go
+++ b/pkg/gui/scheduleview.go
@@ -15,7 +15,7 @@ func (gui *Gui) updateSchedule(g *gocui.Gui) error {
}
out.Clear()
pullJobs := 0
- for _, r := range gui.Repositories {
+ for _, r := range gui.State.Repositories {
if r.Marked {
pullJobs++
}