From 1067c24df29191a73341bba49f4eaa0a733b6094 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Mon, 28 May 2018 21:15:05 -0700 Subject: [PATCH] git: support all git transports Signed-off-by: Tonis Tiigi --- client/llb/source.go | 15 +++++++++++++ frontend/dockerfile/builder/build.go | 31 ++++++++++++++++++-------- frontend/dockerfile/dockerfile_test.go | 6 ++--- solver/pb/attr.go | 1 + source/identifier.go | 2 ++ 5 files changed, 43 insertions(+), 12 deletions(-) diff --git a/client/llb/source.go b/client/llb/source.go index 23629d85e3d5..e7e92abede22 100644 --- a/client/llb/source.go +++ b/client/llb/source.go @@ -141,7 +141,19 @@ type ImageInfo struct { } func Git(remote, ref string, opts ...GitOption) State { + url := "" + + for _, prefix := range []string{ + "http://", "https://", "git://", "git@", + } { + if strings.HasPrefix(remote, prefix) { + url = strings.Split(remote, "#")[0] + remote = strings.TrimPrefix(remote, prefix) + } + } + id := remote + if ref != "" { id += "#" + ref } @@ -154,6 +166,9 @@ func Git(remote, ref string, opts ...GitOption) State { if gi.KeepGitDir { attrs[pb.AttrKeepGitDir] = "true" } + if url != "" { + attrs[pb.AttrFullRemoteURL] = url + } source := NewSource("git://"+id, attrs, gi.Metadata()) return NewState(source.Output()) } diff --git a/frontend/dockerfile/builder/build.go b/frontend/dockerfile/builder/build.go index 820816c6f89c..57a92cb2535a 100644 --- a/frontend/dockerfile/builder/build.go +++ b/frontend/dockerfile/builder/build.go @@ -26,11 +26,11 @@ const ( dockerignoreFilename = ".dockerignore" buildArgPrefix = "build-arg:" labelPrefix = "label:" - gitPrefix = "git://" keyNoCache = "no-cache" ) var httpPrefix = regexp.MustCompile("^https?://") +var gitUrlPathWithFragmentSuffix = regexp.MustCompile(".git(?:#.+)?$") func Build(ctx context.Context, c client.Client) error { opts := c.Opts() @@ -55,12 +55,10 @@ func Build(ctx context.Context, c client.Client) error { llb.SharedKeyHint(defaultDockerfileName), ) var buildContext *llb.State - if strings.HasPrefix(opts[LocalNameContext], gitPrefix) { - src = parseGitSource(opts[LocalNameContext]) + if st, ok := detectGitContext(opts[LocalNameContext]); ok { + src = *st buildContext = &src - } - - if httpPrefix.MatchString(opts[LocalNameContext]) { + } else if httpPrefix.MatchString(opts[LocalNameContext]) { unpack := llb.Image(dockerfile2llb.CopyImage).Run(llb.Shlex("copy --unpack /src/context /out/"), llb.ReadonlyRootFS()) unpack.AddMount("/src", llb.HTTP(opts[LocalNameContext], llb.Filename("context")), llb.Readonly) src = unpack.AddMount("/out", llb.Scratch()) @@ -196,12 +194,27 @@ func filter(opt map[string]string, key string) map[string]string { return m } -func parseGitSource(ref string) llb.State { - ref = strings.TrimPrefix(ref, gitPrefix) +func detectGitContext(ref string) (*llb.State, bool) { + found := false + if httpPrefix.MatchString(ref) && gitUrlPathWithFragmentSuffix.MatchString(ref) { + found = true + } + + for _, prefix := range []string{"git://", "github.com/", "git@"} { + if strings.HasPrefix(ref, prefix) { + found = true + break + } + } + if !found { + return nil, false + } + parts := strings.SplitN(ref, "#", 2) branch := "" if len(parts) > 1 { branch = parts[1] } - return llb.Git(parts[0], branch) + st := llb.Git(parts[0], branch) + return &st, true } diff --git a/frontend/dockerfile/dockerfile_test.go b/frontend/dockerfile/dockerfile_test.go index 290562161293..6ab38d03d58e 100644 --- a/frontend/dockerfile/dockerfile_test.go +++ b/frontend/dockerfile/dockerfile_test.go @@ -1387,7 +1387,7 @@ COPY --from=build foo bar2 ) require.NoError(t, err) - server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join(gitDir, ".git")))) + server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join(gitDir)))) defer server.Close() destDir, err := ioutil.TempDir("", "buildkit") @@ -1401,7 +1401,7 @@ COPY --from=build foo bar2 _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ Frontend: "dockerfile.v0", FrontendAttrs: map[string]string{ - "context": "git://" + server.URL + "/#first", + "context": server.URL + "/.git#first", }, Exporter: client.ExporterLocal, ExporterOutputDir: destDir, @@ -1424,7 +1424,7 @@ COPY --from=build foo bar2 _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ Frontend: "dockerfile.v0", FrontendAttrs: map[string]string{ - "context": "git://" + server.URL + "/", + "context": server.URL + "/.git", }, Exporter: client.ExporterLocal, ExporterOutputDir: destDir, diff --git a/solver/pb/attr.go b/solver/pb/attr.go index 631c16610442..ffbb67a7784f 100644 --- a/solver/pb/attr.go +++ b/solver/pb/attr.go @@ -1,6 +1,7 @@ package pb const AttrKeepGitDir = "git.keepgitdir" +const AttrFullRemoteURL = "git.fullurl" const AttrLocalSessionID = "local.session" const AttrIncludePatterns = "local.includepattern" const AttrExcludePatterns = "local.excludepatterns" diff --git a/source/identifier.go b/source/identifier.go index a5356de6fbc7..0782cceef9d3 100644 --- a/source/identifier.go +++ b/source/identifier.go @@ -62,6 +62,8 @@ func FromLLB(op *pb.Op_Source) (Identifier, error) { if v == "true" { id.KeepGitDir = true } + case pb.AttrFullRemoteURL: + id.Remote = v } } }