@@ -20,19 +20,19 @@ use serde_json::Value;
2020use std:: {
2121 collections:: HashMap ,
2222 env,
23- fs:: File ,
2423 io:: { self , BufReader , Cursor , Read } ,
25- ops:: Deref ,
2624 path:: { Path , PathBuf } ,
2725} ;
2826use tmc_langs:: {
29- file_util,
3027 mooc:: MoocClient ,
3128 tmc:: { request:: FeedbackAnswer , TestMyCodeClient , TestMyCodeClientError } ,
3229 CommandError , Compression , Credentials , DownloadOrUpdateCourseExercisesResult , DownloadResult ,
3330 Language , StyleValidationResult , TmcConfig , UpdatedExercise ,
3431} ;
35- use tmc_langs_util:: deserialize;
32+ use tmc_langs_util:: {
33+ deserialize,
34+ file_util:: { self , Lock , LockOptions } ,
35+ } ;
3636
3737pub enum ParsingResult {
3838 Ok ( Cli ) ,
@@ -180,14 +180,18 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
180180 locale : Locale ( locale) ,
181181 output_path,
182182 } => {
183- file_util:: lock!( exercise_path) ;
183+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
184+ let _guard = lock. lock ( ) ?;
185+
184186 let check_result =
185187 run_checkstyle_write_results ( & exercise_path, output_path. as_deref ( ) , locale) ?;
186188 CliOutput :: finished_with_data ( "ran checkstyle" , check_result. map ( DataKind :: Validation ) )
187189 }
188190
189191 Command :: Clean { exercise_path } => {
190- file_util:: lock!( exercise_path) ;
192+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Write ) ?;
193+ let _guard = lock. lock ( ) ?;
194+
191195 tmc_langs:: clean ( & exercise_path) ?;
192196 CliOutput :: finished ( format ! ( "cleaned exercise at {}" , exercise_path. display( ) ) )
193197 }
@@ -199,7 +203,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
199203 deterministic,
200204 naive,
201205 } => {
202- file_util:: lock!( exercise_path) ;
206+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
207+ let _guard = lock. lock ( ) ?;
208+
203209 let hash = tmc_langs:: compress_project_to (
204210 & exercise_path,
205211 & output_path,
@@ -227,11 +233,11 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
227233 compression,
228234 naive,
229235 } => {
230- let mut archive = file_util :: open_file_locked ( & archive_path) ?;
231- let mut guard = archive . write ( ) ?;
236+ let mut archive_lock = Lock :: file ( & archive_path, LockOptions :: Read ) ?;
237+ let mut archive_guard = archive_lock . lock ( ) ?;
232238
233239 let mut data = vec ! [ ] ;
234- guard . read_to_end ( & mut data) ?;
240+ archive_guard . get_file_mut ( ) . read_to_end ( & mut data) ?;
235241
236242 tmc_langs:: extract_project ( Cursor :: new ( data) , & output_path, compression, true , naive) ?;
237243
@@ -243,7 +249,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
243249 }
244250
245251 Command :: FastAvailablePoints { exercise_path } => {
246- file_util:: lock!( exercise_path) ;
252+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
253+ let _guard = lock. lock ( ) ?;
254+
247255 let points = tmc_langs:: get_available_points ( & exercise_path) ?;
248256 CliOutput :: finished_with_data (
249257 format ! ( "found {} available points" , points. len( ) ) ,
@@ -255,7 +263,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
255263 search_path,
256264 output_path,
257265 } => {
258- file_util:: lock!( search_path) ;
266+ let mut lock = Lock :: dir ( & search_path, LockOptions :: Read ) ?;
267+ let _guard = lock. lock ( ) ?;
268+
259269 let exercises =
260270 tmc_langs:: find_exercise_directories ( & search_path) . with_context ( || {
261271 format ! (
@@ -276,7 +286,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
276286 exercise_path,
277287 output_path,
278288 } => {
279- file_util:: lock!( exercise_path) ;
289+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
290+ let _guard = lock. lock ( ) ?;
291+
280292 let config = tmc_langs:: get_exercise_packaging_configuration ( & exercise_path)
281293 . with_context ( || {
282294 format ! (
@@ -313,7 +325,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
313325 exercise_path,
314326 output_path,
315327 } => {
316- file_util:: lock!( exercise_path) ;
328+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
329+ let _guard = lock. lock ( ) ?;
330+
317331 tmc_langs:: prepare_solution ( & exercise_path, & output_path) . with_context ( || {
318332 format ! (
319333 "Failed to prepare solutions for exercise at {}" ,
@@ -331,7 +345,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
331345 exercise_path,
332346 output_path,
333347 } => {
334- file_util:: lock!( exercise_path) ;
348+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
349+ let _guard = lock. lock ( ) ?;
350+
335351 tmc_langs:: prepare_stub ( & exercise_path, & output_path) . with_context ( || {
336352 format ! (
337353 "Failed to prepare stubs for exercise at {}" ,
@@ -357,6 +373,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
357373 tmc_param,
358374 no_archive_prefix,
359375 } => {
376+ let mut clone_lock = Lock :: dir ( & clone_path, file_util:: LockOptions :: Read ) ?;
377+ let _clone_guard = clone_lock. lock ( ) ?;
378+
360379 // will contain for each key all the values with that key in a list
361380 let mut tmc_params_grouped = HashMap :: new ( ) ;
362381 for value in & tmc_param {
@@ -439,7 +458,8 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
439458 output_path,
440459 wait_for_secret,
441460 } => {
442- file_util:: lock!( exercise_path) ;
461+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
462+ let _guard = lock. lock ( ) ?;
443463
444464 let secret = if wait_for_secret {
445465 let mut s = String :: new ( ) ;
@@ -496,7 +516,8 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
496516 exercise_path,
497517 output_path,
498518 } => {
499- file_util:: lock!( exercise_path) ;
519+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
520+ let _guard = lock. lock ( ) ?;
500521
501522 let exercise_name = exercise_path. file_name ( ) . with_context ( || {
502523 format ! (
@@ -584,6 +605,9 @@ fn run_tmc_inner(
584605 exercise_id,
585606 target,
586607 } => {
608+ let mut output_lock = Lock :: dir ( & target, file_util:: LockOptions :: WriteTruncate ) ?;
609+ let _output_guard = output_lock. lock ( ) ?;
610+
587611 client
588612 . download_model_solution ( exercise_id, & target)
589613 . context ( "Failed to download model solution" ) ?;
@@ -596,6 +620,9 @@ fn run_tmc_inner(
596620 exercise_id,
597621 output_path,
598622 } => {
623+ let mut output_lock = Lock :: dir ( & output_path, file_util:: LockOptions :: Write ) ?;
624+ let _output_guard = output_lock. lock ( ) ?;
625+
599626 tmc_langs:: download_old_submission (
600627 client,
601628 exercise_id,
@@ -837,7 +864,9 @@ fn run_tmc_inner(
837864 paste_message,
838865 submission_path,
839866 } => {
840- file_util:: lock!( submission_path) ;
867+ let mut lock = Lock :: dir ( & submission_path, LockOptions :: Read ) ?;
868+ let _guard = lock. lock ( ) ?;
869+
841870 let locale = locale. map ( |l| l. 0 ) ;
842871 let new_submission = client
843872 . paste ( exercise_id, & submission_path, paste_message, locale)
@@ -851,7 +880,9 @@ fn run_tmc_inner(
851880 message_for_reviewer,
852881 submission_path,
853882 } => {
854- file_util:: lock!( submission_path) ;
883+ let mut lock = Lock :: dir ( & submission_path, LockOptions :: Read ) ?;
884+ let _guard = lock. lock ( ) ?;
885+
855886 let new_submission = client
856887 . request_code_review (
857888 exercise_id,
@@ -871,7 +902,9 @@ fn run_tmc_inner(
871902 save_old_state,
872903 exercise_path,
873904 } => {
874- file_util:: lock!( exercise_path) ;
905+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Write ) ?;
906+ let _guard = lock. lock ( ) ?;
907+
875908 if save_old_state {
876909 // submit current state
877910 client. submit ( exercise_id, & exercise_path, None ) ?;
@@ -923,7 +956,9 @@ fn run_tmc_inner(
923956 submission_path,
924957 exercise_id,
925958 } => {
926- file_util:: lock!( submission_path) ;
959+ let mut lock = Lock :: dir ( & submission_path, LockOptions :: Read ) ?;
960+ let _guard = lock. lock ( ) ?;
961+
927962 let locale = locale. map ( |l| l. 0 ) ;
928963 let new_submission = client
929964 . submit ( exercise_id, & submission_path, locale)
@@ -1040,7 +1075,9 @@ fn run_mooc_inner(mooc: Mooc, client: &mut MoocClient) -> Result<CliOutput> {
10401075 task_id,
10411076 submission_path,
10421077 } => {
1043- file_util:: lock!( submission_path) ;
1078+ let mut lock = Lock :: dir ( & submission_path, LockOptions :: Read ) ?;
1079+ let _guard = lock. lock ( ) ?;
1080+
10441081 let temp = file_util:: named_temp_file ( ) ?;
10451082 tmc_langs:: compress_project_to (
10461083 & submission_path,
@@ -1128,27 +1165,28 @@ fn write_result_to_file_as_json<T: Serialize>(
11281165 pretty : bool ,
11291166 secret : Option < String > ,
11301167) -> Result < ( ) > {
1131- let mut output_file = file_util:: create_file_locked ( output_path) . with_context ( || {
1132- format ! (
1133- "Failed to create results JSON file at {}" ,
1134- output_path. display( )
1135- )
1136- } ) ?;
1137- let guard = output_file. write ( ) ?;
1168+ let mut output_lock =
1169+ Lock :: file ( output_path, LockOptions :: WriteTruncate ) . with_context ( || {
1170+ format ! (
1171+ "Failed to create results JSON file at {}" ,
1172+ output_path. display( )
1173+ )
1174+ } ) ?;
1175+ let mut output_guard = output_lock. lock ( ) ?;
11381176
11391177 if let Some ( secret) = secret {
11401178 let token = tmc_langs:: sign_with_jwt ( result, secret. as_bytes ( ) ) ?;
1141- file_util:: write_to_writer ( token, guard . deref ( ) )
1179+ file_util:: write_to_writer ( token, output_guard . get_file_mut ( ) )
11421180 . with_context ( || format ! ( "Failed to write result to {}" , output_path. display( ) ) ) ?;
11431181 } else if pretty {
1144- serde_json:: to_writer_pretty ( guard . deref ( ) , result) . with_context ( || {
1182+ serde_json:: to_writer_pretty ( output_guard . get_file_mut ( ) , result) . with_context ( || {
11451183 format ! (
11461184 "Failed to write result as JSON to {}" ,
11471185 output_path. display( )
11481186 )
11491187 } ) ?;
11501188 } else {
1151- serde_json:: to_writer ( guard . deref ( ) , result) . with_context ( || {
1189+ serde_json:: to_writer ( output_guard . get_file_mut ( ) , result) . with_context ( || {
11521190 format ! (
11531191 "Failed to write result as JSON to {}" ,
11541192 output_path. display( )
@@ -1172,13 +1210,16 @@ fn run_checkstyle_write_results(
11721210 )
11731211 } ) ?;
11741212 if let Some ( output_path) = output_path {
1175- let output_file = File :: create ( output_path) . with_context ( || {
1176- format ! (
1177- "Failed to create code style check results file at {}" ,
1178- output_path. display( )
1179- )
1180- } ) ?;
1181- serde_json:: to_writer ( output_file, & check_result) . with_context ( || {
1213+ let mut output_lock =
1214+ Lock :: file ( output_path, LockOptions :: WriteTruncate ) . with_context ( || {
1215+ format ! (
1216+ "Failed to create code style check results file at {}" ,
1217+ output_path. display( )
1218+ )
1219+ } ) ?;
1220+ let mut output_guard = output_lock. lock ( ) ?;
1221+
1222+ serde_json:: to_writer ( output_guard. get_file_mut ( ) , & check_result) . with_context ( || {
11821223 format ! (
11831224 "Failed to write code style check results as JSON to {}" ,
11841225 output_path. display( )
0 commit comments