diff options
| author | Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com> | 2018-11-28 02:02:38 +0300 |
|---|---|---|
| committer | Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com> | 2018-11-28 02:02:38 +0300 |
| commit | 4e2de5bf5d5be06a825552e6441221bae648000e (patch) | |
| tree | fade3a0e1b7eab9a0716f376363bb511f88ecb56 | |
| parent | improving queue mechanism (diff) | |
| download | gitbatch-4e2de5bf5d5be06a825552e6441221bae648000e.tar.gz | |
added queue handler and tweaked UX
| -rw-r--r-- | pkg/git/branch.go | 6 | ||||
| -rw-r--r-- | pkg/git/repository.go | 23 | ||||
| -rw-r--r-- | pkg/gui/branchview.go | 3 | ||||
| -rw-r--r-- | pkg/gui/errorview.go | 2 | ||||
| -rw-r--r-- | pkg/gui/execview.go | 127 | ||||
| -rw-r--r-- | pkg/gui/gui.go | 1 | ||||
| -rw-r--r-- | pkg/gui/keybindings.go | 36 | ||||
| -rw-r--r-- | pkg/gui/mainview.go | 76 | ||||
| -rw-r--r-- | pkg/gui/queuehandler.go | 46 | ||||
| -rw-r--r-- | pkg/job/job.go | 29 |
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 { |
