Skip to content

Commit

Permalink
Merge pull request moby#4455 from sipsma/support-always-overwrite-des…
Browse files Browse the repository at this point in the history
…t-path

add support for AlwaysReplaceExistingDestPaths in llb copy
  • Loading branch information
sipsma authored Apr 2, 2024
2 parents 4d94abf + 7bc06cb commit 76596cc
Show file tree
Hide file tree
Showing 6 changed files with 313 additions and 180 deletions.
75 changes: 75 additions & 0 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ var allTests = []func(t *testing.T, sb integration.Sandbox){
testFileOpMkdirMkfile,
testFileOpCopyRm,
testFileOpCopyIncludeExclude,
testFileOpCopyAlwaysReplaceExistingDestPaths,
testFileOpRmWildcard,
testFileOpCopyUIDCache,
testCallDiskUsage,
Expand Down Expand Up @@ -1860,6 +1861,80 @@ func testFileOpCopyIncludeExclude(t *testing.T, sb integration.Sandbox) {
require.Equal(t, randBytes, randBytes2)
}

func testFileOpCopyAlwaysReplaceExistingDestPaths(t *testing.T, sb integration.Sandbox) {
requiresLinux(t)
c, err := New(sb.Context(), sb.Address())
require.NoError(t, err)
defer c.Close()

destDirHostPath := integration.Tmpdir(t,
fstest.CreateDir("root", 0755),
fstest.CreateDir("root/overwritedir", 0755),
fstest.CreateFile("root/overwritedir/subfile", nil, 0755),
fstest.CreateFile("root/overwritefile", nil, 0755),
fstest.Symlink("dir", "root/overwritesymlink"),
fstest.CreateDir("root/dir", 0755),
fstest.CreateFile("root/dir/dirfile1", nil, 0755),
fstest.CreateDir("root/dir/overwritesubdir", 0755),
fstest.CreateFile("root/dir/overwritesubfile", nil, 0755),
fstest.Symlink("dirfile1", "root/dir/overwritesymlink"),
)
destDir := llb.Local("destDir")

srcDirHostPath := integration.Tmpdir(t,
fstest.CreateDir("root", 0755),
fstest.CreateFile("root/overwritedir", nil, 0755),
fstest.CreateDir("root/overwritefile", 0755),
fstest.CreateFile("root/overwritefile/foo", nil, 0755),
fstest.CreateDir("root/overwritesymlink", 0755),
fstest.CreateDir("root/dir", 0755),
fstest.CreateFile("root/dir/dirfile2", nil, 0755),
fstest.CreateFile("root/dir/overwritesubdir", nil, 0755),
fstest.CreateDir("root/dir/overwritesubfile", 0755),
fstest.CreateDir("root/dir/overwritesymlink", 0755),
)
srcDir := llb.Local("srcDir")

resultDir := destDir.File(llb.Copy(srcDir, "/", "/", &llb.CopyInfo{
CopyDirContentsOnly: true,
AlwaysReplaceExistingDestPaths: true,
}))

def, err := resultDir.Marshal(sb.Context())
require.NoError(t, err)

resultDirHostPath := t.TempDir()

_, err = c.Solve(sb.Context(), def, SolveOpt{
Exports: []ExportEntry{
{
Type: ExporterLocal,
OutputDir: resultDirHostPath,
},
},
LocalDirs: map[string]string{
"destDir": destDirHostPath.Name,
"srcDir": srcDirHostPath.Name,
},
}, nil)
require.NoError(t, err)

err = fstest.CheckDirectoryEqualWithApplier(resultDirHostPath, fstest.Apply(
fstest.CreateDir("root", 0755),
fstest.CreateFile("root/overwritedir", nil, 0755),
fstest.CreateDir("root/overwritefile", 0755),
fstest.CreateFile("root/overwritefile/foo", nil, 0755),
fstest.CreateDir("root/overwritesymlink", 0755),
fstest.CreateDir("root/dir", 0755),
fstest.CreateFile("root/dir/dirfile1", nil, 0755),
fstest.CreateFile("root/dir/dirfile2", nil, 0755),
fstest.CreateFile("root/dir/overwritesubdir", nil, 0755),
fstest.CreateDir("root/dir/overwritesubfile", 0755),
fstest.CreateDir("root/dir/overwritesymlink", 0755),
))
require.NoError(t, err)
}

// testFileOpInputSwap is a regression test that cache is invalidated when subset of fileop is built
func testFileOpInputSwap(t *testing.T, sb integration.Sandbox) {
requiresLinux(t)
Expand Down
27 changes: 16 additions & 11 deletions client/llb/fileop.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,17 +488,18 @@ type CopyOption interface {
}

type CopyInfo struct {
Mode *os.FileMode
FollowSymlinks bool
CopyDirContentsOnly bool
IncludePatterns []string
ExcludePatterns []string
AttemptUnpack bool
CreateDestPath bool
AllowWildcard bool
AllowEmptyWildcard bool
ChownOpt *ChownOpt
CreatedTime *time.Time
Mode *os.FileMode
FollowSymlinks bool
CopyDirContentsOnly bool
IncludePatterns []string
ExcludePatterns []string
AttemptUnpack bool
CreateDestPath bool
AllowWildcard bool
AllowEmptyWildcard bool
ChownOpt *ChownOpt
CreatedTime *time.Time
AlwaysReplaceExistingDestPaths bool
}

func (mi *CopyInfo) SetCopyOption(mi2 *CopyInfo) {
Expand Down Expand Up @@ -533,6 +534,7 @@ func (a *fileActionCopy) toProtoAction(ctx context.Context, parent string, base
AttemptUnpackDockerCompatibility: a.info.AttemptUnpack,
CreateDestPath: a.info.CreateDestPath,
Timestamp: marshalTime(a.info.CreatedTime),
AlwaysReplaceExistingDestPaths: a.info.AlwaysReplaceExistingDestPaths,
}
if a.info.Mode != nil {
c.Mode = int32(*a.info.Mode)
Expand Down Expand Up @@ -565,6 +567,9 @@ func (a *fileActionCopy) addCaps(f *FileOp) {
if len(a.info.IncludePatterns) != 0 || len(a.info.ExcludePatterns) != 0 {
addCap(&f.constraints, pb.CapFileCopyIncludeExcludePatterns)
}
if a.info.AlwaysReplaceExistingDestPaths {
addCap(&f.constraints, pb.CapFileCopyAlwaysReplaceExistingDestPaths)
}
}

type CreatedTime time.Time
Expand Down
1 change: 1 addition & 0 deletions solver/llbsolver/file/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *
}
ci.CopyDirContents = action.DirCopyContents
ci.FollowLinks = action.FollowSymlink
ci.AlwaysReplaceExistingDestPaths = action.AlwaysReplaceExistingDestPaths
},
copy.WithXAttrErrorHandler(xattrErrorHandler),
}
Expand Down
15 changes: 11 additions & 4 deletions solver/pb/caps.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,11 @@ const (
CapExecCgroupsMounted apicaps.CapID = "exec.cgroup"
CapExecSecretEnv apicaps.CapID = "exec.secretenv"

CapFileBase apicaps.CapID = "file.base"
CapFileRmWildcard apicaps.CapID = "file.rm.wildcard"
CapFileCopyIncludeExcludePatterns apicaps.CapID = "file.copy.includeexcludepatterns"
CapFileRmNoFollowSymlink apicaps.CapID = "file.rm.nofollowsymlink"
CapFileBase apicaps.CapID = "file.base"
CapFileRmWildcard apicaps.CapID = "file.rm.wildcard"
CapFileCopyIncludeExcludePatterns apicaps.CapID = "file.copy.includeexcludepatterns"
CapFileRmNoFollowSymlink apicaps.CapID = "file.rm.nofollowsymlink"
CapFileCopyAlwaysReplaceExistingDestPaths apicaps.CapID = "file.copy.alwaysreplaceexistingdestpaths"

CapConstraints apicaps.CapID = "constraints"
CapPlatform apicaps.CapID = "platform"
Expand Down Expand Up @@ -384,6 +385,12 @@ func init() {
Status: apicaps.CapStatusExperimental,
})

Caps.Init(apicaps.Cap{
ID: CapFileCopyAlwaysReplaceExistingDestPaths,
Enabled: true,
Status: apicaps.CapStatusExperimental,
})

Caps.Init(apicaps.Cap{
ID: CapConstraints,
Enabled: true,
Expand Down
Loading

0 comments on commit 76596cc

Please sign in to comment.