From c128f5d680f59fd125cafd90f10e39eae5f3a135 Mon Sep 17 00:00:00 2001 From: Jeremy Stribling Date: Mon, 31 Jul 2017 15:34:45 -0700 Subject: plumbing: fix pack commands for the file client on Windows The default git install on Windows doesn't come with commands for receive-pack and upload-pack in the default $PATH. Instead, use --exec-path to find pack executables in that case. --- plumbing/transport/file/client.go | 55 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) (limited to 'plumbing/transport/file/client.go') diff --git a/plumbing/transport/file/client.go b/plumbing/transport/file/client.go index 0b42abf..af4a88b 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,45 @@ 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) + cmd = filepath.Join(execPath, cmd) + + // Make sure it actually exists. + _, err = os.Stat(cmd) + if err != nil { + return "", err + } + return cmd, nil +} + func (r *runner) Command(cmd string, ep transport.Endpoint, auth transport.AuthMethod, ) (common.Command, error) { @@ -40,8 +83,16 @@ func (r *runner) Command(cmd string, ep transport.Endpoint, auth transport.AuthM cmd = r.ReceivePackBin } - if _, err := exec.LookPath(cmd); err != nil { - return nil, err + _, 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 + } + } else { + return nil, err + } } return &command{cmd: exec.Command(cmd, ep.Path())}, nil -- cgit