Skip to content

Commit eeef202

Browse files
committed
Fix parent directories not included in tar
Signed-off-by: Derek McGowan <[email protected]>
1 parent c59bc7e commit eeef202

2 files changed

Lines changed: 129 additions & 1 deletion

File tree

archive/tar.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,10 @@ func (cw *changeWriter) HandleChange(k fs.ChangeKind, p string, f os.FileInfo, e
381381
additionalLinks = cw.inodeRefs[inode]
382382
delete(cw.inodeRefs, inode)
383383
}
384-
} else if k == fs.ChangeKindUnmodified {
384+
} else if k == fs.ChangeKindUnmodified && !f.IsDir() {
385385
// Nothing to write to diff
386+
// Unmodified directories should still be written to keep
387+
// directory permissions correct on direct unpack
386388
return nil
387389
}
388390

archive/tar_test.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,132 @@ func makeWriterToTarTest(wt WriterToTar, a fstest.Applier, validate func(string)
666666
}
667667
}
668668

669+
func TestDiffTar(t *testing.T) {
670+
tests := []struct {
671+
name string
672+
validators []tarEntryValidator
673+
a fstest.Applier
674+
b fstest.Applier
675+
}{
676+
{
677+
name: "EmptyDiff",
678+
validators: []tarEntryValidator{},
679+
a: fstest.Apply(
680+
fstest.CreateDir("/etc/", 0755),
681+
),
682+
b: fstest.Apply(),
683+
},
684+
{
685+
name: "ParentInclusion",
686+
validators: []tarEntryValidator{
687+
dirEntry("d1/", 0755),
688+
dirEntry("d1/d/", 0700),
689+
dirEntry("d2/", 0770),
690+
fileEntry("d2/f", []byte("ok"), 0644),
691+
},
692+
a: fstest.Apply(
693+
fstest.CreateDir("/d1/", 0755),
694+
fstest.CreateDir("/d2/", 0770),
695+
),
696+
b: fstest.Apply(
697+
fstest.CreateDir("/d1/d", 0700),
698+
fstest.CreateFile("/d2/f", []byte("ok"), 0644),
699+
),
700+
},
701+
}
702+
703+
for _, at := range tests {
704+
t.Run(at.name, makeDiffTarTest(at.validators, at.a, at.b))
705+
}
706+
}
707+
708+
type tarEntryValidator func(*tar.Header, []byte) error
709+
710+
func dirEntry(name string, mode int) tarEntryValidator {
711+
return func(hdr *tar.Header, b []byte) error {
712+
if hdr.Typeflag != tar.TypeDir {
713+
return errors.New("not directory type")
714+
}
715+
if hdr.Name != name {
716+
return errors.Errorf("wrong name %q, expected %q", hdr.Name, name)
717+
}
718+
if hdr.Mode != int64(mode) {
719+
return errors.Errorf("wrong mode %o, expected %o", hdr.Mode, mode)
720+
}
721+
return nil
722+
}
723+
}
724+
725+
func fileEntry(name string, expected []byte, mode int) tarEntryValidator {
726+
return func(hdr *tar.Header, b []byte) error {
727+
if hdr.Typeflag != tar.TypeReg {
728+
return errors.New("not file type")
729+
}
730+
if hdr.Name != name {
731+
return errors.Errorf("wrong name %q, expected %q", hdr.Name, name)
732+
}
733+
if hdr.Mode != int64(mode) {
734+
return errors.Errorf("wrong mode %o, expected %o", hdr.Mode, mode)
735+
}
736+
if bytes.Compare(b, expected) != 0 {
737+
return errors.Errorf("different file content")
738+
}
739+
return nil
740+
}
741+
}
742+
743+
func makeDiffTarTest(validators []tarEntryValidator, a, b fstest.Applier) func(*testing.T) {
744+
return func(t *testing.T) {
745+
ad, err := ioutil.TempDir("", "test-make-diff-tar-")
746+
if err != nil {
747+
t.Fatalf("failed to create temp dir: %v", err)
748+
}
749+
defer os.RemoveAll(ad)
750+
if err := a.Apply(ad); err != nil {
751+
t.Fatalf("failed to apply a: %v", err)
752+
}
753+
754+
bd, err := ioutil.TempDir("", "test-make-diff-tar-")
755+
if err != nil {
756+
t.Fatalf("failed to create temp dir: %v", err)
757+
}
758+
defer os.RemoveAll(bd)
759+
if err := fs.CopyDir(bd, ad); err != nil {
760+
t.Fatalf("failed to copy dir: %v", err)
761+
}
762+
if err := b.Apply(bd); err != nil {
763+
t.Fatalf("failed to apply b: %v", err)
764+
}
765+
766+
rc := Diff(context.Background(), ad, bd)
767+
defer rc.Close()
768+
769+
tr := tar.NewReader(rc)
770+
for i := 0; ; i++ {
771+
hdr, err := tr.Next()
772+
if err != nil {
773+
if err == io.EOF {
774+
break
775+
}
776+
t.Fatalf("tar read error: %v", err)
777+
}
778+
var b []byte
779+
if hdr.Typeflag == tar.TypeReg && hdr.Size > 0 {
780+
b, err = ioutil.ReadAll(tr)
781+
if err != nil {
782+
t.Fatalf("tar read file error: %v", err)
783+
}
784+
}
785+
if i >= len(validators) {
786+
t.Fatal("no validator for entry")
787+
}
788+
if err := validators[i](hdr, b); err != nil {
789+
t.Fatalf("tar entry[%d] validation fail: %#v", i, err)
790+
}
791+
}
792+
}
793+
}
794+
669795
type diffApplier struct{}
670796

671797
func (d diffApplier) TestContext(ctx context.Context) (context.Context, func(), error) {

0 commit comments

Comments
 (0)