Skip to content

Commit

Permalink
dockerfile: allow pivot point for --parents flag
Browse files Browse the repository at this point in the history
This replicates similar functionality in rsync.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit 6f8bd4c)
  • Loading branch information
tonistiigi committed Mar 4, 2024
1 parent 9195a11 commit d959049
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 7 deletions.
26 changes: 19 additions & 7 deletions frontend/dockerfile/dockerfile2llb/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -1252,18 +1252,30 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error {
a = a.Copy(st, f, dest, opts...)
}
} else {
var patterns []string
if cfg.parents {
// detect optional pivot point
parent, pattern, ok := strings.Cut(src, "/./")
if !ok {
pattern = src
src = "/"
} else {
src = parent
}

pattern, err = system.NormalizePath("/", pattern, d.platform.OS, false)
if err != nil {
return errors.Wrap(err, "removing drive letter")
}

patterns = []string{strings.TrimPrefix(pattern, "/")}
}

src, err = system.NormalizePath("/", src, d.platform.OS, false)
if err != nil {
return errors.Wrap(err, "removing drive letter")
}

var patterns []string
if cfg.parents {
path := strings.TrimPrefix(src, "/")
patterns = []string{path}
src = "/"
}

opts := append([]llb.CopyOption{&llb.CopyInfo{
Mode: mode,
FollowSymlinks: true,
Expand Down
106 changes: 106 additions & 0 deletions frontend/dockerfile/dockerfile_parents_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

var parentsTests = integration.TestFuncs(
testCopyParents,
testCopyRelativeParents,
)

func init() {
Expand Down Expand Up @@ -75,3 +76,108 @@ COPY --parents foo1/foo2/ba* .
require.NoError(t, err)
require.Equal(t, "testing2", string(dt))
}

func testCopyRelativeParents(t *testing.T, sb integration.Sandbox) {
f := getFrontend(t, sb)

dockerfile := []byte(`
FROM alpine AS base
WORKDIR /test
RUN <<eot
set -ex
mkdir -p a/b/c/d/e
mkdir -p a/b2/c/d/e
mkdir -p a/b/c2/d/e
mkdir -p a/b/c2/d/e2
touch a/b/c/d/foo
touch a/b/c/d/e/bay
touch a/b2/c/d/e/bar
touch a/b/c2/d/e/baz
touch a/b/c2/d/e2/baz
eot
FROM alpine AS middle
COPY --from=base --parents /test/a/b/./c/d /out/
RUN <<eot
set -ex
[ -d /out/c/d/e ]
[ -f /out/c/d/foo ]
[ ! -d /out/a ]
[ ! -d /out/e ]
eot
FROM alpine AS end
COPY --from=base --parents /test/a/b/c/d/. /out/
RUN <<eot
set -ex
[ -d /out/test/a/b/c/d/e ]
[ -f /out/test/a/b/c/d/foo ]
eot
FROM alpine AS start
COPY --from=base --parents ./test/a/b/c/d /out/
RUN <<eot
set -ex
[ -d /out/test/a/b/c/d/e ]
[ -f /out/test/a/b/c/d/foo ]
eot
FROM alpine AS double
COPY --from=base --parents /test/a/./b/./c /out/
RUN <<eot
set -ex
[ -d /out/b/c/d/e ]
[ -f /out/b/c/d/foo ]
eot
FROM alpine AS wildcard
COPY --from=base --parents /test/a/./*/c /out/
RUN <<eot
set -ex
[ -d /out/b/c/d/e ]
[ -f /out/b2/c/d/e/bar ]
eot
FROM alpine AS doublewildcard
COPY --from=base --parents /test/a/b*/./c/**/e /out/
RUN <<eot
set -ex
[ -d /out/c/d/e ]
[ -f /out/c/d/e/bay ] # via b
[ -f /out/c/d/e/bar ] # via b2
eot
FROM alpine AS doubleinputs
COPY --from=base --parents /test/a/b/c*/./d/**/baz /test/a/b*/./c/**/bar /out/
RUN <<eot
set -ex
[ -f /out/d/e/baz ]
[ ! -f /out/d/e/bay ]
[ -f /out/d/e2/baz ]
[ -f /out/c/d/e/bar ] # via b2
eot
`)

dir := integration.Tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
)

c, err := client.New(sb.Context(), sb.Address())
require.NoError(t, err)
defer c.Close()

for _, target := range []string{"middle", "end", "start", "double", "wildcard", "doublewildcard", "doubleinputs"} {
t.Logf("target: %s", target)
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
FrontendAttrs: map[string]string{
"target": target,
},
LocalMounts: map[string]fsutil.FS{
dockerui.DefaultLocalNameDockerfile: dir,
dockerui.DefaultLocalNameContext: dir,
},
}, nil)
require.NoError(t, err)
}
}

0 comments on commit d959049

Please sign in to comment.