diff --git a/pkg/snapshot/snapshot.go b/pkg/snapshot/snapshot.go index 7b3df5661e..449ae918a9 100644 --- a/pkg/snapshot/snapshot.go +++ b/pkg/snapshot/snapshot.go @@ -226,10 +226,28 @@ func writeToTar(t util.Tar, files, whiteouts []string) error { return err } } + + addedPaths := make(map[string]bool) for _, path := range files { + if _, fileExists := addedPaths[path]; fileExists { + continue + } + for _, parentPath := range util.ParentDirectories(path) { + if parentPath == "/" { + continue + } + if _, dirExists := addedPaths[parentPath]; dirExists { + continue + } + if err := t.AddFileToTar(parentPath); err != nil { + return err + } + addedPaths[parentPath] = true + } if err := t.AddFileToTar(path); err != nil { return err } + addedPaths[path] = true } return nil } diff --git a/pkg/snapshot/snapshot_test.go b/pkg/snapshot/snapshot_test.go index a6553228d9..a10db7e135 100644 --- a/pkg/snapshot/snapshot_test.go +++ b/pkg/snapshot/snapshot_test.go @@ -64,6 +64,12 @@ func TestSnapshotFSFileChange(t *testing.T) { fooPath: "newbaz1", batPath: "baz", } + for _, path := range util.ParentDirectoriesWithoutLeadingSlash(batPath) { + if path == "/" { + continue + } + snapshotFiles[path+"/"] = "" + } actualFiles := []string{} for { @@ -77,6 +83,9 @@ func TestSnapshotFSFileChange(t *testing.T) { if _, isFile := snapshotFiles[hdr.Name]; !isFile { t.Fatalf("File %s unexpectedly in tar", hdr.Name) } + if hdr.Typeflag == tar.TypeDir { + continue + } contents, _ := ioutil.ReadAll(tr) if string(contents) != snapshotFiles[hdr.Name] { t.Fatalf("Contents of %s incorrect, expected: %s, actual: %s", hdr.Name, snapshotFiles[hdr.Name], string(contents)) @@ -153,6 +162,12 @@ func TestSnapshotFSChangePermissions(t *testing.T) { snapshotFiles := map[string]string{ batPathWithoutLeadingSlash: "baz2", } + for _, path := range util.ParentDirectoriesWithoutLeadingSlash(batPathWithoutLeadingSlash) { + if path == "/" { + continue + } + snapshotFiles[path+"/"] = "" + } foundFiles := []string{} for { @@ -164,6 +179,9 @@ func TestSnapshotFSChangePermissions(t *testing.T) { if _, isFile := snapshotFiles[hdr.Name]; !isFile { t.Fatalf("File %s unexpectedly in tar", hdr.Name) } + if hdr.Typeflag == tar.TypeDir { + continue + } contents, _ := ioutil.ReadAll(tr) if string(contents) != snapshotFiles[hdr.Name] { t.Fatalf("Contents of %s incorrect, expected: %s, actual: %s", hdr.Name, snapshotFiles[hdr.Name], string(contents)) @@ -203,7 +221,9 @@ func TestSnapshotFiles(t *testing.T) { expectedFiles := []string{ filepath.Join(testDirWithoutLeadingSlash, "foo"), } - expectedFiles = append(expectedFiles, util.ParentDirectoriesWithoutLeadingSlash(filepath.Join(testDir, "foo"))...) + for _, path := range util.ParentDirectoriesWithoutLeadingSlash(filepath.Join(testDir, "foo")) { + expectedFiles = append(expectedFiles, strings.TrimRight(path, "/")+"/") + } f, err := os.Open(tarPath) if err != nil { diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index a5ecaab1bd..230d87669c 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -468,10 +468,10 @@ func ParentDirectories(path string) []string { } dir, _ = filepath.Split(dir) dir = filepath.Clean(dir) - paths = append(paths, dir) + paths = append([]string{dir}, paths...) } if len(paths) == 0 { - paths = append(paths, config.RootDir) + paths = []string{config.RootDir} } return paths } diff --git a/pkg/util/fs_util_test.go b/pkg/util/fs_util_test.go index b560330b2f..5ba37fef98 100644 --- a/pkg/util/fs_util_test.go +++ b/pkg/util/fs_util_test.go @@ -213,8 +213,6 @@ func Test_ParentDirectories(t *testing.T) { defer func() { config.RootDir = original }() config.RootDir = tt.rootDir actual := ParentDirectories(tt.path) - sort.Strings(actual) - sort.Strings(tt.expected) testutil.CheckErrorAndDeepEqual(t, false, nil, tt.expected, actual) }) diff --git a/pkg/util/tar_util.go b/pkg/util/tar_util.go index af83925ca1..ba9dc8738c 100644 --- a/pkg/util/tar_util.go +++ b/pkg/util/tar_util.go @@ -85,6 +85,9 @@ func (t *Tar) AddFileToTar(p string) error { hdr.Name = strings.TrimPrefix(p, config.RootDir) hdr.Name = strings.TrimLeft(hdr.Name, "/") } + if hdr.Typeflag == tar.TypeDir && !strings.HasSuffix(hdr.Name, "/") { + hdr.Name = hdr.Name + "/" + } // rootfs may not have been extracted when using cache, preventing uname/gname from resolving // this makes this layer unnecessarily differ from a cached layer which does contain this information hdr.Uname = ""