##// END OF EJS Templates
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
Raphaël Gomès -
r43227:7a01778b default
parent child Browse files
Show More
@@ -5,7 +5,7 b''
5 5 // This software may be used and distributed according to the terms of the
6 6 // GNU General Public License version 2 or any later version.
7 7
8 use crate::DirstateParseError;
8 use crate::{utils::hg_path::HgPathBuf, DirstateParseError};
9 9 use std::collections::hash_map;
10 10 use std::collections::HashMap;
11 11 use std::convert::TryFrom;
@@ -31,10 +31,10 b' pub struct DirstateEntry {'
31 31 pub size: i32,
32 32 }
33 33
34 pub type StateMap = HashMap<Vec<u8>, DirstateEntry>;
35 pub type StateMapIter<'a> = hash_map::Iter<'a, Vec<u8>, DirstateEntry>;
36 pub type CopyMap = HashMap<Vec<u8>, Vec<u8>>;
37 pub type CopyMapIter<'a> = hash_map::Iter<'a, Vec<u8>, Vec<u8>>;
34 pub type StateMap = HashMap<HgPathBuf, DirstateEntry>;
35 pub type StateMapIter<'a> = hash_map::Iter<'a, HgPathBuf, DirstateEntry>;
36 pub type CopyMap = HashMap<HgPathBuf, HgPathBuf>;
37 pub type CopyMapIter<'a> = hash_map::Iter<'a, HgPathBuf, HgPathBuf>;
38 38
39 39 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
40 40 pub enum EntryState {
@@ -8,6 +8,7 b''
8 8 //! A multiset of directory names.
9 9 //!
10 10 //! Used to counts the references to directories in a manifest or dirstate.
11 use crate::utils::hg_path::{HgPath, HgPathBuf};
11 12 use crate::{
12 13 dirstate::EntryState, utils::files, DirstateEntry, DirstateMapError,
13 14 };
@@ -15,11 +16,11 b' use std::collections::hash_map::{self, E'
15 16 use std::collections::HashMap;
16 17
17 18 // could be encapsulated if we care API stability more seriously
18 pub type DirsMultisetIter<'a> = hash_map::Keys<'a, Vec<u8>, u32>;
19 pub type DirsMultisetIter<'a> = hash_map::Keys<'a, HgPathBuf, u32>;
19 20
20 21 #[derive(PartialEq, Debug)]
21 22 pub struct DirsMultiset {
22 inner: HashMap<Vec<u8>, u32>,
23 inner: HashMap<HgPathBuf, u32>,
23 24 }
24 25
25 26 impl DirsMultiset {
@@ -27,7 +28,7 b' impl DirsMultiset {'
27 28 ///
28 29 /// If `skip_state` is provided, skips dirstate entries with equal state.
29 30 pub fn from_dirstate(
30 vec: &HashMap<Vec<u8>, DirstateEntry>,
31 vec: &HashMap<HgPathBuf, DirstateEntry>,
31 32 skip_state: Option<EntryState>,
32 33 ) -> Self {
33 34 let mut multiset = DirsMultiset {
@@ -49,7 +50,7 b' impl DirsMultiset {'
49 50 }
50 51
51 52 /// Initializes the multiset from a manifest.
52 pub fn from_manifest(vec: &Vec<Vec<u8>>) -> Self {
53 pub fn from_manifest(vec: &Vec<HgPathBuf>) -> Self {
53 54 let mut multiset = DirsMultiset {
54 55 inner: HashMap::new(),
55 56 };
@@ -64,7 +65,7 b' impl DirsMultiset {'
64 65 /// Increases the count of deepest directory contained in the path.
65 66 ///
66 67 /// If the directory is not yet in the map, adds its parents.
67 pub fn add_path(&mut self, path: &[u8]) {
68 pub fn add_path(&mut self, path: &HgPath) {
68 69 for subpath in files::find_dirs(path) {
69 70 if let Some(val) = self.inner.get_mut(subpath) {
70 71 *val += 1;
@@ -81,7 +82,7 b' impl DirsMultiset {'
81 82 /// If the directory is not in the map, something horrible has happened.
82 83 pub fn delete_path(
83 84 &mut self,
84 path: &[u8],
85 path: &HgPath,
85 86 ) -> Result<(), DirstateMapError> {
86 87 for subpath in files::find_dirs(path) {
87 88 match self.inner.entry(subpath.to_owned()) {
@@ -104,7 +105,7 b' impl DirsMultiset {'
104 105 Ok(())
105 106 }
106 107
107 pub fn contains(&self, key: &[u8]) -> bool {
108 pub fn contains(&self, key: &HgPath) -> bool {
108 109 self.inner.contains_key(key)
109 110 }
110 111
@@ -125,20 +126,20 b' mod tests {'
125 126 #[test]
126 127 fn test_delete_path_path_not_found() {
127 128 let mut map = DirsMultiset::from_manifest(&vec![]);
128 let path = b"doesnotexist/";
129 let path = HgPathBuf::from_bytes(b"doesnotexist/");
129 130 assert_eq!(
130 Err(DirstateMapError::PathNotFound(path.to_vec())),
131 map.delete_path(path)
131 Err(DirstateMapError::PathNotFound(path.to_owned())),
132 map.delete_path(&path)
132 133 );
133 134 }
134 135
135 136 #[test]
136 137 fn test_delete_path_empty_path() {
137 let mut map = DirsMultiset::from_manifest(&vec![vec![]]);
138 let path = b"";
138 let mut map = DirsMultiset::from_manifest(&vec![HgPathBuf::new()]);
139 let path = HgPath::new(b"");
139 140 assert_eq!(Ok(()), map.delete_path(path));
140 141 assert_eq!(
141 Err(DirstateMapError::PathNotFound(path.to_vec())),
142 Err(DirstateMapError::PathNotFound(path.to_owned())),
142 143 map.delete_path(path)
143 144 );
144 145 }
@@ -148,34 +149,40 b' mod tests {'
148 149 let mut map = DirsMultiset {
149 150 inner: [("", 5), ("a", 3), ("a/b", 2), ("a/c", 1)]
150 151 .iter()
151 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
152 .map(|(k, v)| (HgPathBuf::from_bytes(k.as_bytes()), *v))
152 153 .collect(),
153 154 };
154 155
155 assert_eq!(Ok(()), map.delete_path(b"a/b/"));
156 assert_eq!(Ok(()), map.delete_path(b"a/b/"));
156 assert_eq!(Ok(()), map.delete_path(HgPath::new(b"a/b/")));
157 eprintln!("{:?}", map);
158 assert_eq!(Ok(()), map.delete_path(HgPath::new(b"a/b/")));
159 eprintln!("{:?}", map);
157 160 assert_eq!(
158 Err(DirstateMapError::PathNotFound(b"a/b/".to_vec())),
159 map.delete_path(b"a/b/")
161 Err(DirstateMapError::PathNotFound(HgPathBuf::from_bytes(
162 b"a/b/"
163 ))),
164 map.delete_path(HgPath::new(b"a/b/"))
160 165 );
161 166
162 assert_eq!(2, *map.inner.get(&b"a".to_vec()).unwrap());
163 assert_eq!(1, *map.inner.get(&b"a/c".to_vec()).unwrap());
167 assert_eq!(2, *map.inner.get(HgPath::new(b"a")).unwrap());
168 assert_eq!(1, *map.inner.get(HgPath::new(b"a/c")).unwrap());
164 169 eprintln!("{:?}", map);
165 assert_eq!(Ok(()), map.delete_path(b"a/"));
170 assert_eq!(Ok(()), map.delete_path(HgPath::new(b"a/")));
166 171 eprintln!("{:?}", map);
167 172
168 assert_eq!(Ok(()), map.delete_path(b"a/c/"));
173 assert_eq!(Ok(()), map.delete_path(HgPath::new(b"a/c/")));
169 174 assert_eq!(
170 Err(DirstateMapError::PathNotFound(b"a/c/".to_vec())),
171 map.delete_path(b"a/c/")
175 Err(DirstateMapError::PathNotFound(HgPathBuf::from_bytes(
176 b"a/c/"
177 ))),
178 map.delete_path(HgPath::new(b"a/c/"))
172 179 );
173 180 }
174 181
175 182 #[test]
176 183 fn test_add_path_empty_path() {
177 184 let mut map = DirsMultiset::from_manifest(&vec![]);
178 let path = b"";
185 let path = HgPath::new(b"");
179 186 map.add_path(path);
180 187
181 188 assert_eq!(1, map.len());
@@ -185,42 +192,42 b' mod tests {'
185 192 fn test_add_path_successful() {
186 193 let mut map = DirsMultiset::from_manifest(&vec![]);
187 194
188 map.add_path(b"a/");
189 assert_eq!(1, *map.inner.get(&b"a".to_vec()).unwrap());
190 assert_eq!(1, *map.inner.get(&Vec::new()).unwrap());
195 map.add_path(HgPath::new(b"a/"));
196 assert_eq!(1, *map.inner.get(HgPath::new(b"a")).unwrap());
197 assert_eq!(1, *map.inner.get(HgPath::new(b"")).unwrap());
191 198 assert_eq!(2, map.len());
192 199
193 200 // Non directory should be ignored
194 map.add_path(b"a");
195 assert_eq!(1, *map.inner.get(&b"a".to_vec()).unwrap());
201 map.add_path(HgPath::new(b"a"));
202 assert_eq!(1, *map.inner.get(HgPath::new(b"a")).unwrap());
196 203 assert_eq!(2, map.len());
197 204
198 205 // Non directory will still add its base
199 map.add_path(b"a/b");
200 assert_eq!(2, *map.inner.get(&b"a".to_vec()).unwrap());
206 map.add_path(HgPath::new(b"a/b"));
207 assert_eq!(2, *map.inner.get(HgPath::new(b"a")).unwrap());
201 208 assert_eq!(2, map.len());
202 209
203 210 // Duplicate path works
204 map.add_path(b"a/");
205 assert_eq!(3, *map.inner.get(&b"a".to_vec()).unwrap());
211 map.add_path(HgPath::new(b"a/"));
212 assert_eq!(3, *map.inner.get(HgPath::new(b"a")).unwrap());
206 213
207 214 // Nested dir adds to its base
208 map.add_path(b"a/b/");
209 assert_eq!(4, *map.inner.get(&b"a".to_vec()).unwrap());
210 assert_eq!(1, *map.inner.get(&b"a/b".to_vec()).unwrap());
215 map.add_path(HgPath::new(b"a/b/"));
216 assert_eq!(4, *map.inner.get(HgPath::new(b"a")).unwrap());
217 assert_eq!(1, *map.inner.get(HgPath::new(b"a/b")).unwrap());
211 218
212 219 // but not its base's base, because it already existed
213 map.add_path(b"a/b/c/");
214 assert_eq!(4, *map.inner.get(&b"a".to_vec()).unwrap());
215 assert_eq!(2, *map.inner.get(&b"a/b".to_vec()).unwrap());
220 map.add_path(HgPath::new(b"a/b/c/"));
221 assert_eq!(4, *map.inner.get(HgPath::new(b"a")).unwrap());
222 assert_eq!(2, *map.inner.get(HgPath::new(b"a/b")).unwrap());
216 223
217 map.add_path(b"a/c/");
218 assert_eq!(1, *map.inner.get(&b"a/c".to_vec()).unwrap());
224 map.add_path(HgPath::new(b"a/c/"));
225 assert_eq!(1, *map.inner.get(HgPath::new(b"a/c")).unwrap());
219 226
220 227 let expected = DirsMultiset {
221 228 inner: [("", 2), ("a", 5), ("a/b", 2), ("a/b/c", 1), ("a/c", 1)]
222 229 .iter()
223 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
230 .map(|(k, v)| (HgPathBuf::from_bytes(k.as_bytes()), *v))
224 231 .collect(),
225 232 };
226 233 assert_eq!(map, expected);
@@ -245,11 +252,11 b' mod tests {'
245 252 fn test_dirsmultiset_new_no_skip() {
246 253 let input_vec = ["a/", "b/", "a/c", "a/d/"]
247 254 .iter()
248 .map(|e| e.as_bytes().to_vec())
255 .map(|e| HgPathBuf::from_bytes(e.as_bytes()))
249 256 .collect();
250 257 let expected_inner = [("", 2), ("a", 3), ("b", 1), ("a/d", 1)]
251 258 .iter()
252 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
259 .map(|(k, v)| (HgPathBuf::from_bytes(k.as_bytes()), *v))
253 260 .collect();
254 261
255 262 let new = DirsMultiset::from_manifest(&input_vec);
@@ -262,7 +269,7 b' mod tests {'
262 269 .iter()
263 270 .map(|f| {
264 271 (
265 f.as_bytes().to_vec(),
272 HgPathBuf::from_bytes(f.as_bytes()),
266 273 DirstateEntry {
267 274 state: EntryState::Normal,
268 275 mode: 0,
@@ -274,7 +281,7 b' mod tests {'
274 281 .collect();
275 282 let expected_inner = [("", 2), ("a", 3), ("b", 1), ("a/d", 1)]
276 283 .iter()
277 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
284 .map(|(k, v)| (HgPathBuf::from_bytes(k.as_bytes()), *v))
278 285 .collect();
279 286
280 287 let new = DirsMultiset::from_dirstate(&input_map, None);
@@ -295,7 +302,7 b' mod tests {'
295 302 .iter()
296 303 .map(|(f, state)| {
297 304 (
298 f.as_bytes().to_vec(),
305 HgPathBuf::from_bytes(f.as_bytes()),
299 306 DirstateEntry {
300 307 state: *state,
301 308 mode: 0,
@@ -309,7 +316,7 b' mod tests {'
309 316 // "a" incremented with "a/c" and "a/d/"
310 317 let expected_inner = [("", 1), ("a", 2), ("a/d", 1)]
311 318 .iter()
312 .map(|(k, v)| (k.as_bytes().to_vec(), *v))
319 .map(|(k, v)| (HgPathBuf::from_bytes(k.as_bytes()), *v))
313 320 .collect();
314 321
315 322 let new =
@@ -5,6 +5,7 b''
5 5 // This software may be used and distributed according to the terms of the
6 6 // GNU General Public License version 2 or any later version.
7 7
8 use crate::utils::hg_path::{HgPath, HgPathBuf};
8 9 use crate::{
9 10 dirstate::{parsers::PARENT_SIZE, EntryState},
10 11 pack_dirstate, parse_dirstate,
@@ -19,7 +20,7 b' use std::iter::FromIterator;'
19 20 use std::ops::Deref;
20 21 use std::time::Duration;
21 22
22 pub type FileFoldMap = HashMap<Vec<u8>, Vec<u8>>;
23 pub type FileFoldMap = HashMap<HgPathBuf, HgPathBuf>;
23 24
24 25 const NULL_ID: [u8; 20] = [0; 20];
25 26 const MTIME_UNSET: i32 = -1;
@@ -32,8 +33,8 b' pub struct DirstateMap {'
32 33 file_fold_map: Option<FileFoldMap>,
33 34 pub dirs: Option<DirsMultiset>,
34 35 pub all_dirs: Option<DirsMultiset>,
35 non_normal_set: HashSet<Vec<u8>>,
36 other_parent_set: HashSet<Vec<u8>>,
36 non_normal_set: HashSet<HgPathBuf>,
37 other_parent_set: HashSet<HgPathBuf>,
37 38 parents: Option<DirstateParents>,
38 39 dirty_parents: bool,
39 40 }
@@ -47,8 +48,8 b' impl Deref for DirstateMap {'
47 48 }
48 49 }
49 50
50 impl FromIterator<(Vec<u8>, DirstateEntry)> for DirstateMap {
51 fn from_iter<I: IntoIterator<Item = (Vec<u8>, DirstateEntry)>>(
51 impl FromIterator<(HgPathBuf, DirstateEntry)> for DirstateMap {
52 fn from_iter<I: IntoIterator<Item = (HgPathBuf, DirstateEntry)>>(
52 53 iter: I,
53 54 ) -> Self {
54 55 Self {
@@ -78,7 +79,7 b' impl DirstateMap {'
78 79 /// Add a tracked file to the dirstate
79 80 pub fn add_file(
80 81 &mut self,
81 filename: &[u8],
82 filename: &HgPath,
82 83 old_state: EntryState,
83 84 entry: DirstateEntry,
84 85 ) {
@@ -111,7 +112,7 b' impl DirstateMap {'
111 112 /// to be more explicit about what that state is.
112 113 pub fn remove_file(
113 114 &mut self,
114 filename: &[u8],
115 filename: &HgPath,
115 116 old_state: EntryState,
116 117 size: i32,
117 118 ) -> Result<(), DirstateMapError> {
@@ -147,7 +148,7 b' impl DirstateMap {'
147 148 /// Returns `true` if the file was previously recorded.
148 149 pub fn drop_file(
149 150 &mut self,
150 filename: &[u8],
151 filename: &HgPath,
151 152 old_state: EntryState,
152 153 ) -> Result<bool, DirstateMapError> {
153 154 let exists = self.state_map.remove(filename).is_some();
@@ -172,7 +173,7 b' impl DirstateMap {'
172 173
173 174 pub fn clear_ambiguous_times(
174 175 &mut self,
175 filenames: Vec<Vec<u8>>,
176 filenames: Vec<HgPathBuf>,
176 177 now: i32,
177 178 ) {
178 179 for filename in filenames {
@@ -197,7 +198,7 b' impl DirstateMap {'
197 198
198 199 pub fn non_normal_other_parent_entries(
199 200 &self,
200 ) -> (HashSet<Vec<u8>>, HashSet<Vec<u8>>) {
201 ) -> (HashSet<HgPathBuf>, HashSet<HgPathBuf>) {
201 202 let mut non_normal = HashSet::new();
202 203 let mut other_parent = HashSet::new();
203 204
@@ -239,12 +240,12 b' impl DirstateMap {'
239 240 }
240 241 }
241 242
242 pub fn has_tracked_dir(&mut self, directory: &[u8]) -> bool {
243 pub fn has_tracked_dir(&mut self, directory: &HgPath) -> bool {
243 244 self.set_dirs();
244 245 self.dirs.as_ref().unwrap().contains(directory)
245 246 }
246 247
247 pub fn has_dir(&mut self, directory: &[u8]) -> bool {
248 pub fn has_dir(&mut self, directory: &HgPath) -> bool {
248 249 self.set_all_dirs();
249 250 self.all_dirs.as_ref().unwrap().contains(directory)
250 251 }
@@ -346,11 +347,11 b' mod tests {'
346 347 assert!(map.dirs.is_none());
347 348 assert!(map.all_dirs.is_none());
348 349
349 assert_eq!(false, map.has_dir(b"nope"));
350 assert_eq!(false, map.has_dir(HgPath::new(b"nope")));
350 351 assert!(map.all_dirs.is_some());
351 352 assert!(map.dirs.is_none());
352 353
353 assert_eq!(false, map.has_tracked_dir(b"nope"));
354 assert_eq!(false, map.has_tracked_dir(HgPath::new(b"nope")));
354 355 assert!(map.dirs.is_some());
355 356 }
356 357
@@ -361,7 +362,7 b' mod tests {'
361 362 assert_eq!(0, map.len());
362 363
363 364 map.add_file(
364 b"meh",
365 HgPath::new(b"meh"),
365 366 EntryState::Normal,
366 367 DirstateEntry {
367 368 state: EntryState::Normal,
@@ -394,7 +395,7 b' mod tests {'
394 395 .iter()
395 396 .map(|(fname, (state, mode, size, mtime))| {
396 397 (
397 fname.to_vec(),
398 HgPathBuf::from_bytes(fname.as_ref()),
398 399 DirstateEntry {
399 400 state: *state,
400 401 mode: *mode,
@@ -409,11 +410,11 b' mod tests {'
409 410 b"f1", b"f2", b"f5", b"f6", b"f7", b"f8", b"f9", b"fa", b"fb",
410 411 ]
411 412 .iter()
412 .map(|x| x.to_vec())
413 .map(|x| HgPathBuf::from_bytes(x.as_ref()))
413 414 .collect();
414 415
415 416 let mut other_parent = HashSet::new();
416 other_parent.insert(b"f4".to_vec());
417 other_parent.insert(HgPathBuf::from_bytes(b"f4"));
417 418
418 419 assert_eq!(
419 420 (non_normal, other_parent),
@@ -3,6 +3,7 b''
3 3 // This software may be used and distributed according to the terms of the
4 4 // GNU General Public License version 2 or any later version.
5 5
6 use crate::utils::hg_path::HgPath;
6 7 use crate::{
7 8 dirstate::{CopyMap, EntryState, StateMap},
8 9 DirstateEntry, DirstatePackError, DirstateParents, DirstateParseError,
@@ -60,10 +61,13 b' pub fn parse_dirstate('
60 61 };
61 62
62 63 if let Some(copy_path) = copy {
63 copy_map.insert(path.to_owned(), copy_path.to_owned());
64 copy_map.insert(
65 HgPath::new(path).to_owned(),
66 HgPath::new(copy_path).to_owned(),
67 );
64 68 };
65 69 state_map.insert(
66 path.to_owned(),
70 HgPath::new(path).to_owned(),
67 71 DirstateEntry {
68 72 state,
69 73 mode,
@@ -106,7 +110,7 b' pub fn pack_dirstate('
106 110 packed.extend(&parents.p2);
107 111
108 112 for (filename, entry) in state_map.iter() {
109 let mut new_filename: Vec<u8> = filename.to_owned();
113 let new_filename = filename.to_owned();
110 114 let mut new_mtime: i32 = entry.mtime;
111 115 if entry.state == EntryState::Normal && entry.mtime == now {
112 116 // The file was last modified "simultaneously" with the current
@@ -127,10 +131,10 b' pub fn pack_dirstate('
127 131 },
128 132 ));
129 133 }
130
134 let mut new_filename = new_filename.into_vec();
131 135 if let Some(copy) = copy_map.get(filename) {
132 136 new_filename.push('\0' as u8);
133 new_filename.extend(copy);
137 new_filename.extend(copy.bytes());
134 138 }
135 139
136 140 packed.write_u8(entry.state.into())?;
@@ -153,6 +157,7 b' pub fn pack_dirstate('
153 157 #[cfg(test)]
154 158 mod tests {
155 159 use super::*;
160 use crate::utils::hg_path::HgPathBuf;
156 161 use std::collections::HashMap;
157 162
158 163 #[test]
@@ -176,7 +181,7 b' mod tests {'
176 181 #[test]
177 182 fn test_pack_dirstate_one_entry() {
178 183 let expected_state_map: StateMap = [(
179 b"f1".to_vec(),
184 HgPathBuf::from_bytes(b"f1"),
180 185 DirstateEntry {
181 186 state: EntryState::Normal,
182 187 mode: 0o644,
@@ -213,7 +218,7 b' mod tests {'
213 218 #[test]
214 219 fn test_pack_dirstate_one_entry_with_copy() {
215 220 let expected_state_map: StateMap = [(
216 b"f1".to_vec(),
221 HgPathBuf::from_bytes(b"f1"),
217 222 DirstateEntry {
218 223 state: EntryState::Normal,
219 224 mode: 0o644,
@@ -226,7 +231,10 b' mod tests {'
226 231 .collect();
227 232 let mut state_map = expected_state_map.clone();
228 233 let mut copymap = HashMap::new();
229 copymap.insert(b"f1".to_vec(), b"copyname".to_vec());
234 copymap.insert(
235 HgPathBuf::from_bytes(b"f1"),
236 HgPathBuf::from_bytes(b"copyname"),
237 );
230 238 let parents = DirstateParents {
231 239 p1: *b"12345678910111213141",
232 240 p2: *b"00000000000000000000",
@@ -251,7 +259,7 b' mod tests {'
251 259 #[test]
252 260 fn test_parse_pack_one_entry_with_copy() {
253 261 let mut state_map: StateMap = [(
254 b"f1".to_vec(),
262 HgPathBuf::from_bytes(b"f1"),
255 263 DirstateEntry {
256 264 state: EntryState::Normal,
257 265 mode: 0o644,
@@ -263,7 +271,10 b' mod tests {'
263 271 .cloned()
264 272 .collect();
265 273 let mut copymap = HashMap::new();
266 copymap.insert(b"f1".to_vec(), b"copyname".to_vec());
274 copymap.insert(
275 HgPathBuf::from_bytes(b"f1"),
276 HgPathBuf::from_bytes(b"copyname"),
277 );
267 278 let parents = DirstateParents {
268 279 p1: *b"12345678910111213141",
269 280 p2: *b"00000000000000000000",
@@ -291,7 +302,7 b' mod tests {'
291 302 fn test_parse_pack_multiple_entries_with_copy() {
292 303 let mut state_map: StateMap = [
293 304 (
294 b"f1".to_vec(),
305 HgPathBuf::from_bytes(b"f1"),
295 306 DirstateEntry {
296 307 state: EntryState::Normal,
297 308 mode: 0o644,
@@ -300,7 +311,7 b' mod tests {'
300 311 },
301 312 ),
302 313 (
303 b"f2".to_vec(),
314 HgPathBuf::from_bytes(b"f2"),
304 315 DirstateEntry {
305 316 state: EntryState::Merged,
306 317 mode: 0o777,
@@ -309,7 +320,7 b' mod tests {'
309 320 },
310 321 ),
311 322 (
312 b"f3".to_vec(),
323 HgPathBuf::from_bytes(b"f3"),
313 324 DirstateEntry {
314 325 state: EntryState::Removed,
315 326 mode: 0o644,
@@ -318,7 +329,7 b' mod tests {'
318 329 },
319 330 ),
320 331 (
321 b"f4\xF6".to_vec(),
332 HgPathBuf::from_bytes(b"f4\xF6"),
322 333 DirstateEntry {
323 334 state: EntryState::Added,
324 335 mode: 0o644,
@@ -331,8 +342,14 b' mod tests {'
331 342 .cloned()
332 343 .collect();
333 344 let mut copymap = HashMap::new();
334 copymap.insert(b"f1".to_vec(), b"copyname".to_vec());
335 copymap.insert(b"f4\xF6".to_vec(), b"copyname2".to_vec());
345 copymap.insert(
346 HgPathBuf::from_bytes(b"f1"),
347 HgPathBuf::from_bytes(b"copyname"),
348 );
349 copymap.insert(
350 HgPathBuf::from_bytes(b"f4\xF6"),
351 HgPathBuf::from_bytes(b"copyname2"),
352 );
336 353 let parents = DirstateParents {
337 354 p1: *b"12345678910111213141",
338 355 p2: *b"00000000000000000000",
@@ -360,7 +377,7 b' mod tests {'
360 377 /// https://www.mercurial-scm.org/repo/hg/rev/af3f26b6bba4
361 378 fn test_parse_pack_one_entry_with_copy_and_time_conflict() {
362 379 let mut state_map: StateMap = [(
363 b"f1".to_vec(),
380 HgPathBuf::from_bytes(b"f1"),
364 381 DirstateEntry {
365 382 state: EntryState::Normal,
366 383 mode: 0o644,
@@ -372,7 +389,10 b' mod tests {'
372 389 .cloned()
373 390 .collect();
374 391 let mut copymap = HashMap::new();
375 copymap.insert(b"f1".to_vec(), b"copyname".to_vec());
392 copymap.insert(
393 HgPathBuf::from_bytes(b"f1"),
394 HgPathBuf::from_bytes(b"copyname"),
395 );
376 396 let parents = DirstateParents {
377 397 p1: *b"12345678910111213141",
378 398 p2: *b"00000000000000000000",
@@ -395,7 +415,7 b' mod tests {'
395 415 (
396 416 parents,
397 417 [(
398 b"f1".to_vec(),
418 HgPathBuf::from_bytes(b"f1"),
399 419 DirstateEntry {
400 420 state: EntryState::Normal,
401 421 mode: 0o644,
@@ -7,15 +7,13 b''
7 7
8 8 //! Handling of Mercurial-specific patterns.
9 9
10 use crate::{
11 utils::{files::get_path_from_bytes, SliceExt},
12 LineNumber, PatternError, PatternFileError,
13 };
10 use crate::{utils::SliceExt, LineNumber, PatternError, PatternFileError};
14 11 use lazy_static::lazy_static;
15 12 use regex::bytes::{NoExpand, Regex};
16 13 use std::collections::HashMap;
17 14 use std::fs::File;
18 15 use std::io::Read;
16 use std::path::{Path, PathBuf};
19 17 use std::vec::Vec;
20 18
21 19 lazy_static! {
@@ -230,11 +228,11 b' lazy_static! {'
230 228 }
231 229
232 230 pub type PatternTuple = (Vec<u8>, LineNumber, Vec<u8>);
233 type WarningTuple = (Vec<u8>, Vec<u8>);
231 type WarningTuple = (PathBuf, Vec<u8>);
234 232
235 pub fn parse_pattern_file_contents(
233 pub fn parse_pattern_file_contents<P: AsRef<Path>>(
236 234 lines: &[u8],
237 file_path: &[u8],
235 file_path: P,
238 236 warn: bool,
239 237 ) -> (Vec<PatternTuple>, Vec<WarningTuple>) {
240 238 let comment_regex = Regex::new(r"((?:^|[^\\])(?:\\\\)*)#.*").unwrap();
@@ -268,7 +266,8 b' pub fn parse_pattern_file_contents('
268 266 if let Some(rel_syntax) = SYNTAXES.get(syntax) {
269 267 current_syntax = rel_syntax;
270 268 } else if warn {
271 warnings.push((file_path.to_owned(), syntax.to_owned()));
269 warnings
270 .push((file_path.as_ref().to_owned(), syntax.to_owned()));
272 271 }
273 272 continue;
274 273 }
@@ -297,11 +296,11 b' pub fn parse_pattern_file_contents('
297 296 (inputs, warnings)
298 297 }
299 298
300 pub fn read_pattern_file(
301 file_path: &[u8],
299 pub fn read_pattern_file<P: AsRef<Path>>(
300 file_path: P,
302 301 warn: bool,
303 302 ) -> Result<(Vec<PatternTuple>, Vec<WarningTuple>), PatternFileError> {
304 let mut f = File::open(get_path_from_bytes(file_path))?;
303 let mut f = File::open(file_path.as_ref())?;
305 304 let mut contents = Vec::new();
306 305
307 306 f.read_to_end(&mut contents)?;
@@ -343,18 +342,21 b' mod tests {'
343 342
344 343 assert_eq!(
345 344 vec![(b"relglob:*.elc".to_vec(), 2, b"*.elc".to_vec())],
346 parse_pattern_file_contents(lines, b"file_path", false).0,
345 parse_pattern_file_contents(lines, Path::new("file_path"), false)
346 .0,
347 347 );
348 348
349 349 let lines = b"syntax: include\nsyntax: glob";
350 350
351 351 assert_eq!(
352 parse_pattern_file_contents(lines, b"file_path", false).0,
352 parse_pattern_file_contents(lines, Path::new("file_path"), false)
353 .0,
353 354 vec![]
354 355 );
355 356 let lines = b"glob:**.o";
356 357 assert_eq!(
357 parse_pattern_file_contents(lines, b"file_path", false).0,
358 parse_pattern_file_contents(lines, Path::new("file_path"), false)
359 .0,
358 360 vec![(b"relglob:**.o".to_vec(), 1, b"**.o".to_vec())]
359 361 );
360 362 }
@@ -18,6 +18,7 b' pub use dirstate::{'
18 18 mod filepatterns;
19 19 pub mod utils;
20 20
21 use crate::utils::hg_path::HgPathBuf;
21 22 pub use filepatterns::{
22 23 build_single_regex, read_pattern_file, PatternSyntax, PatternTuple,
23 24 };
@@ -96,7 +97,7 b' impl From<std::io::Error> for DirstatePa'
96 97 }
97 98 #[derive(Debug, PartialEq)]
98 99 pub enum DirstateMapError {
99 PathNotFound(Vec<u8>),
100 PathNotFound(HgPathBuf),
100 101 EmptyPath,
101 102 }
102 103
@@ -9,7 +9,9 b''
9 9
10 10 //! Functions for fiddling with files.
11 11
12 use crate::utils::hg_path::{HgPath, HgPathBuf};
12 13 use std::iter::FusedIterator;
14
13 15 use std::path::Path;
14 16
15 17 pub fn get_path_from_bytes(bytes: &[u8]) -> &Path {
@@ -23,8 +25,7 b' pub fn get_path_from_bytes(bytes: &[u8])'
23 25 {
24 26 // TODO: convert from Windows MBCS (ANSI encoding) to WTF8.
25 27 // Perhaps, the return type would have to be Result<PathBuf>.
26 use std::os::windows::ffi::OsStrExt;
27 os_str = std::ffi::OsString::from_wide(bytes);
28 unimplemented!()
28 29 }
29 30
30 31 Path::new(os_str)
@@ -33,20 +34,19 b' pub fn get_path_from_bytes(bytes: &[u8])'
33 34 /// An iterator over repository path yielding itself and its ancestors.
34 35 #[derive(Copy, Clone, Debug)]
35 36 pub struct Ancestors<'a> {
36 next: Option<&'a [u8]>,
37 next: Option<&'a HgPath>,
37 38 }
38 39
39 40 impl<'a> Iterator for Ancestors<'a> {
40 // if we had an HgPath type, this would yield &'a HgPath
41 type Item = &'a [u8];
41 type Item = &'a HgPath;
42 42
43 43 fn next(&mut self) -> Option<Self::Item> {
44 44 let next = self.next;
45 45 self.next = match self.next {
46 46 Some(s) if s.is_empty() => None,
47 47 Some(s) => {
48 let p = s.iter().rposition(|&c| c == b'/').unwrap_or(0);
49 Some(&s[..p])
48 let p = s.bytes().rposition(|c| *c == b'/').unwrap_or(0);
49 Some(HgPath::new(&s.as_bytes()[..p]))
50 50 }
51 51 None => None,
52 52 };
@@ -63,7 +63,7 b" impl<'a> FusedIterator for Ancestors<'a>"
63 63 ///
64 64 /// The path itself isn't included unless it is b"" (meaning the root
65 65 /// directory.)
66 pub fn find_dirs<'a>(path: &'a [u8]) -> Ancestors<'a> {
66 pub fn find_dirs<'a>(path: &'a HgPath) -> Ancestors<'a> {
67 67 let mut dirs = Ancestors { next: Some(path) };
68 68 if !path.is_empty() {
69 69 dirs.next(); // skip itself
@@ -71,23 +71,24 b" pub fn find_dirs<'a>(path: &'a [u8]) -> "
71 71 dirs
72 72 }
73 73
74 /// TODO improve handling of utf8 file names. Our overall strategy for
75 /// filenames has to be revisited anyway, since Windows is UTF-16.
76 pub fn normalize_case(bytes: &[u8]) -> Vec<u8> {
74 /// TODO more than ASCII?
75 pub fn normalize_case(path: &HgPath) -> HgPathBuf {
77 76 #[cfg(windows)] // NTFS compares via upper()
78 return bytes.to_ascii_uppercase();
77 return path.to_ascii_uppercase();
79 78 #[cfg(unix)]
80 bytes.to_ascii_lowercase()
79 path.to_ascii_lowercase()
81 80 }
82 81
83 82 #[cfg(test)]
84 83 mod tests {
84 use super::*;
85
85 86 #[test]
86 87 fn find_dirs_some() {
87 let mut dirs = super::find_dirs(b"foo/bar/baz");
88 assert_eq!(dirs.next(), Some(b"foo/bar".as_ref()));
89 assert_eq!(dirs.next(), Some(b"foo".as_ref()));
90 assert_eq!(dirs.next(), Some(b"".as_ref()));
88 let mut dirs = super::find_dirs(HgPath::new(b"foo/bar/baz"));
89 assert_eq!(dirs.next(), Some(HgPath::new(b"foo/bar")));
90 assert_eq!(dirs.next(), Some(HgPath::new(b"foo")));
91 assert_eq!(dirs.next(), Some(HgPath::new(b"")));
91 92 assert_eq!(dirs.next(), None);
92 93 assert_eq!(dirs.next(), None);
93 94 }
@@ -95,8 +96,8 b' mod tests {'
95 96 #[test]
96 97 fn find_dirs_empty() {
97 98 // looks weird, but mercurial.util.finddirs(b"") yields b""
98 let mut dirs = super::find_dirs(b"");
99 assert_eq!(dirs.next(), Some(b"".as_ref()));
99 let mut dirs = super::find_dirs(HgPath::new(b""));
100 assert_eq!(dirs.next(), Some(HgPath::new(b"")));
100 101 assert_eq!(dirs.next(), None);
101 102 assert_eq!(dirs.next(), None);
102 103 }
@@ -17,7 +17,10 b' use cpython::{'
17 17 exc, PyBytes, PyDict, PyErr, PyModule, PyObject, PyResult, PySequence,
18 18 Python,
19 19 };
20 use hg::{DirstateEntry, DirstateParseError, EntryState, StateMap};
20 use hg::{
21 utils::hg_path::HgPathBuf, DirstateEntry, DirstateParseError, EntryState,
22 StateMap,
23 };
21 24 use libc::{c_char, c_int};
22 25 #[cfg(feature = "python27")]
23 26 use python27_sys::PyCapsule_Import;
@@ -75,7 +78,7 b' pub fn extract_dirstate(py: Python, dmap'
75 78 let filename = filename.extract::<PyBytes>(py)?;
76 79 let filename = filename.data(py);
77 80 Ok((
78 filename.to_owned(),
81 HgPathBuf::from(filename.to_owned()),
79 82 DirstateEntry {
80 83 state,
81 84 mode,
@@ -12,7 +12,7 b' use cpython::{PyBytes, PyClone, PyDict, '
12 12 use std::cell::RefCell;
13 13
14 14 use crate::dirstate::dirstate_map::{DirstateMap, DirstateMapLeakedRef};
15 use hg::CopyMapIter;
15 use hg::{utils::hg_path::HgPathBuf, CopyMapIter};
16 16
17 17 py_class!(pub class CopyMap |py| {
18 18 data dirstate_map: DirstateMap;
@@ -85,16 +85,19 b' impl CopyMap {'
85 85 }
86 86 fn translate_key(
87 87 py: Python,
88 res: (&Vec<u8>, &Vec<u8>),
88 res: (&HgPathBuf, &HgPathBuf),
89 89 ) -> PyResult<Option<PyBytes>> {
90 Ok(Some(PyBytes::new(py, res.0)))
90 Ok(Some(PyBytes::new(py, res.0.as_ref())))
91 91 }
92 92 fn translate_key_value(
93 93 py: Python,
94 res: (&Vec<u8>, &Vec<u8>),
94 res: (&HgPathBuf, &HgPathBuf),
95 95 ) -> PyResult<Option<(PyBytes, PyBytes)>> {
96 96 let (k, v) = res;
97 Ok(Some((PyBytes::new(py, k), PyBytes::new(py, v))))
97 Ok(Some((
98 PyBytes::new(py, k.as_ref()),
99 PyBytes::new(py, v.as_ref()),
100 )))
98 101 }
99 102 }
100 103
@@ -16,9 +16,12 b' use cpython::{'
16 16 Python,
17 17 };
18 18
19 use crate::dirstate::extract_dirstate;
20 use crate::ref_sharing::{PySharedRefCell, PySharedState};
19 use crate::{
20 dirstate::extract_dirstate,
21 ref_sharing::{PySharedRefCell, PySharedState},
22 };
21 23 use hg::{
24 utils::hg_path::{HgPath, HgPathBuf},
22 25 DirsMultiset, DirsMultisetIter, DirstateMapError, DirstateParseError,
23 26 EntryState,
24 27 };
@@ -48,9 +51,13 b' py_class!(pub class Dirs |py| {'
48 51 let dirstate = extract_dirstate(py, &map)?;
49 52 DirsMultiset::from_dirstate(&dirstate, skip_state)
50 53 } else {
51 let map: Result<Vec<Vec<u8>>, PyErr> = map
54 let map: Result<Vec<HgPathBuf>, PyErr> = map
52 55 .iter(py)?
53 .map(|o| Ok(o?.extract::<PyBytes>(py)?.data(py).to_owned()))
56 .map(|o| {
57 Ok(HgPathBuf::from_bytes(
58 o?.extract::<PyBytes>(py)?.data(py),
59 ))
60 })
54 61 .collect();
55 62 DirsMultiset::from_manifest(&map?)
56 63 };
@@ -64,14 +71,14 b' py_class!(pub class Dirs |py| {'
64 71
65 72 def addpath(&self, path: PyObject) -> PyResult<PyObject> {
66 73 self.borrow_mut(py)?.add_path(
67 path.extract::<PyBytes>(py)?.data(py),
74 HgPath::new(path.extract::<PyBytes>(py)?.data(py)),
68 75 );
69 76 Ok(py.None())
70 77 }
71 78
72 79 def delpath(&self, path: PyObject) -> PyResult<PyObject> {
73 80 self.borrow_mut(py)?.delete_path(
74 path.extract::<PyBytes>(py)?.data(py),
81 HgPath::new(path.extract::<PyBytes>(py)?.data(py)),
75 82 )
76 83 .and(Ok(py.None()))
77 84 .or_else(|e| {
@@ -98,10 +105,9 b' py_class!(pub class Dirs |py| {'
98 105 }
99 106
100 107 def __contains__(&self, item: PyObject) -> PyResult<bool> {
101 Ok(self
102 .inner(py)
103 .borrow()
104 .contains(item.extract::<PyBytes>(py)?.data(py).as_ref()))
108 Ok(self.inner(py).borrow().contains(HgPath::new(
109 item.extract::<PyBytes>(py)?.data(py).as_ref(),
110 )))
105 111 }
106 112 });
107 113
@@ -116,8 +122,11 b' impl Dirs {'
116 122 )
117 123 }
118 124
119 fn translate_key(py: Python, res: &Vec<u8>) -> PyResult<Option<PyBytes>> {
120 Ok(Some(PyBytes::new(py, res)))
125 fn translate_key(
126 py: Python,
127 res: &HgPathBuf,
128 ) -> PyResult<Option<PyBytes>> {
129 Ok(Some(PyBytes::new(py, res.as_ref())))
121 130 }
122 131 }
123 132
@@ -24,6 +24,7 b' use crate::{'
24 24 ref_sharing::{PySharedRefCell, PySharedState},
25 25 };
26 26 use hg::{
27 utils::hg_path::{HgPath, HgPathBuf},
27 28 DirsMultiset, DirstateEntry, DirstateMap as RustDirstateMap,
28 29 DirstateParents, DirstateParseError, EntryState, StateMapIter,
29 30 PARENT_SIZE,
@@ -65,7 +66,7 b' py_class!(pub class DirstateMap |py| {'
65 66 default: Option<PyObject> = None
66 67 ) -> PyResult<Option<PyObject>> {
67 68 let key = key.extract::<PyBytes>(py)?;
68 match self.inner(py).borrow().get(key.data(py)) {
69 match self.inner(py).borrow().get(HgPath::new(key.data(py))) {
69 70 Some(entry) => {
70 71 // Explicitly go through u8 first, then cast to
71 72 // platform-specific `c_char`.
@@ -91,7 +92,7 b' py_class!(pub class DirstateMap |py| {'
91 92 mtime: PyObject
92 93 ) -> PyResult<PyObject> {
93 94 self.borrow_mut(py)?.add_file(
94 f.extract::<PyBytes>(py)?.data(py),
95 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
95 96 oldstate.extract::<PyBytes>(py)?.data(py)[0]
96 97 .try_into()
97 98 .map_err(|e: DirstateParseError| {
@@ -119,7 +120,7 b' py_class!(pub class DirstateMap |py| {'
119 120 ) -> PyResult<PyObject> {
120 121 self.borrow_mut(py)?
121 122 .remove_file(
122 f.extract::<PyBytes>(py)?.data(py),
123 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
123 124 oldstate.extract::<PyBytes>(py)?.data(py)[0]
124 125 .try_into()
125 126 .map_err(|e: DirstateParseError| {
@@ -143,7 +144,7 b' py_class!(pub class DirstateMap |py| {'
143 144 ) -> PyResult<PyBool> {
144 145 self.borrow_mut(py)?
145 146 .drop_file(
146 f.extract::<PyBytes>(py)?.data(py),
147 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
147 148 oldstate.extract::<PyBytes>(py)?.data(py)[0]
148 149 .try_into()
149 150 .map_err(|e: DirstateParseError| {
@@ -164,10 +165,12 b' py_class!(pub class DirstateMap |py| {'
164 165 files: PyObject,
165 166 now: PyObject
166 167 ) -> PyResult<PyObject> {
167 let files: PyResult<Vec<Vec<u8>>> = files
168 let files: PyResult<Vec<HgPathBuf>> = files
168 169 .iter(py)?
169 170 .map(|filename| {
170 Ok(filename?.extract::<PyBytes>(py)?.data(py).to_owned())
171 Ok(HgPathBuf::from_bytes(
172 filename?.extract::<PyBytes>(py)?.data(py),
173 ))
171 174 })
172 175 .collect();
173 176 self.borrow_mut(py)?
@@ -186,7 +189,7 b' py_class!(pub class DirstateMap |py| {'
186 189 "non_normal",
187 190 non_normal
188 191 .iter()
189 .map(|v| PyBytes::new(py, &v))
192 .map(|v| PyBytes::new(py, v.as_ref()))
190 193 .collect::<Vec<PyBytes>>()
191 194 .to_py_object(py),
192 195 )?;
@@ -195,7 +198,7 b' py_class!(pub class DirstateMap |py| {'
195 198 "other_parent",
196 199 other_parent
197 200 .iter()
198 .map(|v| PyBytes::new(py, &v))
201 .map(|v| PyBytes::new(py, v.as_ref()))
199 202 .collect::<Vec<PyBytes>>()
200 203 .to_py_object(py),
201 204 )?;
@@ -206,14 +209,14 b' py_class!(pub class DirstateMap |py| {'
206 209 def hastrackeddir(&self, d: PyObject) -> PyResult<PyBool> {
207 210 let d = d.extract::<PyBytes>(py)?;
208 211 Ok(self.borrow_mut(py)?
209 .has_tracked_dir(d.data(py))
212 .has_tracked_dir(HgPath::new(d.data(py)))
210 213 .to_py_object(py))
211 214 }
212 215
213 216 def hasdir(&self, d: PyObject) -> PyResult<PyBool> {
214 217 let d = d.extract::<PyBytes>(py)?;
215 218 Ok(self.borrow_mut(py)?
216 .has_dir(d.data(py))
219 .has_dir(HgPath::new(d.data(py)))
217 220 .to_py_object(py))
218 221 }
219 222
@@ -280,10 +283,8 b' py_class!(pub class DirstateMap |py| {'
280 283
281 284 def filefoldmapasdict(&self) -> PyResult<PyDict> {
282 285 let dict = PyDict::new(py);
283 for (key, value) in
284 self.borrow_mut(py)?.build_file_fold_map().iter()
285 {
286 dict.set_item(py, key, value)?;
286 for (key, value) in self.borrow_mut(py)?.build_file_fold_map().iter() {
287 dict.set_item(py, key.as_ref().to_vec(), value.as_ref().to_vec())?;
287 288 }
288 289 Ok(dict)
289 290 }
@@ -294,12 +295,12 b' py_class!(pub class DirstateMap |py| {'
294 295
295 296 def __contains__(&self, key: PyObject) -> PyResult<bool> {
296 297 let key = key.extract::<PyBytes>(py)?;
297 Ok(self.inner(py).borrow().contains_key(key.data(py)))
298 Ok(self.inner(py).borrow().contains_key(HgPath::new(key.data(py))))
298 299 }
299 300
300 301 def __getitem__(&self, key: PyObject) -> PyResult<PyObject> {
301 302 let key = key.extract::<PyBytes>(py)?;
302 let key = key.data(py);
303 let key = HgPath::new(key.data(py));
303 304 match self.inner(py).borrow().get(key) {
304 305 Some(entry) => {
305 306 // Explicitly go through u8 first, then cast to
@@ -314,7 +315,7 b' py_class!(pub class DirstateMap |py| {'
314 315 },
315 316 None => Err(PyErr::new::<exc::KeyError, _>(
316 317 py,
317 String::from_utf8_lossy(key),
318 String::from_utf8_lossy(key.as_bytes()),
318 319 )),
319 320 }
320 321 }
@@ -373,15 +374,19 b' py_class!(pub class DirstateMap |py| {'
373 374 def copymapcopy(&self) -> PyResult<PyDict> {
374 375 let dict = PyDict::new(py);
375 376 for (key, value) in self.inner(py).borrow().copy_map.iter() {
376 dict.set_item(py, PyBytes::new(py, key), PyBytes::new(py, value))?;
377 dict.set_item(
378 py,
379 PyBytes::new(py, key.as_ref()),
380 PyBytes::new(py, value.as_ref()),
381 )?;
377 382 }
378 383 Ok(dict)
379 384 }
380 385
381 386 def copymapgetitem(&self, key: PyObject) -> PyResult<PyBytes> {
382 387 let key = key.extract::<PyBytes>(py)?;
383 match self.inner(py).borrow().copy_map.get(key.data(py)) {
384 Some(copy) => Ok(PyBytes::new(py, copy)),
388 match self.inner(py).borrow().copy_map.get(HgPath::new(key.data(py))) {
389 Some(copy) => Ok(PyBytes::new(py, copy.as_ref())),
385 390 None => Err(PyErr::new::<exc::KeyError, _>(
386 391 py,
387 392 String::from_utf8_lossy(key.data(py)),
@@ -397,7 +402,11 b' py_class!(pub class DirstateMap |py| {'
397 402 }
398 403 def copymapcontains(&self, key: PyObject) -> PyResult<bool> {
399 404 let key = key.extract::<PyBytes>(py)?;
400 Ok(self.inner(py).borrow().copy_map.contains_key(key.data(py)))
405 Ok(self
406 .inner(py)
407 .borrow()
408 .copy_map
409 .contains_key(HgPath::new(key.data(py))))
401 410 }
402 411 def copymapget(
403 412 &self,
@@ -405,8 +414,15 b' py_class!(pub class DirstateMap |py| {'
405 414 default: Option<PyObject>
406 415 ) -> PyResult<Option<PyObject>> {
407 416 let key = key.extract::<PyBytes>(py)?;
408 match self.inner(py).borrow().copy_map.get(key.data(py)) {
409 Some(copy) => Ok(Some(PyBytes::new(py, copy).into_object())),
417 match self
418 .inner(py)
419 .borrow()
420 .copy_map
421 .get(HgPath::new(key.data(py)))
422 {
423 Some(copy) => Ok(Some(
424 PyBytes::new(py, copy.as_ref()).into_object(),
425 )),
410 426 None => Ok(default),
411 427 }
412 428 }
@@ -417,9 +433,10 b' py_class!(pub class DirstateMap |py| {'
417 433 ) -> PyResult<PyObject> {
418 434 let key = key.extract::<PyBytes>(py)?;
419 435 let value = value.extract::<PyBytes>(py)?;
420 self.borrow_mut(py)?
421 .copy_map
422 .insert(key.data(py).to_vec(), value.data(py).to_vec());
436 self.borrow_mut(py)?.copy_map.insert(
437 HgPathBuf::from_bytes(key.data(py)),
438 HgPathBuf::from_bytes(value.data(py)),
439 );
423 440 Ok(py.None())
424 441 }
425 442 def copymappop(
@@ -428,7 +445,11 b' py_class!(pub class DirstateMap |py| {'
428 445 default: Option<PyObject>
429 446 ) -> PyResult<Option<PyObject>> {
430 447 let key = key.extract::<PyBytes>(py)?;
431 match self.borrow_mut(py)?.copy_map.remove(key.data(py)) {
448 match self
449 .borrow_mut(py)?
450 .copy_map
451 .remove(HgPath::new(key.data(py)))
452 {
432 453 Some(_) => Ok(None),
433 454 None => Ok(default),
434 455 }
@@ -457,13 +478,13 b' py_class!(pub class DirstateMap |py| {'
457 478 impl DirstateMap {
458 479 fn translate_key(
459 480 py: Python,
460 res: (&Vec<u8>, &DirstateEntry),
481 res: (&HgPathBuf, &DirstateEntry),
461 482 ) -> PyResult<Option<PyBytes>> {
462 Ok(Some(PyBytes::new(py, res.0)))
483 Ok(Some(PyBytes::new(py, res.0.as_ref())))
463 484 }
464 485 fn translate_key_value(
465 486 py: Python,
466 res: (&Vec<u8>, &DirstateEntry),
487 res: (&HgPathBuf, &DirstateEntry),
467 488 ) -> PyResult<Option<(PyBytes, PyObject)>> {
468 489 let (f, entry) = res;
469 490
@@ -471,7 +492,7 b' impl DirstateMap {'
471 492 // platform-specific `c_char`.
472 493 let state: u8 = entry.state.into();
473 494 Ok(Some((
474 PyBytes::new(py, f),
495 PyBytes::new(py, f.as_ref()),
475 496 decapsule_make_dirstate_tuple(py)?(
476 497 state as c_char,
477 498 entry.mode,
@@ -41,6 +41,7 b' impl GraphError {'
41 41
42 42 py_exception!(rustext, PatternError, RuntimeError);
43 43 py_exception!(rustext, PatternFileError, RuntimeError);
44 py_exception!(rustext, HgPathPyError, RuntimeError);
44 45
45 46 impl PatternError {
46 47 pub fn pynew(py: Python, inner: hg::PatternError) -> PyErr {
@@ -13,9 +13,14 b''
13 13 //!
14 14 use crate::exceptions::{PatternError, PatternFileError};
15 15 use cpython::{
16 PyBytes, PyDict, PyModule, PyObject, PyResult, PyTuple, Python, ToPyObject,
16 PyBytes, PyDict, PyModule, PyObject, PyResult, PyString, PyTuple, Python,
17 ToPyObject,
17 18 };
18 use hg::{build_single_regex, read_pattern_file, LineNumber, PatternTuple};
19 use hg::{
20 build_single_regex, read_pattern_file, utils::files::get_path_from_bytes,
21 LineNumber, PatternTuple,
22 };
23 use std::path::PathBuf;
19 24
20 25 /// Rust does not like functions with different return signatures.
21 26 /// The 3-tuple version is always returned by the hg-core function,
@@ -33,7 +38,9 b' fn read_pattern_file_wrapper('
33 38 warn: bool,
34 39 source_info: bool,
35 40 ) -> PyResult<PyTuple> {
36 match read_pattern_file(file_path.extract::<PyBytes>(py)?.data(py), warn) {
41 let bytes = file_path.extract::<PyBytes>(py)?;
42 let path = get_path_from_bytes(bytes.data(py));
43 match read_pattern_file(path, warn) {
37 44 Ok((patterns, warnings)) => {
38 45 if source_info {
39 46 let itemgetter = |x: &PatternTuple| {
@@ -58,11 +65,16 b' fn read_pattern_file_wrapper('
58 65
59 66 fn warnings_to_py_bytes(
60 67 py: Python,
61 warnings: &[(Vec<u8>, Vec<u8>)],
62 ) -> Vec<(PyBytes, PyBytes)> {
68 warnings: &[(PathBuf, Vec<u8>)],
69 ) -> Vec<(PyString, PyBytes)> {
63 70 warnings
64 71 .iter()
65 .map(|(path, syn)| (PyBytes::new(py, path), PyBytes::new(py, syn)))
72 .map(|(path, syn)| {
73 (
74 PyString::new(py, &path.to_string_lossy()),
75 PyBytes::new(py, syn),
76 )
77 })
66 78 .collect()
67 79 }
68 80
@@ -15,8 +15,8 b' use cpython::{'
15 15 PythonObject, ToPyObject,
16 16 };
17 17 use hg::{
18 pack_dirstate, parse_dirstate, DirstateEntry, DirstatePackError,
19 DirstateParents, DirstateParseError, PARENT_SIZE,
18 pack_dirstate, parse_dirstate, utils::hg_path::HgPathBuf, DirstateEntry,
19 DirstatePackError, DirstateParents, DirstateParseError, PARENT_SIZE,
20 20 };
21 21 use std::collections::HashMap;
22 22 use std::convert::TryInto;
@@ -46,7 +46,7 b' fn parse_dirstate_wrapper('
46 46
47 47 dmap.set_item(
48 48 py,
49 PyBytes::new(py, &filename),
49 PyBytes::new(py, filename.as_ref()),
50 50 decapsule_make_dirstate_tuple(py)?(
51 51 state as c_char,
52 52 entry.mode,
@@ -58,8 +58,8 b' fn parse_dirstate_wrapper('
58 58 for (path, copy_path) in copies {
59 59 copymap.set_item(
60 60 py,
61 PyBytes::new(py, &path),
62 PyBytes::new(py, &copy_path),
61 PyBytes::new(py, path.as_ref()),
62 PyBytes::new(py, copy_path.as_ref()),
63 63 )?;
64 64 }
65 65 Ok(
@@ -99,13 +99,13 b' fn pack_dirstate_wrapper('
99 99
100 100 let mut dirstate_map = extract_dirstate(py, &dmap)?;
101 101
102 let copies: Result<HashMap<Vec<u8>, Vec<u8>>, PyErr> = copymap
102 let copies: Result<HashMap<HgPathBuf, HgPathBuf>, PyErr> = copymap
103 103 .items(py)
104 104 .iter()
105 105 .map(|(key, value)| {
106 106 Ok((
107 key.extract::<PyBytes>(py)?.data(py).to_owned(),
108 value.extract::<PyBytes>(py)?.data(py).to_owned(),
107 HgPathBuf::from_bytes(key.extract::<PyBytes>(py)?.data(py)),
108 HgPathBuf::from_bytes(value.extract::<PyBytes>(py)?.data(py)),
109 109 ))
110 110 })
111 111 .collect();
@@ -144,7 +144,7 b' fn pack_dirstate_wrapper('
144 144 let state: u8 = state.into();
145 145 dmap.set_item(
146 146 py,
147 PyBytes::new(py, &filename[..]),
147 PyBytes::new(py, filename.as_ref()),
148 148 decapsule_make_dirstate_tuple(py)?(
149 149 state as c_char,
150 150 mode,
General Comments 0
You need to be logged in to leave comments. Login now