fix `kratos new -r` not support scp styled git url.issue https://gith… (#2295)
* fix `kratos new -r` not support scp styled git url.issue https://github.com/go-kratos/kratos/issues/2294 * fix lint * fix lint * remove tail space and add test case Co-authored-by: czyt <czyt@w.cn> Co-authored-by: czyt <x-gopher@qq.com>pull/2312/head
parent
890bc21ac1
commit
20c2425c18
@ -0,0 +1,58 @@ |
||||
package base |
||||
|
||||
import ( |
||||
"errors" |
||||
"net/url" |
||||
"regexp" |
||||
"strings" |
||||
) |
||||
|
||||
var ( |
||||
scpSyntaxRe = regexp.MustCompile(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`) |
||||
scheme = []string{"git", "https", "http", "git+ssh", "ssh", "file", "ftp", "ftps"} |
||||
) |
||||
|
||||
// ParseVCSUrl ref https://github.com/golang/go/blob/master/src/cmd/go/internal/vcs/vcs.go
|
||||
// see https://go-review.googlesource.com/c/go/+/12226/
|
||||
// git url define https://git-scm.com/docs/git-clone#_git_urls
|
||||
func ParseVCSUrl(repo string) (*url.URL, error) { |
||||
var ( |
||||
repoURL *url.URL |
||||
err error |
||||
) |
||||
|
||||
if m := scpSyntaxRe.FindStringSubmatch(repo); m != nil { |
||||
// Match SCP-like syntax and convert it to a URL.
|
||||
// Eg, "git@github.com:user/repo" becomes
|
||||
// "ssh://git@github.com/user/repo".
|
||||
repoURL = &url.URL{ |
||||
Scheme: "ssh", |
||||
User: url.User(m[1]), |
||||
Host: m[2], |
||||
Path: m[3], |
||||
} |
||||
} else { |
||||
if !strings.Contains(repo, "//") { |
||||
repo = "//" + repo |
||||
} |
||||
if strings.HasPrefix(repo, "//git@") { |
||||
repo = "ssh:" + repo |
||||
} else if strings.HasPrefix(repo, "//") { |
||||
repo = "https:" + repo |
||||
} |
||||
repoURL, err = url.Parse(repo) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
} |
||||
|
||||
// Iterate over insecure schemes too, because this function simply
|
||||
// reports the state of the repo. If we can't see insecure schemes then
|
||||
// we can't report the actual repo URL.
|
||||
for _, s := range scheme { |
||||
if repoURL.Scheme == s { |
||||
return repoURL, nil |
||||
} |
||||
} |
||||
return nil, errors.New("unable to parse repo url") |
||||
} |
@ -0,0 +1,55 @@ |
||||
package base |
||||
|
||||
import ( |
||||
"net" |
||||
"strings" |
||||
"testing" |
||||
) |
||||
|
||||
func TestParseVCSUrl(t *testing.T) { |
||||
repos := []string{ |
||||
// ssh://[user@]host.xz[:port]/path/to/repo.git/
|
||||
"ssh://git@github.com:7875/go-kratos/kratos.git", |
||||
// git://host.xz[:port]/path/to/repo.git/
|
||||
"git://github.com:7875/go-kratos/kratos.git", |
||||
// http[s]://host.xz[:port]/path/to/repo.git/
|
||||
"https://github.com:7875/go-kratos/kratos.git", |
||||
// ftp[s]://host.xz[:port]/path/to/repo.git/
|
||||
"ftps://github.com:7875/go-kratos/kratos.git", |
||||
//[user@]host.xz:path/to/repo.git/
|
||||
"git@github.com:go-kratos/kratos.git", |
||||
// ssh://[user@]host.xz[:port]/~[user]/path/to/repo.git/
|
||||
"ssh://git@github.com:7875/go-kratos/kratos.git", |
||||
// git://host.xz[:port]/~[user]/path/to/repo.git/
|
||||
"git://github.com:7875/go-kratos/kratos.git", |
||||
//[user@]host.xz:/~[user]/path/to/repo.git/
|
||||
"git@github.com:go-kratos/kratos.git", |
||||
///path/to/repo.git/
|
||||
"~/go-kratos/kratos.git", |
||||
// file:///path/to/repo.git/
|
||||
"file://~/go-kratos/kratos.git", |
||||
} |
||||
for _, repo := range repos { |
||||
url, err := ParseVCSUrl(repo) |
||||
if err != nil { |
||||
t.Fatal(repo, err) |
||||
} |
||||
urlPath := strings.TrimLeft(url.Path, "/") |
||||
if urlPath != "go-kratos/kratos.git" { |
||||
t.Fatal(repo, "parse url failed", urlPath) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestParseSsh(t *testing.T) { |
||||
repo := "ssh://git@github.com:7875/go-kratos/kratos.git" |
||||
url, err := ParseVCSUrl(repo) |
||||
if err != nil { |
||||
t.Fatal(err) |
||||
} |
||||
host, _, err := net.SplitHostPort(url.Host) |
||||
if err != nil { |
||||
host = url.Host |
||||
} |
||||
t.Log(host, url.Path) |
||||
} |
Loading…
Reference in new issue