|
1 | 1 | use proc_macro2::{Span, TokenStream}; |
2 | 2 | use quote::{quote, TokenStreamExt}; |
3 | 3 | use std::collections::hash_map::DefaultHasher; |
| 4 | +use std::env; |
4 | 5 | use std::hash::{Hash, Hasher}; |
5 | 6 | use std::io::Write; |
6 | 7 | use std::iter; |
7 | 8 | use std::path::{Path, PathBuf}; |
8 | | -use std::time::Duration; |
9 | | -use std::{env, thread}; |
10 | 9 | use syn::parse::{ParseStream, Parser, Result as ParseResult}; |
11 | 10 | use syn::punctuated::Punctuated; |
12 | 11 | use syn::{Fields, Ident, ItemStruct, LitBool, LitChar, LitStr, Token}; |
@@ -216,36 +215,16 @@ fn derive_template_common_impl( |
216 | 215 |
|
217 | 216 | std::fs::create_dir_all(output_file.parent().unwrap()).unwrap(); |
218 | 217 |
|
219 | | - // This makes sure max 1 process creates a new file, "create_new" check+create is an |
220 | | - // atomic operation. Cargo sometimes runs multiple macro invocations for the same |
221 | | - // file in parallel, so that's important to prevent a race condition. |
222 | | - struct Lock<'path> { |
223 | | - path: &'path Path, |
224 | | - } |
225 | | - |
226 | | - impl<'path> Lock<'path> { |
227 | | - fn new(path: &'path Path) -> std::io::Result<Self> { |
228 | | - std::fs::OpenOptions::new() |
229 | | - .write(true) |
230 | | - .create_new(true) |
231 | | - .open(path) |
232 | | - .map(|_| Lock { path }) |
233 | | - } |
234 | | - } |
235 | | - |
236 | | - impl<'path> Drop for Lock<'path> { |
237 | | - fn drop(&mut self) { |
238 | | - std::fs::remove_file(self.path) |
239 | | - .expect("Failed to clean up lock file {}. Delete it manually, or run `cargo clean`."); |
240 | | - } |
241 | | - } |
242 | | - |
243 | 218 | let deps = with_compiler(config, |compiler| { |
244 | 219 | let dep_path = output_file.with_extension("deps"); |
245 | 220 | let lock_path = output_file.with_extension("lock"); |
246 | | - let lock = Lock::new(&lock_path); |
247 | | - match lock { |
248 | | - Ok(lock) => { |
| 221 | + let lock_file = std::fs::OpenOptions::new() |
| 222 | + .create(true) |
| 223 | + .truncate(false) |
| 224 | + .write(true) |
| 225 | + .open(&lock_path); |
| 226 | + match lock_file.as_ref().map(|file| file.lock()) { |
| 227 | + Ok(_) => { |
249 | 228 | let (tsource, report) = compiler.resolve_file(&input_file)?; |
250 | 229 |
|
251 | 230 | let output_filetime = filetime(&output_file); |
@@ -292,27 +271,8 @@ fn derive_template_common_impl( |
292 | 271 | ); |
293 | 272 | } |
294 | 273 |
|
295 | | - drop(lock); |
296 | 274 | Ok(report.deps) |
297 | 275 | } |
298 | | - // Lock file exists, template is already (currently being?) compiled. |
299 | | - Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => { |
300 | | - let mut load_attempts = 0; |
301 | | - while lock_path.exists() { |
302 | | - load_attempts += 1; |
303 | | - if load_attempts > 100 { |
304 | | - panic!("Lock file {:?} is stuck. Try deleting it.", lock_path); |
305 | | - } |
306 | | - thread::sleep(Duration::from_millis(10)); |
307 | | - } |
308 | | - |
309 | | - Ok(std::fs::read_to_string(&dep_path) |
310 | | - .unwrap() |
311 | | - .trim() |
312 | | - .lines() |
313 | | - .map(PathBuf::from) |
314 | | - .collect()) |
315 | | - } |
316 | 276 | Err(e) => panic!("{:?}: {}. Maybe try `cargo clean`?", lock_path, e), |
317 | 277 | } |
318 | 278 | }) |
|
0 commit comments