Skip to content

Commit 75c53e3

Browse files
authored
Merge pull request #3682 from crazy-max/bake-print-subdir
bake: preserve git subdir in remote bake context paths
2 parents 00cc36c + 50fa13d commit 75c53e3

File tree

3 files changed

+89
-4
lines changed

3 files changed

+89
-4
lines changed

bake/bake.go

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"io"
99
"maps"
10+
"net/url"
1011
"os"
1112
"path"
1213
"path/filepath"
@@ -29,6 +30,7 @@ import (
2930
hcl "github.com/hashicorp/hcl/v2"
3031
"github.com/moby/buildkit/client"
3132
"github.com/moby/buildkit/client/llb"
33+
"github.com/moby/buildkit/frontend/dockerfile/dfgitutil"
3234
"github.com/pkg/errors"
3335
"github.com/zclconf/go-cty/cty"
3436
"github.com/zclconf/go-cty/cty/convert"
@@ -1310,7 +1312,7 @@ func updateContext(t *build.Inputs, inp *Input) {
13101312
st := llb.Scratch().File(llb.Copy(*inp.State, v.Path, "/", &llb.CopyInfo{
13111313
CopyDirContentsOnly: true,
13121314
}), llb.WithCustomNamef("set context %s to %s", k, v.Path))
1313-
t.NamedContexts[k] = build.NamedContext{State: &st, Path: inp.URL}
1315+
t.NamedContexts[k] = build.NamedContext{State: &st, Path: remoteURLWithSubdir(inp.URL, v.Path)}
13141316
}
13151317

13161318
if t.ContextPath == "." {
@@ -1330,7 +1332,44 @@ func updateContext(t *build.Inputs, inp *Input) {
13301332
llb.WithCustomNamef("set context to %s", t.ContextPath),
13311333
)
13321334
t.ContextState = &st
1333-
t.ContextPath = inp.URL
1335+
t.ContextPath = remoteURLWithSubdir(inp.URL, t.ContextPath)
1336+
}
1337+
1338+
func remoteURLWithSubdir(remoteURL, subdir string) string {
1339+
subdir = path.Clean(subdir)
1340+
if subdir == "." || remoteURL == "" {
1341+
return remoteURL
1342+
}
1343+
1344+
// only relevant for git urls
1345+
parsed, ok, err := dfgitutil.ParseGitRef(remoteURL)
1346+
if err != nil || !ok {
1347+
return remoteURL
1348+
}
1349+
if parsed.SubDir != "" {
1350+
subdir = path.Clean(path.Join(parsed.SubDir, subdir))
1351+
}
1352+
1353+
// keep query string and transport style untouched nad only append/adjust
1354+
// fragment subdir
1355+
if !strings.Contains(remoteURL, "#") && subdir != "" {
1356+
if u, err := url.Parse(remoteURL); err == nil {
1357+
q := u.Query()
1358+
if q.Has("subdir") {
1359+
q.Set("subdir", subdir)
1360+
u.RawQuery = q.Encode()
1361+
return u.String()
1362+
}
1363+
}
1364+
}
1365+
1366+
// otherwise, we adjust the fragment part to add/replace subdir
1367+
base, frag, _ := strings.Cut(remoteURL, "#")
1368+
ref, _, _ := strings.Cut(frag, ":")
1369+
if ref == "" {
1370+
return base + "#:" + subdir
1371+
}
1372+
return base + "#" + ref + ":" + subdir
13341373
}
13351374

13361375
func collectLocalPaths(t build.Inputs) []string {

bake/bake_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2415,6 +2415,52 @@ target "mtx" {
24152415
}
24162416
}
24172417

2418+
func TestRemoteURLWithSubdir(t *testing.T) {
2419+
tests := []struct {
2420+
name string
2421+
remote string
2422+
subdir string
2423+
want string
2424+
}{
2425+
{
2426+
name: "git no ref",
2427+
remote: "https://github.com/docker/buildx.git",
2428+
subdir: "components/interface",
2429+
want: "https://github.com/docker/buildx.git#:components/interface",
2430+
},
2431+
{
2432+
name: "git with ref",
2433+
remote: "https://github.com/docker/buildx.git#main",
2434+
subdir: "components/interface",
2435+
want: "https://github.com/docker/buildx.git#main:components/interface",
2436+
},
2437+
{
2438+
name: "git with existing subdir",
2439+
remote: "https://github.com/docker/buildx.git#main:base",
2440+
subdir: "components/interface",
2441+
want: "https://github.com/docker/buildx.git#main:base/components/interface",
2442+
},
2443+
{
2444+
name: "git query ref",
2445+
remote: "https://github.com/docker/buildx.git?branch=main",
2446+
subdir: "components/interface",
2447+
want: "https://github.com/docker/buildx.git?branch=main#:components/interface",
2448+
},
2449+
{
2450+
name: "non git",
2451+
remote: "https://example.com/context.tar.gz",
2452+
subdir: "components/interface",
2453+
want: "https://example.com/context.tar.gz",
2454+
},
2455+
}
2456+
for _, tt := range tests {
2457+
t.Run(tt.name, func(t *testing.T) {
2458+
got := remoteURLWithSubdir(tt.remote, tt.subdir)
2459+
assert.Equal(t, tt.want, got)
2460+
})
2461+
}
2462+
}
2463+
24182464
func stringify[V fmt.Stringer](values []V) []string {
24192465
s := make([]string, len(values))
24202466
for i, v := range values {

tests/bake.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -565,12 +565,12 @@ COPY super-cool.txt /
565565
}{
566566
{
567567
name: "no ref",
568-
expectedContext: addr,
568+
expectedContext: addr + "#:bar",
569569
},
570570
{
571571
name: "branch ref",
572572
ref: "main",
573-
expectedContext: addr + "#main",
573+
expectedContext: addr + "#main:bar",
574574
},
575575
}
576576
for _, tt := range tests {

0 commit comments

Comments
 (0)