summaryrefslogtreecommitdiffstats
path: root/pkg/commands/os.go
diff options
context:
space:
mode:
authormjarkk <mkopenga@gmail.com>2018-10-17 20:38:13 +0200
committermjarkk <mkopenga@gmail.com>2018-10-17 20:38:13 +0200
commitcecd5733a8e455677f61b1eb861133f50954e8a5 (patch)
treeb98c36e50928bbe856b9e5af19e8e5f69912c5db /pkg/commands/os.go
parent1d733f3adc65fc1bc449c5d2590db1384acf7473 (diff)
Basic file for getting the fix working
Diffstat (limited to 'pkg/commands/os.go')
-rw-r--r--pkg/commands/os.go88
1 files changed, 88 insertions, 0 deletions
diff --git a/pkg/commands/os.go b/pkg/commands/os.go
index c8ca40f29..5e11844b6 100644
--- a/pkg/commands/os.go
+++ b/pkg/commands/os.go
@@ -1,13 +1,17 @@
package commands
import (
+ "bufio"
"errors"
"os"
"os/exec"
+ "regexp"
"strings"
+ "github.com/ionrock/procs"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/utils"
+ "github.com/kr/pty"
"github.com/mgutz/str"
@@ -57,6 +61,90 @@ func (c *OSCommand) RunCommandWithOutput(command string) (string, error) {
)
}
+// RunCommandWithOutputLive runs a command and return every word that gets written in stdout
+// Output is a function that executes by every word that gets read by bufio
+// As return of output you need to give a string that will be written to stdin
+// NOTE: If the return data is empty it won't written anything to stdin
+// NOTE: You don't have to include a enter in the return data this function will do that for you
+func (c *OSCommand) RunCommandWithOutputLive(command string, output func(string) string) error {
+ splitCmd := str.ToArgv(command)
+ cmd := exec.Command(splitCmd[0], splitCmd[1:]...)
+
+ cmd.Env = procs.Env(map[string]string{
+ "LANG": "en_US.utf8",
+ "LC_ALL": "en_US.UTF-8",
+ }, true)
+
+ tty, err := pty.Start(cmd)
+
+ if err != nil {
+ return err
+ }
+
+ defer func() { _ = tty.Close() }()
+
+ go func() {
+ // Regex to cleanup the command output
+ re := regexp.MustCompile(`(^\s*)|(\s*$)`)
+
+ scanner := bufio.NewScanner(tty)
+ scanner.Split(bufio.ScanWords)
+ for scanner.Scan() {
+ toWrite := output(re.ReplaceAllString(scanner.Text(), ""))
+ if len(toWrite) > 0 {
+ tty.Write([]byte(toWrite + "\n"))
+ }
+ }
+ }()
+
+ if err := cmd.Wait(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// DetectUnamePass detect a username / password question in a command
+// ask is a function that gets executen when this function detect you need to fillin a password
+// The ask argument will be "username" or "password" and expects the user's password or username back
+func (c *OSCommand) DetectUnamePass(command string, ask func(string) string) error {
+ ttyText := ""
+ errors := []error{}
+ err := c.RunCommandWithOutputLive(command, func(word string) string {
+ ttyText = ttyText + " " + word
+
+ // detect username question
+ detectUname, err := regexp.MatchString(`Username\s*for\s*'.+':`, ttyText)
+ if err != nil {
+ errors = append(errors, err)
+ }
+ if detectUname {
+ // reset the text and return the user's username
+ ttyText = ""
+ return ask("username")
+ }
+
+ // detect password question
+ detectPass, err := regexp.MatchString(`Password\s*for\s*'.+':`, ttyText)
+ if err != nil {
+ errors = append(errors, err)
+ }
+ if detectPass {
+ // reset the text and return the user's username
+ ttyText = ""
+ return ask("password")
+ }
+ return ""
+ })
+ if err != nil {
+ return err
+ }
+ if len(errors) > 0 {
+ return errors[0]
+ }
+ return nil
+}
+
// RunCommand runs a command and just returns the error
func (c *OSCommand) RunCommand(command string) error {
_, err := c.RunCommandWithOutput(command)