summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pkg/git/job-queue.go28
-rw-r--r--pkg/gui/authenticationview.go11
-rw-r--r--pkg/gui/gui.go16
-rw-r--r--pkg/gui/keybindings.go8
-rw-r--r--pkg/gui/mainview.go40
-rw-r--r--pkg/gui/util-textstyle.go9
6 files changed, 69 insertions, 43 deletions
diff --git a/pkg/git/job-queue.go b/pkg/git/job-queue.go
index 3eee605..e6e6f0c 100644
--- a/pkg/git/job-queue.go
+++ b/pkg/git/job-queue.go
@@ -2,6 +2,7 @@ package git
import (
"errors"
+ "sync"
)
// JobQueue holds the slice of Jobs
@@ -66,13 +67,34 @@ func (jq *JobQueue) RemoveFromQueue(entity *RepoEntity) error {
// IsInTheQueue function; since the job and entity is not tied with its own
// struct, this function returns true if that entity is in the queue along with
// the jobs type
-func (jq *JobQueue) IsInTheQueue(entity *RepoEntity) (inTheQueue bool, jt JobType) {
+func (jq *JobQueue) IsInTheQueue(entity *RepoEntity) (inTheQueue bool, j *Job) {
inTheQueue = false
for _, job := range jq.series {
if job.Entity.RepoID == entity.RepoID {
inTheQueue = true
- jt = job.JobType
+ j = job
}
}
- return inTheQueue, jt
+ return inTheQueue, j
+}
+
+// StartJobsAsync start he jobs in the queue asynchronously
+func (jq *JobQueue) StartJobsAsync() map[*Job]error {
+ fails := make(map[*Job]error)
+ var wg sync.WaitGroup
+ var mx sync.Mutex
+ for range jq.series {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ j, _, err := jq.StartNext()
+ if err != nil {
+ mx.Lock()
+ fails[j] = err
+ mx.Unlock()
+ }
+ }()
+ }
+ wg.Wait()
+ return fails
}
diff --git a/pkg/gui/authenticationview.go b/pkg/gui/authenticationview.go
index a274425..7d4861f 100644
--- a/pkg/gui/authenticationview.go
+++ b/pkg/gui/authenticationview.go
@@ -125,16 +125,7 @@ func (gui *Gui) submitAuthenticationView(g *gocui.Gui, v *gocui.View) error {
return err
}
- if err := gui.closeAuthenticationView(g, v); err != nil {
- return err // should return??
- }
-
- vReturn, err := g.View(authenticationReturnView)
- if err != nil {
- return err // should return??
- }
-
- return gui.startQueue(g, vReturn)
+ return gui.closeAuthenticationView(g, v)
}
// open an error view to inform user with a message and a useful note
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index b19772b..6d5de19 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -21,10 +21,11 @@ type Gui struct {
// guiState struct holds the repositories, directiories, mode and queue of the
// gui object. These values are not static
type guiState struct {
- Repositories []*git.RepoEntity
- Directories []string
- Mode mode
- Queue *git.JobQueue
+ Repositories []*git.RepoEntity
+ Directories []string
+ Mode mode
+ Queue *git.JobQueue
+ FailoverQueue *git.JobQueue
}
// this struct encapsulates the name and title of a view. the name of a view is
@@ -77,9 +78,10 @@ var (
// NewGui creates a Gui opject and fill it's state related entites
func NewGui(mode string, directoies []string) (*Gui, error) {
initialState := guiState{
- Directories: directoies,
- Mode: fetchMode,
- Queue: git.CreateJobQueue(),
+ Directories: directoies,
+ Mode: fetchMode,
+ Queue: git.CreateJobQueue(),
+ FailoverQueue: git.CreateJobQueue(),
}
gui := &Gui{
State: initialState,
diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go
index 7aaee56..668fe90 100644
--- a/pkg/gui/keybindings.go
+++ b/pkg/gui/keybindings.go
@@ -310,6 +310,14 @@ func (gui *Gui) generateKeybindings() error {
// Main view controls
{
View: mainViewFeature.Name,
+ Key: 'u',
+ Modifier: gocui.ModNone,
+ Handler: gui.submitCredentials,
+ Display: "u",
+ Description: "Submit Credentials",
+ Vital: false,
+ }, {
+ View: mainViewFeature.Name,
Key: gocui.KeyArrowUp,
Modifier: gocui.ModNone,
Handler: gui.cursorUp,
diff --git a/pkg/gui/mainview.go b/pkg/gui/mainview.go
index 6cd43bb..8ee31ba 100644
--- a/pkg/gui/mainview.go
+++ b/pkg/gui/mainview.go
@@ -231,29 +231,33 @@ func (gui *Gui) removeFromQueue(entity *git.RepoEntity) error {
// this function starts the queue and updates the gui with the result of an
// operation
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()
+ go func(gui_go *Gui) {
+ fails := gui_go.State.Queue.StartJobsAsync()
+ gui_go.State.Queue = git.CreateJobQueue()
+ for j, err := range fails {
+ if err == git.ErrAuthenticationRequired {
+ j.Entity.SetState(git.Paused)
+ gui_go.State.FailoverQueue.AddJob(j)
+ }
+ }
+ }(gui)
+ return nil
+}
+func (gui *Gui) submitCredentials(g *gocui.Gui, v *gocui.View) error {
+ if is, j := gui.State.FailoverQueue.IsInTheQueue(gui.getSelectedRepository()); is {
+ if j.Entity.State() == git.Paused {
+ gui.State.FailoverQueue.RemoveFromQueue(j.Entity)
+ err := gui.openAuthenticationView(g, gui.State.Queue, j, v.Name())
if err != nil {
- if err == git.ErrAuthenticationRequired {
- // pause the job, so it will be indicated to being blocking
- job.Entity.SetState(git.Paused)
- err := gui_go.openAuthenticationView(g, gui_go.State.Queue, job, v.Name())
- if err != nil {
- log.Warn(err.Error())
- return
- }
- }
- return
- // with not returning here, we simply ignore and continue
+ log.Warn(err.Error())
+ return err
}
- // if queue is finished simply return from this goroutine
- if finished {
- return
+ if isnt, _ := gui.State.Queue.IsInTheQueue(j.Entity); !isnt {
+ gui.State.FailoverQueue.AddJob(j)
}
}
- }(gui, g)
+ }
return nil
}
diff --git a/pkg/gui/util-textstyle.go b/pkg/gui/util-textstyle.go
index 95c8de7..1bb3635 100644
--- a/pkg/gui/util-textstyle.go
+++ b/pkg/gui/util-textstyle.go
@@ -84,8 +84,8 @@ func (gui *Gui) repositoryLabel(e *git.RepoEntity) string {
var suffix string
// rendering the satus according to repository's state
if e.State() == git.Queued {
- if inQueue, ty := gui.State.Queue.IsInTheQueue(e); inQueue {
- switch mode := ty; mode {
+ if inQueue, j := gui.State.Queue.IsInTheQueue(e); inQueue {
+ switch mode := j.JobType; mode {
case git.FetchJob:
suffix = blue.Sprint(queuedSymbol)
case git.PullJob:
@@ -103,12 +103,11 @@ func (gui *Gui) repositoryLabel(e *git.RepoEntity) string {
} else if e.State() == git.Success {
return prefix + repoName + ws + green.Sprint(successSymbol)
} else if e.State() == git.Paused {
- return prefix + repoName + ws + yellow.Sprint(pauseSymbol)
+ return prefix + repoName + ws + yellow.Sprint("auth required (u)")
} else if e.State() == git.Fail {
return prefix + repoName + ws + red.Sprint(failSymbol)
- } else {
- return prefix + repoName
}
+ return prefix + repoName
}
func commitLabel(c *git.Commit) string {