mirror of
https://github.com/moby/buildkit.git
synced 2025-10-25 16:57:55 +03:00
Sources are a pretty neat extension point, except there are a few code paths that hard-code against each type. This moves code around and adjusts interfaces so that Source implementations are self-contained and merely need to be registered with the source.Manager. Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
111 lines
2.5 KiB
Go
111 lines
2.5 KiB
Go
package git
|
|
|
|
import (
|
|
"net/url"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/moby/buildkit/solver/llbsolver/provenance"
|
|
"github.com/moby/buildkit/source"
|
|
srctypes "github.com/moby/buildkit/source/types"
|
|
"github.com/moby/buildkit/util/sshutil"
|
|
)
|
|
|
|
type GitIdentifier struct {
|
|
Remote string
|
|
Ref string
|
|
Subdir string
|
|
KeepGitDir bool
|
|
AuthTokenSecret string
|
|
AuthHeaderSecret string
|
|
MountSSHSock string
|
|
KnownSSHHosts string
|
|
}
|
|
|
|
func NewGitIdentifier(remoteURL string) (*GitIdentifier, error) {
|
|
repo := GitIdentifier{}
|
|
|
|
if !isGitTransport(remoteURL) {
|
|
remoteURL = "https://" + remoteURL
|
|
}
|
|
|
|
var fragment string
|
|
if sshutil.IsImplicitSSHTransport(remoteURL) {
|
|
// implicit ssh urls such as "git@.." are not actually a URL, so cannot be parsed as URL
|
|
parts := strings.SplitN(remoteURL, "#", 2)
|
|
|
|
repo.Remote = parts[0]
|
|
if len(parts) == 2 {
|
|
fragment = parts[1]
|
|
}
|
|
repo.Ref, repo.Subdir = getRefAndSubdir(fragment)
|
|
} else {
|
|
u, err := url.Parse(remoteURL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
repo.Ref, repo.Subdir = getRefAndSubdir(u.Fragment)
|
|
u.Fragment = ""
|
|
repo.Remote = u.String()
|
|
}
|
|
if sd := path.Clean(repo.Subdir); sd == "/" || sd == "." {
|
|
repo.Subdir = ""
|
|
}
|
|
return &repo, nil
|
|
}
|
|
|
|
func (GitIdentifier) Scheme() string {
|
|
return srctypes.GitScheme
|
|
}
|
|
|
|
var _ source.Identifier = (*GitIdentifier)(nil)
|
|
|
|
func (id *GitIdentifier) Capture(c *provenance.Capture, pin string) error {
|
|
url := id.Remote
|
|
if id.Ref != "" {
|
|
url += "#" + id.Ref
|
|
}
|
|
c.AddGit(provenance.GitSource{
|
|
URL: url,
|
|
Commit: pin,
|
|
})
|
|
if id.AuthTokenSecret != "" {
|
|
c.AddSecret(provenance.Secret{
|
|
ID: id.AuthTokenSecret,
|
|
Optional: true,
|
|
})
|
|
}
|
|
if id.AuthHeaderSecret != "" {
|
|
c.AddSecret(provenance.Secret{
|
|
ID: id.AuthHeaderSecret,
|
|
Optional: true,
|
|
})
|
|
}
|
|
if id.MountSSHSock != "" {
|
|
c.AddSSH(provenance.SSH{
|
|
ID: id.MountSSHSock,
|
|
Optional: true,
|
|
})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// isGitTransport returns true if the provided str is a git transport by inspecting
|
|
// the prefix of the string for known protocols used in git.
|
|
func isGitTransport(str string) bool {
|
|
return strings.HasPrefix(str, "http://") || strings.HasPrefix(str, "https://") || strings.HasPrefix(str, "git://") || strings.HasPrefix(str, "ssh://") || sshutil.IsImplicitSSHTransport(str)
|
|
}
|
|
|
|
func getRefAndSubdir(fragment string) (ref string, subdir string) {
|
|
refAndDir := strings.SplitN(fragment, ":", 2)
|
|
ref = ""
|
|
if len(refAndDir[0]) != 0 {
|
|
ref = refAndDir[0]
|
|
}
|
|
if len(refAndDir) > 1 && len(refAndDir[1]) != 0 {
|
|
subdir = refAndDir[1]
|
|
}
|
|
return
|
|
}
|