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