|
1 | 1 | use std::{
|
2 | 2 | cell::{Cell, RefCell},
|
3 | 3 | env, fs,
|
4 |
| - sync::Once, |
| 4 | + sync::{Once, OnceLock}, |
5 | 5 | time::Duration,
|
6 | 6 | };
|
7 | 7 |
|
@@ -140,13 +140,36 @@ impl Project<'_> {
|
140 | 140 | /// if there is a path to config dir in the test fixture. However, in certain cases we create a
|
141 | 141 | /// file in the config dir after server is run, something where our naive approach comes short.
|
142 | 142 | /// Using a `prelock` allows us to force a lock when we know we need it.
|
143 |
| - pub(crate) fn server_with_lock(self, prelock: bool) -> Server { |
144 |
| - static CONFIG_DIR_LOCK: Mutex<()> = Mutex::new(()); |
145 |
| - |
146 |
| - let mut config_dir_guard = if prelock { |
147 |
| - let v = Some(CONFIG_DIR_LOCK.lock()); |
148 |
| - env::set_var("__TEST_RA_USER_CONFIG_DIR", TestDir::new().path()); |
149 |
| - v |
| 143 | + pub(crate) fn server_with_lock(self, config_lock: bool) -> Server { |
| 144 | + static CONFIG_DIR_LOCK: OnceLock<(Utf8PathBuf, Mutex<()>)> = OnceLock::new(); |
| 145 | + |
| 146 | + let config_dir_guard = if config_lock { |
| 147 | + Some({ |
| 148 | + let (path, mutex) = CONFIG_DIR_LOCK.get_or_init(|| { |
| 149 | + let value = TestDir::new().keep().path().to_owned(); |
| 150 | + env::set_var("__TEST_RA_USER_CONFIG_DIR", &value); |
| 151 | + (value, Mutex::new(())) |
| 152 | + }); |
| 153 | + #[allow(dyn_drop)] |
| 154 | + (mutex.lock(), { |
| 155 | + Box::new({ |
| 156 | + struct Dropper(Utf8PathBuf); |
| 157 | + impl Drop for Dropper { |
| 158 | + fn drop(&mut self) { |
| 159 | + for entry in fs::read_dir(&self.0).unwrap() { |
| 160 | + let path = entry.unwrap().path(); |
| 161 | + if path.is_file() { |
| 162 | + fs::remove_file(path).unwrap(); |
| 163 | + } else if path.is_dir() { |
| 164 | + fs::remove_dir_all(path).unwrap(); |
| 165 | + } |
| 166 | + } |
| 167 | + } |
| 168 | + } |
| 169 | + Dropper(path.clone()) |
| 170 | + }) as Box<dyn Drop> |
| 171 | + }) |
| 172 | + }) |
150 | 173 | } else {
|
151 | 174 | None
|
152 | 175 | };
|
@@ -185,11 +208,6 @@ impl Project<'_> {
|
185 | 208 |
|
186 | 209 | for entry in fixture {
|
187 | 210 | if let Some(pth) = entry.path.strip_prefix("/$$CONFIG_DIR$$") {
|
188 |
| - if config_dir_guard.is_none() { |
189 |
| - config_dir_guard = Some(CONFIG_DIR_LOCK.lock()); |
190 |
| - env::set_var("__TEST_RA_USER_CONFIG_DIR", TestDir::new().path()); |
191 |
| - } |
192 |
| - |
193 | 211 | let path = Config::user_config_dir_path().unwrap().join(&pth['/'.len_utf8()..]);
|
194 | 212 | fs::create_dir_all(path.parent().unwrap()).unwrap();
|
195 | 213 | fs::write(path.as_path(), entry.text.as_bytes()).unwrap();
|
@@ -293,12 +311,14 @@ pub(crate) struct Server {
|
293 | 311 | client: Connection,
|
294 | 312 | /// XXX: remove the tempdir last
|
295 | 313 | dir: TestDir,
|
296 |
| - _config_dir_guard: Option<MutexGuard<'static, ()>>, |
| 314 | + #[allow(dyn_drop)] |
| 315 | + _config_dir_guard: Option<(MutexGuard<'static, ()>, Box<dyn Drop>)>, |
297 | 316 | }
|
298 | 317 |
|
299 | 318 | impl Server {
|
| 319 | + #[allow(dyn_drop)] |
300 | 320 | fn new(
|
301 |
| - config_dir_guard: Option<MutexGuard<'static, ()>>, |
| 321 | + config_dir_guard: Option<(MutexGuard<'static, ()>, Box<dyn Drop>)>, |
302 | 322 | dir: TestDir,
|
303 | 323 | config: Config,
|
304 | 324 | ) -> Server {
|
|
0 commit comments