@@ -10,7 +10,8 @@ use self::config::{CourseConfig, Credentials, Exercise, TmcConfig};
1010use self :: error:: { InvalidTokenError , SandboxTestError } ;
1111use self :: output:: {
1212 CombinedCourseData , DownloadOrUpdateCourseExercise , DownloadOrUpdateCourseExercisesResult ,
13- ErrorData , Kind , LocalExercise , Output , OutputData , OutputResult , Status , Warnings ,
13+ ErrorData , Kind , LocalExercise , Output , OutputData , OutputResult , Status , UpdatedExercise ,
14+ Warnings ,
1415} ;
1516use anyhow:: { Context , Result } ;
1617use clap:: { ArgMatches , Error , ErrorKind } ;
@@ -765,6 +766,52 @@ fn run_core(
765766
766767 // proof of having printed the output
767768 let printed: PrintToken = match matches. subcommand ( ) {
769+ ( "check-exercise-updates" , Some ( _) ) => {
770+ let mut updated_exercises = vec ! [ ] ;
771+
772+ let projects_dir = TmcConfig :: load ( client_name) ?. projects_dir ;
773+ let config = ProjectsConfig :: load ( & projects_dir) ?;
774+ let local_exercises = config
775+ . courses
776+ . into_iter ( )
777+ . map ( |c| c. 1 . exercises )
778+ . flatten ( )
779+ . map ( |e| e. 1 )
780+ . collect :: < Vec < _ > > ( ) ;
781+
782+ if !local_exercises. is_empty ( ) {
783+ let exercise_ids = local_exercises. iter ( ) . map ( |e| e. id ) . collect :: < Vec < _ > > ( ) ;
784+ let server_exercises = client
785+ . get_exercises_details ( exercise_ids) ?
786+ . into_iter ( )
787+ . map ( |e| ( e. id , e) )
788+ . collect :: < HashMap < _ , _ > > ( ) ;
789+ for local_exercise in local_exercises {
790+ let server_exercise =
791+ server_exercises. get ( & local_exercise. id ) . with_context ( || {
792+ format ! (
793+ "Server did not return details for local exercise with id {}" ,
794+ local_exercise. id
795+ )
796+ } ) ?;
797+ if server_exercise. checksum != local_exercise. checksum {
798+ // server has an updated exercise
799+ updated_exercises. push ( UpdatedExercise {
800+ id : local_exercise. id ,
801+ } ) ;
802+ }
803+ }
804+ }
805+
806+ let output = Output :: OutputData ( OutputData {
807+ status : Status :: Finished ,
808+ message : None ,
809+ result : OutputResult :: RetrievedData ,
810+ percent_done : 1.0 ,
811+ data : Some ( updated_exercises) ,
812+ } ) ;
813+ print_output ( & output, pretty, & warnings) ?
814+ }
768815 ( "download-model-solution" , Some ( matches) ) => {
769816 let solution_download_url = matches. value_of ( "solution-download-url" ) . unwrap ( ) ;
770817 let solution_download_url = into_url ( solution_download_url) ?;
@@ -845,7 +892,7 @@ fn run_core(
845892 let projects_dir = TmcConfig :: load ( client_name) ?. projects_dir ;
846893 let mut projects_config = ProjectsConfig :: load ( & projects_dir) ?;
847894
848- let mut course_data = HashMap :: < String , Vec < ( String , String ) > > :: new ( ) ;
895+ let mut course_data = HashMap :: < String , Vec < ( String , String , usize ) > > :: new ( ) ;
849896 let mut exercises_and_paths = vec ! [ ] ;
850897 let mut downloaded = vec ! [ ] ;
851898 let mut skipped = vec ! [ ] ;
@@ -888,7 +935,11 @@ fn run_core(
888935
889936 let entry = course_data. entry ( exercise_detail. course_name ) ;
890937 let course_exercises = entry. or_default ( ) ;
891- course_exercises. push ( ( exercise_detail. exercise_name , exercise_detail. checksum ) ) ;
938+ course_exercises. push ( (
939+ exercise_detail. exercise_name ,
940+ exercise_detail. checksum ,
941+ exercise_detail. id ,
942+ ) ) ;
892943
893944 exercises_and_paths. push ( ( exercise_detail. id , target) ) ;
894945 }
@@ -898,8 +949,8 @@ fn run_core(
898949
899950 for ( course_name, exercise_names) in course_data {
900951 let mut exercises = BTreeMap :: new ( ) ;
901- for ( exercise_name, checksum) in exercise_names {
902- exercises. insert ( exercise_name, Exercise { checksum } ) ;
952+ for ( exercise_name, checksum, id ) in exercise_names {
953+ exercises. insert ( exercise_name, Exercise { id , checksum } ) ;
903954 }
904955
905956 if let Some ( course_config) = projects_config. courses . get_mut ( & course_name) {
@@ -1523,6 +1574,9 @@ fn run_settings(
15231574
15241575 let course_slug = matches. value_of ( "course-slug" ) . unwrap ( ) ;
15251576
1577+ let exercise_id = matches. value_of ( "exercise-id" ) . unwrap ( ) ;
1578+ let exercise_id = into_usize ( exercise_id) ?;
1579+
15261580 let exercise_slug = matches. value_of ( "exercise-slug" ) . unwrap ( ) ;
15271581
15281582 let exercise_checksum = matches. value_of ( "exercise-checksum" ) . unwrap ( ) ;
@@ -1548,6 +1602,7 @@ fn run_settings(
15481602 course_config. exercises . insert (
15491603 exercise_slug. to_string ( ) ,
15501604 Exercise {
1605+ id : exercise_id,
15511606 checksum : exercise_checksum. to_string ( ) ,
15521607 } ,
15531608 ) ;
0 commit comments