@@ -13,7 +13,7 @@ use std::fmt;
1313use std:: fs:: { self , File } ;
1414use std:: io:: { BufRead , BufReader , Read , Write } ;
1515use std:: net:: { SocketAddr , TcpListener , TcpStream } ;
16- use std:: path:: PathBuf ;
16+ use std:: path:: { Path , PathBuf } ;
1717use std:: thread:: { self , JoinHandle } ;
1818use tar:: { Builder , Header } ;
1919use time:: format_description:: well_known:: Rfc3339 ;
@@ -98,6 +98,8 @@ pub struct RegistryBuilder {
9898 configure_registry : bool ,
9999 /// API responders.
100100 custom_responders : HashMap < & ' static str , Box < dyn Send + Fn ( & Request , & HttpServer ) -> Response > > ,
101+ /// If nonzero, the git index update to be delayed by the given number of seconds.
102+ delayed_index_update : usize ,
101103}
102104
103105pub struct TestRegistry {
@@ -157,6 +159,7 @@ impl RegistryBuilder {
157159 configure_registry : true ,
158160 configure_token : true ,
159161 custom_responders : HashMap :: new ( ) ,
162+ delayed_index_update : 0 ,
160163 }
161164 }
162165
@@ -171,6 +174,13 @@ impl RegistryBuilder {
171174 self
172175 }
173176
177+ /// Configures the git index update to be delayed by the given number of seconds.
178+ #[ must_use]
179+ pub fn delayed_index_update ( mut self , delay : usize ) -> Self {
180+ self . delayed_index_update = delay;
181+ self
182+ }
183+
174184 /// Sets whether or not to initialize as an alternative registry.
175185 #[ must_use]
176186 pub fn alternative_named ( mut self , alt : & str ) -> Self {
@@ -264,6 +274,7 @@ impl RegistryBuilder {
264274 token. clone ( ) ,
265275 self . auth_required ,
266276 self . custom_responders ,
277+ self . delayed_index_update ,
267278 ) ;
268279 let index_url = if self . http_index {
269280 server. index_url ( )
@@ -589,6 +600,7 @@ pub struct HttpServer {
589600 token : Token ,
590601 auth_required : bool ,
591602 custom_responders : HashMap < & ' static str , Box < dyn Send + Fn ( & Request , & HttpServer ) -> Response > > ,
603+ delayed_index_update : usize ,
592604}
593605
594606/// A helper struct that collects the arguments for [HttpServer::check_authorized].
@@ -610,6 +622,7 @@ impl HttpServer {
610622 & ' static str ,
611623 Box < dyn Send + Fn ( & Request , & HttpServer ) -> Response > ,
612624 > ,
625+ delayed_index_update : usize ,
613626 ) -> HttpServerHandle {
614627 let listener = TcpListener :: bind ( "127.0.0.1:0" ) . unwrap ( ) ;
615628 let addr = listener. local_addr ( ) . unwrap ( ) ;
@@ -621,6 +634,7 @@ impl HttpServer {
621634 token,
622635 auth_required,
623636 custom_responders : api_responders,
637+ delayed_index_update,
624638 } ;
625639 let handle = Some ( thread:: spawn ( move || server. start ( ) ) ) ;
626640 HttpServerHandle { addr, handle }
@@ -1030,49 +1044,23 @@ impl HttpServer {
10301044 return self . unauthorized ( req) ;
10311045 }
10321046
1033- // Write the `.crate`
10341047 let dst = self
10351048 . dl_path
10361049 . join ( & new_crate. name )
10371050 . join ( & new_crate. vers )
10381051 . join ( "download" ) ;
1039- t ! ( fs:: create_dir_all( dst. parent( ) . unwrap( ) ) ) ;
1040- t ! ( fs:: write( & dst, file) ) ;
1041-
1042- let deps = new_crate
1043- . deps
1044- . iter ( )
1045- . map ( |dep| {
1046- let ( name, package) = match & dep. explicit_name_in_toml {
1047- Some ( explicit) => ( explicit. to_string ( ) , Some ( dep. name . to_string ( ) ) ) ,
1048- None => ( dep. name . to_string ( ) , None ) ,
1049- } ;
1050- serde_json:: json!( {
1051- "name" : name,
1052- "req" : dep. version_req,
1053- "features" : dep. features,
1054- "default_features" : true ,
1055- "target" : dep. target,
1056- "optional" : dep. optional,
1057- "kind" : dep. kind,
1058- "registry" : dep. registry,
1059- "package" : package,
1060- } )
1061- } )
1062- . collect :: < Vec < _ > > ( ) ;
1063-
1064- let line = create_index_line (
1065- serde_json:: json!( new_crate. name) ,
1066- & new_crate. vers ,
1067- deps,
1068- & file_cksum,
1069- new_crate. features ,
1070- false ,
1071- new_crate. links ,
1072- None ,
1073- ) ;
10741052
1075- write_to_index ( & self . registry_path , & new_crate. name , line, false ) ;
1053+ if self . delayed_index_update == 0 {
1054+ save_new_crate ( dst, new_crate, file, file_cksum, & self . registry_path ) ;
1055+ } else {
1056+ let delayed_index_update = self . delayed_index_update ;
1057+ let registry_path = self . registry_path . clone ( ) ;
1058+ let file = Vec :: from ( file) ;
1059+ thread:: spawn ( move || {
1060+ thread:: sleep ( std:: time:: Duration :: new ( delayed_index_update as u64 , 0 ) ) ;
1061+ save_new_crate ( dst, new_crate, & file, file_cksum, & registry_path) ;
1062+ } ) ;
1063+ }
10761064
10771065 self . ok ( & req)
10781066 } else {
@@ -1085,6 +1073,53 @@ impl HttpServer {
10851073 }
10861074}
10871075
1076+ fn save_new_crate (
1077+ dst : PathBuf ,
1078+ new_crate : crates_io:: NewCrate ,
1079+ file : & [ u8 ] ,
1080+ file_cksum : String ,
1081+ registry_path : & Path ,
1082+ ) {
1083+ // Write the `.crate`
1084+ t ! ( fs:: create_dir_all( dst. parent( ) . unwrap( ) ) ) ;
1085+ t ! ( fs:: write( & dst, file) ) ;
1086+
1087+ let deps = new_crate
1088+ . deps
1089+ . iter ( )
1090+ . map ( |dep| {
1091+ let ( name, package) = match & dep. explicit_name_in_toml {
1092+ Some ( explicit) => ( explicit. to_string ( ) , Some ( dep. name . to_string ( ) ) ) ,
1093+ None => ( dep. name . to_string ( ) , None ) ,
1094+ } ;
1095+ serde_json:: json!( {
1096+ "name" : name,
1097+ "req" : dep. version_req,
1098+ "features" : dep. features,
1099+ "default_features" : true ,
1100+ "target" : dep. target,
1101+ "optional" : dep. optional,
1102+ "kind" : dep. kind,
1103+ "registry" : dep. registry,
1104+ "package" : package,
1105+ } )
1106+ } )
1107+ . collect :: < Vec < _ > > ( ) ;
1108+
1109+ let line = create_index_line (
1110+ serde_json:: json!( new_crate. name) ,
1111+ & new_crate. vers ,
1112+ deps,
1113+ & file_cksum,
1114+ new_crate. features ,
1115+ false ,
1116+ new_crate. links ,
1117+ None ,
1118+ ) ;
1119+
1120+ write_to_index ( registry_path, & new_crate. name , line, false ) ;
1121+ }
1122+
10881123impl Package {
10891124 /// Creates a new package builder.
10901125 /// Call `publish()` to finalize and build the package.
0 commit comments