@@ -192,13 +192,8 @@ impl<'a> DownloadCfg<'a> {
192192pub ( crate ) struct DownloadTracker {
193193 /// MultiProgress bar for the downloads.
194194 multi_progress_bars : MultiProgress ,
195- /// Mapping of URLs being downloaded to their corresponding progress bars.
196- /// The `Option<Instant>` represents the instant where the download is being retried,
197- /// allowing us delay the reappearance of the progress bar so that the user can see
198- /// the message "retrying download" for at least a second.
199- /// Without it, the progress bar would reappear immediately, not allowing the user to
200- /// correctly see the message, before the progress bar starts again.
201- file_progress_bars : Mutex < HashMap < String , ( ProgressBar , Option < Instant > ) > > ,
195+ /// Mapping of URLs being downloaded to their corresponding download status.
196+ file_progress_bars : Mutex < HashMap < String , DownloadStatus > > ,
202197}
203198
204199impl DownloadTracker {
@@ -218,42 +213,96 @@ impl DownloadTracker {
218213
219214 /// Creates a new ProgressBar for the given component.
220215 pub ( crate ) fn create_progress_bar ( & self , component : String , url : String ) {
221- let pb = ProgressBar :: hidden ( ) ;
222- pb. set_style (
223- ProgressStyle :: with_template (
224- "{msg:>12.bold} [{bar:40}] {bytes}/{total_bytes} ({bytes_per_sec}, ETA: {eta})" ,
225- )
226- . unwrap ( )
227- . progress_chars ( "## " ) ,
228- ) ;
229- pb. set_message ( component) ;
230- self . multi_progress_bars . add ( pb. clone ( ) ) ;
231- self . file_progress_bars
232- . lock ( )
233- . unwrap ( )
234- . insert ( url, ( pb, None ) ) ;
216+ let status = DownloadStatus :: new ( component) ;
217+ self . multi_progress_bars . add ( status. progress . clone ( ) ) ;
218+ self . file_progress_bars . lock ( ) . unwrap ( ) . insert ( url, status) ;
235219 }
236220
237221 /// Sets the length for a new ProgressBar and gives it a style.
238222 pub ( crate ) fn content_length_received ( & self , content_len : u64 , url : & str ) {
239- if let Some ( ( pb, _) ) = self . file_progress_bars . lock ( ) . unwrap ( ) . get ( url) {
240- pb. reset ( ) ;
241- pb. set_length ( content_len) ;
223+ if let Some ( status) = self . file_progress_bars . lock ( ) . unwrap ( ) . get ( url) {
224+ status. received_length ( content_len) ;
242225 }
243226 }
244227
245228 /// Notifies self that data of size `len` has been received.
246229 pub ( crate ) fn data_received ( & self , len : usize , url : & str ) {
247230 let mut map = self . file_progress_bars . lock ( ) . unwrap ( ) ;
248- let Some ( ( pb , retry_time ) ) = map. get_mut ( url) else {
249- return ;
231+ if let Some ( status ) = map. get_mut ( url) {
232+ status . received_data ( len ) ;
250233 } ;
251- pb. inc ( len as u64 ) ;
252- if !retry_time. is_some_and ( |instant| instant. elapsed ( ) > Duration :: from_secs ( 1 ) ) {
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+ } ;
258+ }
259+ }
260+
261+ struct DownloadStatus {
262+ progress : ProgressBar ,
263+ /// The instant where the download is being retried.
264+ ///
265+ /// Allows us to delay the reappearance of the progress bar so that the user can see
266+ /// the message "retrying download" for at least a second. Without it, the progress
267+ /// bar would reappear immediately, not allowing the user to correctly see the message,
268+ /// before the progress bar starts again.
269+ retry_time : Option < Instant > ,
270+ }
271+
272+ impl DownloadStatus {
273+ fn new ( component : String ) -> Self {
274+ let progress = ProgressBar :: hidden ( ) ;
275+ progress. set_style (
276+ ProgressStyle :: with_template (
277+ "{msg:>12.bold} [{bar:40}] {bytes}/{total_bytes} ({bytes_per_sec}, ETA: {eta})" ,
278+ )
279+ . unwrap ( )
280+ . progress_chars ( "## " ) ,
281+ ) ;
282+ progress. set_message ( component) ;
283+
284+ Self {
285+ progress,
286+ retry_time : None ,
287+ }
288+ }
289+
290+ fn received_length ( & self , len : u64 ) {
291+ self . progress . reset ( ) ;
292+ self . progress . set_length ( len) ;
293+ }
294+
295+ fn received_data ( & mut self , len : usize ) {
296+ self . progress . inc ( len as u64 ) ;
297+ if !self
298+ . retry_time
299+ . is_some_and ( |instant| instant. elapsed ( ) > Duration :: from_secs ( 1 ) )
300+ {
253301 return ;
254302 }
255- * retry_time = None ;
256- pb. set_style (
303+
304+ self . retry_time = None ;
305+ self . progress . set_style (
257306 ProgressStyle :: with_template (
258307 "{msg:>12.bold} [{bar:40}] {bytes}/{total_bytes} ({bytes_per_sec}, ETA: {eta})" ,
259308 )
@@ -262,40 +311,26 @@ impl DownloadTracker {
262311 ) ;
263312 }
264313
265- /// Notifies self that the download has finished.
266- pub ( crate ) fn download_finished ( & self , url : & str ) {
267- let map = self . file_progress_bars . lock ( ) . unwrap ( ) ;
268- let Some ( ( pb, _) ) = map. get ( url) else {
269- return ;
270- } ;
271- pb. set_style (
314+ fn finished ( & self ) {
315+ self . progress . set_style (
272316 ProgressStyle :: with_template ( "{msg:>12.bold} downloaded {total_bytes} in {elapsed}" )
273317 . unwrap ( ) ,
274318 ) ;
275- pb . finish ( ) ;
319+ self . progress . finish ( ) ;
276320 }
277321
278- /// Notifies self that the download has failed.
279- pub ( crate ) fn download_failed ( & self , url : & str ) {
280- let map = self . file_progress_bars . lock ( ) . unwrap ( ) ;
281- let Some ( ( pb, _) ) = map. get ( url) else {
282- return ;
283- } ;
284- pb. set_style (
322+ fn failed ( & self ) {
323+ self . progress . set_style (
285324 ProgressStyle :: with_template ( "{msg:>12.bold} download failed after {elapsed}" )
286325 . unwrap ( ) ,
287326 ) ;
288- pb . finish ( ) ;
327+ self . progress . finish ( ) ;
289328 }
290329
291- /// Notifies self that the download is being retried.
292- pub ( crate ) fn retrying_download ( & self , url : & str ) {
293- let mut map = self . file_progress_bars . lock ( ) . unwrap ( ) ;
294- let Some ( ( pb, retry_time) ) = map. get_mut ( url) else {
295- return ;
296- } ;
297- * retry_time = Some ( Instant :: now ( ) ) ;
298- pb. set_style ( ProgressStyle :: with_template ( "{msg:>12.bold} retrying download" ) . unwrap ( ) ) ;
330+ fn retrying ( & mut self ) {
331+ self . retry_time = Some ( Instant :: now ( ) ) ;
332+ self . progress
333+ . set_style ( ProgressStyle :: with_template ( "{msg:>12.bold} retrying download" ) . unwrap ( ) ) ;
299334 }
300335}
301336
0 commit comments