mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
vendor: update buildkit to master@cbfd4023383d
Signed-off-by: Justin Chadwell <me@jedevc.com>
This commit is contained in:
243
vendor/github.com/moby/buildkit/util/gitutil/git_cli.go
generated
vendored
Normal file
243
vendor/github.com/moby/buildkit/util/gitutil/git_cli.go
generated
vendored
Normal file
@ -0,0 +1,243 @@
|
||||
package gitutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// GitCLI carries config to pass to the git cli to make running multiple
|
||||
// commands less repetitive.
|
||||
type GitCLI struct {
|
||||
git string
|
||||
exec func(context.Context, *exec.Cmd) error
|
||||
|
||||
args []string
|
||||
dir string
|
||||
streams StreamFunc
|
||||
|
||||
workTree string
|
||||
gitDir string
|
||||
|
||||
sshAuthSock string
|
||||
sshKnownHosts string
|
||||
}
|
||||
|
||||
// Option provides a variadic option for configuring the git client.
|
||||
type Option func(b *GitCLI)
|
||||
|
||||
// WithGitBinary sets the git binary path.
|
||||
func WithGitBinary(path string) Option {
|
||||
return func(b *GitCLI) {
|
||||
b.git = path
|
||||
}
|
||||
}
|
||||
|
||||
// WithExec sets the command exec function.
|
||||
func WithExec(exec func(context.Context, *exec.Cmd) error) Option {
|
||||
return func(b *GitCLI) {
|
||||
b.exec = exec
|
||||
}
|
||||
}
|
||||
|
||||
// WithArgs sets extra args.
|
||||
func WithArgs(args ...string) Option {
|
||||
return func(b *GitCLI) {
|
||||
b.args = append(b.args, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// WithDir sets working directory.
|
||||
//
|
||||
// This should be a path to any directory within a standard git repository.
|
||||
func WithDir(dir string) Option {
|
||||
return func(b *GitCLI) {
|
||||
b.dir = dir
|
||||
}
|
||||
}
|
||||
|
||||
// WithWorkTree sets the --work-tree arg.
|
||||
//
|
||||
// This should be the path to the top-level directory of the checkout. When
|
||||
// setting this, you also likely need to set WithGitDir.
|
||||
func WithWorkTree(workTree string) Option {
|
||||
return func(b *GitCLI) {
|
||||
b.workTree = workTree
|
||||
}
|
||||
}
|
||||
|
||||
// WithGitDir sets the --git-dir arg.
|
||||
//
|
||||
// This should be the path to the .git directory. When setting this, you may
|
||||
// also need to set WithWorkTree, unless you are working with a bare
|
||||
// repository.
|
||||
func WithGitDir(gitDir string) Option {
|
||||
return func(b *GitCLI) {
|
||||
b.gitDir = gitDir
|
||||
}
|
||||
}
|
||||
|
||||
// WithSSHAuthSock sets the ssh auth sock.
|
||||
func WithSSHAuthSock(sshAuthSock string) Option {
|
||||
return func(b *GitCLI) {
|
||||
b.sshAuthSock = sshAuthSock
|
||||
}
|
||||
}
|
||||
|
||||
// WithSSHKnownHosts sets the known hosts file.
|
||||
func WithSSHKnownHosts(sshKnownHosts string) Option {
|
||||
return func(b *GitCLI) {
|
||||
b.sshKnownHosts = sshKnownHosts
|
||||
}
|
||||
}
|
||||
|
||||
type StreamFunc func(context.Context) (io.WriteCloser, io.WriteCloser, func())
|
||||
|
||||
// WithStreams configures a callback for getting the streams for a command. The
|
||||
// stream callback will be called once for each command, and both writers will
|
||||
// be closed after the command has finished.
|
||||
func WithStreams(streams StreamFunc) Option {
|
||||
return func(b *GitCLI) {
|
||||
b.streams = streams
|
||||
}
|
||||
}
|
||||
|
||||
// New initializes a new git client
|
||||
func NewGitCLI(opts ...Option) *GitCLI {
|
||||
c := &GitCLI{}
|
||||
for _, opt := range opts {
|
||||
opt(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// New returns a new git client with the same config as the current one, but
|
||||
// with the given options applied on top.
|
||||
func (cli *GitCLI) New(opts ...Option) *GitCLI {
|
||||
c := &GitCLI{
|
||||
git: cli.git,
|
||||
dir: cli.dir,
|
||||
workTree: cli.workTree,
|
||||
gitDir: cli.gitDir,
|
||||
args: append([]string{}, cli.args...),
|
||||
streams: cli.streams,
|
||||
sshAuthSock: cli.sshAuthSock,
|
||||
sshKnownHosts: cli.sshKnownHosts,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Run executes a git command with the given args.
|
||||
func (cli *GitCLI) Run(ctx context.Context, args ...string) (_ []byte, err error) {
|
||||
gitBinary := "git"
|
||||
if cli.git != "" {
|
||||
gitBinary = cli.git
|
||||
}
|
||||
|
||||
for {
|
||||
var cmd *exec.Cmd
|
||||
if cli.exec == nil {
|
||||
cmd = exec.CommandContext(ctx, gitBinary)
|
||||
} else {
|
||||
cmd = exec.Command(gitBinary)
|
||||
}
|
||||
|
||||
cmd.Dir = cli.dir
|
||||
if cmd.Dir == "" {
|
||||
cmd.Dir = cli.workTree
|
||||
}
|
||||
|
||||
// Block sneaky repositories from using repos from the filesystem as submodules.
|
||||
cmd.Args = append(cmd.Args, "-c", "protocol.file.allow=user")
|
||||
if cli.workTree != "" {
|
||||
cmd.Args = append(cmd.Args, "--work-tree", cli.workTree)
|
||||
}
|
||||
if cli.gitDir != "" {
|
||||
cmd.Args = append(cmd.Args, "--git-dir", cli.gitDir)
|
||||
}
|
||||
cmd.Args = append(cmd.Args, cli.args...)
|
||||
cmd.Args = append(cmd.Args, args...)
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
errbuf := bytes.NewBuffer(nil)
|
||||
cmd.Stdin = nil
|
||||
cmd.Stdout = buf
|
||||
cmd.Stderr = errbuf
|
||||
if cli.streams != nil {
|
||||
stdout, stderr, flush := cli.streams(ctx)
|
||||
if stdout != nil {
|
||||
cmd.Stdout = io.MultiWriter(stdout, cmd.Stdout)
|
||||
}
|
||||
if stderr != nil {
|
||||
cmd.Stderr = io.MultiWriter(stderr, cmd.Stderr)
|
||||
}
|
||||
defer stdout.Close()
|
||||
defer stderr.Close()
|
||||
defer func() {
|
||||
if err != nil {
|
||||
flush()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
cmd.Env = []string{
|
||||
"PATH=" + os.Getenv("PATH"),
|
||||
"GIT_TERMINAL_PROMPT=0",
|
||||
"GIT_SSH_COMMAND=" + getGitSSHCommand(cli.sshKnownHosts),
|
||||
// "GIT_TRACE=1",
|
||||
"GIT_CONFIG_NOSYSTEM=1", // Disable reading from system gitconfig.
|
||||
"HOME=/dev/null", // Disable reading from user gitconfig.
|
||||
"LC_ALL=C", // Ensure consistent output.
|
||||
}
|
||||
if cli.sshAuthSock != "" {
|
||||
cmd.Env = append(cmd.Env, "SSH_AUTH_SOCK="+cli.sshAuthSock)
|
||||
}
|
||||
|
||||
if cli.exec != nil {
|
||||
// remote git commands spawn helper processes that inherit FDs and don't
|
||||
// handle parent death signal so exec.CommandContext can't be used
|
||||
err = cli.exec(ctx, cmd)
|
||||
} else {
|
||||
err = cmd.Run()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if strings.Contains(errbuf.String(), "--depth") || strings.Contains(errbuf.String(), "shallow") {
|
||||
if newArgs := argsNoDepth(args); len(args) > len(newArgs) {
|
||||
args = newArgs
|
||||
continue
|
||||
}
|
||||
}
|
||||
return buf.Bytes(), errors.Errorf("git error: %s\nstderr:\n%s", err, errbuf.String())
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
}
|
||||
|
||||
func getGitSSHCommand(knownHosts string) string {
|
||||
gitSSHCommand := "ssh -F /dev/null"
|
||||
if knownHosts != "" {
|
||||
gitSSHCommand += " -o UserKnownHostsFile=" + knownHosts
|
||||
} else {
|
||||
gitSSHCommand += " -o StrictHostKeyChecking=no"
|
||||
}
|
||||
return gitSSHCommand
|
||||
}
|
||||
|
||||
func argsNoDepth(args []string) []string {
|
||||
out := make([]string, 0, len(args))
|
||||
for _, a := range args {
|
||||
if a != "--depth=1" {
|
||||
out = append(out, a)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
44
vendor/github.com/moby/buildkit/util/gitutil/git_cli_helpers.go
generated
vendored
Normal file
44
vendor/github.com/moby/buildkit/util/gitutil/git_cli_helpers.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
package gitutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (cli *GitCLI) Dir() string {
|
||||
if cli.dir != "" {
|
||||
return cli.dir
|
||||
}
|
||||
return cli.workTree
|
||||
}
|
||||
|
||||
func (cli *GitCLI) WorkTree(ctx context.Context) (string, error) {
|
||||
if cli.workTree != "" {
|
||||
return cli.workTree, nil
|
||||
}
|
||||
return cli.clean(cli.Run(ctx, "rev-parse", "--show-toplevel"))
|
||||
}
|
||||
|
||||
func (cli *GitCLI) GitDir(ctx context.Context) (string, error) {
|
||||
if cli.gitDir != "" {
|
||||
return cli.gitDir, nil
|
||||
}
|
||||
|
||||
dir, err := cli.WorkTree(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(dir, ".git"), nil
|
||||
}
|
||||
|
||||
func (cli *GitCLI) clean(dt []byte, err error) (string, error) {
|
||||
out := string(dt)
|
||||
out = strings.ReplaceAll(strings.Split(out, "\n")[0], "'", "")
|
||||
if err != nil {
|
||||
err = errors.New(strings.TrimSuffix(err.Error(), "\n"))
|
||||
}
|
||||
return out, err
|
||||
}
|
46
vendor/github.com/moby/buildkit/util/gitutil/git_protocol.go
generated
vendored
46
vendor/github.com/moby/buildkit/util/gitutil/git_protocol.go
generated
vendored
@ -1,46 +0,0 @@
|
||||
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
|
||||
}
|
47
vendor/github.com/moby/buildkit/util/gitutil/git_ref.go
generated
vendored
47
vendor/github.com/moby/buildkit/util/gitutil/git_ref.go
generated
vendored
@ -1,10 +1,11 @@
|
||||
package gitutil
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// GitRef represents a git ref.
|
||||
@ -51,35 +52,51 @@ type GitRef struct {
|
||||
func ParseGitRef(ref string) (*GitRef, error) {
|
||||
res := &GitRef{}
|
||||
|
||||
var (
|
||||
remote *url.URL
|
||||
err error
|
||||
)
|
||||
|
||||
if strings.HasPrefix(ref, "github.com/") {
|
||||
res.IndistinguishableFromLocal = true // Deprecated
|
||||
} else {
|
||||
_, proto := ParseProtocol(ref)
|
||||
switch proto {
|
||||
case UnknownProtocol:
|
||||
return nil, errdefs.ErrInvalidArgument
|
||||
remote = &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "github.com",
|
||||
Path: strings.TrimPrefix(ref, "github.com/"),
|
||||
}
|
||||
switch proto {
|
||||
} else {
|
||||
remote, err = ParseURL(ref)
|
||||
if errors.Is(err, ErrUnknownProtocol) {
|
||||
remote, err = ParseURL("https://" + ref)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch remote.Scheme {
|
||||
case HTTPProtocol, GitProtocol:
|
||||
res.UnencryptedTCP = true // Discouraged, but not deprecated
|
||||
}
|
||||
switch proto {
|
||||
|
||||
switch remote.Scheme {
|
||||
// An HTTP(S) URL is considered to be a valid git ref only when it has the ".git[...]" suffix.
|
||||
case HTTPProtocol, HTTPSProtocol:
|
||||
var gitURLPathWithFragmentSuffix = regexp.MustCompile(`\.git(?:#.+)?$`)
|
||||
if !gitURLPathWithFragmentSuffix.MatchString(ref) {
|
||||
if !strings.HasSuffix(remote.Path, ".git") {
|
||||
return nil, errdefs.ErrInvalidArgument
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var fragment string
|
||||
res.Remote, fragment, _ = strings.Cut(ref, "#")
|
||||
if len(res.Remote) == 0 {
|
||||
return res, errdefs.ErrInvalidArgument
|
||||
res.Commit, res.SubDir = SplitGitFragment(remote.Fragment)
|
||||
remote.Fragment = ""
|
||||
|
||||
res.Remote = remote.String()
|
||||
if res.IndistinguishableFromLocal {
|
||||
_, res.Remote, _ = strings.Cut(res.Remote, "://")
|
||||
}
|
||||
res.Commit, res.SubDir, _ = strings.Cut(fragment, ":")
|
||||
|
||||
repoSplitBySlash := strings.Split(res.Remote, "/")
|
||||
res.ShortName = strings.TrimSuffix(repoSplitBySlash[len(repoSplitBySlash)-1], ".git")
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
71
vendor/github.com/moby/buildkit/util/gitutil/git_url.go
generated
vendored
Normal file
71
vendor/github.com/moby/buildkit/util/gitutil/git_url.go
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
package gitutil
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/moby/buildkit/util/sshutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
HTTPProtocol string = "http"
|
||||
HTTPSProtocol string = "https"
|
||||
SSHProtocol string = "ssh"
|
||||
GitProtocol string = "git"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUnknownProtocol = errors.New("unknown protocol")
|
||||
ErrInvalidProtocol = errors.New("invalid protocol")
|
||||
)
|
||||
|
||||
var supportedProtos = map[string]struct{}{
|
||||
HTTPProtocol: {},
|
||||
HTTPSProtocol: {},
|
||||
SSHProtocol: {},
|
||||
GitProtocol: {},
|
||||
}
|
||||
|
||||
var protoRegexp = regexp.MustCompile(`^[a-zA-Z0-9]+://`)
|
||||
|
||||
// ParseURL parses a git URL and returns a parsed URL object.
|
||||
//
|
||||
// ParseURL understands implicit ssh URLs such as "git@host:repo", and
|
||||
// returns the same response as if the URL were "ssh://git@host/repo".
|
||||
func ParseURL(remote string) (*url.URL, error) {
|
||||
if proto := protoRegexp.FindString(remote); proto != "" {
|
||||
proto = strings.ToLower(strings.TrimSuffix(proto, "://"))
|
||||
if _, ok := supportedProtos[proto]; !ok {
|
||||
return nil, errors.Wrap(ErrInvalidProtocol, proto)
|
||||
}
|
||||
|
||||
return url.Parse(remote)
|
||||
}
|
||||
|
||||
if sshutil.IsImplicitSSHTransport(remote) {
|
||||
remote, fragment, _ := strings.Cut(remote, "#")
|
||||
remote, path, _ := strings.Cut(remote, ":")
|
||||
user, host, _ := strings.Cut(remote, "@")
|
||||
if !strings.HasPrefix(path, "/") {
|
||||
path = "/" + path
|
||||
}
|
||||
return &url.URL{
|
||||
Scheme: SSHProtocol,
|
||||
User: url.User(user),
|
||||
Host: host,
|
||||
Path: path,
|
||||
Fragment: fragment,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, ErrUnknownProtocol
|
||||
}
|
||||
|
||||
// SplitGitFragments splits a git URL fragment into its respective git
|
||||
// reference and subdirectory components.
|
||||
func SplitGitFragment(fragment string) (ref string, subdir string) {
|
||||
ref, subdir, _ = strings.Cut(fragment, ":")
|
||||
return ref, subdir
|
||||
}
|
Reference in New Issue
Block a user