Skip to content

Commit b527659

Browse files
authored
Merge pull request #212 from rage/huh
Fix file locking
2 parents d5fb905 + 275da72 commit b527659

File tree

22 files changed

+944
-620
lines changed

22 files changed

+944
-620
lines changed

Cargo.lock

+171-163
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ authors = [
2222
edition = "2021"
2323
license = "MIT OR Apache-2.0"
2424
rust-version = "1.70.0"
25-
version = "0.36.3"
25+
version = "0.36.4"
2626

2727
[workspace.dependencies]
2828
mooc-langs-api = { git = "https://github.com/rage/secret-project-331.git", rev = "9fb5f894c72932e77dafa6d0f00df7a8abdfa84c" }

crates/bindings/tmc-langs-node/src/de.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use serde::de::{
1010
pub fn from_value<'j, C, T>(cx: &mut C, value: Handle<'j, JsValue>) -> LibResult<T>
1111
where
1212
C: Context<'j>,
13-
T: DeserializeOwned + ?Sized,
13+
T: DeserializeOwned,
1414
{
1515
let mut deserializer: Deserializer<C> = Deserializer::new(cx, value);
1616
let t = T::deserialize(&mut deserializer)?;

crates/bindings/tmc-langs-node/src/helpers.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ macro_rules! lock {
99
( $cx: ident, $( $path: expr ),+ ) => {
1010
$(
1111
let path_buf: PathBuf = (&$path).into();
12-
let mut fl = $crate::file_util::FileLock::new(path_buf).map_err(|e| $crate::helpers::convert_err(&mut $cx, e))?;
13-
let _lock = fl.lock().map_err(|e| $crate::helpers::convert_err(&mut $cx, e))?;
12+
let mut lock = $crate::file_util::Lock::dir(path_buf, $crate::file_util::LockOptions::Write).map_err(|e| $crate::helpers::convert_err(&mut $cx, e))?;
13+
let _guard = lock.lock().map_err(|e| $crate::helpers::convert_err(&mut $cx, e))?;
1414
)*
1515
};
1616
}

crates/bindings/tmc-langs-node/src/lib.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,14 @@ fn extract_project(mut cx: FunctionContext) -> JsResult<JsValue> {
134134
compression: Compression
135135
);
136136

137-
let mut archive =
138-
file_util::open_file_locked(archive_path).map_err(|e| convert_err(&mut cx, e))?;
139-
let mut guard = archive.write().expect("failed to lock file");
137+
let mut archive_lock = file_util::Lock::file(archive_path, file_util::LockOptions::Read)
138+
.map_err(|e| convert_err(&mut cx, e))?;
139+
let mut archive_guard = archive_lock.lock().map_err(|e| convert_err(&mut cx, e))?;
140140
let mut data = vec![];
141-
guard.read_to_end(&mut data).expect("failed to read data");
141+
archive_guard
142+
.get_file_mut()
143+
.read_to_end(&mut data)
144+
.expect("failed to read data");
142145

143146
let res =
144147
tmc_langs::extract_project(Cursor::new(data), &output_path, compression, false, false);

crates/bindings/tmc-langs-node/ts/generated.d.ts

+222-54
Large diffs are not rendered by default.

crates/plugins/make/src/check_log.rs

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::collections::HashMap;
55
use tmc_langs_framework::{RunResult, RunStatus, TestResult};
66

77
#[derive(Debug, Deserialize)]
8+
#[allow(dead_code)]
89
pub struct CheckLog {
910
#[allow(dead_code)]
1011
pub datetime: String,
@@ -52,6 +53,7 @@ impl CheckLog {
5253
}
5354

5455
#[derive(Debug, Deserialize)]
56+
#[allow(dead_code)]
5557
pub struct TestSuite {
5658
#[allow(dead_code)]
5759
pub title: String,
@@ -60,6 +62,7 @@ pub struct TestSuite {
6062
}
6163

6264
#[derive(Debug, Deserialize)]
65+
#[allow(dead_code)]
6366
pub struct Test {
6467
pub result: String,
6568
#[allow(dead_code)]

crates/plugins/make/src/valgrind_log.rs

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use std::{
1111
use tmc_langs_util::{file_util, FileError};
1212

1313
#[derive(Debug)]
14+
#[allow(dead_code)]
1415
pub struct ValgrindLog {
1516
#[allow(dead_code)]
1617
pub header: (String, Vec<String>),
@@ -80,6 +81,7 @@ impl ValgrindLog {
8081
}
8182

8283
#[derive(Debug)]
84+
#[allow(dead_code)]
8385
pub struct ValgrindResult {
8486
#[allow(dead_code)]
8587
pub pid: String,

crates/tmc-langs-cli/src/lib.rs

+80-39
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,19 @@ use serde_json::Value;
2020
use std::{
2121
collections::HashMap,
2222
env,
23-
fs::File,
2423
io::{self, BufReader, Cursor, Read},
25-
ops::Deref,
2624
path::{Path, PathBuf},
2725
};
2826
use 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

3737
pub 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()

crates/tmc-langs-framework/src/archive.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ fn walk_dir_for_compression(
365365
.sort_by_file_name()
366366
.into_iter()
367367
// filter windows lock files
368-
.filter_entry(|e| e.file_name() != ".tmc.lock")
368+
.filter_entry(|e| e.file_name() != file_util::LOCK_FILE_NAME)
369369
{
370370
let entry = entry?;
371371
let stripped = entry

0 commit comments

Comments
 (0)