@@ -585,6 +585,71 @@ mod blocking_io {
585585 Ok ( ( ) )
586586 }
587587
588+ #[ test]
589+ fn fetch_and_checkout_into_non_empty_directory ( ) -> crate :: Result {
590+ let tmp = gix_testtools:: tempfile:: TempDir :: new ( ) ?;
591+ let existing_path = tmp. path ( ) . join ( "existing.txt" ) ;
592+ let existing_content = b"I was here before you" ;
593+ std:: fs:: write ( & existing_path, existing_content) ?;
594+
595+ let mut prepare = gix:: clone:: PrepareFetch :: new (
596+ remote:: repo ( "base" ) . path ( ) ,
597+ tmp. path ( ) ,
598+ gix:: create:: Kind :: WithWorktree ,
599+ gix:: create:: Options {
600+ destination_must_be_empty : Some ( false ) ,
601+ ..Default :: default ( )
602+ } ,
603+ restricted ( ) ,
604+ ) ?;
605+ let ( mut checkout, _out) =
606+ prepare. fetch_then_checkout ( gix:: progress:: Discard , & std:: sync:: atomic:: AtomicBool :: default ( ) ) ?;
607+ let ( repo, _) = checkout. main_worktree ( gix:: progress:: Discard , & std:: sync:: atomic:: AtomicBool :: default ( ) ) ?;
608+
609+ let index = repo. index ( ) ?;
610+ assert_eq ! ( index. entries( ) . len( ) , 1 , "All entries are known as per HEAD tree" ) ;
611+ assure_index_entries_on_disk ( & index, repo. workdir ( ) . expect ( "non-bare" ) ) ;
612+
613+ assert_eq ! ( std:: fs:: read( & existing_path) ?, existing_content) ;
614+ Ok ( ( ) )
615+ }
616+
617+ #[ test]
618+ fn drop_after_failed_fetch_into_non_empty_directory_preserves_pre_existing_files ( ) -> crate :: Result {
619+ let tmp = gix_testtools:: tempfile:: TempDir :: new ( ) ?;
620+ let existing_path = tmp. path ( ) . join ( "existing.txt" ) ;
621+ let existing_content = b"I was here before you" ;
622+ std:: fs:: write ( & existing_path, existing_content) ?;
623+
624+ let mut prepare = gix:: clone:: PrepareFetch :: new (
625+ remote:: repo ( "base" ) . path ( ) ,
626+ tmp. path ( ) ,
627+ gix:: create:: Kind :: WithWorktree ,
628+ gix:: create:: Options {
629+ destination_must_be_empty : Some ( false ) ,
630+ ..Default :: default ( )
631+ } ,
632+ restricted ( ) ,
633+ ) ?
634+ . with_ref_name ( Some ( "does-not-exist" ) ) ?;
635+
636+ prepare
637+ . fetch_then_checkout ( gix:: progress:: Discard , & AtomicBool :: default ( ) )
638+ . expect_err ( "non-existing ref must fail" ) ;
639+ drop ( prepare) ;
640+
641+ assert_eq ! (
642+ std:: fs:: read( & existing_path) ?,
643+ existing_content,
644+ "pre-existing user files must survive a failed clone+drop"
645+ ) ;
646+ assert ! (
647+ !tmp. path( ) . join( ".git" ) . exists( ) ,
648+ "only the .git directory we created should have been cleaned up"
649+ ) ;
650+ Ok ( ( ) )
651+ }
652+
588653 #[ test]
589654 fn fetch_and_checkout_specific_ref ( ) -> crate :: Result {
590655 let tmp = gix_testtools:: tempfile:: TempDir :: new ( ) ?;
@@ -832,6 +897,26 @@ fn clone_and_destination_must_be_empty() -> crate::Result {
832897 Ok ( ( ) )
833898}
834899
900+ #[ test]
901+ fn clone_with_worktree_and_destination_must_be_empty ( ) -> crate :: Result {
902+ let tmp = gix_testtools:: tempfile:: TempDir :: new ( ) ?;
903+ std:: fs:: write ( tmp. path ( ) . join ( "file" ) , b"hello" ) ?;
904+ match gix:: clone:: PrepareFetch :: new (
905+ remote:: repo ( "base" ) . path ( ) ,
906+ tmp. path ( ) ,
907+ gix:: create:: Kind :: WithWorktree ,
908+ Default :: default ( ) ,
909+ restricted ( ) ,
910+ ) {
911+ Ok ( _) => unreachable ! ( "this should fail as the directory isn't empty" ) ,
912+ Err ( err) => assert ! (
913+ err. to_string( )
914+ . starts_with( "Refusing to initialize the non-empty directory as " )
915+ ) ,
916+ }
917+ Ok ( ( ) )
918+ }
919+
835920#[ test]
836921fn clone_bare_into_empty_directory_and_early_drop ( ) -> crate :: Result {
837922 let tmp = gix_testtools:: tempfile:: TempDir :: new ( ) ?;
0 commit comments