aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Stribling <strib@keyba.se>2017-07-31 15:34:45 -0700
committerJeremy Stribling <strib@alum.mit.edu>2017-08-03 10:46:03 -0700
commitc128f5d680f59fd125cafd90f10e39eae5f3a135 (patch)
tree234a5da875d8c01dbd7e5ebe06ab8fc845cf8100
parent63b30fba572b7e70833fae4785c6d22f167c6641 (diff)
downloadgo-git-c128f5d680f59fd125cafd90f10e39eae5f3a135.tar.gz
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.
-rw-r--r--plumbing/transport/file/client.go55
-rw-r--r--plumbing/transport/file/client_test.go22
2 files changed, 75 insertions, 2 deletions
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
diff --git a/plumbing/transport/file/client_test.go b/plumbing/transport/file/client_test.go
index 030175e..3532a4c 100644
--- a/plumbing/transport/file/client_test.go
+++ b/plumbing/transport/file/client_test.go
@@ -14,6 +14,28 @@ import (
func Test(t *testing.T) { TestingT(t) }
+type ClientSuite struct {
+ CommonSuite
+}
+
+var _ = Suite(&ClientSuite{})
+
+func (s *ClientSuite) TestCommand(c *C) {
+ runner := &runner{
+ UploadPackBin: transport.UploadPackServiceName,
+ ReceivePackBin: transport.ReceivePackServiceName,
+ }
+ ep, err := transport.NewEndpoint(filepath.Join("fake", "repo"))
+ c.Assert(err, IsNil)
+ var emptyAuth transport.AuthMethod
+ _, err = runner.Command("git-receive-pack", ep, emptyAuth)
+ c.Assert(err, IsNil)
+
+ // Make sure we get an error for one that doesn't exist.
+ _, err = runner.Command("git-fake-command", ep, emptyAuth)
+ c.Assert(os.IsNotExist(err), Equals, true)
+}
+
const bareConfig = `[core]
repositoryformatversion = 0
filemode = true