summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2022-01-09 12:56:29 +1100
committerJesse Duffield <jessedduffield@gmail.com>2022-01-09 14:09:53 +1100
commita936c0592ff879d2c9a194556bae568d7943c5da (patch)
tree09d1b4810ed05972fbf988dd4e0d9beb3956b929
parent06687c8a59be6fe5466bf44ae2730354c2daa0e1 (diff)
more refactoring
-rw-r--r--pkg/commands/oscommands/cmd_obj_runner.go150
-rw-r--r--pkg/commands/oscommands/cmd_obj_runner_default.go (renamed from pkg/commands/oscommands/exec_live_default.go)0
-rw-r--r--pkg/commands/oscommands/cmd_obj_runner_win.go (renamed from pkg/commands/oscommands/exec_live_win.go)0
-rw-r--r--pkg/commands/oscommands/exec_live.go116
-rw-r--r--pkg/commands/oscommands/gui_io.go4
5 files changed, 135 insertions, 135 deletions
diff --git a/pkg/commands/oscommands/cmd_obj_runner.go b/pkg/commands/oscommands/cmd_obj_runner.go
index bbd3c85cc..24ce5a73b 100644
--- a/pkg/commands/oscommands/cmd_obj_runner.go
+++ b/pkg/commands/oscommands/cmd_obj_runner.go
@@ -2,6 +2,10 @@ package oscommands
import (
"bufio"
+ "bytes"
+ "io"
+ "regexp"
+ "strings"
"github.com/go-errors/errors"
"github.com/jesseduffield/lazygit/pkg/utils"
@@ -14,6 +18,14 @@ type ICmdObjRunner interface {
RunAndProcessLines(cmdObj ICmdObj, onLine func(line string) (bool, error)) error
}
+type CredentialType int
+
+const (
+ Password CredentialType = iota
+ Username
+ Passphrase
+)
+
type cmdObjRunner struct {
log *logrus.Entry
guiIO *guiIO
@@ -21,20 +33,6 @@ type cmdObjRunner struct {
var _ ICmdObjRunner = &cmdObjRunner{}
-func (self *cmdObjRunner) runWithCredentialHandling(cmdObj ICmdObj) error {
- switch cmdObj.GetCredentialStrategy() {
- case PROMPT:
- return self.RunAndDetectCredentialRequest(cmdObj, self.guiIO.promptForCredentialFn)
- case FAIL:
- return self.RunAndDetectCredentialRequest(cmdObj, func(CredentialType) string { return "\n" })
- case NONE:
- // we should never land here
- return errors.New("runWithCredentialHandling called but cmdObj does not have a a credential strategy")
- }
-
- return errors.New("unexpected credential strategy")
-}
-
func (self *cmdObjRunner) Run(cmdObj ICmdObj) error {
if cmdObj.GetCredentialStrategy() == NONE {
_, err := self.RunWithOutput(cmdObj)
@@ -44,10 +42,6 @@ func (self *cmdObjRunner) Run(cmdObj ICmdObj) error {
}
}
-func (self *cmdObjRunner) logCmdObj(cmdObj ICmdObj) {
- self.guiIO.logCommandFn(cmdObj.ToString(), true)
-}
-
func (self *cmdObjRunner) RunWithOutput(cmdObj ICmdObj) (string, error) {
if cmdObj.GetCredentialStrategy() != NONE {
err := self.runWithCredentialHandling(cmdObj)
@@ -106,6 +100,30 @@ func (self *cmdObjRunner) RunAndProcessLines(cmdObj ICmdObj, onLine func(line st
return nil
}
+// Whenever we're asked for a password we just enter a newline, which will
+// eventually cause the command to fail.
+var failPromptFn = func(CredentialType) string { return "\n" }
+
+func (self *cmdObjRunner) runWithCredentialHandling(cmdObj ICmdObj) error {
+ var promptFn func(CredentialType) string
+
+ switch cmdObj.GetCredentialStrategy() {
+ case PROMPT:
+ promptFn = self.guiIO.promptForCredentialFn
+ case FAIL:
+ promptFn = failPromptFn
+ case NONE:
+ // we should never land here
+ return errors.New("runWithCredentialHandling called but cmdObj does not have a a credential strategy")
+ }
+
+ return self.runAndDetectCredentialRequest(cmdObj, promptFn)
+}
+
+func (self *cmdObjRunner) logCmdObj(cmdObj ICmdObj) {
+ self.guiIO.logCommandFn(cmdObj.ToString(), true)
+}
+
func sanitisedCommandOutput(output []byte, err error) (string, error) {
outputString := string(output)
if err != nil {
@@ -118,3 +136,99 @@ func sanitisedCommandOutput(output []byte, err error) (string, error) {
}
return outputString, nil
}
+
+type cmdHandler struct {
+ stdoutPipe io.Reader
+ stdinPipe io.Writer
+ close func() error
+}
+
+// runAndDetectCredentialRequest detect a username / password / passphrase question in a command
+// promptUserForCredential is a function that gets executed when this function detect you need to fillin a password or passphrase
+// The promptUserForCredential argument will be "username", "password" or "passphrase" and expects the user's password/passphrase or username back
+func (self *cmdObjRunner) runAndDetectCredentialRequest(
+ cmdObj ICmdObj,
+ promptUserForCredential func(CredentialType) string,
+) error {
+ cmdWriter := self.guiIO.newCmdWriterFn()
+
+ if cmdObj.ShouldLog() {
+ self.logCmdObj(cmdObj)
+ }
+ self.log.WithField("command", cmdObj.ToString()).Info("RunCommand")
+ cmd := cmdObj.AddEnvVars("LANG=en_US.UTF-8", "LC_ALL=en_US.UTF-8").GetCmd()
+
+ var stderr bytes.Buffer
+ cmd.Stderr = io.MultiWriter(cmdWriter, &stderr)
+
+ handler, err := self.getCmdHandler(cmd)
+ if err != nil {
+ return err
+ }
+
+ defer func() {
+ if closeErr := handler.close(); closeErr != nil {
+ self.log.Error(closeErr)
+ }
+ }()
+
+ tr := io.TeeReader(handler.stdoutPipe, cmdWriter)
+
+ go utils.Safe(func() {
+ self.processOutput(tr, handler.stdinPipe, promptUserForCredential)
+ })
+
+ err = cmd.Wait()
+ if err != nil {
+ return errors.New(stderr.String())
+ }
+
+ return nil
+}
+
+func (self *cmdObjRunner) processOutput(reader io.Reader, writer io.Writer, promptUserForCredential func(CredentialType) string) {
+ checkForCredentialRequest := self.getCheckForCredentialRequestFunc()
+
+ scanner := bufio.NewScanner(reader)
+ scanner.Split(bufio.ScanBytes)
+ for scanner.Scan() {
+ newBytes := scanner.Bytes()
+ askFor, ok := checkForCredentialRequest(newBytes)
+ if ok {
+ toInput := promptUserForCredential(askFor)
+ // If the return data is empty we don't write anything to stdin
+ if toInput != "" {
+ _, _ = writer.Write([]byte(toInput))
+ }
+ }
+ }
+}
+
+// having a function that returns a function because we need to maintain some state inbetween calls hence the closure
+func (self *cmdObjRunner) getCheckForCredentialRequestFunc() func([]byte) (CredentialType, bool) {
+ var ttyText strings.Builder
+ // this function takes each word of output from the command and builds up a string to see if we're being asked for a password
+ return func(newBytes []byte) (CredentialType, bool) {
+ _, err := ttyText.Write(newBytes)
+ if err != nil {
+ self.log.Error(err)
+ }
+
+ prompts := map[string]CredentialType{
+ `Password:`: Password,
+ `.+'s password:`: Password,
+ `Password\s*for\s*'.+':`: Password,
+ `Username\s*for\s*'.+':`: Username,
+ `Enter\s*passphrase\s*for\s*key\s*'.+':`: Passphrase,
+ }
+
+ for pattern, askFor := range prompts {
+ if match, _ := regexp.MatchString(pattern, ttyText.String()); match {
+ ttyText.Reset()
+ return askFor, true
+ }
+ }
+
+ return 0, false
+ }
+}
diff --git a/pkg/commands/oscommands/exec_live_default.go b/pkg/commands/oscommands/cmd_obj_runner_default.go
index 567dcf970..567dcf970 100644
--- a/pkg/commands/oscommands/exec_live_default.go
+++ b/pkg/commands/oscommands/cmd_obj_runner_default.go
diff --git a/pkg/commands/oscommands/exec_live_win.go b/pkg/commands/oscommands/cmd_obj_runner_win.go
index 9e3d1fd02..9e3d1fd02 100644
--- a/pkg/commands/oscommands/exec_live_win.go
+++ b/pkg/commands/oscommands/cmd_obj_runner_win.go
diff --git a/pkg/commands/oscommands/exec_live.go b/pkg/commands/oscommands/exec_live.go
deleted file mode 100644
index 1b3e9697c..000000000
--- a/pkg/commands/oscommands/exec_live.go
+++ /dev/null
@@ -1,116 +0,0 @@
-package oscommands
-
-import (
- "bufio"
- "bytes"
- "io"
- "regexp"
- "strings"
-
- "github.com/go-errors/errors"
- "github.com/jesseduffield/lazygit/pkg/utils"
-)
-
-type CredentialType int
-
-const (
- Password CredentialType = iota
- Username
- Passphrase
-)
-
-type cmdHandler struct {
- stdoutPipe io.Reader
- stdinPipe io.Writer
- close func() error
-}
-
-// RunAndDetectCredentialRequest detect a username / password / passphrase question in a command
-// promptUserForCredential is a function that gets executed when this function detect you need to fillin a password or passphrase
-// The promptUserForCredential argument will be "username", "password" or "passphrase" and expects the user's password/passphrase or username back
-func (self *cmdObjRunner) RunAndDetectCredentialRequest(
- cmdObj ICmdObj,
- promptUserForCredential func(CredentialType) string,
-) error {
- self.log.Warn("HERE")
- cmdWriter := self.guiIO.newCmdWriterFn()
- self.log.WithField("command", cmdObj.ToString()).Info("RunCommand")
- if cmdObj.ShouldLog() {
- self.logCmdObj(cmdObj)
- }
- cmd := cmdObj.AddEnvVars("LANG=en_US.UTF-8", "LC_ALL=en_US.UTF-8").GetCmd()
-
- var stderr bytes.Buffer
- cmd.Stderr = io.MultiWriter(cmdWriter, &stderr)
-
- handler, err := self.getCmdHandler(cmd)
- if err != nil {
- return err
- }
-
- defer func() {
- if closeErr := handler.close(); closeErr != nil {
- self.log.Error(closeErr)
- }
- }()
-
- tr := io.TeeReader(handler.stdoutPipe, cmdWriter)
-
- go utils.Safe(func() {
- self.processOutput(tr, handler.stdinPipe, promptUserForCredential)
- })
-
- err = cmd.Wait()
- if err != nil {
- return errors.New(stderr.String())
- }
-
- return nil
-}
-
-func (self *cmdObjRunner) processOutput(reader io.Reader, writer io.Writer, promptUserForCredential func(CredentialType) string) {
- checkForCredentialRequest := self.getCheckForCredentialRequestFunc()
-
- scanner := bufio.NewScanner(reader)
- scanner.Split(bufio.ScanBytes)
- for scanner.Scan() {
- newBytes := scanner.Bytes()
- askFor, ok := checkForCredentialRequest(newBytes)
- if ok {
- toInput := promptUserForCredential(askFor)
- // If the return data is empty we don't write anything to stdin
- if toInput != "" {
- _, _ = writer.Write([]byte(toInput))
- }
- }
- }
-}
-
-// having a function that returns a function because we need to maintain some state inbetween calls hence the closure
-func (self *cmdObjRunner) getCheckForCredentialRequestFunc() func([]byte) (CredentialType, bool) {
- var ttyText strings.Builder
- // this function takes each word of output from the command and builds up a string to see if we're being asked for a password
- return func(newBytes []byte) (CredentialType, bool) {
- _, err := ttyText.Write(newBytes)
- if err != nil {
- self.log.Error(err)
- }
-
- prompts := map[string]CredentialType{
- `Password:`: Password,
- `.+'s password:`: Password,
- `Password\s*for\s*'.+':`: Password,
- `Username\s*for\s*'.+':`: Username,
- `Enter\s*passphrase\s*for\s*key\s*'.+':`: Passphrase,
- }
-
- for pattern, askFor := range prompts {
- if match, _ := regexp.MatchString(pattern, ttyText.String()); match {
- ttyText.Reset()
- return askFor, true
- }
- }
-
- return 0, false
- }
-}
diff --git a/pkg/commands/oscommands/gui_io.go b/pkg/commands/oscommands/gui_io.go
index 33a02874b..9540c13e1 100644
--- a/pkg/commands/oscommands/gui_io.go
+++ b/pkg/commands/oscommands/gui_io.go
@@ -39,11 +39,13 @@ func NewGuiIO(log *logrus.Entry, logCommandFn func(string, bool), newCmdWriterFn
}
}
+// we use this function when we want to access the functionality of our OS struct but we
+// don't have anywhere to log things, or request input from the user.
func NewNullGuiIO(log *logrus.Entry) *guiIO {
return &guiIO{
log: log,
logCommandFn: func(string, bool) {},
newCmdWriterFn: func() io.Writer { return ioutil.Discard },
- promptForCredentialFn: func(CredentialType) string { return "" },
+ promptForCredentialFn: failPromptFn,
}
}