diff --git a/rootfs/rootfs.go b/rootfs/rootfs.go index a5c5f13..d6341f2 100644 --- a/rootfs/rootfs.go +++ b/rootfs/rootfs.go @@ -123,7 +123,10 @@ func RootFS(in io.ReadSeeker, out io.Writer) (err error) { if err != nil { return err } - if file2layer[hdr.Name] != i { + + // only directories can have multiple entries with the same name. + // all other file types cannot. + if hdr.Typeflag != tar.TypeDir && file2layer[hdr.Name] != i { continue } diff --git a/rootfs/rootfs_test.go b/rootfs/rootfs_test.go index a9a8775..da725f7 100644 --- a/rootfs/rootfs_test.go +++ b/rootfs/rootfs_test.go @@ -103,10 +103,13 @@ func TestRootFS(t *testing.T) { } layer1 := tarball{ - dir{name: "/", uid: 1}, file{name: "/file", uid: 0, contents: []byte("from 1")}, } + layer2 := tarball{ + dir{name: "/", uid: 1}, + } + tests := []struct { name string image tarball @@ -124,17 +127,31 @@ func TestRootFS(t *testing.T) { wantErr: "bad or missing manifest.json", }, { - name: "basic overwrite, 2 layers", + name: "basic file overwrite, layer order mixed", image: tarball{ file{name: "layer1/layer.tar", contents: layer1.bytes(t)}, file{name: "layer0/layer.tar", contents: layer0.bytes(t)}, manifest{"layer0/layer.tar", "layer1/layer.tar"}, }, want: []file{ - {name: "/", uid: 1}, + {name: "/", uid: 0}, {name: "/file", uid: 0, contents: []byte("from 1")}, }, }, + { + name: "directory overwrite retains original dir", + image: tarball{ + file{name: "layer0/layer.tar", contents: layer0.bytes(t)}, + file{name: "layer1/layer.tar", contents: layer1.bytes(t)}, + file{name: "layer2/layer.tar", contents: layer2.bytes(t)}, + manifest{"layer0/layer.tar", "layer1/layer.tar", "layer2/layer.tar"}, + }, + want: []file{ + {name: "/", uid: 0}, + {name: "/file", uid: 0, contents: []byte("from 1")}, + {name: "/", uid: 1}, + }, + }, } for _, tt := range tests {