summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIbrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>2018-12-13 02:12:03 +0300
committerIbrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>2018-12-13 02:12:03 +0300
commita4a29171fb11c98432ead8e72bc0948a549d9979 (patch)
tree1525cc43a0a86e79a174b4b214cc2ad64e58aaaa
parentimplementing authentication for fetch operation (diff)
downloadgitbatch-a4a29171fb11c98432ead8e72bc0948a549d9979.tar.gz
login implementation stablized, some renaming, some refactoring and updated readme
-rw-r--r--README.md19
-rw-r--r--pkg/git/cmd-add.go (renamed from pkg/git/add.go)0
-rw-r--r--pkg/git/cmd-fetch.go (renamed from pkg/git/fetch.go)18
-rw-r--r--pkg/git/cmd-merge.go (renamed from pkg/git/merge.go)0
-rw-r--r--pkg/git/cmd-reset.go (renamed from pkg/git/reset.go)0
-rw-r--r--pkg/git/cmd-rev-list.go (renamed from pkg/git/rev-list.go)0
-rw-r--r--pkg/git/cmd-stash.go (renamed from pkg/git/stash.go)0
-rw-r--r--pkg/git/cmd-status.go (renamed from pkg/git/status.go)0
-rw-r--r--pkg/git/cmd.go (renamed from pkg/git/commands.go)0
-rw-r--r--pkg/git/job-queue.go (renamed from pkg/git/queue.go)0
-rw-r--r--pkg/git/job.go26
-rw-r--r--pkg/git/repository.go6
-rw-r--r--pkg/git/util-errors.go (renamed from pkg/git/errors.go)0
-rw-r--r--pkg/git/util-load.go (renamed from pkg/git/load.go)0
-rw-r--r--pkg/git/util-repository-sort.go (renamed from pkg/git/repository-sort.go)0
-rw-r--r--pkg/gui/authenticationview.go81
-rw-r--r--pkg/gui/cheatsheet.go12
-rw-r--r--pkg/gui/diffview.go9
-rw-r--r--pkg/gui/errorview.go12
-rw-r--r--pkg/gui/gui-util.go14
-rw-r--r--pkg/gui/keybindings.go4
-rw-r--r--pkg/gui/mainview.go3
-rw-r--r--pkg/gui/queuehandler.go8
-rw-r--r--pkg/gui/stagedview.go6
-rw-r--r--pkg/gui/statusview.go27
-rw-r--r--pkg/gui/textstyle.go5
26 files changed, 128 insertions, 122 deletions
diff --git a/README.md b/README.md
index fcfef40..7719c88 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,13 @@
[![Build Status](https://travis-ci.com/isacikgoz/gitbatch.svg?branch=master)](https://travis-ci.com/isacikgoz/gitbatch) [![MIT License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](/LICENSE) [![Go Report Card](https://goreportcard.com/badge/github.com/isacikgoz/gitbatch)](https://goreportcard.com/report/github.com/isacikgoz/gitbatch)
## gitbatch
-This tool has been built to make your local repositories synchronized with remotes easily. I love lazygit, with that inspiration, decided to build this project to be even more lazy; Since my daily work is tied to many repositories I often end up walking on many directories and manually pulling updates etc. To make this routine faster, I created a simple tool to handle this job. I really enjoy working on this project and I hope it will be a useful tool.
-
-**Disclaimer**
-- Unauthenticated repositories are **not supported** so using ssh is recommended if you need to authenticate to fetch/pull
- - [Connecting to GitHub with SSH](https://help.github.com/articles/connecting-to-github-with-ssh/)
- - [GitLab and SSH keys](https://docs.gitlab.com/ee/ssh/)
- - [BitBucket Set up an SSH key](https://confluence.atlassian.com/bitbucket/set-up-ssh-for-git-728138079.html)
-- Feedbacks are welcome. For now, known issues are:
- - At very low probability app fails to load repositories, try again it will load next time (multithreading problem).
- - Colors vary to your terminal theme colors, so if the contrast is not enough on some color decisions; discussions are welcome.
+This tool is beening built to make your local repositories synchronized with remotes easily. Although the focus is batch jobs, you can still do de facto micro management of your git repositories (e.g *add/reset, stash, commit etc.*)
Here is the screencast of the app:
[![asciicast](https://asciinema.org/a/eXgXpzZfuHxMpZqGMVODUipyc.svg)](https://asciinema.org/a/eXgXpzZfuHxMpZqGMVODUipyc)
## Installation
-For now, installation requires golang compiler and minimum golang 1.10 is recommended.
+For now, installation requires golang compiler and minimum golang 1.10 is recommended. (binary distribution will be provided on minimum viable product)
- If you don't have golang installed refer to [golang.org](https://golang.org/dl/).
- You should have $GOPATH env variable set and your $PATH should include $GOPATH/bin to run app from anywhere.
@@ -42,9 +33,11 @@ For more information;
## Further goals
- add testing
- full src-d/go-git integration (*having some performance issues*)
-- resolve authentication issues
- add commit and maybe push?
+## Known issues
+Please refer to [Known issues page](https://github.com/isacikgoz/gitbatch/wiki/Known-issues)
+
## Credits
- [go-git](https://github.com/src-d/go-git) for git interface (partially)
- [gocui](https://github.com/jroimartin/gocui) for user interface
@@ -53,3 +46,5 @@ For more information;
- [color](https://github.com/fatih/color) for colored text
- [lazygit](https://github.com/jesseduffield/lazygit) as app template and reference
- [kingpin](https://github.com/alecthomas/kingpin) for command-line flag&options
+
+I love [lazygit](https://github.com/jesseduffield/lazygit), with that inspiration, decided to build this project to be even more lazy. The rationale was; my daily work is tied to many repositories and I often end up walking on many directories and manually pulling updates etc. To make this routine faster, I created a simple tool to handle this job. I really enjoy working on this project and I hope it will be a useful tool.
diff --git a/pkg/git/add.go b/pkg/git/cmd-add.go
index 61fd587..61fd587 100644
--- a/pkg/git/add.go
+++ b/pkg/git/cmd-add.go
diff --git a/pkg/git/fetch.go b/pkg/git/cmd-fetch.go
index 39a0277..8a8bf9c 100644
--- a/pkg/git/fetch.go
+++ b/pkg/git/cmd-fetch.go
@@ -50,7 +50,7 @@ func Fetch(entity *RepoEntity, options FetchOptions) (err error) {
}
switch fetchCmdMode {
case fetchCmdModeLegacy:
- err = fetchWithGit(entity.AbsPath, options)
+ err = fetchWithGit(entity, options)
return err
case fetchCmdModeNative:
// this should be the refspec as default, let's give it a try
@@ -58,15 +58,13 @@ func Fetch(entity *RepoEntity, options FetchOptions) (err error) {
err = fetchWithGoGit(entity, options, refspec)
return err
}
- // till this step everything should be ok
- err = entity.Refresh()
- return err
+ return nil
}
// fetchWithGit is simply a bare git fetch <remote> command which is flexible
// for complex operations, but on the other hand, it ties the app to another
// tool. To avoid that, using native implementation is preferred.
-func fetchWithGit(abspath string, options FetchOptions) (err error) {
+func fetchWithGit(entity *RepoEntity, options FetchOptions) (err error) {
args := make([]string, 0)
args = append(args, fetchCommand)
// parse options to command line arguments
@@ -82,9 +80,12 @@ func fetchWithGit(abspath string, options FetchOptions) (err error) {
if options.DryRun {
args = append(args, "--dry-run")
}
- if err := GenericGitCommand(abspath, args); err != nil {
+ if err := GenericGitCommand(entity.AbsPath, args); err != nil {
log.Warn("Error at git command (fetch)")
+ return err
}
+ // till this step everything should be ok
+ err = entity.Refresh()
return err
}
@@ -100,6 +101,7 @@ func fetchWithGoGit(entity *RepoEntity, options FetchOptions, refspec string) (e
RefSpecs: []config.RefSpec{config.RefSpec(refspec)},
Force: options.Force,
}
+ // if any credential is given, let's add it to the git.FetchOptions
if len(options.Credentials.User) > 0 {
protocol, err := entity.authProtocol(entity.Remote)
if err != nil {
@@ -138,5 +140,7 @@ func fetchWithGoGit(entity *RepoEntity, options FetchOptions, refspec string) (e
return err
}
}
- return nil
+ // till this step everything should be ok
+ err = entity.Refresh()
+ return err
}
diff --git a/pkg/git/merge.go b/pkg/git/cmd-merge.go
index 984bc4b..984bc4b 100644
--- a/pkg/git/merge.go
+++ b/pkg/git/cmd-merge.go
diff --git a/pkg/git/reset.go b/pkg/git/cmd-reset.go
index f93225c..f93225c 100644
--- a/pkg/git/reset.go
+++ b/pkg/git/cmd-reset.go
diff --git a/pkg/git/rev-list.go b/pkg/git/cmd-rev-list.go
index 664d69f..664d69f 100644
--- a/pkg/git/rev-list.go
+++ b/pkg/git/cmd-rev-list.go
diff --git a/pkg/git/stash.go b/pkg/git/cmd-stash.go
index 9d813a6..9d813a6 100644
--- a/pkg/git/stash.go
+++ b/pkg/git/cmd-stash.go
diff --git a/pkg/git/status.go b/pkg/git/cmd-status.go
index 4cca604..4cca604 100644
--- a/pkg/git/status.go
+++ b/pkg/git/cmd-status.go
diff --git a/pkg/git/commands.go b/pkg/git/cmd.go
index b78b501..b78b501 100644
--- a/pkg/git/commands.go
+++ b/pkg/git/cmd.go
diff --git a/pkg/git/queue.go b/pkg/git/job-queue.go
index e95250a..e95250a 100644
--- a/pkg/git/queue.go
+++ b/pkg/git/job-queue.go
diff --git a/pkg/git/job.go b/pkg/git/job.go
index 13ef566..7dc4126 100644
--- a/pkg/git/job.go
+++ b/pkg/git/job.go
@@ -1,13 +1,14 @@
package git
-import (
- "time"
-)
+import ()
// Job relates the type of the operation and the entity
type Job struct {
+ // JobType is to select operation type that will be applied to repository
JobType JobType
- Entity *RepoEntity
+ // Entity points to the repository that will be used for operation
+ Entity *RepoEntity
+ // Options is a placeholder for operation options
Options interface{}
}
@@ -26,9 +27,8 @@ const (
// starts the job
func (job *Job) start() error {
job.Entity.State = Working
- // added for testing, TODO: remove
- time.Sleep(time.Second)
// TODO: Handle errors?
+ // TOOD: Better implementation required
switch mode := job.JobType; mode {
case FetchJob:
var opts FetchOptions
@@ -44,11 +44,17 @@ func (job *Job) start() error {
return err
}
case PullJob:
- if err := Fetch(job.Entity, FetchOptions{
- RemoteName: job.Entity.Remote.Name,
- }); err != nil {
+ var opts FetchOptions
+ if job.Options != nil {
+ opts = job.Options.(FetchOptions)
+ } else {
+ opts = FetchOptions{
+ RemoteName: job.Entity.Remote.Name,
+ }
+ }
+ if err := Fetch(job.Entity, opts); err != nil {
job.Entity.State = Fail
- return nil
+ return err
}
if err := Merge(job.Entity, MergeOptions{
BranchName: job.Entity.Remote.Branch.Name,
diff --git a/pkg/git/repository.go b/pkg/git/repository.go
index 8d0160b..ff67611 100644
--- a/pkg/git/repository.go
+++ b/pkg/git/repository.go
@@ -39,10 +39,12 @@ const (
Queued RepoState = 1
// Working means an operation is just started for this repository
Working RepoState = 2
+ // Paused is expected when a user interaction is required
+ Paused RepoState = 3
// Success is the expected outcome of the operation
- Success RepoState = 3
+ Success RepoState = 4
// Fail is the unexpected outcome of the operation
- Fail RepoState = 4
+ Fail RepoState = 5
)
// InitializeRepository initializes a RepoEntity struct with its belongings.
diff --git a/pkg/git/errors.go b/pkg/git/util-errors.go
index 8621cbc..8621cbc 100644
--- a/pkg/git/errors.go
+++ b/pkg/git/util-errors.go
diff --git a/pkg/git/load.go b/pkg/git/util-load.go
index e35e1c1..e35e1c1 100644
--- a/pkg/git/load.go
+++ b/pkg/git/util-load.go
diff --git a/pkg/git/repository-sort.go b/pkg/git/util-repository-sort.go
index de5f454..de5f454 100644
--- a/pkg/git/repository-sort.go
+++ b/pkg/git/util-repository-sort.go
diff --git a/pkg/gui/authenticationview.go b/pkg/gui/authenticationview.go
index 240b46c..9c830cd 100644
--- a/pkg/gui/authenticationview.go
+++ b/pkg/gui/authenticationview.go
@@ -2,30 +2,40 @@ package gui
import (
"fmt"
+ "regexp"
+
"github.com/isacikgoz/gitbatch/pkg/git"
"github.com/jroimartin/gocui"
log "github.com/sirupsen/logrus"
)
var (
- authenticationReturnView string
+ // this is required so we can know where we can return
+ authenticationReturnView string
+ // these views used as a label for git repository address and credential views
authenticationViewFeature = viewFeature{Name: "authentication", Title: " Authentication "}
- authUserFeature = viewFeature{Name: "authuser", Title: " User "}
- authPasswordViewFeature = viewFeature{Name: "authpasswd", Title: " Password "}
authUserLabelFeature = viewFeature{Name: "authuserlabel", Title: " User: "}
authPswdLabelViewFeature = viewFeature{Name: "authpasswdlabel", Title: " Password: "}
+ // these views used as a input for the credentials
+ authUserFeature = viewFeature{Name: "authuser", Title: " User "}
+ authPasswordViewFeature = viewFeature{Name: "authpasswd", Title: " Password "}
+ // these are the view groups, so that we can assign common keybindings
authViews = []viewFeature{authUserFeature, authPasswordViewFeature}
authLabels = []viewFeature{authenticationViewFeature, authUserLabelFeature, authPswdLabelViewFeature}
+ // we can hold the job that is required to authenticate
jobRequiresAuth *git.Job
)
-// open an error view to inform user with a message and a useful note
+// open an auth view to get user credentials
func (gui *Gui) openAuthenticationView(g *gocui.Gui, jobQueue *git.JobQueue, job *git.Job, returnViewName string) error {
maxX, maxY := g.Size()
- // lets remove this job from the queue so that it won't block anything
+ // lets add this job since it is removed from the queue
// also it is already unsuccessfully finished
+ if err := jobQueue.AddJob(job); err != nil {
+ return err
+ }
jobRequiresAuth = job
if job.Entity.State != git.Fail {
if err := jobQueue.RemoveFromQueue(job.Entity); err != nil {
@@ -33,26 +43,22 @@ func (gui *Gui) openAuthenticationView(g *gocui.Gui, jobQueue *git.JobQueue, job
return err
}
}
-
authenticationReturnView = returnViewName
v, err := g.SetView(authenticationViewFeature.Name, maxX/2-30, maxY/2-2, maxX/2+30, maxY/2+2)
if err != nil {
if err != gocui.ErrUnknownView {
return err
}
- fmt.Fprintln(v, " Enter credentials for: "+red.Sprint(job.Entity.Remote.URL[0]))
+ fmt.Fprintln(v, keySymbol+selectionIndicator+red.Sprint(jobRequiresAuth.Entity.Remote.URL[0]))
}
g.Cursor = true
if err := gui.openUserView(g); err != nil {
- return nil
- }
- if err := gui.openPasswordView(g); err != nil {
- return nil
+ return err
}
- return nil
+ return gui.openPasswordView(g)
}
-// close the opened error view
+// close the opened auth views
func (gui *Gui) closeAuthenticationView(g *gocui.Gui, v *gocui.View) error {
g.Cursor = false
for _, vf := range authLabels {
@@ -65,21 +71,20 @@ func (gui *Gui) closeAuthenticationView(g *gocui.Gui, v *gocui.View) error {
return nil
}
}
- if _, err := g.SetCurrentView(authenticationReturnView); err != nil {
- return err
- }
- gui.updateKeyBindingsView(g, authenticationReturnView)
- return nil
+ return gui.closeViewCleanup(authenticationReturnView)
}
-// close the opened error view
+// close the opened auth views and submit the credentials
func (gui *Gui) submitAuthenticationView(g *gocui.Gui, v *gocui.View) error {
g.Cursor = false
+ // in order to read buffer of the views, first we need to find'em
v_user, err := g.View(authUserFeature.Name)
v_pswd, err := g.View(authPasswordViewFeature.Name)
- creduser := v_user.ViewBuffer()
- credpswd := v_pswd.ViewBuffer()
- // Maybe pause implementation can be added
+ // the return string of the views contain trailing new lines
+ re := regexp.MustCompile(`\r?\n`)
+ creduser := re.ReplaceAllString(v_user.ViewBuffer(), "")
+ credpswd := re.ReplaceAllString(v_pswd.ViewBuffer(), "")
+ // since the git ops require different types of options we better switch
switch mode := jobRequiresAuth.JobType; mode {
case git.FetchJob:
jobRequiresAuth.Options = git.FetchOptions{
@@ -89,21 +94,34 @@ func (gui *Gui) submitAuthenticationView(g *gocui.Gui, v *gocui.View) error {
Password: credpswd,
},
}
+ case git.PullJob:
+ // we handle pull as fetch&merge so same rule applies
+ jobRequiresAuth.Options = git.FetchOptions{
+ RemoteName: jobRequiresAuth.Entity.Remote.Name,
+ Credentials: git.Credentials{
+ User: creduser,
+ Password: credpswd,
+ },
+ }
}
+ jobRequiresAuth.Entity.State = git.Queued
+ // add this job to the last of the queue
err = gui.State.Queue.AddJob(jobRequiresAuth)
if err != nil {
return err
}
- jobRequiresAuth.Entity.State = git.Queued
+ // refresh views with the updates
gui.refreshMain(g)
- gui.refreshViews(g, jobRequiresAuth.Entity)
gui.closeAuthenticationView(g, v)
+ v_return, err := g.View(authenticationReturnView)
+ gui.startQueue(g, v_return)
return nil
}
// open an error view to inform user with a message and a useful note
func (gui *Gui) openUserView(g *gocui.Gui) error {
maxX, maxY := g.Size()
+ // first, create the label for user
vlabel, err := g.SetView(authUserLabelFeature.Name, maxX/2-30, maxY/2-1, maxX/2-19, maxY/2+1)
if err != nil {
if err != gocui.ErrUnknownView {
@@ -112,6 +130,7 @@ func (gui *Gui) openUserView(g *gocui.Gui) error {
fmt.Fprintln(vlabel, authUserLabelFeature.Title)
vlabel.Frame = false
}
+ // second, crete the user input
v, err := g.SetView(authUserFeature.Name, maxX/2-18, maxY/2-1, maxX/2+29, maxY/2+1)
if err != nil {
if err != gocui.ErrUnknownView {
@@ -121,16 +140,13 @@ func (gui *Gui) openUserView(g *gocui.Gui) error {
v.Editable = true
v.Frame = false
}
- gui.updateKeyBindingsView(g, authUserFeature.Name)
- if _, err := g.SetCurrentView(authUserFeature.Name); err != nil {
- return err
- }
- return nil
+ return gui.focusToView(authUserFeature.Name)
}
// open an error view to inform user with a message and a useful note
func (gui *Gui) openPasswordView(g *gocui.Gui) error {
maxX, maxY := g.Size()
+ // first, create the label for password
vlabel, err := g.SetView(authPswdLabelViewFeature.Name, maxX/2-30, maxY/2, maxX/2-19, maxY/2+2)
if err != nil {
if err != gocui.ErrUnknownView {
@@ -139,6 +155,7 @@ func (gui *Gui) openPasswordView(g *gocui.Gui) error {
fmt.Fprintln(vlabel, authPswdLabelViewFeature.Title)
vlabel.Frame = false
}
+ // second, crete the masked password input
v, err := g.SetView(authPasswordViewFeature.Name, maxX/2-18, maxY/2, maxX/2+29, maxY/2+2)
if err != nil {
if err != gocui.ErrUnknownView {
@@ -157,9 +174,3 @@ func (gui *Gui) nextAuthView(g *gocui.Gui, v *gocui.View) error {
err := gui.nextViewOfGroup(g, v, authViews)
return err
}
-
-// focus to previous view
-func (gui *Gui) previousAuthView(g *gocui.Gui, v *gocui.View) error {
- err := gui.previousViewOfGroup(g, v, authViews)
- return err
-}
diff --git a/pkg/gui/cheatsheet.go b/pkg/gui/cheatsheet.go
index 43020a5..4b2f97e 100644
--- a/pkg/gui/cheatsheet.go
+++ b/pkg/gui/cheatsheet.go
@@ -24,11 +24,7 @@ func (gui *Gui) openCheatSheetView(g *gocui.Gui, v *gocui.View) error {
}
}
}
- gui.updateKeyBindingsView(g, cheatSheetViewFeature.Name)
- if _, err := g.SetCurrentView(cheatSheetViewFeature.Name); err != nil {
- return err
- }
- return nil
+ return gui.focusToView(cheatSheetViewFeature.Name)
}
// close the application controls and do the clean job
@@ -36,9 +32,5 @@ func (gui *Gui) closeCheatSheetView(g *gocui.Gui, v *gocui.View) error {
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
+ return gui.closeViewCleanup(mainViewFeature.Name)
}
diff --git a/pkg/gui/diffview.go b/pkg/gui/diffview.go
index f99d7f2..04c9e10 100644
--- a/pkg/gui/diffview.go
+++ b/pkg/gui/diffview.go
@@ -22,8 +22,7 @@ func (gui *Gui) prepareDiffView(g *gocui.Gui, v *gocui.View, display []string) (
out.Title = diffViewFeature.Title
out.Overwrite = true
out.Wrap = true
- gui.updateKeyBindingsView(g, diffViewFeature.Name)
- if _, err = g.SetCurrentView(diffViewFeature.Name); err != nil {
+ if err = gui.focusToView(diffViewFeature.Name); err != nil {
return out, err
}
for _, line := range display {
@@ -126,9 +125,5 @@ func (gui *Gui) closeCommitDiffView(g *gocui.Gui, v *gocui.View) error {
if err := g.DeleteView(v.Name()); err != nil {
return nil
}
- if _, err := g.SetCurrentView(diffReturnView); err != nil {
- return err
- }
- gui.updateKeyBindingsView(g, diffReturnView)
- return nil
+ return gui.closeViewCleanup(diffReturnView)
}
diff --git a/pkg/gui/errorview.go b/pkg/gui/errorview.go
index b4be162..f679b54 100644
--- a/pkg/gui/errorview.go
+++ b/pkg/gui/errorview.go
@@ -23,11 +23,7 @@ func (gui *Gui) openErrorView(g *gocui.Gui, message, note, returnViewName string
fmt.Fprintln(v, message)
fmt.Fprintln(v, ps)
}
- gui.updateKeyBindingsView(g, errorViewFeature.Name)
- if _, err := g.SetCurrentView(errorViewFeature.Name); err != nil {
- return err
- }
- return nil
+ return gui.focusToView(errorViewFeature.Name)
}
// close the opened error view
@@ -36,9 +32,5 @@ func (gui *Gui) closeErrorView(g *gocui.Gui, v *gocui.View) error {
if err := g.DeleteView(v.Name()); err != nil {
return nil
}
- if _, err := g.SetCurrentView(errorReturnView); err != nil {
- return err
- }
- gui.updateKeyBindingsView(g, errorReturnView)
- return nil
+ return gui.closeViewCleanup(errorReturnView)
}
diff --git a/pkg/gui/gui-util.go b/pkg/gui/gui-util.go
index bd02f7c..343e293 100644
--- a/pkg/gui/gui-util.go
+++ b/pkg/gui/gui-util.go
@@ -193,3 +193,17 @@ func (gui *Gui) fastCursorUp(g *gocui.Gui, v *gocui.View) error {
}
return nil
}
+
+// closeViewCleanup both updates the keybidings view and focuses to returning view
+func (gui *Gui) closeViewCleanup(returningViewName string) (err error) {
+ if _, err = gui.g.SetCurrentView(returningViewName); err != nil {
+ return err
+ }
+ err = gui.updateKeyBindingsView(gui.g, returningViewName)
+ return err
+}
+
+// focus to view same as closeViewCleanup but its just a wrapper for easy reading
+func (gui *Gui) focusToView(viewName string) (err error) {
+ return gui.closeViewCleanup(viewName)
+}
diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go
index 9b23fa2..1d4dd6d 100644
--- a/pkg/gui/keybindings.go
+++ b/pkg/gui/keybindings.go
@@ -191,7 +191,7 @@ func (gui *Gui) generateKeybindings() error {
Handler: gui.nextAuthView,
Display: "tab",
Description: "Next Panel",
- Vital: false,
+ Vital: true,
}, {
View: view.Name,
Key: gocui.KeyEnter,
@@ -199,7 +199,7 @@ func (gui *Gui) generateKeybindings() error {
Handler: gui.submitAuthenticationView,
Display: "enter",
Description: "Submit",
- Vital: false,
+ Vital: true,
},
}
for _, binding := range authKeybindings {
diff --git a/pkg/gui/mainview.go b/pkg/gui/mainview.go
index fe8931b..389d66d 100644
--- a/pkg/gui/mainview.go
+++ b/pkg/gui/mainview.go
@@ -147,7 +147,8 @@ func (gui *Gui) removeFromQueue(entity *git.RepoEntity) error {
// function does take its current state into account before adding it
func (gui *Gui) markRepository(g *gocui.Gui, v *gocui.View) error {
r := gui.getSelectedRepository()
- if r.State == git.Available || r.State == git.Success {
+ // maybe, failed entities may be added to queue again
+ if r.State == git.Available || r.State == git.Success || r.State == git.Paused {
if err := gui.addToQueue(r); err != nil {
return err
}
diff --git a/pkg/gui/queuehandler.go b/pkg/gui/queuehandler.go
index cec6f8b..a814c47 100644
--- a/pkg/gui/queuehandler.go
+++ b/pkg/gui/queuehandler.go
@@ -12,13 +12,17 @@ func (gui *Gui) startQueue(g *gocui.Gui, v *gocui.View) error {
go func(gui_go *Gui, g_go *gocui.Gui) {
for {
job, finished, err := gui_go.State.Queue.StartNext()
+ // for each job execution we better refresh the main
+ // it would be nice if we can also refresh side views
g_go.Update(func(gu *gocui.Gui) error {
gui_go.refreshMain(gu)
return nil
})
- defer gui.updateKeyBindingsView(g, mainViewFeature.Name)
+
if err != nil {
if err == git.ErrAuthenticationRequired {
+ // pause the job, so it will be indicated to being blocking
+ job.Entity.State = git.Paused
err := gui_go.openAuthenticationView(g, gui_go.State.Queue, job, v.Name())
if err != nil {
log.Warn(err.Error())
@@ -26,7 +30,9 @@ func (gui *Gui) startQueue(g *gocui.Gui, v *gocui.View) error {
}
}
return
+ // with not returning here, we simply ignore and continue
}
+ // if queue is finished simply return from this goroutine
if finished {
return
}
diff --git a/pkg/gui/stagedview.go b/pkg/gui/stagedview.go
index e27d35d..f12c06d 100644
--- a/pkg/gui/stagedview.go
+++ b/pkg/gui/stagedview.go
@@ -22,11 +22,7 @@ func (gui *Gui) openStageView(g *gocui.Gui) error {
if err := refreshStagedView(g, entity); err != nil {
return err
}
- gui.updateKeyBindingsView(g, stageViewFeature.Name)
- if _, err := g.SetCurrentView(stageViewFeature.Name); err != nil {
- return err
- }
- return nil
+ return gui.focusToView(stageViewFeature.Name)
}
func (gui *Gui) resetChanges(g *gocui.Gui, v *gocui.View) error {
diff --git a/pkg/gui/statusview.go b/pkg/gui/statusview.go
index 494e07a..b241ed6 100644
--- a/pkg/gui/statusview.go
+++ b/pkg/gui/statusview.go
@@ -11,8 +11,7 @@ import (
)
var (
- statusHeaderViewFeature = viewFeature{Name: "status-header", Title: " Status Header "}
- // statusViewFeature = viewFeature{Name: "status", Title: " Status "}
+ statusHeaderViewFeature = viewFeature{Name: "status-header", Title: " Status Header "}
stageViewFeature = viewFeature{Name: "staged", Title: " Staged "}
unstageViewFeature = viewFeature{Name: "unstaged", Title: " Not Staged "}
stashViewFeature = viewFeature{Name: "stash", Title: " Stash "}
@@ -105,21 +104,14 @@ func (gui *Gui) openStatusHeaderView(g *gocui.Gui) error {
// close the opened stat views
func (gui *Gui) closeStatusView(g *gocui.Gui, v *gocui.View) error {
- if err := g.DeleteView(stashViewFeature.Name); err != nil {
- return err
- }
- if err := g.DeleteView(unstageViewFeature.Name); err != nil {
- return err
- }
- if err := g.DeleteView(stageViewFeature.Name); err != nil {
- return err
+ for _, view := range statusViews {
+ if err := g.DeleteView(view.Name); err != nil {
+ return err
+ }
}
if err := g.DeleteView(statusHeaderViewFeature.Name); err != nil {
return err
}
- if _, err := g.SetCurrentView(mainViewFeature.Name); err != nil {
- return err
- }
entity := gui.getSelectedRepository()
if err := gui.refreshMain(g); err != nil {
return err
@@ -127,8 +119,7 @@ func (gui *Gui) closeStatusView(g *gocui.Gui, v *gocui.View) error {
if err := gui.refreshViews(g, entity); err != nil {
return err
}
- gui.updateKeyBindingsView(g, mainViewFeature.Name)
- return nil
+ return gui.closeViewCleanup(mainViewFeature.Name)
}
func generateFileLists(entity *git.RepoEntity) (staged, unstaged []*git.File, err error) {
@@ -228,9 +219,6 @@ func (gui *Gui) closeCommitMessageView(g *gocui.Gui, v *gocui.View) error {
if err := g.DeleteView(commitMessageViewFeature.Name); err != nil {
return err
}
- if _, err := g.SetCurrentView(commitMesageReturnView); err != nil {
- return err
- }
if err := gui.refreshMain(g); err != nil {
return err
}
@@ -240,6 +228,5 @@ func (gui *Gui) closeCommitMessageView(g *gocui.Gui, v *gocui.View) error {
if err := refreshAllStatusView(g, entity); err != nil {
return err
}
- gui.updateKeyBindingsView(g, commitMesageReturnView)
- return nil
+ return gui.closeViewCleanup(commitMesageReturnView)
}
diff --git a/pkg/gui/textstyle.go b/pkg/gui/textstyle.go
index efbbceb..7c36263 100644
--- a/pkg/gui/textstyle.go
+++ b/pkg/gui/textstyle.go
@@ -35,12 +35,15 @@ var (
queuedSymbol = "•"
workingSymbol = "•"
successSymbol = "✔"
+ pauseSymbol = "॥"
failSymbol = "✗"
fetchSymbol = "↓"
pullSymbol = "↓↳"
mergeSymbol = "↳"
+ keySymbol = ws + yellow.Sprint("🔑") + ws
+
modeSeperator = ""
keyBindingSeperator = "░"
@@ -102,6 +105,8 @@ func (gui *Gui) displayString(entity *git.RepoEntity) string {
return prefix + repoName + ws + green.Sprint(workingSymbol)
} else if entity.State == git.Success {
return prefix + repoName + ws + green.Sprint(successSymbol)
+ } else if entity.State == git.Paused {
+ return prefix + repoName + ws + yellow.Sprint(pauseSymbol)
} else if entity.State == git.Fail {
return prefix + repoName + ws + red.Sprint(failSymbol)
} else {