@@ -831,6 +831,173 @@ func testFetchAnnotatedTagChecksums(t *testing.T, format string, keepGitDir bool
831831 }
832832}
833833
834+ func TestFetchMutatedTagSHA1 (t * testing.T ) {
835+ testFetchMutatedTag (t , "sha1" , false )
836+ }
837+
838+ func TestFetchMutatedTagKeepGitDirSHA1 (t * testing.T ) {
839+ testFetchMutatedTag (t , "sha1" , true )
840+ }
841+
842+ func TestFetchMutatedTagSHA256 (t * testing.T ) {
843+ testFetchMutatedTag (t , "sha256" , false )
844+ }
845+
846+ func TestFetchMutatedTagKeepGitDirSHA256 (t * testing.T ) {
847+ testFetchMutatedTag (t , "sha256" , true )
848+ }
849+
850+ func testFetchMutatedTag (t * testing.T , format string , keepGitDir bool ) {
851+ ctx := t .Context ()
852+ if runtime .GOOS == "windows" {
853+ t .Skip ("Depends on unimplemented containerd bind-mount support on Windows" )
854+ }
855+ repo := setupGitRepo (t , format )
856+ cmd := exec .Command ("git" , "rev-parse" , "v1.2.3" )
857+ cmd .Dir = repo .mainPath
858+
859+ out , err := cmd .Output ()
860+ require .NoError (t , err )
861+
862+ expLen := 40
863+ if format == "sha256" {
864+ expLen = 64
865+ }
866+ shaTag := strings .TrimSpace (string (out ))
867+ require .Equal (t , expLen , len (shaTag ))
868+
869+ id := & GitIdentifier {Remote : repo .mainURL , Ref : shaTag , KeepGitDir : keepGitDir }
870+ gs := setupGitSource (t , t .TempDir ())
871+
872+ g , err := gs .Resolve (ctx , id , nil , nil )
873+ require .NoError (t , err )
874+
875+ key1 , pin1 , _ , done , err := g .CacheKey (ctx , nil , 0 )
876+ require .NoError (t , err )
877+ require .True (t , done )
878+
879+ ref , err := g .Snapshot (ctx , nil )
880+ require .NoError (t , err )
881+ ref .Release (context .TODO ())
882+
883+ // mutate the tag to point to another commit
884+ cmd = exec .Command ("git" , "tag" , "-f" , "v1.2.3" , "feature" )
885+ cmd .Dir = repo .mainPath
886+ out , err = cmd .CombinedOutput ()
887+ require .NoError (t , err , string (out ))
888+
889+ // verify that the tag now points to a different commit
890+ cmd = exec .Command ("git" , "rev-parse" , "v1.2.3" )
891+ cmd .Dir = repo .mainPath
892+
893+ out , err = cmd .Output ()
894+ require .NoError (t , err )
895+
896+ shaTagMutated := strings .TrimSpace (string (out ))
897+ require .Equal (t , expLen , len (shaTagMutated ))
898+ require .NotEqual (t , shaTag , shaTagMutated )
899+
900+ id = & GitIdentifier {Remote : repo .mainURL , Ref : shaTagMutated , KeepGitDir : keepGitDir }
901+
902+ // fetching the original tag should still return the original commit because of caching
903+ g , err = gs .Resolve (ctx , id , nil , nil )
904+ require .NoError (t , err )
905+
906+ key2 , pin2 , _ , done , err := g .CacheKey (ctx , nil , 0 )
907+ require .NoError (t , err )
908+ require .True (t , done )
909+
910+ require .NotEqual (t , key1 , key2 )
911+ require .NotEqual (t , pin1 , pin2 )
912+
913+ ref , err = g .Snapshot (ctx , nil )
914+ require .NoError (t , err )
915+ ref .Release (context .TODO ())
916+ }
917+
918+ func TestFetchMutatedBranchSHA1 (t * testing.T ) {
919+ testFetchMutatedBranch (t , "sha1" , false )
920+ }
921+
922+ func TestFetchMutatedBranchKeepGitDirSHA1 (t * testing.T ) {
923+ testFetchMutatedBranch (t , "sha1" , true )
924+ }
925+
926+ func TestFetchMutatedBranchSHA256 (t * testing.T ) {
927+ testFetchMutatedBranch (t , "sha256" , false )
928+ }
929+
930+ func TestFetchMutatedBranchKeepGitDirSHA256 (t * testing.T ) {
931+ testFetchMutatedBranch (t , "sha256" , true )
932+ }
933+
934+ // testFetchMutatedBranch tests that if a branch is mutated in a way that previous
935+ // ref becomes parent directory of new ref, causing collision to existing checkouts
936+ func testFetchMutatedBranch (t * testing.T , format string , keepGitDir bool ) {
937+ ctx := t .Context ()
938+ if runtime .GOOS == "windows" {
939+ t .Skip ("Depends on unimplemented containerd bind-mount support on Windows" )
940+ }
941+ repo := setupGitRepo (t , format )
942+ cmd := exec .Command ("git" , "rev-parse" , "feature" )
943+ cmd .Dir = repo .mainPath
944+
945+ out , err := cmd .Output ()
946+ require .NoError (t , err )
947+
948+ expLen := 40
949+ if format == "sha256" {
950+ expLen = 64
951+ }
952+ shaBranch := strings .TrimSpace (string (out ))
953+ require .Equal (t , expLen , len (shaBranch ))
954+
955+ id := & GitIdentifier {Remote : repo .mainURL , Ref : "feature" , KeepGitDir : keepGitDir }
956+ gs := setupGitSource (t , t .TempDir ())
957+
958+ g , err := gs .Resolve (ctx , id , nil , nil )
959+ require .NoError (t , err )
960+
961+ key1 , pin1 , _ , done , err := g .CacheKey (ctx , nil , 0 )
962+ require .NoError (t , err )
963+ require .True (t , done )
964+
965+ ref , err := g .Snapshot (ctx , nil )
966+ require .NoError (t , err )
967+ ref .Release (context .TODO ())
968+
969+ // mutate the branch to point to become parent dir
970+ cmd = exec .Command ("git" , "branch" , "-D" , "feature" )
971+ cmd .Dir = repo .mainPath
972+ out , err = cmd .CombinedOutput ()
973+ require .NoError (t , err , string (out ))
974+
975+ cmd = exec .Command ("git" , "branch" , "feature/new" , shaBranch )
976+ cmd .Dir = repo .mainPath
977+ out , err = cmd .CombinedOutput ()
978+ require .NoError (t , err , string (out ))
979+
980+ id = & GitIdentifier {Remote : repo .mainURL , Ref : "feature/new" , KeepGitDir : keepGitDir }
981+
982+ g , err = gs .Resolve (ctx , id , nil , nil )
983+ require .NoError (t , err )
984+
985+ key2 , pin2 , _ , done , err := g .CacheKey (ctx , nil , 0 )
986+ require .NoError (t , err )
987+ require .True (t , done )
988+
989+ if keepGitDir {
990+ require .NotEqual (t , key1 , key2 ) // key contains new ref
991+ } else {
992+ require .Equal (t , key1 , key2 )
993+ }
994+ require .Equal (t , pin1 , pin2 )
995+
996+ ref , err = g .Snapshot (ctx , nil )
997+ require .NoError (t , err )
998+ ref .Release (context .TODO ())
999+ }
1000+
8341001func TestMultipleTagAccessKeepGitDirSHA1 (t * testing.T ) {
8351002 testMultipleTagAccess (t , true , "sha1" )
8361003}
0 commit comments