@@ -20,19 +20,19 @@ use serde_json::Value;
20
20
use std:: {
21
21
collections:: HashMap ,
22
22
env,
23
- fs:: File ,
24
23
io:: { self , BufReader , Cursor , Read } ,
25
- ops:: Deref ,
26
24
path:: { Path , PathBuf } ,
27
25
} ;
28
26
use tmc_langs:: {
29
- file_util,
30
27
mooc:: MoocClient ,
31
28
tmc:: { request:: FeedbackAnswer , TestMyCodeClient , TestMyCodeClientError } ,
32
29
CommandError , Compression , Credentials , DownloadOrUpdateCourseExercisesResult , DownloadResult ,
33
30
Language , StyleValidationResult , TmcConfig , UpdatedExercise ,
34
31
} ;
35
- use tmc_langs_util:: deserialize;
32
+ use tmc_langs_util:: {
33
+ deserialize,
34
+ file_util:: { self , Lock , LockOptions } ,
35
+ } ;
36
36
37
37
pub enum ParsingResult {
38
38
Ok ( Cli ) ,
@@ -180,14 +180,18 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
180
180
locale : Locale ( locale) ,
181
181
output_path,
182
182
} => {
183
- file_util:: lock!( exercise_path) ;
183
+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
184
+ let _guard = lock. lock ( ) ?;
185
+
184
186
let check_result =
185
187
run_checkstyle_write_results ( & exercise_path, output_path. as_deref ( ) , locale) ?;
186
188
CliOutput :: finished_with_data ( "ran checkstyle" , check_result. map ( DataKind :: Validation ) )
187
189
}
188
190
189
191
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
+
191
195
tmc_langs:: clean ( & exercise_path) ?;
192
196
CliOutput :: finished ( format ! ( "cleaned exercise at {}" , exercise_path. display( ) ) )
193
197
}
@@ -199,7 +203,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
199
203
deterministic,
200
204
naive,
201
205
} => {
202
- file_util:: lock!( exercise_path) ;
206
+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
207
+ let _guard = lock. lock ( ) ?;
208
+
203
209
let hash = tmc_langs:: compress_project_to (
204
210
& exercise_path,
205
211
& output_path,
@@ -227,11 +233,11 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
227
233
compression,
228
234
naive,
229
235
} => {
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 ( ) ?;
232
238
233
239
let mut data = vec ! [ ] ;
234
- guard . read_to_end ( & mut data) ?;
240
+ archive_guard . get_file_mut ( ) . read_to_end ( & mut data) ?;
235
241
236
242
tmc_langs:: extract_project ( Cursor :: new ( data) , & output_path, compression, true , naive) ?;
237
243
@@ -243,7 +249,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
243
249
}
244
250
245
251
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
+
247
255
let points = tmc_langs:: get_available_points ( & exercise_path) ?;
248
256
CliOutput :: finished_with_data (
249
257
format ! ( "found {} available points" , points. len( ) ) ,
@@ -255,7 +263,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
255
263
search_path,
256
264
output_path,
257
265
} => {
258
- file_util:: lock!( search_path) ;
266
+ let mut lock = Lock :: dir ( & search_path, LockOptions :: Read ) ?;
267
+ let _guard = lock. lock ( ) ?;
268
+
259
269
let exercises =
260
270
tmc_langs:: find_exercise_directories ( & search_path) . with_context ( || {
261
271
format ! (
@@ -276,7 +286,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
276
286
exercise_path,
277
287
output_path,
278
288
} => {
279
- file_util:: lock!( exercise_path) ;
289
+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
290
+ let _guard = lock. lock ( ) ?;
291
+
280
292
let config = tmc_langs:: get_exercise_packaging_configuration ( & exercise_path)
281
293
. with_context ( || {
282
294
format ! (
@@ -313,7 +325,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
313
325
exercise_path,
314
326
output_path,
315
327
} => {
316
- file_util:: lock!( exercise_path) ;
328
+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
329
+ let _guard = lock. lock ( ) ?;
330
+
317
331
tmc_langs:: prepare_solution ( & exercise_path, & output_path) . with_context ( || {
318
332
format ! (
319
333
"Failed to prepare solutions for exercise at {}" ,
@@ -331,7 +345,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
331
345
exercise_path,
332
346
output_path,
333
347
} => {
334
- file_util:: lock!( exercise_path) ;
348
+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
349
+ let _guard = lock. lock ( ) ?;
350
+
335
351
tmc_langs:: prepare_stub ( & exercise_path, & output_path) . with_context ( || {
336
352
format ! (
337
353
"Failed to prepare stubs for exercise at {}" ,
@@ -357,6 +373,9 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
357
373
tmc_param,
358
374
no_archive_prefix,
359
375
} => {
376
+ let mut clone_lock = Lock :: dir ( & clone_path, file_util:: LockOptions :: Read ) ?;
377
+ let _clone_guard = clone_lock. lock ( ) ?;
378
+
360
379
// will contain for each key all the values with that key in a list
361
380
let mut tmc_params_grouped = HashMap :: new ( ) ;
362
381
for value in & tmc_param {
@@ -439,7 +458,8 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
439
458
output_path,
440
459
wait_for_secret,
441
460
} => {
442
- file_util:: lock!( exercise_path) ;
461
+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
462
+ let _guard = lock. lock ( ) ?;
443
463
444
464
let secret = if wait_for_secret {
445
465
let mut s = String :: new ( ) ;
@@ -496,7 +516,8 @@ fn run_app(cli: Cli) -> Result<CliOutput> {
496
516
exercise_path,
497
517
output_path,
498
518
} => {
499
- file_util:: lock!( exercise_path) ;
519
+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Read ) ?;
520
+ let _guard = lock. lock ( ) ?;
500
521
501
522
let exercise_name = exercise_path. file_name ( ) . with_context ( || {
502
523
format ! (
@@ -584,6 +605,9 @@ fn run_tmc_inner(
584
605
exercise_id,
585
606
target,
586
607
} => {
608
+ let mut output_lock = Lock :: dir ( & target, file_util:: LockOptions :: WriteTruncate ) ?;
609
+ let _output_guard = output_lock. lock ( ) ?;
610
+
587
611
client
588
612
. download_model_solution ( exercise_id, & target)
589
613
. context ( "Failed to download model solution" ) ?;
@@ -596,6 +620,9 @@ fn run_tmc_inner(
596
620
exercise_id,
597
621
output_path,
598
622
} => {
623
+ let mut output_lock = Lock :: dir ( & output_path, file_util:: LockOptions :: Write ) ?;
624
+ let _output_guard = output_lock. lock ( ) ?;
625
+
599
626
tmc_langs:: download_old_submission (
600
627
client,
601
628
exercise_id,
@@ -837,7 +864,9 @@ fn run_tmc_inner(
837
864
paste_message,
838
865
submission_path,
839
866
} => {
840
- file_util:: lock!( submission_path) ;
867
+ let mut lock = Lock :: dir ( & submission_path, LockOptions :: Read ) ?;
868
+ let _guard = lock. lock ( ) ?;
869
+
841
870
let locale = locale. map ( |l| l. 0 ) ;
842
871
let new_submission = client
843
872
. paste ( exercise_id, & submission_path, paste_message, locale)
@@ -851,7 +880,9 @@ fn run_tmc_inner(
851
880
message_for_reviewer,
852
881
submission_path,
853
882
} => {
854
- file_util:: lock!( submission_path) ;
883
+ let mut lock = Lock :: dir ( & submission_path, LockOptions :: Read ) ?;
884
+ let _guard = lock. lock ( ) ?;
885
+
855
886
let new_submission = client
856
887
. request_code_review (
857
888
exercise_id,
@@ -871,7 +902,9 @@ fn run_tmc_inner(
871
902
save_old_state,
872
903
exercise_path,
873
904
} => {
874
- file_util:: lock!( exercise_path) ;
905
+ let mut lock = Lock :: dir ( & exercise_path, LockOptions :: Write ) ?;
906
+ let _guard = lock. lock ( ) ?;
907
+
875
908
if save_old_state {
876
909
// submit current state
877
910
client. submit ( exercise_id, & exercise_path, None ) ?;
@@ -923,7 +956,9 @@ fn run_tmc_inner(
923
956
submission_path,
924
957
exercise_id,
925
958
} => {
926
- file_util:: lock!( submission_path) ;
959
+ let mut lock = Lock :: dir ( & submission_path, LockOptions :: Read ) ?;
960
+ let _guard = lock. lock ( ) ?;
961
+
927
962
let locale = locale. map ( |l| l. 0 ) ;
928
963
let new_submission = client
929
964
. submit ( exercise_id, & submission_path, locale)
@@ -1040,7 +1075,9 @@ fn run_mooc_inner(mooc: Mooc, client: &mut MoocClient) -> Result<CliOutput> {
1040
1075
task_id,
1041
1076
submission_path,
1042
1077
} => {
1043
- file_util:: lock!( submission_path) ;
1078
+ let mut lock = Lock :: dir ( & submission_path, LockOptions :: Read ) ?;
1079
+ let _guard = lock. lock ( ) ?;
1080
+
1044
1081
let temp = file_util:: named_temp_file ( ) ?;
1045
1082
tmc_langs:: compress_project_to (
1046
1083
& submission_path,
@@ -1128,27 +1165,28 @@ fn write_result_to_file_as_json<T: Serialize>(
1128
1165
pretty : bool ,
1129
1166
secret : Option < String > ,
1130
1167
) -> 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 ( ) ?;
1138
1176
1139
1177
if let Some ( secret) = secret {
1140
1178
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 ( ) )
1142
1180
. with_context ( || format ! ( "Failed to write result to {}" , output_path. display( ) ) ) ?;
1143
1181
} 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 ( || {
1145
1183
format ! (
1146
1184
"Failed to write result as JSON to {}" ,
1147
1185
output_path. display( )
1148
1186
)
1149
1187
} ) ?;
1150
1188
} else {
1151
- serde_json:: to_writer ( guard . deref ( ) , result) . with_context ( || {
1189
+ serde_json:: to_writer ( output_guard . get_file_mut ( ) , result) . with_context ( || {
1152
1190
format ! (
1153
1191
"Failed to write result as JSON to {}" ,
1154
1192
output_path. display( )
@@ -1172,13 +1210,16 @@ fn run_checkstyle_write_results(
1172
1210
)
1173
1211
} ) ?;
1174
1212
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 ( || {
1182
1223
format ! (
1183
1224
"Failed to write code style check results as JSON to {}" ,
1184
1225
output_path. display( )
0 commit comments