1- use std:: collections :: HashMap ;
1+ use std:: borrow :: Cow ;
22use std:: fs;
33use std:: ops;
44use std:: path:: { Path , PathBuf } ;
@@ -42,7 +42,12 @@ impl<'a> DownloadCfg<'a> {
4242 /// Partial downloads are stored in `self.download_dir`, keyed by hash. If the
4343 /// target file already exists, then the hash is checked and it is returned
4444 /// immediately without re-downloading.
45- pub ( crate ) async fn download ( & self , url : & Url , hash : & str ) -> Result < File > {
45+ pub ( crate ) async fn download (
46+ & self ,
47+ url : & Url ,
48+ hash : & str ,
49+ status : & DownloadStatus ,
50+ ) -> Result < File > {
4651 utils:: ensure_dir_exists ( "Download Directory" , self . download_dir ) ?;
4752 let target_file = self . download_dir . join ( Path :: new ( hash) ) ;
4853
@@ -76,7 +81,7 @@ impl<'a> DownloadCfg<'a> {
7681 & partial_file_path,
7782 Some ( & mut hasher) ,
7883 true ,
79- & self . tracker ,
84+ Some ( status ) ,
8085 self . process ,
8186 )
8287 . await
@@ -125,7 +130,7 @@ impl<'a> DownloadCfg<'a> {
125130 let hash_url = utils:: parse_url ( & ( url. to_owned ( ) + ".sha256" ) ) ?;
126131 let hash_file = self . tmp_cx . new_file ( ) ?;
127132
128- download_file ( & hash_url, & hash_file, None , & self . tracker , self . process ) . await ?;
133+ download_file ( & hash_url, & hash_file, None , None , self . process ) . await ?;
129134
130135 utils:: read_file ( "hash" , & hash_file) . map ( |s| s[ 0 ..64 ] . to_owned ( ) )
131136 }
@@ -139,6 +144,7 @@ impl<'a> DownloadCfg<'a> {
139144 & self ,
140145 url_str : & str ,
141146 update_hash : Option < & Path > ,
147+ status : Option < & DownloadStatus > ,
142148 ext : & str ,
143149 ) -> Result < Option < ( temp:: File , String ) > > {
144150 let hash = self . download_hash ( url_str) . await ?;
@@ -166,7 +172,7 @@ impl<'a> DownloadCfg<'a> {
166172 let file = self . tmp_cx . new_file_with_ext ( "" , ext) ?;
167173
168174 let mut hasher = Sha256 :: new ( ) ;
169- download_file ( & url, & file, Some ( & mut hasher) , & self . tracker , self . process ) . await ?;
175+ download_file ( & url, & file, Some ( & mut hasher) , status , self . process ) . await ?;
170176 let actual_hash = format ! ( "{:x}" , hasher. finalize( ) ) ;
171177
172178 if hash != actual_hash {
@@ -192,8 +198,6 @@ impl<'a> DownloadCfg<'a> {
192198pub ( crate ) struct DownloadTracker {
193199 /// MultiProgress bar for the downloads.
194200 multi_progress_bars : MultiProgress ,
195- /// Mapping of URLs being downloaded to their corresponding download status.
196- file_progress_bars : Mutex < HashMap < String , DownloadStatus > > ,
197201}
198202
199203impl DownloadTracker {
@@ -207,70 +211,30 @@ impl DownloadTracker {
207211
208212 Self {
209213 multi_progress_bars,
210- file_progress_bars : Mutex :: new ( HashMap :: new ( ) ) ,
211214 }
212215 }
213216
214217 /// Creates a new ProgressBar for the given component.
215- pub ( crate ) fn create_progress_bar ( & self , component : String , url : String ) {
218+ pub ( crate ) fn status_for ( & self , component : impl Into < Cow < ' static , str > > ) -> DownloadStatus {
216219 let status = DownloadStatus :: new ( component) ;
217220 self . multi_progress_bars . add ( status. progress . clone ( ) ) ;
218- self . file_progress_bars . lock ( ) . unwrap ( ) . insert ( url, status) ;
219- }
220-
221- /// Sets the length for a new ProgressBar and gives it a style.
222- pub ( crate ) fn content_length_received ( & self , content_len : u64 , url : & str ) {
223- if let Some ( status) = self . file_progress_bars . lock ( ) . unwrap ( ) . get ( url) {
224- status. received_length ( content_len) ;
225- }
226- }
227-
228- /// Notifies self that data of size `len` has been received.
229- pub ( crate ) fn data_received ( & self , len : usize , url : & str ) {
230- let mut map = self . file_progress_bars . lock ( ) . unwrap ( ) ;
231- if let Some ( status) = map. get_mut ( url) {
232- status. received_data ( len) ;
233- } ;
234- }
235-
236- /// Notifies self that the download has finished.
237- pub ( crate ) fn download_finished ( & self , url : & str ) {
238- let map = self . file_progress_bars . lock ( ) . unwrap ( ) ;
239- if let Some ( status) = map. get ( url) {
240- status. finished ( )
241- } ;
242- }
243-
244- /// Notifies self that the download has failed.
245- pub ( crate ) fn download_failed ( & self , url : & str ) {
246- let map = self . file_progress_bars . lock ( ) . unwrap ( ) ;
247- if let Some ( status) = map. get ( url) {
248- status. failed ( ) ;
249- } ;
250- }
251-
252- /// Notifies self that the download is being retried.
253- pub ( crate ) fn retrying_download ( & self , url : & str ) {
254- let mut map = self . file_progress_bars . lock ( ) . unwrap ( ) ;
255- if let Some ( status) = map. get_mut ( url) {
256- status. retrying ( ) ;
257- } ;
221+ status
258222 }
259223}
260224
261- struct DownloadStatus {
225+ pub ( crate ) struct DownloadStatus {
262226 progress : ProgressBar ,
263227 /// The instant where the download is being retried.
264228 ///
265229 /// Allows us to delay the reappearance of the progress bar so that the user can see
266230 /// the message "retrying download" for at least a second. Without it, the progress
267231 /// bar would reappear immediately, not allowing the user to correctly see the message,
268232 /// before the progress bar starts again.
269- retry_time : Option < Instant > ,
233+ retry_time : Mutex < Option < Instant > > ,
270234}
271235
272236impl DownloadStatus {
273- fn new ( component : String ) -> Self {
237+ fn new ( component : impl Into < Cow < ' static , str > > ) -> Self {
274238 let progress = ProgressBar :: hidden ( ) ;
275239 progress. set_style (
276240 ProgressStyle :: with_template (
@@ -283,25 +247,23 @@ impl DownloadStatus {
283247
284248 Self {
285249 progress,
286- retry_time : None ,
250+ retry_time : Mutex :: new ( None ) ,
287251 }
288252 }
289253
290- fn received_length ( & self , len : u64 ) {
254+ pub ( crate ) fn received_length ( & self , len : u64 ) {
291255 self . progress . reset ( ) ;
292256 self . progress . set_length ( len) ;
293257 }
294258
295- fn received_data ( & mut self , len : usize ) {
259+ pub ( crate ) fn received_data ( & self , len : usize ) {
296260 self . progress . inc ( len as u64 ) ;
297- if !self
298- . retry_time
299- . is_some_and ( |instant| instant. elapsed ( ) > Duration :: from_secs ( 1 ) )
300- {
261+ let mut retry_time = self . retry_time . lock ( ) . unwrap ( ) ;
262+ if !retry_time. is_some_and ( |instant| instant. elapsed ( ) > Duration :: from_secs ( 1 ) ) {
301263 return ;
302264 }
303265
304- self . retry_time = None ;
266+ * retry_time = None ;
305267 self . progress . set_style (
306268 ProgressStyle :: with_template (
307269 "{msg:>12.bold} [{bar:40}] {bytes}/{total_bytes} ({bytes_per_sec}, ETA: {eta})" ,
@@ -311,24 +273,24 @@ impl DownloadStatus {
311273 ) ;
312274 }
313275
314- fn finished ( & self ) {
276+ pub ( crate ) fn finished ( & self ) {
315277 self . progress . set_style (
316278 ProgressStyle :: with_template ( "{msg:>12.bold} downloaded {total_bytes} in {elapsed}" )
317279 . unwrap ( ) ,
318280 ) ;
319281 self . progress . finish ( ) ;
320282 }
321283
322- fn failed ( & self ) {
284+ pub ( crate ) fn failed ( & self ) {
323285 self . progress . set_style (
324286 ProgressStyle :: with_template ( "{msg:>12.bold} download failed after {elapsed}" )
325287 . unwrap ( ) ,
326288 ) ;
327289 self . progress . finish ( ) ;
328290 }
329291
330- fn retrying ( & mut self ) {
331- self . retry_time = Some ( Instant :: now ( ) ) ;
292+ pub ( crate ) fn retrying ( & self ) {
293+ * self . retry_time . lock ( ) . unwrap ( ) = Some ( Instant :: now ( ) ) ;
332294 self . progress
333295 . set_style ( ProgressStyle :: with_template ( "{msg:>12.bold} retrying download" ) . unwrap ( ) ) ;
334296 }
0 commit comments