@@ -16,6 +16,7 @@ use tmc_langs_framework::io::submission_processing;
1616use tmc_langs_util:: { task_executor, Language } ;
1717use url:: Url ;
1818use walkdir:: WalkDir ;
19+ use tempfile:: NamedTempFile ;
1920
2021#[ quit:: main]
2122fn main ( ) {
@@ -123,11 +124,11 @@ fn run() -> Result<()> {
123124 . arg ( Arg :: with_name ( "checkstyle-output-path" )
124125 . long ( "checkstyle-output-path" )
125126 . help ( "Runs checkstyle if defined" )
126- . takes_value ( true ) )
127+ . takes_value ( true )
128+ . requires ( "locale" ) )
127129 . arg ( Arg :: with_name ( "locale" )
128130 . help ( "Language as a three letter ISO 639-3 code, e.g. 'eng' or 'fin'." )
129131 . long ( "locale" )
130- . help ( "Required if checkstyle-output-path is defined" )
131132 . takes_value ( true ) ) )
132133
133134 . subcommand ( SubCommand :: with_name ( "scan-exercise" )
@@ -183,11 +184,13 @@ fn run() -> Result<()> {
183184 . arg ( Arg :: with_name ( "email" )
184185 . help ( "The email address of your TMC account" )
185186 . long ( "email" )
186- . takes_value ( true ) )
187+ . takes_value ( true )
188+ . required_unless ( "set-access-token" ) )
187189 . arg ( Arg :: with_name ( "set-access-token" )
188190 . help ( "The OAUTH2 access token that should be used for authentication" )
189191 . long ( "set-access-token" )
190- . takes_value ( true ) ) )
192+ . takes_value ( true )
193+ . required_unless ( "email" ) ) )
191194
192195 . subcommand ( SubCommand :: with_name ( "logout" )
193196 . about ( "Logout and remove OAuth2 token from config." ) )
@@ -357,6 +360,36 @@ fn run() -> Result<()> {
357360 . arg ( Arg :: with_name ( "target" )
358361 . long ( "target" )
359362 . required ( true )
363+ . takes_value ( true ) ) )
364+
365+ . subcommand ( SubCommand :: with_name ( "reset-exercise" )
366+ . about ( "Reset exercise, optionally submitting it before doing so." )
367+ . arg ( Arg :: with_name ( "exercise-path" )
368+ . long ( "exercise-path" )
369+ . required ( true )
370+ . takes_value ( true ) )
371+ . arg ( Arg :: with_name ( "save-old-state" )
372+ . long ( "save-old-state" )
373+ . requires ( "submission-url" ) )
374+ . arg ( Arg :: with_name ( "submission-url" )
375+ . long ( "submission-url" )
376+ . takes_value ( true ) ) )
377+
378+ . subcommand ( SubCommand :: with_name ( "download-old-submission" )
379+ . about ( "Downloads an old submission." )
380+ . arg ( Arg :: with_name ( "exercise-id" )
381+ . long ( "exercise-id" )
382+ . required ( true )
383+ . takes_value ( true ) )
384+ . arg ( Arg :: with_name ( "output-path" )
385+ . long ( "exercise-path" )
386+ . required ( true )
387+ . takes_value ( true ) )
388+ . arg ( Arg :: with_name ( "save-old-state" )
389+ . long ( "save-old-state" )
390+ . requires ( "submission-url" ) )
391+ . arg ( Arg :: with_name ( "submission-url" )
392+ . long ( "submission-url" )
360393 . takes_value ( true ) ) ) )
361394
362395 . get_matches ( ) ;
@@ -447,9 +480,6 @@ fn run() -> Result<()> {
447480 let checkstyle_output_path = matches. value_of ( "checkstyle-output-path" ) ;
448481 let checkstyle_output_path: Option < & Path > = checkstyle_output_path. map ( Path :: new) ;
449482
450- let optional_locale = matches. value_of ( "locale" ) ;
451- let optional_locale = optional_locale. map ( into_locale) ;
452-
453483 let test_result = task_executor:: run_tests ( exercise_path) . with_context ( || {
454484 format ! (
455485 "Failed to run tests for exercise at {}" ,
@@ -460,13 +490,8 @@ fn run() -> Result<()> {
460490 write_result_to_file_as_json ( & test_result, output_path) ?;
461491
462492 if let Some ( checkstyle_output_path) = checkstyle_output_path {
463- let locale = optional_locale. unwrap_or_else ( || {
464- Error :: with_description (
465- "Locale must be given if checkstyle-output-path is given." ,
466- ErrorKind :: ArgumentNotFound ,
467- )
468- . exit ( )
469- } ) ?;
493+ let locale = matches. value_of ( "locale" ) . unwrap ( ) ;
494+ let locale = into_locale ( locale) ?;
470495
471496 run_checkstyle ( exercise_path, checkstyle_output_path, locale) ?;
472497 }
@@ -601,11 +626,7 @@ fn run() -> Result<()> {
601626 . context ( "Failed to authenticate with TMC" ) ?;
602627 token
603628 } else {
604- Error :: with_description (
605- "Either the --email or --set-access-token argument should be given" ,
606- ErrorKind :: MissingRequiredArgument ,
607- )
608- . exit ( ) ;
629+ unreachable ! ( "validation error" ) ;
609630 } ;
610631
611632 // create token file
@@ -850,6 +871,43 @@ fn run() -> Result<()> {
850871
851872 core. download_model_solution ( solution_download_url, target)
852873 . context ( "Failed to download model solution" ) ?;
874+ } else if let Some ( matches) = matches. subcommand_matches ( "reset-exercise" ) {
875+ let exercise_path = matches. value_of ( "exercise-path" ) . unwrap ( ) ;
876+ let exercise_path = Path :: new ( exercise_path) ;
877+
878+ let exercise_id = matches. value_of ( "exercise-id" ) . unwrap ( ) ;
879+ let exercise_id = into_usize ( exercise_id) ?;
880+
881+ let save_old_state = matches. is_present ( "save-old-state" ) ;
882+
883+ if save_old_state {
884+ let submission_url = matches. value_of ( "submission_url" ) . unwrap ( ) ;
885+ let submission_url = into_url ( submission_url) ?;
886+ core. submit ( submission_url, exercise_path, None ) ?;
887+ }
888+ core. reset ( exercise_id, exercise_path) ?;
889+ } else if let Some ( matches) = matches. subcommand_matches ( "download-old-submission" ) {
890+ let exercise_id = matches. value_of ( "exercise-id" ) . unwrap ( ) ;
891+ let exercise_id = into_usize ( exercise_id) ?;
892+
893+ let submission_id = matches. value_of ( "submission-id" ) . unwrap ( ) ;
894+ let submission_id = into_usize ( submission_id) ?;
895+
896+ let output_path = matches. value_of ( "output-path" ) . unwrap ( ) ;
897+ let output_path = Path :: new ( output_path) ;
898+
899+ let save_old_state = matches. is_present ( "save-old-state" ) ;
900+
901+ if save_old_state {
902+ let submission_url = matches. value_of ( "submission_url" ) . unwrap ( ) ;
903+ let submission_url = into_url ( submission_url) ?;
904+ core. submit ( submission_url, output_path, None ) ?;
905+ }
906+ core. reset ( exercise_id, output_path) ?;
907+
908+ let temp_zip = NamedTempFile :: new ( ) . context ( "Failed to create a temporary archive" ) ?;
909+ core. download_old_submission ( submission_id, temp_zip. path ( ) ) ?;
910+ task_executor:: extract_project ( temp_zip. path ( ) , output_path) ?;
853911 }
854912 }
855913 Ok ( ( ) )
0 commit comments