diff --git a/client/llb/source.go b/client/llb/source.go index f00099c31a00..7d389e8bda1f 100644 --- a/client/llb/source.go +++ b/client/llb/source.go @@ -11,6 +11,7 @@ import ( "github.com/docker/distribution/reference" "github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/util/apicaps" + "github.com/moby/buildkit/util/gitutil" "github.com/moby/buildkit/util/sshutil" digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" @@ -198,52 +199,14 @@ type ImageInfo struct { RecordType string } -const ( - gitProtocolHTTP = iota + 1 - gitProtocolHTTPS - gitProtocolSSH - gitProtocolGit - gitProtocolUnknown -) - -func getGitProtocol(remote string) (string, int) { - prefixes := map[string]int{ - "http://": gitProtocolHTTP, - "https://": gitProtocolHTTPS, - "git://": gitProtocolGit, - "ssh://": gitProtocolSSH, - } - protocolType := gitProtocolUnknown - for prefix, potentialType := range prefixes { - if strings.HasPrefix(remote, prefix) { - remote = strings.TrimPrefix(remote, prefix) - protocolType = potentialType - } - } - - if protocolType == gitProtocolUnknown && sshutil.IsImplicitSSHTransport(remote) { - protocolType = gitProtocolSSH - } - - // remove name from ssh - if protocolType == gitProtocolSSH { - parts := strings.SplitN(remote, "@", 2) - if len(parts) == 2 { - remote = parts[1] - } - } - - return remote, protocolType -} - func Git(remote, ref string, opts ...GitOption) State { url := strings.Split(remote, "#")[0] var protocolType int - remote, protocolType = getGitProtocol(remote) + remote, protocolType = gitutil.ParseProtocol(remote) var sshHost string - if protocolType == gitProtocolSSH { + if protocolType == gitutil.SSHProtocol { parts := strings.SplitN(remote, ":", 2) if len(parts) == 2 { sshHost = parts[0] @@ -251,7 +214,7 @@ func Git(remote, ref string, opts ...GitOption) State { remote = parts[0] + "/" + parts[1] } } - if protocolType == gitProtocolUnknown { + if protocolType == gitutil.UnknownProtocol { url = "https://" + url } @@ -289,7 +252,7 @@ func Git(remote, ref string, opts ...GitOption) State { addCap(&gi.Constraints, pb.CapSourceGitHTTPAuth) } } - if protocolType == gitProtocolSSH { + if protocolType == gitutil.SSHProtocol { if gi.KnownSSHHosts != "" { attrs[pb.AttrKnownSSHHosts] = gi.KnownSSHHosts } else if sshHost != "" { diff --git a/util/gitutil/git_protocol.go b/util/gitutil/git_protocol.go new file mode 100644 index 000000000000..3b9df83920b7 --- /dev/null +++ b/util/gitutil/git_protocol.go @@ -0,0 +1,46 @@ +package gitutil + +import ( + "strings" + + "github.com/moby/buildkit/util/sshutil" +) + +const ( + HTTPProtocol = iota + 1 + HTTPSProtocol + SSHProtocol + GitProtocol + UnknownProtocol +) + +// ParseProtocol parses a git URL and returns the remote url and protocol type +func ParseProtocol(remote string) (string, int) { + prefixes := map[string]int{ + "http://": HTTPProtocol, + "https://": HTTPSProtocol, + "git://": GitProtocol, + "ssh://": SSHProtocol, + } + protocolType := UnknownProtocol + for prefix, potentialType := range prefixes { + if strings.HasPrefix(remote, prefix) { + remote = strings.TrimPrefix(remote, prefix) + protocolType = potentialType + } + } + + if protocolType == UnknownProtocol && sshutil.IsImplicitSSHTransport(remote) { + protocolType = SSHProtocol + } + + // remove name from ssh + if protocolType == SSHProtocol { + parts := strings.SplitN(remote, "@", 2) + if len(parts) == 2 { + remote = parts[1] + } + } + + return remote, protocolType +} diff --git a/util/gitutil/git_protocol_test.go b/util/gitutil/git_protocol_test.go new file mode 100644 index 000000000000..6ebdb6671337 --- /dev/null +++ b/util/gitutil/git_protocol_test.go @@ -0,0 +1,51 @@ +package gitutil + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseProtocol(t *testing.T) { + tests := []struct { + url string + protocol int + remote string + }{ + { + url: "http://github.com/moby/buildkit", + protocol: HTTPProtocol, + remote: "github.com/moby/buildkit", + }, + { + url: "https://github.com/moby/buildkit", + protocol: HTTPSProtocol, + remote: "github.com/moby/buildkit", + }, + { + url: "git@github.com:moby/buildkit.git", + protocol: SSHProtocol, + remote: "github.com:moby/buildkit.git", + }, + { + url: "nonstandarduser@example.com:/srv/repos/weird/project.git", + protocol: SSHProtocol, + remote: "example.com:/srv/repos/weird/project.git", + }, + { + url: "ssh://root@subdomain.example.hostname:2222/root/my/really/weird/path/foo.git", + protocol: SSHProtocol, + remote: "subdomain.example.hostname:2222/root/my/really/weird/path/foo.git", + }, + { + url: "git://host.xz:1234/path/to/repo.git", + protocol: GitProtocol, + remote: "host.xz:1234/path/to/repo.git", + }, + } + for _, test := range tests { + remote, protocol := ParseProtocol(test.url) + require.Equal(t, remote, test.remote) + require.Equal(t, protocol, test.protocol) + } +}