Perform a git operation with both in-process and cross-process synchronization.
(&self, repo_path: &Path, operation: F)
| 23 | |
| 24 | /// Perform a git operation with both in-process and cross-process synchronization. |
| 25 | pub async fn with_repo_lock<F, Fut, T>(&self, repo_path: &Path, operation: F) -> T |
| 26 | where |
| 27 | F: FnOnce() -> Fut, |
| 28 | Fut: std::future::Future<Output = T>, |
| 29 | { |
| 30 | let canonical_path = canonicalize_path(repo_path); |
| 31 | |
| 32 | let lock = self.get_or_create_lock(&canonical_path).await; |
| 33 | let _guard = lock.lock().await; |
| 34 | |
| 35 | let lock_dir = crate::repo_utils::resolve_git_common_dir(&canonical_path) |
| 36 | .unwrap_or_else(|_| canonical_path.join(".git")); |
| 37 | let lock_path = lock_dir.join("tsk.lock"); |
| 38 | let _flock_file = acquire_flock(lock_path.clone()).await.unwrap_or_else(|e| { |
| 39 | panic!( |
| 40 | "Failed to acquire repository file lock at {}: {}", |
| 41 | lock_path.display(), |
| 42 | e |
| 43 | ) |
| 44 | }); |
| 45 | |
| 46 | operation().await |
| 47 | } |
| 48 | |
| 49 | /// Get or create an in-process lock for a canonicalized repository path. |
| 50 | async fn get_or_create_lock(&self, canonical_path: &Path) -> Arc<Mutex<()>> { |