1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
package gui
import (
"fmt"
"regexp"
"github.com/isacikgoz/gitbatch/internal/command"
"github.com/isacikgoz/gitbatch/internal/git"
"github.com/isacikgoz/gitbatch/internal/job"
"github.com/jroimartin/gocui"
)
var (
// 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 "}
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 *job.Job
)
// open an auth view to get user credentials
func (gui *Gui) openAuthenticationView(g *gocui.Gui, jobQueue *job.Queue, job *job.Job, returnViewName string) error {
maxX, maxY := g.Size()
// 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.Repository.WorkStatus() != git.Fail {
if err := jobQueue.RemoveFromQueue(job.Repository); err != nil {
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, keySymbol+selectionIndicator+red.Sprint(jobRequiresAuth.Repository.State.Remote.URL[0]))
}
g.Cursor = true
if err := gui.openUserView(g); err != nil {
return err
}
return gui.openPasswordView(g)
}
// close the opened auth views
func (gui *Gui) closeAuthenticationView(g *gocui.Gui, v *gocui.View) error {
g.Cursor = false
for _, vf := range authLabels {
if err := g.DeleteView(vf.Name); err != nil {
return nil
}
}
for _, vf := range authViews {
if err := g.DeleteView(vf.Name); err != nil {
return nil
}
}
return gui.closeViewCleanup(authenticationReturnView)
}
// 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 them
vUser, err := g.View(authUserFeature.Name)
if err != nil {
return err // should return??
}
vPswd, err := g.View(authPasswordViewFeature.Name)
if err != nil {
return err // should return??
}
// the return string of the views contain trailing new lines
re := regexp.MustCompile(`\r?\n`)
creduser := re.ReplaceAllString(vUser.ViewBuffer(), "")
credpswd := re.ReplaceAllString(vPswd.ViewBuffer(), "")
// since the git ops require different types of options we better switch
switch mode := jobRequiresAuth.JobType; mode {
case job.FetchJob:
jobRequiresAuth.Options = &command.FetchOptions{
RemoteName: jobRequiresAuth.Repository.State.Remote.Name,
Credentials: &git.Credentials{
User: creduser,
Password: credpswd,
},
}
case job.PullJob:
// we handle pull as fetch&merge so same rule applies
jobRequiresAuth.Options = &command.PullOptions{
RemoteName: jobRequiresAuth.Repository.State.Remote.Name,
Credentials: &git.Credentials{
User: creduser,
Password: credpswd,
},
}
}
jobRequiresAuth.Repository.SetWorkStatus(git.Queued)
// add this job to the last of the queue
if err := gui.State.Queue.AddJob(jobRequiresAuth); err != nil {
return err
}
return gui.closeAuthenticationView(g, v)
}
// 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 {
return err
}
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 {
return err
}
v.Title = authUserFeature.Title
v.Editable = true
v.Frame = false
}
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 {
return err
}
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 {
return err
}
v.Title = authPasswordViewFeature.Title
v.Editable = true
v.Mask ^= '*'
v.Frame = false
}
return nil
}
// focus to next view
func (gui *Gui) nextAuthView(g *gocui.Gui, v *gocui.View) error {
err := gui.nextViewOfGroup(g, v, authViews)
return err
}
|