提交 96d8bfc6 编写于 作者: J Jingwen Owen Ou

Merge pull request #679 from github/ssh_url_fix

Ignore replacing ssh host that fixes limited network
package git
import (
"bufio"
"os"
"path/filepath"
"regexp"
"strings"
)
const (
hostReStr = "^[ \t]*(Host|HostName|Hostname)[ \t]+(.+)$"
)
type SSHConfig map[string]string
func newSSHConfigReader() *SSHConfigReader {
return &SSHConfigReader{
Files: []string{
filepath.Join(os.Getenv("HOME"), ".ssh/config"),
"/etc/ssh_config",
"/etc/ssh/ssh_config",
},
}
}
type SSHConfigReader struct {
Files []string
}
func (r *SSHConfigReader) Read() SSHConfig {
config := make(SSHConfig)
hostRe := regexp.MustCompile(hostReStr)
for _, filename := range r.Files {
r.readFile(config, hostRe, filename)
}
return config
}
func (r *SSHConfigReader) readFile(c SSHConfig, re *regexp.Regexp, f string) error {
file, err := os.Open(f)
if err != nil {
return err
}
defer file.Close()
hosts := []string{"*"}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
match := re.FindStringSubmatch(line)
if match == nil {
continue
}
names := strings.Fields(match[2])
if match[1] == "Host" {
hosts = names
} else {
for _, host := range hosts {
for _, name := range names {
c[host] = name
}
}
}
}
return scanner.Err()
}
package git
import (
"io/ioutil"
"os"
"testing"
"github.com/bmizerany/assert"
)
func TestSSHConfigReader_Read(t *testing.T) {
f, _ := ioutil.TempFile("", "ssh-config")
c := `Host github.com
Hostname ssh.github.com
Port 443
`
ioutil.WriteFile(f.Name(), []byte(c), os.ModePerm)
r := &SSHConfigReader{[]string{f.Name()}}
sc := r.Read()
assert.Equal(t, "ssh.github.com", sc["github.com"])
}
package git
import (
"bufio"
"net/url"
"os"
"path/filepath"
"regexp"
"strings"
)
var (
ProtocolRe = regexp.MustCompile("^[a-zA-Z_-]+://")
SshConfigFiles = []string{
filepath.Join(os.Getenv("HOME"), ".ssh/config"),
"/etc/ssh_config",
"/etc/ssh/ssh_config",
}
SshConfig map[string]string
cachedSSHConfig SSHConfig
protocolRe = regexp.MustCompile("^[a-zA-Z_-]+://")
)
func ParseURL(rawurl string) (u *url.URL, err error) {
if !ProtocolRe.MatchString(rawurl) && strings.Contains(rawurl, ":") {
rawurl = "ssh://" + strings.Replace(rawurl, ":", "/", 1)
type URLParser struct {
SSHConfig SSHConfig
}
func (p *URLParser) Parse(rawURL string) (u *url.URL, err error) {
if !protocolRe.MatchString(rawURL) && strings.Contains(rawURL, ":") {
rawURL = "ssh://" + strings.Replace(rawURL, ":", "/", 1)
}
u, err = url.Parse(rawURL)
if err != nil {
return
}
u, err = url.Parse(rawurl)
if err == nil {
if SshConfig == nil {
SshConfig = readSshConfig()
}
if SshConfig[u.Host] != "" {
u.Host = SshConfig[u.Host]
}
sshHost := p.SSHConfig[u.Host]
// ignore replacing host that fixes for limited network
// https://help.github.com/articles/using-ssh-over-the-https-port
ignoredHost := u.Host == "github.com" && sshHost == "ssh.github.com"
if !ignoredHost && sshHost != "" {
u.Host = sshHost
}
return
}
func readSshConfig() map[string]string {
config := make(map[string]string)
hostRe := regexp.MustCompile("^[ \t]*(Host|HostName)[ \t]+(.+)$")
for _, filename := range SshConfigFiles {
file, err := os.Open(filename)
if err != nil {
continue
}
hosts := []string{"*"}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
match := hostRe.FindStringSubmatch(line)
if match == nil {
continue
}
names := strings.Fields(match[2])
if match[1] == "Host" {
hosts = names
} else {
for _, host := range hosts {
for _, name := range names {
config[host] = name
}
}
}
}
file.Close()
func ParseURL(rawURL string) (u *url.URL, err error) {
if cachedSSHConfig == nil {
cachedSSHConfig = newSSHConfigReader().Read()
}
return config
p := &URLParser{cachedSSHConfig}
return p.Parse(rawURL)
}
package git
import (
"github.com/bmizerany/assert"
"testing"
"github.com/bmizerany/assert"
)
func TestURL_ParseURL(t *testing.T) {
u, err := ParseURL("https://github.com/octokit/go-octokit.git")
func TestURLParser_ParseURL(t *testing.T) {
c := make(SSHConfig)
c["github.com"] = "ssh.github.com"
c["git.company.com"] = "ssh.git.company.com"
p := &URLParser{c}
u, err := p.Parse("https://github.com/octokit/go-octokit.git")
assert.Equal(t, nil, err)
assert.Equal(t, "github.com", u.Host)
assert.Equal(t, "https", u.Scheme)
assert.Equal(t, "/octokit/go-octokit.git", u.Path)
u, err = ParseURL("git://github.com/octokit/go-octokit.git")
u, err = p.Parse("git://github.com/octokit/go-octokit.git")
assert.Equal(t, nil, err)
assert.Equal(t, "github.com", u.Host)
assert.Equal(t, "git", u.Scheme)
assert.Equal(t, "/octokit/go-octokit.git", u.Path)
u, err = ParseURL("git@github.com:lostisland/go-sawyer.git")
u, err = p.Parse("git@github.com:lostisland/go-sawyer.git")
assert.Equal(t, nil, err)
assert.Equal(t, "github.com", u.Host)
assert.Equal(t, "ssh", u.Scheme)
assert.Equal(t, "git", u.User.Username())
assert.Equal(t, "/lostisland/go-sawyer.git", u.Path)
u, err = p.Parse("https://git.company.com/octokit/go-octokit.git")
assert.Equal(t, nil, err)
assert.Equal(t, "ssh.git.company.com", u.Host)
assert.Equal(t, "https", u.Scheme)
assert.Equal(t, "/octokit/go-octokit.git", u.Path)
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册