Show More
@@ -698,7 +698,7 b" pub fn status<'a: 'c, 'b: 'c, 'c>(" | |||
|
698 | 698 | // We walked all dirs under the roots that weren't ignored, and |
|
699 | 699 | // everything that matched was stat'ed and is already in results. |
|
700 | 700 | // The rest must thus be ignored or under a symlink. |
|
701 |
let |
|
|
701 | let path_auditor = PathAuditor::new(root_dir); | |
|
702 | 702 | |
|
703 | 703 | for (ref filename, entry) in to_visit { |
|
704 | 704 | // Report ignored items in the dmap as long as they are not |
@@ -210,7 +210,7 b' pub fn canonical_path(' | |||
|
210 | 210 | } else { |
|
211 | 211 | name.to_owned() |
|
212 | 212 | }; |
|
213 |
let |
|
|
213 | let auditor = PathAuditor::new(&root); | |
|
214 | 214 | if name != root && name.starts_with(&root) { |
|
215 | 215 | let name = name.strip_prefix(&root).unwrap(); |
|
216 | 216 | auditor.audit_path(path_to_hg_path_buf(name)?)?; |
@@ -13,13 +13,14 b' use crate::utils::{' | |||
|
13 | 13 | }; |
|
14 | 14 | use std::collections::HashSet; |
|
15 | 15 | use std::path::{Path, PathBuf}; |
|
16 | use std::sync::{Mutex, RwLock}; | |
|
16 | 17 | |
|
17 | 18 | /// Ensures that a path is valid for use in the repository i.e. does not use |
|
18 | 19 | /// any banned components, does not traverse a symlink, etc. |
|
19 | 20 | #[derive(Debug, Default)] |
|
20 | 21 | pub struct PathAuditor { |
|
21 | audited: HashSet<HgPathBuf>, | |
|
22 | audited_dirs: HashSet<HgPathBuf>, | |
|
22 | audited: Mutex<HashSet<HgPathBuf>>, | |
|
23 | audited_dirs: RwLock<HashSet<HgPathBuf>>, | |
|
23 | 24 | root: PathBuf, |
|
24 | 25 | } |
|
25 | 26 | |
@@ -31,7 +32,7 b' impl PathAuditor {' | |||
|
31 | 32 | } |
|
32 | 33 | } |
|
33 | 34 | pub fn audit_path( |
|
34 |
& |
|
|
35 | &self, | |
|
35 | 36 | path: impl AsRef<HgPath>, |
|
36 | 37 | ) -> Result<(), HgPathError> { |
|
37 | 38 | // TODO windows "localpath" normalization |
@@ -40,7 +41,7 b' impl PathAuditor {' | |||
|
40 | 41 | return Ok(()); |
|
41 | 42 | } |
|
42 | 43 | // TODO case normalization |
|
43 | if self.audited.contains(path) { | |
|
44 | if self.audited.lock().unwrap().contains(path) { | |
|
44 | 45 | return Ok(()); |
|
45 | 46 | } |
|
46 | 47 | // AIX ignores "/" at end of path, others raise EISDIR. |
@@ -113,14 +114,14 b' impl PathAuditor {' | |||
|
113 | 114 | for index in 0..parts.len() { |
|
114 | 115 | let prefix = &parts[..index + 1].join(&b'/'); |
|
115 | 116 | let prefix = HgPath::new(prefix); |
|
116 | if self.audited_dirs.contains(prefix) { | |
|
117 | if self.audited_dirs.read().unwrap().contains(prefix) { | |
|
117 | 118 | continue; |
|
118 | 119 | } |
|
119 | 120 | self.check_filesystem(&prefix, &path)?; |
|
120 | self.audited_dirs.insert(prefix.to_owned()); | |
|
121 | self.audited_dirs.write().unwrap().insert(prefix.to_owned()); | |
|
121 | 122 | } |
|
122 | 123 | |
|
123 | self.audited.insert(path.to_owned()); | |
|
124 | self.audited.lock().unwrap().insert(path.to_owned()); | |
|
124 | 125 | |
|
125 | 126 | Ok(()) |
|
126 | 127 | } |
@@ -171,7 +172,7 b' impl PathAuditor {' | |||
|
171 | 172 | Ok(()) |
|
172 | 173 | } |
|
173 | 174 | |
|
174 |
pub fn check(& |
|
|
175 | pub fn check(&self, path: impl AsRef<HgPath>) -> bool { | |
|
175 | 176 | self.audit_path(path).is_ok() |
|
176 | 177 | } |
|
177 | 178 | } |
@@ -184,7 +185,7 b' mod tests {' | |||
|
184 | 185 | |
|
185 | 186 | #[test] |
|
186 | 187 | fn test_path_auditor() { |
|
187 |
let |
|
|
188 | let auditor = PathAuditor::new(get_path_from_bytes(b"/tmp")); | |
|
188 | 189 | |
|
189 | 190 | let path = HgPath::new(b".hg/00changelog.i"); |
|
190 | 191 | assert_eq!( |
General Comments 0
You need to be logged in to leave comments.
Login now