diff --git a/commands/unpack.go b/commands/unpack.go index 6b58ca0..6edd77e 100644 --- a/commands/unpack.go +++ b/commands/unpack.go @@ -11,13 +11,14 @@ import ( "github.com/concourse/go-archive/tarfs" "github.com/fatih/color" - "github.com/google/go-containerregistry/pkg/v1" + v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/sirupsen/logrus" "github.com/vbauerster/mpb" "github.com/vbauerster/mpb/decor" ) const whiteoutPrefix = ".wh." +const whiteoutOpaqueDir = whiteoutPrefix + whiteoutPrefix + ".opq" func unpackImage(dest string, img v1.Image, debug bool, out io.Writer) error { layers, err := img.Layers() @@ -102,7 +103,24 @@ func extractLayer(dest string, layer v1.Layer, bar *mpb.Bar, chown bool) error { log.Debug("unpacking") - if strings.HasPrefix(base, whiteoutPrefix) { + if base == whiteoutOpaqueDir { + fi, err := os.Lstat(dir) + if err != nil && !os.IsNotExist(err) { + return err + } + + log.Debugf("removing contents of %s", dir) + + if err := os.RemoveAll(dir); err != nil { + return err + + } + if err := os.Mkdir(dir, fi.Mode()&os.ModePerm); err != nil { + return err + } + + continue + } else if strings.HasPrefix(base, whiteoutPrefix) { // layer has marked a file as deleted name := strings.TrimPrefix(base, whiteoutPrefix) removedPath := filepath.Join(dir, name) diff --git a/in_test.go b/in_test.go index 43ea2be..9c30a75 100644 --- a/in_test.go +++ b/in_test.go @@ -221,6 +221,14 @@ var _ = Describe("In", func() { stat, err = os.Stat(rootfsPath("top-dir-2")) Expect(err).To(HaveOccurred()) + + infos, err = ioutil.ReadDir(rootfsPath("top-dir-3")) + Expect(err).ToNot(HaveOccurred()) + Expect(infos).To(HaveLen(1)) + + stat, err = os.Stat(rootfsPath("top-dir-3", "nested-dir")) + Expect(err).ToNot(HaveOccurred()) + Expect(stat.IsDir()).To(BeTrue()) }) }) diff --git a/suite_test.go b/suite_test.go index 08e32b3..ed6b2e1 100644 --- a/suite_test.go +++ b/suite_test.go @@ -40,7 +40,7 @@ const OLDER_LIBRARY_DIGEST = "sha256:2131f09e4044327fd101ca1fd4043e6f3ad921ae7ee // see testdata/static/Dockerfile const OLDER_STATIC_DIGEST = "sha256:7dabedca9d367a71d1cd646bd8d79f14de7b07327e4417ab691f5f13be5647a9" -const LATEST_STATIC_DIGEST = "sha256:fc484c7e21a5616c600778d7ee720b3adfe1373c896be4f068c3da4a205d4a2e" +const LATEST_STATIC_DIGEST = "sha256:29eddd288c312215a0af1070d26478b1f530a3137d4589314df1bc79e586860a" // see testdata/static.tagged/Dockerfile const LATEST_TAGGED_STATIC_DIGEST = "sha256:ecfdc2527b0a5d7d134be55234590336209e7feafc2ec364a930adf4a9c722e2" diff --git a/testdata/whiteout/Dockerfile b/testdata/whiteout/Dockerfile index 007b8c7..e03464a 100644 --- a/testdata/whiteout/Dockerfile +++ b/testdata/whiteout/Dockerfile @@ -15,9 +15,12 @@ RUN touch top-dir-2/file-gone RUN mkdir top-dir-2/nested-dir-gone RUN touch top-dir-2/nested-dir-gone/nested-file-gone RUN rm -rf top-dir-2 +RUN mkdir -p top-dir-3/nested-dir-gone +RUN rm -r top-dir-3 && mkdir -p top-dir-3/nested-dir # resulting file tree should be: # /top-dir-1/nested-file # /top-dir-1/nested-dir/file-here # /top-dir-1/nested-dir/file-recreated # /top-dir-1/nested-dir/file-then-dir +# /top-dir-3/nested-dir