240929.2 · 4161403a1d6286f6ba7898b1f22f30d01d85b8dc
--tmux: Export bash functions
Fix #4001
reading declarations
@@ -9,6 +9,7 @@ import ( "os/exec" "os/signal" "path/filepath"+ "regexp" "strings" "time" @@ -32,7 +33,7 @@ func fifo(name string) (string, error) { return output, nil } -func runProxy(commandPrefix string, cmdBuilder func(temp string) *exec.Cmd, opts *Options, withExports bool) (int, error) {+func runProxy(commandPrefix string, cmdBuilder func(temp string, needBash bool) (*exec.Cmd, error), opts *Options, withExports bool) (int, error) { output, err := fifo("proxy-output") if err != nil { return ExitError, err@@ -92,17 +93,28 @@ func runProxy(commandPrefix string, cmdBuilder func(temp string) *exec.Cmd, opts // To ensure that the options are processed by a POSIX-compliant shell, // we need to write the command to a temporary file and execute it with sh. var exports []string+ needBash := false if withExports {- exports = os.Environ()- for idx, pairStr := range exports {+ validIdentifier := regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)+ for _, pairStr := range os.Environ() { pair := strings.SplitN(pairStr, "=", 2)- exports[idx] = fmt.Sprintf("export %s=%s", pair[0], escapeSingleQuote(pair[1]))+ if validIdentifier.MatchString(pair[0]) {+ exports = append(exports, fmt.Sprintf("export %s=%s", pair[0], escapeSingleQuote(pair[1])))+ } else if strings.HasPrefix(pair[0], "BASH_FUNC_") && strings.HasSuffix(pair[0], "%%") {+ name := pair[0][10 : len(pair[0])-2]+ exports = append(exports, name+pair[1])+ exports = append(exports, "export -f "+name)+ needBash = true+ } } } temp := WriteTemporaryFile(append(exports, command), "\n") defer os.Remove(temp) - cmd := cmdBuilder(temp)+ cmd, err := cmdBuilder(temp, needBash)+ if err != nil {+ return ExitError, err+ } cmd.Stderr = os.Stderr intChan := make(chan os.Signal, 1) defer close(intChan)
@@ -9,7 +9,10 @@ import ( "golang.org/x/sys/unix" ) -func sh() (string, error) {+func sh(bash bool) (string, error) {+ if bash {+ return "bash", nil+ } return "sh", nil }
@@ -13,12 +13,16 @@ import ( var shPath atomic.Value -func sh() (string, error) {+func sh(bash bool) (string, error) { if cached := shPath.Load(); cached != nil { return cached.(string), nil } - cmd := exec.Command("cygpath", "-w", "/usr/bin/sh")+ name := "sh"+ if bash {+ name = "bash"+ }+ cmd := exec.Command("cygpath", "-w", "/usr/bin/"+name) bytes, err := cmd.Output() if err != nil { return "", err@@ -31,7 +35,7 @@ func sh() (string, error) { func mkfifo(path string, mode uint32) (string, error) { m := strconv.FormatUint(uint64(mode), 8)- sh, err := sh()+ sh, err := sh(false) if err != nil { return path, err }@@ -43,7 +47,7 @@ func mkfifo(path string, mode uint32) (string, error) { } func withOutputPipe(output string, task func(io.ReadCloser)) error {- sh, err := sh()+ sh, err := sh(false) if err != nil { return err }@@ -62,7 +66,7 @@ func withOutputPipe(output string, task func(io.ReadCloser)) error { } func withInputPipe(input string, task func(io.WriteCloser)) error {- sh, err := sh()+ sh, err := sh(false) if err != nil { return err }
@@ -49,9 +49,12 @@ func runTmux(args []string, opts *Options) (int, error) { tmuxArgs = append(tmuxArgs, "-w"+opts.Tmux.width.String()) tmuxArgs = append(tmuxArgs, "-h"+opts.Tmux.height.String()) - return runProxy(argStr, func(temp string) *exec.Cmd {- sh, _ := sh()+ return runProxy(argStr, func(temp string, needBash bool) (*exec.Cmd, error) {+ sh, err := sh(needBash)+ if err != nil {+ return nil, err+ } tmuxArgs = append(tmuxArgs, sh, temp)- return exec.Command("tmux", tmuxArgs...)+ return exec.Command("tmux", tmuxArgs...), nil }, opts, true) }
@@ -44,11 +44,6 @@ func needWinpty(opts *Options) bool { } func runWinpty(args []string, opts *Options) (int, error) {- sh, err := sh()- if err != nil {- return ExitError, err- }- argStr := escapeSingleQuote(args[0]) for _, arg := range args[1:] { argStr += " " + escapeSingleQuote(arg)@@ -56,20 +51,30 @@ func runWinpty(args []string, opts *Options) (int, error) { argStr += ` --no-winpty` if isMintty345() {- return runProxy(argStr, func(temp string) *exec.Cmd {+ return runProxy(argStr, func(temp string, needBash bool) (*exec.Cmd, error) {+ sh, err := sh(needBash)+ if err != nil {+ return nil, err+ }+ cmd := exec.Command(sh, temp) cmd.Env = append(os.Environ(), "MSYS=enable_pcon") cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr- return cmd+ return cmd, nil }, opts, false) } - return runProxy(argStr, func(temp string) *exec.Cmd {+ return runProxy(argStr, func(temp string, needBash bool) (*exec.Cmd, error) {+ sh, err := sh(needBash)+ if err != nil {+ return nil, err+ }+ cmd := exec.Command(sh, "-c", fmt.Sprintf(`winpty < /dev/tty > /dev/tty -- sh %q`, temp)) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr- return cmd+ return cmd, nil }, opts, false) }