Skip to content

Commit

Permalink
parse short scp-like syntax into proper ssh urls
Browse files Browse the repository at this point in the history
currently we're lelying on an underlying library (libssh2) to be able to
handle the shorter `[user@]host:path` syntax, but we should be good
citizens and convert it ourselves.

one key thing to note is that we don't convert any syntax that omits the
user (i.e. `host:path`). while git allows this and will use the current
user (i.e. cnb), this is a behaviour we don't want people to rely on.

Signed-off-by: Bohan Chen <danielchen97dc@gmail.com>
  • Loading branch information
chenbh committed Nov 10, 2022
1 parent 5fe3f96 commit 50c1b4a
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 2 deletions.
2 changes: 1 addition & 1 deletion pkg/git/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (f Fetcher) Fetch(dir, gitURL, gitRevision, metadataDir string) error {
}
defer repository.Free()

remote, err := repository.Remotes.CreateWithOptions(gitURL, &git2go.RemoteCreateOptions{
remote, err := repository.Remotes.CreateWithOptions(parseURL(gitURL), &git2go.RemoteCreateOptions{
Name: "origin",
Flags: git2go.RemoteCreateSkipInsteadof,
})
Expand Down
2 changes: 1 addition & 1 deletion pkg/git/remote_git_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (*remoteGitResolver) Resolve(keychain GitKeychain, sourceConfig corev1alpha
}
defer repository.Free()

remote, err := repository.Remotes.CreateWithOptions(sourceConfig.Git.URL, &git2go.RemoteCreateOptions{
remote, err := repository.Remotes.CreateWithOptions(parseURL(sourceConfig.Git.URL), &git2go.RemoteCreateOptions{
Name: defaultRemote,
Flags: git2go.RemoteCreateSkipInsteadof,
})
Expand Down
26 changes: 26 additions & 0 deletions pkg/git/url_parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package git

import (
"fmt"
"regexp"
)

var shortScpRegex = regexp.MustCompile(`^(ssh://)?(.*)@([[:alnum:]\.-]+):(.*)$`)

// ParseURL converts a short scp-like SSH syntax to a proper SSH URL.
// Git's ssh protocol supports a url like user@hostname:path syntax, which is
// not a valid ssh url but is inherited from scp. Because the library we
// use for git relies on the Golang SSH support, we need to convert it to a
// proper SSH URL.
// See https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols
func parseURL(url string) string {
parts := shortScpRegex.FindStringSubmatch(url)
if len(parts) == 0 {
return url
}
if parts[1] == "ssh://" {
return url
}

return fmt.Sprintf("ssh://%v@%v/%v", parts[2], parts[3], parts[4])
}
59 changes: 59 additions & 0 deletions pkg/git/url_parser_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package git

import (
"testing"

"github.com/sclevine/spec"
"github.com/stretchr/testify/assert"
)

func TestParseURL(t *testing.T) {
spec.Focus(t, "Test Parse Git URL", testParseURL)
}

func testParseURL(t *testing.T, when spec.G, it spec.S) {
type entry struct {
url string
expected string
}

testURLs := func(table []entry) {
for _, e := range table {
assert.Equal(t, e.expected, parseURL(e.url))
}
}

// https: //stackoverflow.com/questions/31801271/what-are-the-supported-git-url-formats
when("using the local protcol", func() {
it("parses the url correctly", func() {
testURLs([]entry{
{url: "/path/to/repo.git", expected: "/path/to/repo.git"},
{url: "file:///path/to/repo.git", expected: "file:///path/to/repo.git"},
})
})
})
when("using the https protcol", func() {
it("parses the url correctly", func() {
testURLs([]entry{
{url: "http://host.xz/path/to/repo.git", expected: "http://host.xz/path/to/repo.git"},
{url: "https://host.xz/path/to/repo.git", expected: "https://host.xz/path/to/repo.git"},
})
})
})
when("using the ssh protcol", func() {
it("parses the url correctly", func() {
testURLs([]entry{
{url: "ssh://user@host.xz:port/path/to/repo.git/", expected: "ssh://user@host.xz:port/path/to/repo.git/"},
{url: "ssh://user@host.xz/path/to/repo.git/", expected: "ssh://user@host.xz/path/to/repo.git/"},
{url: "user@host.xz:path/to/repo.git", expected: "ssh://user@host.xz/path/to/repo.git"},
})
})
})
when("using the git protcol", func() {
it("parses the url correctly", func() {
testURLs([]entry{
{url: "git://host.xz/path/to/repo.git", expected: "git://host.xz/path/to/repo.git"},
})
})
})
}

0 comments on commit 50c1b4a

Please sign in to comment.