summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIbrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>2018-11-28 02:02:38 +0300
committerIbrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>2018-11-28 02:02:38 +0300
commit4e2de5bf5d5be06a825552e6441221bae648000e (patch)
treefade3a0e1b7eab9a0716f376363bb511f88ecb56
parentimproving queue mechanism (diff)
downloadgitbatch-4e2de5bf5d5be06a825552e6441221bae648000e.tar.gz
added queue handler and tweaked UX
-rw-r--r--pkg/git/branch.go6
-rw-r--r--pkg/git/repository.go23
-rw-r--r--pkg/gui/branchview.go3
-rw-r--r--pkg/gui/errorview.go2
-rw-r--r--pkg/gui/execview.go127
-rw-r--r--pkg/gui/gui.go1
-rw-r--r--pkg/gui/keybindings.go36
-rw-r--r--pkg/gui/mainview.go76
-rw-r--r--pkg/gui/queuehandler.go46
-rw-r--r--pkg/job/job.go29
10 files changed, 104 insertions, 245 deletions
diff --git a/pkg/git/branch.go b/pkg/git/branch.go
index ed5f83a..432cde8 100644
--- a/pkg/git/branch.go
+++ b/pkg/git/branch.go
@@ -70,10 +70,10 @@ func (entity *RepoEntity) Checkout(branch *Branch) error {
}); err != nil {
return err
}
- branch.Pushables, branch.Pullables = UpstreamDifferenceCount(entity.AbsPath)
entity.loadCommits()
entity.Commit = entity.Commits[0]
entity.Branch = branch
+ entity.Branch.Pushables, entity.Branch.Pullables = UpstreamDifferenceCount(entity.AbsPath)
return nil
}
@@ -88,3 +88,7 @@ func (entity *RepoEntity) isClean() bool {
}
return status.IsClean()
}
+
+func (entity *RepoEntity) RefreshPushPull() {
+ entity.Branch.Pushables, entity.Branch.Pullables = UpstreamDifferenceCount(entity.AbsPath)
+}
diff --git a/pkg/git/repository.go b/pkg/git/repository.go
index 3b81b0f..d3ea1ec 100644
--- a/pkg/git/repository.go
+++ b/pkg/git/repository.go
@@ -20,7 +20,7 @@ type RepoEntity struct {
Remotes []*Remote
Commit *Commit
Commits []*Commit
- Marked bool
+ State RepoState
}
type RepoState uint8
@@ -28,8 +28,9 @@ type RepoState uint8
const (
Available RepoState = 0
Queued RepoState = 1
- Success RepoState = 2
- Fail RepoState = 3
+ Working RepoState = 2
+ Success RepoState = 3
+ Fail RepoState = 4
)
func InitializeRepository(directory string) (entity *RepoEntity, err error) {
@@ -49,7 +50,7 @@ func InitializeRepository(directory string) (entity *RepoEntity, err error) {
Name: fileInfo.Name(),
AbsPath: directory,
Repository: *r,
- Marked: false,
+ State: Available,
}
entity.loadLocalBranches()
entity.loadCommits()
@@ -69,14 +70,6 @@ func InitializeRepository(directory string) (entity *RepoEntity, err error) {
return entity, nil
}
-func (entity *RepoEntity) Mark() {
- entity.Marked = true
-}
-
-func (entity *RepoEntity) Unmark() {
- entity.Marked = false
-}
-
func (entity *RepoEntity) Pull() error {
// TODO: Migrate this code to src-d/go-git
// 2018-11-25: tried but it fails, will investigate.
@@ -106,12 +99,6 @@ func (entity *RepoEntity) Fetch() error {
}
entity.Refresh()
entity.Checkout(entity.Branch)
- // err := entity.Repository.Fetch(&git.FetchOptions{
- // RemoteName: remote,
- // })
- // if err != nil {
- // return err
- // }
return nil
}
func (entity *RepoEntity) Refresh() error {
diff --git a/pkg/gui/branchview.go b/pkg/gui/branchview.go
index ef0ca6c..0358e82 100644
--- a/pkg/gui/branchview.go
+++ b/pkg/gui/branchview.go
@@ -44,7 +44,8 @@ func (gui *Gui) nextBranch(g *gocui.Gui, v *gocui.View) error {
return err
}
if err = entity.Checkout(entity.NextBranch()); err != nil {
- if err = gui.openErrorView(g, "Stage your changes before checkout", "You should manually manage this issue"); err != nil {
+ if err = gui.openErrorView(g, "Please commit your changes or stash them before you switch branches",
+ "You should manually resolve this issue"); err != nil {
return err
}
return nil
diff --git a/pkg/gui/errorview.go b/pkg/gui/errorview.go
index cf44108..36284fb 100644
--- a/pkg/gui/errorview.go
+++ b/pkg/gui/errorview.go
@@ -18,7 +18,7 @@ func (gui *Gui) openErrorView(g *gocui.Gui, message string, note string) error {
v.Wrap = true
ps := red.Sprint("Note:") + " " + note
fmt.Fprintln(v, message)
- fmt.Fprintln(v, "\n"+ps)
+ fmt.Fprintln(v, ps)
}
gui.updateKeyBindingsView(g, errorViewFeature.Name)
if _, err := g.SetCurrentView(errorViewFeature.Name); err != nil {
diff --git a/pkg/gui/execview.go b/pkg/gui/execview.go
deleted file mode 100644
index eba8509..0000000
--- a/pkg/gui/execview.go
+++ /dev/null
@@ -1,127 +0,0 @@
-package gui
-
-import (
- "errors"
- "fmt"
- // "strconv"
-
- "github.com/jroimartin/gocui"
-)
-
-func (gui *Gui) openExecConfirmationView(g *gocui.Gui, v *gocui.View) error {
- // maxX, maxY := g.Size()
- go func(gui_go *Gui, g_go *gocui.Gui) {
- for {
- finished, err := gui_go.State.Queue.StartNext()
- g.Update(func(gu *gocui.Gui) error {
- gui_go.refreshMain(gu)
- return nil
- })
- if err != nil {
- return
- }
- if finished {
- return
- }
- }
- }(gui, g)
- return nil
- // if mrs, _ := gui.getMarkedEntities(); len(mrs) < 1 {
- // return nil
- // }
-
- // v, err := g.SetView(execViewFeature.Name, maxX/2-35, maxY/2-5, maxX/2+35, maxY/2+5)
- // if err != nil {
- // if err != gocui.ErrUnknownView {
- // return err
- // }
- // v.Title = gui.State.Mode.DisplayString + " Confirmation"
- // v.Wrap = true
- // mrs, _ := gui.getMarkedEntities()
- // jobs := strconv.Itoa(len(mrs)) + " " + gui.State.Mode.ExecString + ":"
- // fmt.Fprintln(v, jobs)
- // for _, r := range mrs {
- // line := " - " + green.Sprint(r.Name) + ": " + r.Remote.Name + green.Sprint(" → ") + r.Branch.Name
- // fmt.Fprintln(v, line)
- // }
- // ps := red.Sprint("Note:") + " When " + gui.State.Mode.CommandString + " operation is completed, you will be notified."
- // fmt.Fprintln(v, "\n"+ps)
- // }
- // gui.updateKeyBindingsView(g, execViewFeature.Name)
- // if _, err := g.SetCurrentView(execViewFeature.Name); err != nil {
- // return err
- // }
- return nil
-}
-
-func (gui *Gui) closeExecView(g *gocui.Gui, v *gocui.View) error {
- go g.Update(func(g *gocui.Gui) error {
- mainView, _ := g.View(mainViewFeature.Name)
- entity, err := gui.getSelectedRepository(g, mainView)
- if err != nil {
- return err
- }
- gui.updateCommits(g, entity)
- return nil
- })
- if err := g.DeleteView(v.Name()); err != nil {
- return nil
- }
- if _, err := g.SetCurrentView(mainViewFeature.Name); err != nil {
- return err
- }
- gui.updateKeyBindingsView(g, mainViewFeature.Name)
- return nil
-}
-
-func (gui *Gui) execute(g *gocui.Gui, v *gocui.View) error {
- // somehow this fucntion called after this method returns, strange?
- go g.Update(func(g *gocui.Gui) error {
- err := updateKeyBindingsViewForExecution(g)
- if err != nil {
- return err
- }
- return nil
- })
-
- mrs, _ := gui.getMarkedEntities()
- for _, mr := range mrs {
- // here we will be waiting
- switch mode := gui.State.Mode.ModeID; mode {
- case FetchMode:
- err := mr.Fetch()
- if err != nil {
- cv, _ := g.View(execViewFeature.Name)
- gui.closeExecView(g, cv)
- gui.openErrorView(g, err.Error(), "An error occured, manual resolving reuqired")
- return nil
- }
- case PullMode:
- err := mr.Pull()
- if err != nil {
- cv, _ := g.View(execViewFeature.Name)
- gui.closeExecView(g, cv)
- gui.openErrorView(g, err.Error(), "It maybe a conflict, manual resolving reuqired")
- return nil
- }
- default:
- return errors.New("No mode is selected")
- }
- mr.Unmark()
- gui.refreshMain(g)
- }
- return nil
-}
-
-func updateKeyBindingsViewForExecution(g *gocui.Gui) error {
- v, err := g.View(keybindingsViewFeature.Name)
- if err != nil {
- return err
- }
- v.Clear()
- v.BgColor = gocui.ColorGreen
- v.FgColor = gocui.ColorBlack
- v.Frame = false
- fmt.Fprintln(v, " Operation Completed; c: close/cancel")
- return nil
-}
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index 674a4b8..427179c 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -49,7 +49,6 @@ var (
commitViewFeature = viewFeature{Name: "commits", Title: " Commits "}
scheduleViewFeature = viewFeature{Name: "schedule", Title: " Schedule "}
keybindingsViewFeature = viewFeature{Name: "keybindings", Title: " Keybindings "}
- execViewFeature = viewFeature{Name: "execution", Title: " Execution Parameters "}
commitdetailViewFeature = viewFeature{Name: "commitdetail", Title: " Commit Detail "}
cheatSheetViewFeature = viewFeature{Name: "cheatsheet", Title: " Application Controls "}
errorViewFeature = viewFeature{Name: "error", Title: " Error "}
diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go
index 51ce61c..4930e99 100644
--- a/pkg/gui/keybindings.go
+++ b/pkg/gui/keybindings.go
@@ -110,9 +110,9 @@ func (gui *Gui) generateKeybindings() error {
View: mainViewFeature.Name,
Key: gocui.KeyEnter,
Modifier: gocui.ModNone,
- Handler: gui.openExecConfirmationView,
+ Handler: gui.startQueue,
Display: "enter",
- Description: "Execute jobs",
+ Description: "Start queue",
Vital: true,
}, {
View: mainViewFeature.Name,
@@ -123,22 +123,6 @@ func (gui *Gui) generateKeybindings() error {
Description: "Select",
Vital: true,
}, {
- View: mainViewFeature.Name,
- Key: 'a',
- Modifier: gocui.ModNone,
- Handler: gui.markAllRepositories,
- Display: "a",
- Description: "Select all",
- Vital: false,
- }, {
- View: mainViewFeature.Name,
- Key: 'd',
- Modifier: gocui.ModNone,
- Handler: gui.unMarkAllRepositories,
- Display: "d",
- Description: "Deselect all",
- Vital: false,
- }, {
View: commitdetailViewFeature.Name,
Key: 'c',
Modifier: gocui.ModNone,
@@ -171,22 +155,6 @@ func (gui *Gui) generateKeybindings() error {
Description: "close/cancel",
Vital: true,
}, {
- View: execViewFeature.Name,
- Key: 'c',
- Modifier: gocui.ModNone,
- Handler: gui.closeExecView,
- Display: "c",
- Description: "close/cancel",
- Vital: true,
- }, {
- View: execViewFeature.Name,
- Key: gocui.KeyEnter,
- Modifier: gocui.ModNone,
- Handler: gui.execute,
- Display: "enter",
- Description: "Execute",
- Vital: true,
- }, {
View: errorViewFeature.Name,
Key: 'c',
Modifier: gocui.ModNone,
diff --git a/pkg/gui/mainview.go b/pkg/gui/mainview.go
index 4c4ce36..faa5c74 100644
--- a/pkg/gui/mainview.go
+++ b/pkg/gui/mainview.go
@@ -3,7 +3,7 @@ package gui
import (
"fmt"
"regexp"
- "sync"
+ // "sync"
"github.com/isacikgoz/gitbatch/pkg/git"
"github.com/isacikgoz/gitbatch/pkg/job"
@@ -111,54 +111,38 @@ func (gui *Gui) markRepository(g *gocui.Gui, v *gocui.View) error {
}
return nil
}
- if !r.Marked {
+ if r.State == git.Available || r.State == git.Success {
+ var jt job.JobType
+ switch mode := gui.State.Mode.ModeID; mode {
+ case FetchMode:
+ jt = job.Fetch
+ case PullMode:
+ jt = job.Pull
+ default:
+ return nil
+ }
err := gui.State.Queue.AddJob(&job.Job{
- JobType: job.Fetch,
+ JobType: jt,
Entity: r,
- Args: make([]string, 0),
})
if err != nil {
- if err = gui.openErrorView(g, "This repository is already queued for another operation",
- "You switch mode and deselect to remove operaton from the queue"); err != nil {
- return err
- }
- return nil
+ return err
}
- r.Mark()
- } else {
+ r.State = git.Queued
+ } else if r.State == git.Queued {
err := gui.State.Queue.RemoveFromQueue(r)
if err != nil {
return err
}
- r.Unmark()
+ r.State = git.Available
+ } else {
+ return nil
}
gui.refreshMain(g)
}
return nil
}
-func (gui *Gui) markAllRepositories(g *gocui.Gui, v *gocui.View) error {
- for _, r := range gui.State.Repositories {
- if r.Branch.Clean {
- r.Mark()
- }
- }
- if err := gui.refreshMain(g); err != nil {
- return err
- }
- return nil
-}
-
-func (gui *Gui) unMarkAllRepositories(g *gocui.Gui, v *gocui.View) error {
- for _, r := range gui.State.Repositories {
- r.Unmark()
- }
- if err := gui.refreshMain(g); err != nil {
- return err
- }
- return nil
-}
-
func (gui *Gui) refreshMain(g *gocui.Gui) error {
mainView, err := g.View(mainViewFeature.Name)
@@ -172,24 +156,6 @@ func (gui *Gui) refreshMain(g *gocui.Gui) error {
return nil
}
-func (gui *Gui) getMarkedEntities() (rs []*git.RepoEntity, err error) {
- var wg sync.WaitGroup
- var mu sync.Mutex
- for _, r := range gui.State.Repositories {
- wg.Add(1)
- go func(repo *git.RepoEntity) {
- defer wg.Done()
- if repo.Marked {
- mu.Lock()
- rs = append(rs, repo)
- mu.Unlock()
- }
- }(r)
- }
- wg.Wait()
- return rs, nil
-}
-
func displayString(entity *git.RepoEntity) string {
prefix := ""
if entity.Branch.Pushables != "?" {
@@ -199,8 +165,12 @@ func displayString(entity *git.RepoEntity) string {
prefix = prefix + magenta.Sprint("?") + string(yellow.Sprint(" → "))
}
prefix = prefix + string(cyan.Sprint(entity.Branch.Name)) + " "
- if entity.Marked {
+ if entity.State == 1 {
+ return prefix + string(green.Sprint(entity.Name))
+ } else if entity.State == 2 {
return prefix + string(green.Sprint(entity.Name))
+ } else if entity.State == 4 {
+ return prefix + string(red.Sprint(entity.Name))
} else if !entity.Branch.Clean {
return prefix + string(yellow.Sprint(entity.Name))
} else {
diff --git a/pkg/gui/queuehandler.go b/pkg/gui/queuehandler.go
new file mode 100644
index 0000000..0cf6d67
--- /dev/null
+++ b/pkg/gui/queuehandler.go
@@ -0,0 +1,46 @@
+package gui
+
+import (
+ "github.com/jroimartin/gocui"
+)
+
+func (gui *Gui) startQueue(g *gocui.Gui, v *gocui.View) error {
+ go func(gui_go *Gui, g_go *gocui.Gui) {
+ indicateQueueStarted(g_go)
+ for {
+ job, finished, err := gui_go.State.Queue.StartNext()
+ g_go.Update(func(gu *gocui.Gui) error {
+ gui_go.refreshMain(gu)
+ return nil
+ })
+ defer indicateQueueFinished(g_go)
+ if err != nil {
+ return
+ }
+ if finished {
+ return
+ } else {
+ gui_go.refreshViews(g, job.Entity)
+ }
+ }
+ }(gui, g)
+ return nil
+}
+
+func indicateQueueStarted(g *gocui.Gui) error {
+ v, err := g.View(keybindingsViewFeature.Name)
+ if err != nil {
+ return err
+ }
+ v.BgColor = gocui.ColorGreen
+ return nil
+}
+
+func indicateQueueFinished(g *gocui.Gui) error {
+ v, err := g.View(keybindingsViewFeature.Name)
+ if err != nil {
+ return err
+ }
+ v.BgColor = gocui.ColorWhite
+ return nil
+}
diff --git a/pkg/job/job.go b/pkg/job/job.go
index eaa1820..8341e69 100644
--- a/pkg/job/job.go
+++ b/pkg/job/job.go
@@ -11,7 +11,6 @@ import (
type Job struct {
JobType JobType
Entity *git.RepoEntity
- Args []string
}
type JobQueue struct {
@@ -32,14 +31,26 @@ func CreateJob() (j *Job, err error) {
func (job *Job) start() error {
time.Sleep(2*time.Second)
- job.Entity.Marked = false
+ job.Entity.State = git.Working
+ // TODO: Handle errors?
switch mode := job.JobType; mode {
case Fetch:
- job.Entity.PullTest()
+ if err := job.Entity.Fetch(); err != nil {
+ job.Entity.State = git.Fail
+ return nil
+ }
+ job.Entity.RefreshPushPull()
+ job.Entity.State = git.Success
case Pull:
- job.Entity.PullTest()
+ if err := job.Entity.Pull(); err != nil {
+ job.Entity.State = git.Fail
+ return nil
+ }
+ job.Entity.RefreshPushPull()
+ job.Entity.State = git.Success
default:
- return errors.New("Unknown job type")
+ job.Entity.State = git.Available
+ return nil
}
return nil
}
@@ -61,19 +72,19 @@ func (jobQueue *JobQueue) AddJob(j *Job) error {
return nil
}
-func (jobQueue *JobQueue) StartNext() (finished bool, err error) {
+func (jobQueue *JobQueue) StartNext() (j *Job, finished bool, err error) {
finished = false
if len(jobQueue.series) < 1 {
finished = true
- return finished, nil
+ return nil, finished, nil
}
i := len(jobQueue.series)-1
lastJob := jobQueue.series[i]
jobQueue.series = jobQueue.series[:i]
if err = lastJob.start(); err != nil {
- return finished, err
+ return lastJob, finished, err
}
- return finished, nil
+ return lastJob, finished, nil
}
func (jobQueue *JobQueue) RemoveFromQueue(entity *git.RepoEntity) error {