equal
deleted
inserted
replaced
9 //! |
9 //! |
10 //! Used to counts the references to directories in a manifest or dirstate. |
10 //! Used to counts the references to directories in a manifest or dirstate. |
11 use std::collections::hash_map::{Entry, Iter}; |
11 use std::collections::hash_map::{Entry, Iter}; |
12 use std::collections::HashMap; |
12 use std::collections::HashMap; |
13 use {DirsIterable, DirstateEntry, DirstateMapError}; |
13 use {DirsIterable, DirstateEntry, DirstateMapError}; |
|
14 use utils::files; |
14 |
15 |
15 #[derive(PartialEq, Debug)] |
16 #[derive(PartialEq, Debug)] |
16 pub struct DirsMultiset { |
17 pub struct DirsMultiset { |
17 inner: HashMap<Vec<u8>, u32>, |
18 inner: HashMap<Vec<u8>, u32>, |
18 } |
19 } |
47 } |
48 } |
48 |
49 |
49 multiset |
50 multiset |
50 } |
51 } |
51 |
52 |
52 /// Returns the slice up to the next directory name from right to left, |
|
53 /// without trailing slash |
|
54 fn find_dir(path: &[u8]) -> &[u8] { |
|
55 let mut path = path; |
|
56 loop { |
|
57 if let Some(new_pos) = path.len().checked_sub(1) { |
|
58 if path[new_pos] == b'/' { |
|
59 break &path[..new_pos]; |
|
60 } |
|
61 path = &path[..new_pos]; |
|
62 } else { |
|
63 break &[]; |
|
64 } |
|
65 } |
|
66 } |
|
67 |
|
68 /// Increases the count of deepest directory contained in the path. |
53 /// Increases the count of deepest directory contained in the path. |
69 /// |
54 /// |
70 /// If the directory is not yet in the map, adds its parents. |
55 /// If the directory is not yet in the map, adds its parents. |
71 pub fn add_path(&mut self, path: &[u8]) { |
56 pub fn add_path(&mut self, path: &[u8]) { |
72 let mut pos = path.len(); |
57 for subpath in files::find_dirs(path) { |
73 |
|
74 loop { |
|
75 let subpath = Self::find_dir(&path[..pos]); |
|
76 if let Some(val) = self.inner.get_mut(subpath) { |
58 if let Some(val) = self.inner.get_mut(subpath) { |
77 *val += 1; |
59 *val += 1; |
78 break; |
60 break; |
79 } |
61 } |
80 self.inner.insert(subpath.to_owned(), 1); |
62 self.inner.insert(subpath.to_owned(), 1); |
81 |
|
82 pos = subpath.len(); |
|
83 if pos == 0 { |
|
84 break; |
|
85 } |
|
86 } |
63 } |
87 } |
64 } |
88 |
65 |
89 /// Decreases the count of deepest directory contained in the path. |
66 /// Decreases the count of deepest directory contained in the path. |
90 /// |
67 /// |
93 /// If the directory is not in the map, something horrible has happened. |
70 /// If the directory is not in the map, something horrible has happened. |
94 pub fn delete_path( |
71 pub fn delete_path( |
95 &mut self, |
72 &mut self, |
96 path: &[u8], |
73 path: &[u8], |
97 ) -> Result<(), DirstateMapError> { |
74 ) -> Result<(), DirstateMapError> { |
98 let mut pos = path.len(); |
75 for subpath in files::find_dirs(path) { |
99 |
|
100 loop { |
|
101 let subpath = Self::find_dir(&path[..pos]); |
|
102 match self.inner.entry(subpath.to_owned()) { |
76 match self.inner.entry(subpath.to_owned()) { |
103 Entry::Occupied(mut entry) => { |
77 Entry::Occupied(mut entry) => { |
104 let val = entry.get().clone(); |
78 let val = entry.get().clone(); |
105 if val > 1 { |
79 if val > 1 { |
106 entry.insert(val - 1); |
80 entry.insert(val - 1); |
112 return Err(DirstateMapError::PathNotFound( |
86 return Err(DirstateMapError::PathNotFound( |
113 path.to_owned(), |
87 path.to_owned(), |
114 )) |
88 )) |
115 } |
89 } |
116 }; |
90 }; |
117 |
|
118 pos = subpath.len(); |
|
119 if pos == 0 { |
|
120 break; |
|
121 } |
|
122 } |
91 } |
123 |
92 |
124 Ok(()) |
93 Ok(()) |
125 } |
94 } |
126 |
95 |