@@ -14,12 +14,15 @@ mod shallow {
1414mod  blocking_and_async_io { 
1515    use  std:: sync:: atomic:: AtomicBool ; 
1616
17+     use  gix:: interrupt:: IS_INTERRUPTED ; 
1718    use  gix:: { 
1819        config:: tree:: Protocol , 
1920        remote:: { fetch,  fetch:: Status ,  Direction :: Fetch } , 
2021    } ; 
2122    use  gix_features:: progress; 
23+     use  gix_odb:: store:: init:: Slots ; 
2224    use  gix_protocol:: maybe_async; 
25+     use  gix_testtools:: tempfile; 
2326    use  gix_testtools:: tempfile:: TempDir ; 
2427
2528    use  crate :: { 
@@ -85,6 +88,64 @@ mod blocking_and_async_io {
8588        try_repo_rw ( name) . unwrap ( ) 
8689    } 
8790
91+     #[ test]  
92+     fn  fetch_more_packs_than_can_be_handled ( )  -> gix_testtools:: Result  { 
93+         fn  create_empty_commit ( repo :  & gix:: Repository )  -> anyhow:: Result < ( ) >  { 
94+             let  name = repo. head_name ( ) ?. expect ( "no detached head" ) ; 
95+             repo. commit ( 
96+                 name. as_bstr ( ) , 
97+                 "empty" , 
98+                 gix:: hash:: ObjectId :: empty_tree ( repo. object_hash ( ) ) , 
99+                 repo. try_find_reference ( name. as_ref ( ) ) ?. map ( |r| r. id ( ) ) , 
100+             ) ?; 
101+             Ok ( ( ) ) 
102+         } 
103+         for  max_packs in  1 ..=3  { 
104+             let  remote_dir = tempfile:: tempdir ( ) ?; 
105+             let  remote_repo = gix:: init_bare ( remote_dir. path ( ) ) ?; 
106+             create_empty_commit ( & remote_repo) ?; 
107+ 
108+             let  local_dir = tempfile:: tempdir ( ) ?; 
109+             let  ( local_repo,  _)  = gix:: clone:: PrepareFetch :: new ( 
110+                 remote_repo. path ( ) , 
111+                 local_dir. path ( ) , 
112+                 gix:: create:: Kind :: Bare , 
113+                 Default :: default ( ) , 
114+                 gix:: open:: Options :: isolated ( ) . object_store_slots ( Slots :: Given ( max_packs) ) , 
115+             ) ?
116+             . fetch_only ( gix:: progress:: Discard ,  & IS_INTERRUPTED ) ?; 
117+ 
118+             let  remote = local_repo
119+                 . branch_remote ( 
120+                     local_repo. head_ref ( ) ?. expect ( "branch available" ) . name ( ) . shorten ( ) , 
121+                     Fetch , 
122+                 ) 
123+                 . expect ( "remote is configured after clone" ) ?; 
124+             for  _round_to_create_pack in  1 ..12  { 
125+                 create_empty_commit ( & remote_repo) ?; 
126+                 match  remote
127+                     . connect ( Fetch ) ?
128+                     . prepare_fetch ( gix:: progress:: Discard ,  Default :: default ( ) ) ?
129+                     . receive ( gix:: progress:: Discard ,  & IS_INTERRUPTED ) 
130+                 { 
131+                     Ok ( out)  => { 
132+                         for  local_tracking_branch_name in  out. ref_map . mappings . into_iter ( ) . filter_map ( |m| m. local )  { 
133+                             let  r = local_repo. find_reference ( & local_tracking_branch_name) ?; 
134+                             r. id ( ) 
135+                                 . object ( ) 
136+                                 . expect ( "object should be present after fetching, triggering pack refreshes works" ) ; 
137+                             local_repo. head_ref ( ) ?. unwrap ( ) . set_target_id ( r. id ( ) ,  "post fetch" ) ?; 
138+                         } 
139+                     } 
140+                     Err ( err)  => assert ! ( err
141+                         . to_string( ) 
142+                         . starts_with( "The slotmap turned out to be too small with " ) ) , 
143+                 } 
144+             } 
145+         } 
146+         Ok ( ( ) ) 
147+     } 
148+ 
88149    #[ test]  
89150    #[ cfg( feature = "blocking-network-client" ) ]  
90151    #[ allow( clippy:: result_large_err) ]  
0 commit comments