diff --git a/cmd/jb/main_test.go b/cmd/jb/main_test.go index 52c841a..c299103 100644 --- a/cmd/jb/main_test.go +++ b/cmd/jb/main_test.go @@ -64,7 +64,7 @@ func TestParseDependency(t *testing.T) { }, { name: "SSH", - path: "git+ssh://git@github.com:jsonnet-bundler/jsonnet-bundler.git", + path: "git+ssh://git@github.com/jsonnet-bundler/jsonnet-bundler.git", want: &deps.Dependency{ Source: deps.Source{ GitSource: &deps.Git{ diff --git a/spec/deps/git.go b/spec/deps/git.go index e547850..c201084 100644 --- a/spec/deps/git.go +++ b/spec/deps/git.go @@ -87,7 +87,7 @@ func (gs *Git) LegacyName() string { } var gitProtoFmts = map[string]string{ - GitSchemeSSH: GitSchemeSSH + "%s:%s/%s.git", + GitSchemeSSH: GitSchemeSSH + "%s/%s/%s.git", GitSchemeHTTPS: GitSchemeHTTPS + "%s/%s/%s", } @@ -100,20 +100,18 @@ func (gs *Git) Remote() string { // regular expressions for matching package uris const ( - gitSSHExp = `git\+ssh://git@(?P[^:]+):(?P[^/]+)/(?P[^/]+).git` + gitSSHExp = `ssh://git@(?P.+)/(?P.+)/(?P.+).git` + gitSCPExp = `^git@(?P.+):(?P.+)/(?P.+).git` githubSlugExp = `github.com/(?P[-_a-zA-Z0-9]+)/(?P[-_a-zA-Z0-9]+)` ) var ( - gitSSHRegex = regexp.MustCompile(gitSSHExp) - gitSSHWithVersionRegex = regexp.MustCompile(gitSSHExp + `@(?P.*)`) - gitSSHWithPathRegex = regexp.MustCompile(gitSSHExp + `/(?P.*)`) - gitSSHWithPathAndVersionRegex = regexp.MustCompile(gitSSHExp + `/(?P.*)@(?P.*)`) + gitSSHRegex = regexp.MustCompile(gitSSHExp) + githubSlugRegex = regexp.MustCompile(githubSlugExp) - githubSlugRegex = regexp.MustCompile(githubSlugExp) - githubSlugWithVersionRegex = regexp.MustCompile(githubSlugExp + `@(?P.*)`) - githubSlugWithPathRegex = regexp.MustCompile(githubSlugExp + `/(?P.*)`) - githubSlugWithPathAndVersionRegex = regexp.MustCompile(githubSlugExp + `/(?P.*)@(?P.*)`) + VersionRegex = `@(?P.*)` + PathRegex = `/(?P.*)` + PathAndVersionRegex = `/(?P.*)@(?P.*)` ) func parseGit(uri string) *Dependency { @@ -125,10 +123,16 @@ func parseGit(uri string) *Dependency { var version string switch { - case githubSlugRegex.MatchString(uri): - gs, version = parseGitHub(uri) - case gitSSHRegex.MatchString(uri): - gs, version = parseGitSSH(uri) + case reMatch(gitSSHExp, uri): + gs, version = match(uri, gitSSHExp) + gs.Scheme = GitSchemeSSH + case reMatch(gitSCPExp, uri): + gs, version = match(uri, gitSCPExp) + gs.Scheme = GitSchemeSSH + case reMatch(githubSlugExp, uri): + gs, version = match(uri, githubSlugExp) + gs.Scheme = GitSchemeHTTPS + gs.Host = "github.com" default: return nil } @@ -144,33 +148,16 @@ func parseGit(uri string) *Dependency { return &d } -func parseGitSSH(p string) (gs *Git, version string) { - gs, version = match(p, []*regexp.Regexp{ - gitSSHWithPathAndVersionRegex, - gitSSHWithPathRegex, - gitSSHWithVersionRegex, - gitSSHRegex, - }) - - gs.Scheme = GitSchemeSSH - return gs, version -} - -func parseGitHub(p string) (gs *Git, version string) { - gs, version = match(p, []*regexp.Regexp{ - githubSlugWithPathAndVersionRegex, - githubSlugWithPathRegex, - githubSlugWithVersionRegex, - githubSlugRegex, - }) - - gs.Scheme = GitSchemeHTTPS - gs.Host = "github.com" - return gs, version -} - -func match(p string, exps []*regexp.Regexp) (gs *Git, version string) { +func match(p string, exp string) (gs *Git, version string) { gs = &Git{} + + exps := []*regexp.Regexp{ + regexp.MustCompile(exp + PathAndVersionRegex), + regexp.MustCompile(exp + PathRegex), + regexp.MustCompile(exp + VersionRegex), + regexp.MustCompile(exp), + } + for _, e := range exps { if !e.MatchString(p) { continue @@ -190,6 +177,10 @@ func match(p string, exps []*regexp.Regexp) (gs *Git, version string) { return gs, "" } +func reMatch(exp string, str string) bool { + return regexp.MustCompile(exp).MatchString(str) +} + func reSubMatchMap(r *regexp.Regexp, str string) map[string]string { match := r.FindStringSubmatch(str) subMatchMap := make(map[string]string) diff --git a/spec/deps/git_test.go b/spec/deps/git_test.go index fc95441..ba264cb 100644 --- a/spec/deps/git_test.go +++ b/spec/deps/git_test.go @@ -17,9 +17,23 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestParseGit(t *testing.T) { + sshWant := func(host string) *Dependency { + return &Dependency{ + Version: "v1", + Source: Source{GitSource: &Git{ + Scheme: GitSchemeSSH, + Host: host, + User: "user", + Repo: "repo", + Subdir: "/foobar", + }}, + } + } + tests := []struct { name string uri string @@ -27,7 +41,7 @@ func TestParseGit(t *testing.T) { wantRemote string }{ { - name: "GitHub", + name: "github-slug", uri: "github.com/ksonnet/ksonnet-lib/ksonnet.beta.3", want: &Dependency{ Version: "master", @@ -42,26 +56,28 @@ func TestParseGit(t *testing.T) { wantRemote: "https://github.com/ksonnet/ksonnet-lib", }, { - name: "SSH", - uri: "git+ssh://git@my.host:user/repo.git/foobar@v1", - want: &Dependency{ - Version: "v1", - Source: Source{GitSource: &Git{ - Scheme: GitSchemeSSH, - Host: "my.host", - User: "user", - Repo: "repo", - Subdir: "/foobar", - }}, - }, - wantRemote: "ssh://git@my.host:user/repo.git", + name: "ssh.ssh", + uri: "ssh://git@example.com/user/repo.git/foobar@v1", + want: sshWant("example.com"), + wantRemote: "ssh://git@example.com/user/repo.git", + }, + { + name: "ssh.scp", + uri: "git@my.host:user/repo.git/foobar@v1", + want: sshWant("my.host"), + wantRemote: "ssh://git@my.host/user/repo.git", // want ssh format here }, } for _, c := range tests { t.Run(c.name, func(t *testing.T) { got := Parse("", c.uri) + require.NotNilf(t, got, "parsed dependency is nil. Most likely, no regex matched the format.") + assert.Equal(t, c.want, got) + + require.NotNil(t, got.Source) + require.NotNil(t, got.Source.GitSource) assert.Equal(t, c.wantRemote, got.Source.GitSource.Remote()) }) }