gitai/remote/cache/
lock.rs1use std::collections::HashMap;
2use std::sync::{Arc, Mutex};
3
4type RepoUrl = String;
6
7#[derive(Default)]
8pub struct RepositoryLockManager {
9 locks: Arc<Mutex<HashMap<RepoUrl, Arc<Mutex<bool>>>>>,
11}
12
13impl RepositoryLockManager {
14 pub fn new() -> Self {
15 Self {
16 locks: Arc::new(Mutex::new(HashMap::new())),
17 }
18 }
19
20 pub fn acquire_lock(&self, repo_url: &str) -> Result<(), String> {
22 let mut locks = self
23 .locks
24 .lock()
25 .expect("Failed to acquire global lock for repository locks");
26
27 let repo_lock = locks
29 .entry(repo_url.to_string())
30 .or_insert_with(|| Arc::new(Mutex::new(false)));
31
32 let lock_clone = Arc::clone(repo_lock);
34 drop(locks); let guard = lock_clone
38 .lock()
39 .unwrap_or_else(|_| panic!("Failed to acquire repository lock for URL: {repo_url}"));
40
41 std::mem::drop(guard);
45
46 Ok(())
47 }
48
49 pub fn try_acquire_lock(&self, repo_url: &str) -> Result<bool, String> {
51 let mut locks = self
52 .locks
53 .lock()
54 .expect("Failed to acquire global lock for repository locks");
55
56 let repo_lock = locks
58 .entry(repo_url.to_string())
59 .or_insert_with(|| Arc::new(Mutex::new(false)));
60
61 let lock_clone = Arc::clone(repo_lock);
63 drop(locks); match lock_clone.try_lock() {
67 Ok(guard) => {
68 std::mem::drop(guard); Ok(true)
71 }
72 Err(_) => Ok(false), }
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn test_lock_manager_creation() {
83 let lock_manager = RepositoryLockManager::new();
84 assert_eq!(
85 lock_manager
86 .locks
87 .lock()
88 .expect("Failed to acquire lock on repository locks map")
89 .len(),
90 0
91 );
92 }
93
94 #[test]
95 fn test_acquire_lock() {
96 let lock_manager = RepositoryLockManager::new();
97 let repo_url = "https://github.com/example/repo.git";
98
99 let result = lock_manager.acquire_lock(repo_url);
100 assert!(result.is_ok());
101 }
102
103 #[test]
104 fn test_try_acquire_lock() {
105 let lock_manager = RepositoryLockManager::new();
106 let repo_url = "https://github.com/example/repo.git";
107
108 let result = lock_manager.try_acquire_lock(repo_url);
110 assert!(result.is_ok());
111 assert!(
112 result.expect("Failed to unwrap try_acquire_lock result"),
113 "Expected to acquire lock successfully on first attempt"
114 );
115 }
116}