aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2017-12-11 13:24:12 +0100
committerGitHub <noreply@github.com>2017-12-11 13:24:12 +0100
commitafdd28d3cfe11c280723c4f5f33845fd415350d6 (patch)
tree19a209865143ff9aa746bb36ee7ba28208161b6f
parente9037637fbcf832e0325a3884d9ae360c3c4dc2c (diff)
parent264d094d8dce590d00fba1683cb7c74ff0c01a74 (diff)
downloadgo-git-afdd28d3cfe11c280723c4f5f33845fd415350d6.tar.gz
Merge pull request #687 from smithrobs/sshconfig
check .ssh/config for host and port overrides; fixes #629
-rw-r--r--plumbing/transport/ssh/common.go43
-rw-r--r--plumbing/transport/ssh/common_test.go67
2 files changed, 110 insertions, 0 deletions
diff --git a/plumbing/transport/ssh/common.go b/plumbing/transport/ssh/common.go
index f5bc9a7..e4a3d18 100644
--- a/plumbing/transport/ssh/common.go
+++ b/plumbing/transport/ssh/common.go
@@ -4,16 +4,26 @@ package ssh
import (
"fmt"
"reflect"
+ "strconv"
"gopkg.in/src-d/go-git.v4/plumbing/transport"
"gopkg.in/src-d/go-git.v4/plumbing/transport/internal/common"
+ "github.com/kevinburke/ssh_config"
"golang.org/x/crypto/ssh"
)
// DefaultClient is the default SSH client.
var DefaultClient = NewClient(nil)
+// DefaultSSHConfig is the reader used to access parameters stored in the
+// system's ssh_config files. If nil all the ssh_config are ignored.
+var DefaultSSHConfig sshConfig = ssh_config.DefaultUserSettings
+
+type sshConfig interface {
+ Get(alias, key string) string
+}
+
// NewClient creates a new SSH client with an optional *ssh.ClientConfig.
func NewClient(config *ssh.ClientConfig) transport.Transport {
return common.NewClient(&runner{config: config})
@@ -121,6 +131,10 @@ func (c *command) connect() error {
}
func (c *command) getHostWithPort() string {
+ if addr, found := c.doGetHostWithPortFromSSHConfig(); found {
+ return addr
+ }
+
host := c.endpoint.Host
port := c.endpoint.Port
if port <= 0 {
@@ -130,6 +144,35 @@ func (c *command) getHostWithPort() string {
return fmt.Sprintf("%s:%d", host, port)
}
+func (c *command) doGetHostWithPortFromSSHConfig() (addr string, found bool) {
+ if DefaultSSHConfig == nil {
+ return
+ }
+
+ host := c.endpoint.Host
+ port := c.endpoint.Port
+
+ configHost := DefaultSSHConfig.Get(c.endpoint.Host, "Hostname")
+ if configHost != "" {
+ host = configHost
+ found = true
+ }
+
+ if !found {
+ return
+ }
+
+ configPort := DefaultSSHConfig.Get(c.endpoint.Host, "Port")
+ if configPort != "" {
+ if i, err := strconv.Atoi(configPort); err == nil {
+ port = i
+ }
+ }
+
+ addr = fmt.Sprintf("%s:%d", host, port)
+ return
+}
+
func (c *command) setAuthFromEndpoint() error {
var err error
c.auth, err = DefaultAuthBuilder(c.endpoint.User)
diff --git a/plumbing/transport/ssh/common_test.go b/plumbing/transport/ssh/common_test.go
index 5315e28..faa0503 100644
--- a/plumbing/transport/ssh/common_test.go
+++ b/plumbing/transport/ssh/common_test.go
@@ -3,9 +3,12 @@ package ssh
import (
"testing"
+ "github.com/kevinburke/ssh_config"
+
"golang.org/x/crypto/ssh"
. "gopkg.in/check.v1"
+ "gopkg.in/src-d/go-git.v4/plumbing/transport"
)
func Test(t *testing.T) { TestingT(t) }
@@ -39,3 +42,67 @@ func (s *SuiteCommon) TestOverrideConfigKeep(c *C) {
overrideConfig(config, target)
c.Assert(target.User, Equals, "foo")
}
+
+func (s *SuiteCommon) TestDefaultSSHConfig(c *C) {
+ defer func() {
+ DefaultSSHConfig = ssh_config.DefaultUserSettings
+ }()
+
+ DefaultSSHConfig = &mockSSHConfig{map[string]map[string]string{
+ "github.com": map[string]string{
+ "Hostname": "foo.local",
+ "Port": "42",
+ },
+ }}
+
+ ep, err := transport.NewEndpoint("git@github.com:foo/bar.git")
+ c.Assert(err, IsNil)
+
+ cmd := &command{endpoint: ep}
+ c.Assert(cmd.getHostWithPort(), Equals, "foo.local:42")
+}
+
+func (s *SuiteCommon) TestDefaultSSHConfigNil(c *C) {
+ defer func() {
+ DefaultSSHConfig = ssh_config.DefaultUserSettings
+ }()
+
+ DefaultSSHConfig = nil
+
+ ep, err := transport.NewEndpoint("git@github.com:foo/bar.git")
+ c.Assert(err, IsNil)
+
+ cmd := &command{endpoint: ep}
+ c.Assert(cmd.getHostWithPort(), Equals, "github.com:22")
+}
+
+func (s *SuiteCommon) TestDefaultSSHConfigWildcard(c *C) {
+ defer func() {
+ DefaultSSHConfig = ssh_config.DefaultUserSettings
+ }()
+
+ DefaultSSHConfig = &mockSSHConfig{Values: map[string]map[string]string{
+ "*": map[string]string{
+ "Port": "42",
+ },
+ }}
+
+ ep, err := transport.NewEndpoint("git@github.com:foo/bar.git")
+ c.Assert(err, IsNil)
+
+ cmd := &command{endpoint: ep}
+ c.Assert(cmd.getHostWithPort(), Equals, "github.com:22")
+}
+
+type mockSSHConfig struct {
+ Values map[string]map[string]string
+}
+
+func (c *mockSSHConfig) Get(alias, key string) string {
+ a, ok := c.Values[alias]
+ if !ok {
+ return c.Values["*"][key]
+ }
+
+ return a[key]
+}