Skip to content
This repository has been archived by the owner on Sep 11, 2020. It is now read-only.

Commit

Permalink
plumbing: fix pack commands for the file client on Windows
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
strib committed Aug 3, 2017
1 parent 63b30fb commit c128f5d
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 2 deletions.
55 changes: 53 additions & 2 deletions plumbing/transport/file/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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) {

Expand All @@ -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
Expand Down
22 changes: 22 additions & 0 deletions plumbing/transport/file/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit c128f5d

Please sign in to comment.