@@ -666,6 +666,201 @@ 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+ name : "HardlinkParentInclusion" ,
703+ validators : []tarEntryValidator {
704+ dirEntry ("d2/" , 0755 ),
705+ fileEntry ("d2/l1" , []byte ("link me" ), 0644 ),
706+ // d1/f1 and its parent is included after the new link,
707+ // before the new link was included, these files would
708+ // not habe needed
709+ dirEntry ("d1/" , 0755 ),
710+ linkEntry ("d1/f1" , "d2/l1" ),
711+ dirEntry ("d3/" , 0755 ),
712+ fileEntry ("d3/l1" , []byte ("link me" ), 0644 ),
713+ dirEntry ("d4/" , 0755 ),
714+ linkEntry ("d4/f1" , "d3/l1" ),
715+ whiteoutEntry ("d6/l1" ),
716+ whiteoutEntry ("d6/l2" ),
717+ },
718+ a : fstest .Apply (
719+ fstest .CreateDir ("/d1/" , 0755 ),
720+ fstest .CreateFile ("/d1/f1" , []byte ("link me" ), 0644 ),
721+ fstest .CreateDir ("/d2/" , 0755 ),
722+ fstest .CreateFile ("/d2/f1" , []byte ("link me" ), 0644 ),
723+ fstest .CreateDir ("/d3/" , 0755 ),
724+ fstest .CreateDir ("/d4/" , 0755 ),
725+ fstest .CreateFile ("/d4/f1" , []byte ("link me" ), 0644 ),
726+ fstest .CreateDir ("/d5/" , 0755 ),
727+ fstest .CreateFile ("/d5/f1" , []byte ("link me" ), 0644 ),
728+ fstest .CreateDir ("/d6/" , 0755 ),
729+ fstest .Link ("/d1/f1" , "/d6/l1" ),
730+ fstest .Link ("/d5/f1" , "/d6/l2" ),
731+ ),
732+ b : fstest .Apply (
733+ fstest .Link ("/d1/f1" , "/d2/l1" ),
734+ fstest .Link ("/d4/f1" , "/d3/l1" ),
735+ fstest .Remove ("/d6/l1" ),
736+ fstest .Remove ("/d6/l2" ),
737+ ),
738+ },
739+ }
740+
741+ for _ , at := range tests {
742+ t .Run (at .name , makeDiffTarTest (at .validators , at .a , at .b ))
743+ }
744+ }
745+
746+ type tarEntryValidator func (* tar.Header , []byte ) error
747+
748+ func dirEntry (name string , mode int ) tarEntryValidator {
749+ return func (hdr * tar.Header , b []byte ) error {
750+ if hdr .Typeflag != tar .TypeDir {
751+ return errors .New ("not directory type" )
752+ }
753+ if hdr .Name != name {
754+ return errors .Errorf ("wrong name %q, expected %q" , hdr .Name , name )
755+ }
756+ if hdr .Mode != int64 (mode ) {
757+ return errors .Errorf ("wrong mode %o, expected %o" , hdr .Mode , mode )
758+ }
759+ return nil
760+ }
761+ }
762+
763+ func fileEntry (name string , expected []byte , mode int ) tarEntryValidator {
764+ return func (hdr * tar.Header , b []byte ) error {
765+ if hdr .Typeflag != tar .TypeReg {
766+ return errors .New ("not file type" )
767+ }
768+ if hdr .Name != name {
769+ return errors .Errorf ("wrong name %q, expected %q" , hdr .Name , name )
770+ }
771+ if hdr .Mode != int64 (mode ) {
772+ return errors .Errorf ("wrong mode %o, expected %o" , hdr .Mode , mode )
773+ }
774+ if bytes .Compare (b , expected ) != 0 {
775+ return errors .Errorf ("different file content" )
776+ }
777+ return nil
778+ }
779+ }
780+
781+ func linkEntry (name , link string ) tarEntryValidator {
782+ return func (hdr * tar.Header , b []byte ) error {
783+ if hdr .Typeflag != tar .TypeLink {
784+ return errors .New ("not link type" )
785+ }
786+ if hdr .Name != name {
787+ return errors .Errorf ("wrong name %q, expected %q" , hdr .Name , name )
788+ }
789+ if hdr .Linkname != link {
790+ return errors .Errorf ("wrong link %q, expected %q" , hdr .Linkname , link )
791+ }
792+ return nil
793+ }
794+ }
795+
796+ func whiteoutEntry (name string ) tarEntryValidator {
797+ whiteOutDir := filepath .Dir (name )
798+ whiteOutBase := filepath .Base (name )
799+ whiteOut := filepath .Join (whiteOutDir , whiteoutPrefix + whiteOutBase )
800+
801+ return func (hdr * tar.Header , b []byte ) error {
802+ if hdr .Typeflag != tar .TypeReg {
803+ return errors .Errorf ("not file type: %q" , hdr .Typeflag )
804+ }
805+ if hdr .Name != whiteOut {
806+ return errors .Errorf ("wrong name %q, expected whiteout %q" , hdr .Name , name )
807+ }
808+ return nil
809+ }
810+ }
811+
812+ func makeDiffTarTest (validators []tarEntryValidator , a , b fstest.Applier ) func (* testing.T ) {
813+ return func (t * testing.T ) {
814+ ad , err := ioutil .TempDir ("" , "test-make-diff-tar-" )
815+ if err != nil {
816+ t .Fatalf ("failed to create temp dir: %v" , err )
817+ }
818+ defer os .RemoveAll (ad )
819+ if err := a .Apply (ad ); err != nil {
820+ t .Fatalf ("failed to apply a: %v" , err )
821+ }
822+
823+ bd , err := ioutil .TempDir ("" , "test-make-diff-tar-" )
824+ if err != nil {
825+ t .Fatalf ("failed to create temp dir: %v" , err )
826+ }
827+ defer os .RemoveAll (bd )
828+ if err := fs .CopyDir (bd , ad ); err != nil {
829+ t .Fatalf ("failed to copy dir: %v" , err )
830+ }
831+ if err := b .Apply (bd ); err != nil {
832+ t .Fatalf ("failed to apply b: %v" , err )
833+ }
834+
835+ rc := Diff (context .Background (), ad , bd )
836+ defer rc .Close ()
837+
838+ tr := tar .NewReader (rc )
839+ for i := 0 ; ; i ++ {
840+ hdr , err := tr .Next ()
841+ if err != nil {
842+ if err == io .EOF {
843+ break
844+ }
845+ t .Fatalf ("tar read error: %v" , err )
846+ }
847+ var b []byte
848+ if hdr .Typeflag == tar .TypeReg && hdr .Size > 0 {
849+ b , err = ioutil .ReadAll (tr )
850+ if err != nil {
851+ t .Fatalf ("tar read file error: %v" , err )
852+ }
853+ }
854+ if i >= len (validators ) {
855+ t .Fatal ("no validator for entry" )
856+ }
857+ if err := validators [i ](hdr , b ); err != nil {
858+ t .Fatalf ("tar entry[%d] validation fail: %#v" , i , err )
859+ }
860+ }
861+ }
862+ }
863+
669864type diffApplier struct {}
670865
671866func (d diffApplier ) TestContext (ctx context.Context ) (context.Context , func (), error ) {
0 commit comments