@@ -20,7 +20,7 @@ use std::sync::{
2020use std:: thread;
2121use std:: time:: Duration ;
2222use tempfile:: NamedTempFile ;
23- use tmc_langs_util:: { file_util, progress_reporter:: ProgressReporter , task_executor, FileIo } ;
23+ use tmc_langs_util:: { file_util, progress_reporter, task_executor, FileIo } ;
2424use walkdir:: WalkDir ;
2525
2626pub type Token =
@@ -45,7 +45,6 @@ struct TmcCore {
4545 api_url : Url ,
4646 auth_url : String ,
4747 token : Option < Token > ,
48- progress_reporter : Option < ProgressReporter < ' static , ClientUpdateData > > ,
4948 client_name : String ,
5049 client_version : String ,
5150}
@@ -88,7 +87,6 @@ impl TmcClient {
8887 api_url,
8988 auth_url,
9089 token : None ,
91- progress_reporter : None ,
9290 client_name,
9391 client_version,
9492 } ) ) )
@@ -121,51 +119,6 @@ impl TmcClient {
121119 Ok ( ( ) )
122120 }
123121
124- pub fn set_progress_reporter (
125- & mut self ,
126- progress_reporter : ProgressReporter < ' static , ClientUpdateData > ,
127- ) -> Result < ( ) , ClientError > {
128- Arc :: get_mut ( & mut self . 0 )
129- . ok_or ( ClientError :: ArcBorrowed ) ?
130- . progress_reporter = Some ( progress_reporter) ;
131- Ok ( ( ) )
132- }
133-
134- fn progress (
135- & self ,
136- message : String ,
137- step_percent_done : f64 ,
138- data : Option < ClientUpdateData > ,
139- ) -> Result < ( ) , ClientError > {
140- if let Some ( reporter) = & self . 0 . progress_reporter {
141- reporter
142- . progress ( message, step_percent_done, data)
143- . map_err ( ClientError :: ProgressReport )
144- } else {
145- Ok ( ( ) )
146- }
147- }
148-
149- fn step_complete (
150- & self ,
151- message : String ,
152- data : Option < ClientUpdateData > ,
153- ) -> Result < ( ) , ClientError > {
154- if let Some ( reporter) = & self . 0 . progress_reporter {
155- reporter
156- . finish_step ( message, data)
157- . map_err ( ClientError :: ProgressReport )
158- } else {
159- Ok ( ( ) )
160- }
161- }
162-
163- pub fn increment_progress_steps ( & self ) {
164- if let Some ( reporter) = & self . 0 . progress_reporter {
165- reporter. increment_progress_steps ( 1 ) ;
166- }
167- }
168-
169122 /// Attempts to log in with the given credentials, returns an error if an authentication token is already present.
170123 /// Username can be the user's username or email.
171124 ///
@@ -265,27 +218,24 @@ impl TmcClient {
265218 ) -> Result < ( ) , ClientError > {
266219 // todo: bit of a mess, refactor
267220 let exercises_len = exercises. len ( ) ;
268- self . progress (
221+ start_stage (
222+ exercises_len * 2 + 1 , // each download progresses at 2 points, plus the final finishing step
269223 format ! ( "Downloading {} exercises" , exercises_len) ,
270- 0.0 ,
271224 None ,
272- ) ? ;
225+ ) ;
273226
274227 let thread_count = exercises_len. min ( 4 ) ; // max 4 threads
275228 let mut handles = vec ! [ ] ;
276229 let exercises = Arc :: new ( Mutex :: new ( exercises) ) ;
277230 let starting_download_counter = Arc :: new ( AtomicUsize :: new ( 1 ) ) ;
278231 let downloaded_counter = Arc :: new ( AtomicUsize :: new ( 1 ) ) ;
279- let progress_counter = Arc :: new ( AtomicUsize :: new ( 1 ) ) ;
280- let progress_goal = ( exercises_len * 2 ) as f64 ; // each download increases progress at 2 points
281232
282233 // spawn threads
283234 for _thread_id in 0 ..thread_count {
284235 let client = Arc :: clone ( & self . 0 ) ;
285236 let exercises = Arc :: clone ( & exercises) ;
286237 let starting_download_counter = Arc :: clone ( & starting_download_counter) ;
287238 let downloaded_counter = Arc :: clone ( & downloaded_counter) ;
288- let progress_counter = Arc :: clone ( & progress_counter) ;
289239
290240 // each thread returns either a list of successful downloads, or a tuple of successful downloads and errors
291241 type ThreadErr = ( Vec < usize > , Vec < ( usize , Box < ClientError > ) > ) ;
@@ -311,43 +261,38 @@ impl TmcClient {
311261 // TODO: do in memory without zip_file?
312262 let starting_download_count =
313263 starting_download_counter. fetch_add ( 1 , Ordering :: SeqCst ) ;
314- let progress_count = progress_counter. fetch_add ( 1 , Ordering :: SeqCst ) ;
315- let progress = progress_count as f64 / progress_goal;
316264 let zip_file = NamedTempFile :: new ( ) . map_err ( ClientError :: TempFile ) ?;
317- client_clone. progress (
265+
266+ progress_stage (
318267 format ! (
319268 "Downloading exercise {} to '{}'. ({} out of {})" ,
320269 exercise_id,
321270 target. display( ) ,
322271 starting_download_count,
323272 exercises_len
324273 ) ,
325- progress,
326- Some ( ClientUpdateData :: ExerciseDownload {
274+ ClientUpdateData :: ExerciseDownload {
327275 id : exercise_id,
328276 path : target. clone ( ) ,
329- } ) ,
330- ) ? ;
277+ } ,
278+ ) ;
331279
332280 client_clone. download_exercise ( exercise_id, zip_file. path ( ) ) ?;
333281 let downloaded_count = downloaded_counter. fetch_add ( 1 , Ordering :: SeqCst ) ;
334- let progress_count = progress_counter. fetch_add ( 1 , Ordering :: SeqCst ) ;
335- let progress = progress_count as f64 / progress_goal;
336282 task_executor:: extract_project ( zip_file, & target, true ) ?;
337- client_clone . progress (
283+ progress_stage (
338284 format ! (
339285 "Downloaded exercise {} to '{}'. ({} out of {})" ,
340286 exercise_id,
341287 target. display( ) ,
342288 downloaded_count,
343289 exercises_len
344290 ) ,
345- progress,
346- Some ( ClientUpdateData :: ExerciseDownload {
291+ ClientUpdateData :: ExerciseDownload {
347292 id : exercise_id,
348293 path : target,
349- } ) ,
350- ) ? ;
294+ } ,
295+ ) ;
351296 Ok ( ( ) )
352297 } ( ) ;
353298
@@ -383,14 +328,14 @@ impl TmcClient {
383328 }
384329 }
385330
386- self . step_complete (
331+ finish_stage (
387332 format ! (
388333 "Successfully downloaded {} out of {} exercises." ,
389334 successful. len( ) ,
390335 exercises_len
391336 ) ,
392337 None ,
393- ) ? ;
338+ ) ;
394339 if !failed. is_empty ( ) {
395340 Err ( ClientError :: IncompleteDownloadResult {
396341 downloaded : successful,
@@ -536,25 +481,22 @@ impl TmcClient {
536481 return Err ( ClientError :: NotLoggedIn ) ;
537482 }
538483
539- self . progress ( "Compressing submission..." . to_string ( ) , 0.0 , None ) ? ;
484+ start_stage ( 2 , "Compressing submission..." , None ) ;
540485 let compressed = task_executor:: compress_project ( submission_path) ?;
541486 let mut file = NamedTempFile :: new ( ) . map_err ( ClientError :: TempFile ) ?;
542487 file. write_all ( & compressed) . map_err ( |e| {
543488 ClientError :: Tmc ( FileIo :: FileWrite ( file. path ( ) . to_path_buf ( ) , e) . into ( ) )
544489 } ) ?;
545- self . progress (
546- "Compressed submission. Posting submission..." . to_string ( ) ,
547- 0.5 ,
548- None ,
549- ) ?;
490+ progress_stage ( "Compressed submission. Posting submission..." , None ) ;
550491
551492 let result = self . post_submission ( submission_url, file. path ( ) , locale) ?;
552- self . progress (
553- format ! ( "Submission running at {0}" , result. show_submission_url) ,
554- 1.0 ,
555- Some ( ClientUpdateData :: PostedSubmission ( result. clone ( ) ) ) ,
556- ) ?;
557- self . step_complete ( "Submission finished!" . to_string ( ) , None ) ?;
493+ finish_stage (
494+ format ! (
495+ "Submission finished, running at {0}" ,
496+ result. show_submission_url
497+ ) ,
498+ ClientUpdateData :: PostedSubmission ( result. clone ( ) ) ,
499+ ) ;
558500 Ok ( result)
559501 }
560502
@@ -608,20 +550,19 @@ impl TmcClient {
608550 & self ,
609551 submission_url : & str ,
610552 ) -> Result < SubmissionFinished , ClientError > {
553+ start_stage ( 4 , "Waiting for submission" , None ) ;
554+
611555 let mut previous_status = None ;
612556 loop {
613557 match self . check_submission ( submission_url) ? {
614558 SubmissionProcessingStatus :: Finished ( f) => {
615- self . step_complete ( "Submission finished processing!" . to_string ( ) , None ) ? ;
559+ finish_stage ( "Submission finished processing!" , None ) ;
616560 return Ok ( * f) ;
617561 }
618562 SubmissionProcessingStatus :: Processing ( p) => {
619563 if p. status == SubmissionStatus :: Hidden {
620564 // hidden status, return constructed status
621- self . step_complete (
622- "Submission status hidden, stopping waiting." . to_string ( ) ,
623- None ,
624- ) ?;
565+ finish_stage ( "Submission status hidden, stopping waiting." , None ) ;
625566 let finished = SubmissionFinished {
626567 api_version : 8 ,
627568 all_tests_passed : Some ( true ) ,
@@ -662,13 +603,13 @@ impl TmcClient {
662603 // new status, update progress
663604 match status {
664605 SandboxStatus :: Created => {
665- self . progress ( "Created on sandbox" . to_string ( ) , 0.25 , None ) ?
606+ progress_stage ( "Created on sandbox" , None )
666607 }
667608 SandboxStatus :: SendingToSandbox => {
668- self . progress ( "Sending to sandbox" . to_string ( ) , 0.5 , None ) ? ;
609+ progress_stage ( "Sending to sandbox" , None ) ;
669610 }
670611 SandboxStatus :: ProcessingOnSandbox => {
671- self . progress ( "Processing on sandbox" . to_string ( ) , 0.75 , None ) ? ;
612+ progress_stage ( "Processing on sandbox" , None ) ;
672613 }
673614 }
674615 previous_status = Some ( status) ;
@@ -805,6 +746,22 @@ impl AsRef<TmcCore> for TmcClient {
805746 }
806747}
807748
749+ fn start_stage (
750+ steps : usize ,
751+ message : impl Into < String > ,
752+ data : impl Into < Option < ClientUpdateData > > ,
753+ ) {
754+ progress_reporter:: start_stage ( steps, message. into ( ) , data. into ( ) )
755+ }
756+
757+ fn progress_stage ( message : impl Into < String > , data : impl Into < Option < ClientUpdateData > > ) {
758+ progress_reporter:: progress_stage ( message. into ( ) , data. into ( ) )
759+ }
760+
761+ fn finish_stage ( message : impl Into < String > , data : impl Into < Option < ClientUpdateData > > ) {
762+ progress_reporter:: finish_stage ( message. into ( ) , data. into ( ) )
763+ }
764+
808765#[ cfg( test) ]
809766mod test {
810767 use super :: * ;
0 commit comments