From e97dabe6b0211915f6853bfeaa71b9d34dfe6667 Mon Sep 17 00:00:00 2001 From: Jeremy Stribling Date: Wed, 2 Aug 2017 14:52:46 -0700 Subject: [PATCH] plumbing: use --exec-path to find pack executables Suggested by smola. Issue: #527 --- plumbing/transport/file/client.go | 48 ++++++++++++++++++- plumbing/transport/file/client_cmd_unix.go | 18 ------- plumbing/transport/file/client_cmd_windows.go | 29 ----------- 3 files changed, 47 insertions(+), 48 deletions(-) delete mode 100644 plumbing/transport/file/client_cmd_unix.go delete mode 100644 plumbing/transport/file/client_cmd_windows.go diff --git a/plumbing/transport/file/client.go b/plumbing/transport/file/client.go index 3d058aa0c..f093a7b94 100644 --- a/plumbing/transport/file/client.go +++ b/plumbing/transport/file/client.go @@ -2,9 +2,13 @@ package file import ( + "bufio" + "errors" "io" "os" "os/exec" + "path/filepath" + "strings" "gopkg.in/src-d/go-git.v4/plumbing/transport" "gopkg.in/src-d/go-git.v4/plumbing/transport/internal/common" @@ -30,6 +34,38 @@ func NewClient(uploadPackBin, receivePackBin string) transport.Transport { }) } +func prefixExecPath(cmd string) (string, error) { + // Use `git --exec-path` to find the exec path. + execCmd := exec.Command("git", "--exec-path") + + stdout, err := execCmd.StdoutPipe() + if err != nil { + return "", err + } + stdoutBuf := bufio.NewReader(stdout) + + err = execCmd.Start() + if err != nil { + return "", err + } + + execPathBytes, isPrefix, err := stdoutBuf.ReadLine() + if err != nil { + return "", err + } + if isPrefix { + return "", errors.New("Couldn't read exec-path line all at once") + } + + err = execCmd.Wait() + if err != nil { + return "", err + } + execPath := string(execPathBytes) + execPath = strings.TrimSpace(execPath) + return filepath.Join(execPath, cmd), nil +} + func (r *runner) Command(cmd string, ep transport.Endpoint, auth transport.AuthMethod, ) (common.Command, error) { @@ -40,7 +76,17 @@ func (r *runner) Command(cmd string, ep transport.Endpoint, auth transport.AuthM cmd = r.ReceivePackBin } - return makeCommand(cmd, ep) + _, err := exec.LookPath(cmd) + if err != nil { + if e, ok := err.(*exec.Error); ok && e.Err == exec.ErrNotFound { + cmd, err = prefixExecPath(cmd) + if err != nil { + return nil, err + } + } + } + + return &command{cmd: exec.Command(cmd, ep.Path())}, nil } type command struct { diff --git a/plumbing/transport/file/client_cmd_unix.go b/plumbing/transport/file/client_cmd_unix.go deleted file mode 100644 index abe3e9ffd..000000000 --- a/plumbing/transport/file/client_cmd_unix.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build !windows - -package file - -import ( - "os/exec" - - "gopkg.in/src-d/go-git.v4/plumbing/transport" - "gopkg.in/src-d/go-git.v4/plumbing/transport/internal/common" -) - -func makeCommand(cmd string, ep transport.Endpoint) (common.Command, error) { - if _, err := exec.LookPath(cmd); err != nil { - return nil, err - } - - return &command{cmd: exec.Command(cmd, ep.Path())}, nil -} diff --git a/plumbing/transport/file/client_cmd_windows.go b/plumbing/transport/file/client_cmd_windows.go deleted file mode 100644 index b58bbb2da..000000000 --- a/plumbing/transport/file/client_cmd_windows.go +++ /dev/null @@ -1,29 +0,0 @@ -// +build windows - -package file - -import ( - "os/exec" - "strings" - - "gopkg.in/src-d/go-git.v4/plumbing/transport" - "gopkg.in/src-d/go-git.v4/plumbing/transport/internal/common" -) - -// In the default Windows git install, there is no separate -// git-upload-pack or git-receive-pack binaries; we must use "git -// upload-pack" and "git receive-pack" instead. -func makeCommand(cmd string, ep transport.Endpoint) (common.Command, error) { - var subcommands []string - if strings.HasPrefix(cmd, "git-") { - subcommands = strings.SplitN(cmd, "-", 2) - cmd = subcommands[0] - } - - if _, err := exec.LookPath(cmd); err != nil { - return nil, err - } - - return &command{cmd: exec.Command( - cmd, append(subcommands[1:], ep.Path())...)}, nil -}