mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
bake: update ReadRemoteFiles to use buildkit api
Signed-off-by: Justin Chadwell <me@jedevc.com>
This commit is contained in:
194
vendor/github.com/moby/buildkit/frontend/dockerui/context.go
generated
vendored
Normal file
194
vendor/github.com/moby/buildkit/frontend/dockerui/context.go
generated
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
package dockerui
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"context"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/moby/buildkit/client/llb"
|
||||
"github.com/moby/buildkit/frontend/gateway/client"
|
||||
gwpb "github.com/moby/buildkit/frontend/gateway/pb"
|
||||
"github.com/moby/buildkit/util/gitutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultLocalNameContext = "context"
|
||||
DefaultLocalNameDockerfile = "dockerfile"
|
||||
DefaultDockerfileName = "Dockerfile"
|
||||
DefaultDockerignoreName = ".dockerignore"
|
||||
EmptyImageName = "scratch"
|
||||
)
|
||||
|
||||
const (
|
||||
keyFilename = "filename"
|
||||
keyContextSubDir = "contextsubdir"
|
||||
keyNameContext = "contextkey"
|
||||
keyNameDockerfile = "dockerfilekey"
|
||||
)
|
||||
|
||||
var httpPrefix = regexp.MustCompile(`^https?://`)
|
||||
|
||||
type buildContext struct {
|
||||
context *llb.State // set if not local
|
||||
dockerfile *llb.State // override remoteContext if set
|
||||
contextLocalName string
|
||||
dockerfileLocalName string
|
||||
filename string
|
||||
forceLocalDockerfile bool
|
||||
}
|
||||
|
||||
func (bc *Client) marshalOpts() []llb.ConstraintsOpt {
|
||||
return []llb.ConstraintsOpt{llb.WithCaps(bc.bopts.Caps)}
|
||||
}
|
||||
|
||||
func (bc *Client) initContext(ctx context.Context) (*buildContext, error) {
|
||||
opts := bc.bopts.Opts
|
||||
gwcaps := bc.bopts.Caps
|
||||
|
||||
localNameContext := DefaultLocalNameContext
|
||||
if v, ok := opts[keyNameContext]; ok {
|
||||
localNameContext = v
|
||||
}
|
||||
|
||||
bctx := &buildContext{
|
||||
contextLocalName: DefaultLocalNameContext,
|
||||
dockerfileLocalName: DefaultLocalNameDockerfile,
|
||||
filename: DefaultDockerfileName,
|
||||
}
|
||||
|
||||
if v, ok := opts[keyFilename]; ok {
|
||||
bctx.filename = v
|
||||
}
|
||||
|
||||
if v, ok := opts[keyNameDockerfile]; ok {
|
||||
bctx.forceLocalDockerfile = true
|
||||
bctx.dockerfileLocalName = v
|
||||
}
|
||||
|
||||
keepGit := false
|
||||
if v, err := strconv.ParseBool(opts[keyContextKeepGitDirArg]); err == nil {
|
||||
keepGit = v
|
||||
}
|
||||
if st, ok := DetectGitContext(opts[localNameContext], keepGit); ok {
|
||||
bctx.context = st
|
||||
bctx.dockerfile = st
|
||||
} else if st, filename, ok := DetectHTTPContext(opts[localNameContext]); ok {
|
||||
def, err := st.Marshal(ctx, bc.marshalOpts()...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to marshal httpcontext")
|
||||
}
|
||||
res, err := bc.client.Solve(ctx, client.SolveRequest{
|
||||
Definition: def.ToPB(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to resolve httpcontext")
|
||||
}
|
||||
|
||||
ref, err := res.SingleRef()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dt, err := ref.ReadFile(ctx, client.ReadRequest{
|
||||
Filename: filename,
|
||||
Range: &client.FileRange{
|
||||
Length: 1024,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to read downloaded context")
|
||||
}
|
||||
if isArchive(dt) {
|
||||
bc := llb.Scratch().File(llb.Copy(*st, filepath.Join("/", filename), "/", &llb.CopyInfo{
|
||||
AttemptUnpack: true,
|
||||
}))
|
||||
bctx.context = &bc
|
||||
} else {
|
||||
bctx.filename = filename
|
||||
bctx.context = st
|
||||
}
|
||||
bctx.dockerfile = bctx.context
|
||||
} else if (&gwcaps).Supports(gwpb.CapFrontendInputs) == nil {
|
||||
inputs, err := bc.client.Inputs(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get frontend inputs")
|
||||
}
|
||||
|
||||
if !bctx.forceLocalDockerfile {
|
||||
inputDockerfile, ok := inputs[bctx.dockerfileLocalName]
|
||||
if ok {
|
||||
bctx.dockerfile = &inputDockerfile
|
||||
}
|
||||
}
|
||||
|
||||
inputCtx, ok := inputs[DefaultLocalNameContext]
|
||||
if ok {
|
||||
bctx.context = &inputCtx
|
||||
}
|
||||
}
|
||||
|
||||
if bctx.context != nil {
|
||||
if sub, ok := opts[keyContextSubDir]; ok {
|
||||
bctx.context = scopeToSubDir(bctx.context, sub)
|
||||
}
|
||||
}
|
||||
|
||||
return bctx, nil
|
||||
}
|
||||
|
||||
func DetectGitContext(ref string, keepGit bool) (*llb.State, bool) {
|
||||
g, err := gitutil.ParseGitRef(ref)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
commit := g.Commit
|
||||
if g.SubDir != "" {
|
||||
commit += ":" + g.SubDir
|
||||
}
|
||||
gitOpts := []llb.GitOption{WithInternalName("load git source " + ref)}
|
||||
if keepGit {
|
||||
gitOpts = append(gitOpts, llb.KeepGitDir())
|
||||
}
|
||||
|
||||
st := llb.Git(g.Remote, commit, gitOpts...)
|
||||
return &st, true
|
||||
}
|
||||
|
||||
func DetectHTTPContext(ref string) (*llb.State, string, bool) {
|
||||
filename := "context"
|
||||
if httpPrefix.MatchString(ref) {
|
||||
st := llb.HTTP(ref, llb.Filename(filename), WithInternalName("load remote build context"))
|
||||
return &st, filename, true
|
||||
}
|
||||
return nil, "", false
|
||||
}
|
||||
|
||||
func isArchive(header []byte) bool {
|
||||
for _, m := range [][]byte{
|
||||
{0x42, 0x5A, 0x68}, // bzip2
|
||||
{0x1F, 0x8B, 0x08}, // gzip
|
||||
{0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}, // xz
|
||||
} {
|
||||
if len(header) < len(m) {
|
||||
continue
|
||||
}
|
||||
if bytes.Equal(m, header[:len(m)]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
r := tar.NewReader(bytes.NewBuffer(header))
|
||||
_, err := r.Next()
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func scopeToSubDir(c *llb.State, dir string) *llb.State {
|
||||
bc := llb.Scratch().File(llb.Copy(*c, dir, "/", &llb.CopyInfo{
|
||||
CopyDirContentsOnly: true,
|
||||
}))
|
||||
return &bc
|
||||
}
|
Reference in New Issue
Block a user