Show More
@@ -55,19 +55,19 b' impl<G: Graph> AncestorsIterator<G> {' | |||
|
55 | 55 | let filtered_initrevs = initrevs.into_iter().filter(|&r| r >= stoprev); |
|
56 | 56 | if inclusive { |
|
57 | 57 | let visit: BinaryHeap<Revision> = filtered_initrevs.collect(); |
|
58 |
let seen = visit.iter(). |
|
|
58 | let seen = visit.iter().cloned().collect(); | |
|
59 | 59 | return Ok(AncestorsIterator { |
|
60 |
visit |
|
|
61 |
seen |
|
|
62 |
stoprev |
|
|
63 |
graph |
|
|
60 | visit, | |
|
61 | seen, | |
|
62 | stoprev, | |
|
63 | graph, | |
|
64 | 64 | }); |
|
65 | 65 | } |
|
66 | 66 | let mut this = AncestorsIterator { |
|
67 | 67 | visit: BinaryHeap::new(), |
|
68 | 68 | seen: HashSet::new(), |
|
69 |
stoprev |
|
|
70 |
graph |
|
|
69 | stoprev, | |
|
70 | graph, | |
|
71 | 71 | }; |
|
72 | 72 | this.seen.insert(NULL_REVISION); |
|
73 | 73 | for rev in filtered_initrevs { |
@@ -107,7 +107,7 b' impl<G: Graph> AncestorsIterator<G> {' | |||
|
107 | 107 | } |
|
108 | 108 | |
|
109 | 109 | pub fn peek(&self) -> Option<Revision> { |
|
110 |
self.visit.peek(). |
|
|
110 | self.visit.peek().cloned() | |
|
111 | 111 | } |
|
112 | 112 | |
|
113 | 113 | /// Tell if the iterator is about an empty set |
@@ -182,8 +182,8 b' impl<G: Graph + Clone> LazyAncestors<G> ' | |||
|
182 | 182 | inclusive, |
|
183 | 183 | )?, |
|
184 | 184 | initrevs: v, |
|
185 |
stoprev |
|
|
186 |
inclusive |
|
|
185 | stoprev, | |
|
186 | inclusive, | |
|
187 | 187 | }) |
|
188 | 188 | } |
|
189 | 189 | |
@@ -211,7 +211,7 b' impl<G: Graph + Clone> LazyAncestors<G> ' | |||
|
211 | 211 | impl<G: Graph> MissingAncestors<G> { |
|
212 | 212 | pub fn new(graph: G, bases: impl IntoIterator<Item = Revision>) -> Self { |
|
213 | 213 | let mut created = MissingAncestors { |
|
214 |
graph |
|
|
214 | graph, | |
|
215 | 215 | bases: HashSet::new(), |
|
216 | 216 | max_base: NULL_REVISION, |
|
217 | 217 | }; |
@@ -16,10 +16,10 b' use super::{Graph, GraphError, Revision,' | |||
|
16 | 16 | use crate::ancestors::AncestorsIterator; |
|
17 | 17 | use std::collections::{BTreeSet, HashSet}; |
|
18 | 18 | |
|
19 | fn remove_parents( | |
|
19 | fn remove_parents<S: std::hash::BuildHasher>( | |
|
20 | 20 | graph: &impl Graph, |
|
21 | 21 | rev: Revision, |
|
22 | set: &mut HashSet<Revision>, | |
|
22 | set: &mut HashSet<Revision, S>, | |
|
23 | 23 | ) -> Result<(), GraphError> { |
|
24 | 24 | for parent in graph.parents(rev)?.iter() { |
|
25 | 25 | if *parent != NULL_REVISION { |
@@ -65,9 +65,9 b" pub fn heads<'a>(" | |||
|
65 | 65 | /// |
|
66 | 66 | /// # Performance notes |
|
67 | 67 | /// Internally, this function will store a full copy of `revs` in a `Vec`. |
|
68 | pub fn retain_heads( | |
|
68 | pub fn retain_heads<S: std::hash::BuildHasher>( | |
|
69 | 69 | graph: &impl Graph, |
|
70 | revs: &mut HashSet<Revision>, | |
|
70 | revs: &mut HashSet<Revision, S>, | |
|
71 | 71 | ) -> Result<(), GraphError> { |
|
72 | 72 | revs.remove(&NULL_REVISION); |
|
73 | 73 | // we need to construct an iterable copy of revs to avoid itering while |
@@ -84,9 +84,9 b' pub fn retain_heads(' | |||
|
84 | 84 | /// Roots of `revs`, passed as a `HashSet` |
|
85 | 85 | /// |
|
86 | 86 | /// They are returned in arbitrary order |
|
87 | pub fn roots<G: Graph>( | |
|
87 | pub fn roots<G: Graph, S: std::hash::BuildHasher>( | |
|
88 | 88 | graph: &G, |
|
89 | revs: &HashSet<Revision>, | |
|
89 | revs: &HashSet<Revision, S>, | |
|
90 | 90 | ) -> Result<Vec<Revision>, GraphError> { |
|
91 | 91 | let mut roots: Vec<Revision> = Vec::new(); |
|
92 | 92 | for rev in revs { |
@@ -229,7 +229,8 b' mod tests {' | |||
|
229 | 229 | graph: &impl Graph, |
|
230 | 230 | revs: &[Revision], |
|
231 | 231 | ) -> Result<Vec<Revision>, GraphError> { |
|
232 |
let |
|
|
232 | let set: HashSet<_> = revs.iter().cloned().collect(); | |
|
233 | let mut as_vec = roots(graph, &set)?; | |
|
233 | 234 | as_vec.sort(); |
|
234 | 235 | Ok(as_vec) |
|
235 | 236 | } |
@@ -108,7 +108,7 b' impl DirsMultiset {' | |||
|
108 | 108 | for subpath in files::find_dirs(path.as_ref()) { |
|
109 | 109 | match self.inner.entry(subpath.to_owned()) { |
|
110 | 110 | Entry::Occupied(mut entry) => { |
|
111 |
let val = entry.get() |
|
|
111 | let val = *entry.get(); | |
|
112 | 112 | if val > 1 { |
|
113 | 113 | entry.insert(val - 1); |
|
114 | 114 | break; |
@@ -137,6 +137,10 b' impl DirsMultiset {' | |||
|
137 | 137 | pub fn len(&self) -> usize { |
|
138 | 138 | self.inner.len() |
|
139 | 139 | } |
|
140 | ||
|
141 | pub fn is_empty(&self) -> bool { | |
|
142 | self.len() == 0 | |
|
143 | } | |
|
140 | 144 | } |
|
141 | 145 | |
|
142 | 146 | /// This is basically a reimplementation of `DirsMultiset` that stores the |
@@ -156,7 +160,7 b" impl<'a> DirsChildrenMultiset<'a> {" | |||
|
156 | 160 | let mut new = Self { |
|
157 | 161 | inner: HashMap::default(), |
|
158 | 162 | only_include: only_include |
|
159 |
.map(|s| s.iter().map( |
|
|
163 | .map(|s| s.iter().map(AsRef::as_ref).collect()), | |
|
160 | 164 | }; |
|
161 | 165 | |
|
162 | 166 | for path in paths { |
@@ -223,7 +223,7 b' impl DirstateMap {' | |||
|
223 | 223 | self.get_non_normal_other_parent_entries() |
|
224 | 224 | .0 |
|
225 | 225 | .union(&other) |
|
226 |
.map( |
|
|
226 | .map(ToOwned::to_owned) | |
|
227 | 227 | .collect() |
|
228 | 228 | } |
|
229 | 229 |
@@ -135,7 +135,7 b' pub fn pack_dirstate(' | |||
|
135 | 135 | } |
|
136 | 136 | let mut new_filename = new_filename.into_vec(); |
|
137 | 137 | if let Some(copy) = copy_map.get(filename) { |
|
138 |
new_filename.push('\0' |
|
|
138 | new_filename.push(b'\0'); | |
|
139 | 139 | new_filename.extend(copy.bytes()); |
|
140 | 140 | } |
|
141 | 141 |
@@ -127,7 +127,7 b' fn list_directory(' | |||
|
127 | 127 | if skip_dot_hg && filename.as_bytes() == b".hg" && file_type.is_dir() { |
|
128 | 128 | return Ok(vec![]); |
|
129 | 129 | } else { |
|
130 |
results.push(( |
|
|
130 | results.push((filename, entry)) | |
|
131 | 131 | } |
|
132 | 132 | } |
|
133 | 133 | |
@@ -164,14 +164,15 b' fn dispatch_found(' | |||
|
164 | 164 | (mode ^ st_mode as i32) & 0o100 != 0o000 && options.check_exec; |
|
165 | 165 | let metadata_changed = size >= 0 && (size_changed || mode_changed); |
|
166 | 166 | let other_parent = size == SIZE_FROM_OTHER_PARENT; |
|
167 | ||
|
167 | 168 | if metadata_changed |
|
168 | 169 | || other_parent |
|
169 | 170 | || copy_map.contains_key(filename.as_ref()) |
|
170 | 171 | { |
|
171 | 172 | Dispatch::Modified |
|
172 |
} else if mod_compare(mtime, st_mtime as i32) |
|
|
173 | Dispatch::Unsure | |
|
174 | } else if st_mtime == options.last_normal_time { | |
|
173 | } else if mod_compare(mtime, st_mtime as i32) | |
|
174 | || st_mtime == options.last_normal_time | |
|
175 | { | |
|
175 | 176 | // the file may have just been marked as normal and |
|
176 | 177 | // it may have changed in the same second without |
|
177 | 178 | // changing its size. This can happen if we quickly |
@@ -226,9 +227,9 b" fn walk_explicit<'a>(" | |||
|
226 | 227 | files |
|
227 | 228 | .unwrap_or(&DEFAULT_WORK) |
|
228 | 229 | .par_iter() |
|
229 | .map(move |filename| { | |
|
230 | .map(move |&filename| { | |
|
230 | 231 | // TODO normalization |
|
231 |
let normalized = filename |
|
|
232 | let normalized = filename; | |
|
232 | 233 | |
|
233 | 234 | let buf = match hg_path_to_path_buf(normalized) { |
|
234 | 235 | Ok(x) => x, |
@@ -254,33 +255,31 b" fn walk_explicit<'a>(" | |||
|
254 | 255 | ))); |
|
255 | 256 | } |
|
256 | 257 | Some(Ok((normalized, Dispatch::Unknown))) |
|
258 | } else if file_type.is_dir() { | |
|
259 | if options.collect_traversed_dirs { | |
|
260 | traversed_sender | |
|
261 | .send(normalized.to_owned()) | |
|
262 | .expect("receiver should outlive sender"); | |
|
263 | } | |
|
264 | Some(Ok(( | |
|
265 | normalized, | |
|
266 | Dispatch::Directory { | |
|
267 | was_file: in_dmap.is_some(), | |
|
268 | }, | |
|
269 | ))) | |
|
257 | 270 | } else { |
|
258 |
|
|
|
259 |
|
|
|
260 | traversed_sender | |
|
261 |
|
|
|
262 | .expect("receiver should outlive sender"); | |
|
263 | } | |
|
264 | Some(Ok(( | |
|
265 |
|
|
|
266 |
|
|
|
267 |
|
|
|
268 |
|
|
|
269 |
|
|
|
270 | } else { | |
|
271 | Some(Ok(( | |
|
272 | normalized, | |
|
273 | Dispatch::Bad(BadMatch::BadType( | |
|
274 | // TODO do more than unknown | |
|
275 | // Support for all `BadType` variant | |
|
276 | // varies greatly between platforms. | |
|
277 | // So far, no tests check the type and | |
|
278 | // this should be good enough for most | |
|
279 | // users. | |
|
280 | BadType::Unknown, | |
|
281 | )), | |
|
282 | ))) | |
|
283 | } | |
|
271 | Some(Ok(( | |
|
272 | normalized, | |
|
273 | Dispatch::Bad(BadMatch::BadType( | |
|
274 | // TODO do more than unknown | |
|
275 | // Support for all `BadType` variant | |
|
276 | // varies greatly between platforms. | |
|
277 | // So far, no tests check the type and | |
|
278 | // this should be good enough for most | |
|
279 | // users. | |
|
280 | BadType::Unknown, | |
|
281 | )), | |
|
282 | ))) | |
|
284 | 283 | }; |
|
285 | 284 | } |
|
286 | 285 | Err(_) => { |
@@ -381,12 +380,10 b" fn handle_traversed_entry<'a>(" | |||
|
381 | 380 | .send(Ok((filename.to_owned(), Dispatch::Ignored))) |
|
382 | 381 | .unwrap(); |
|
383 | 382 | } |
|
384 | } else { | |
|
385 | if options.list_unknown { | |
|
386 | files_sender | |
|
387 | .send(Ok((filename.to_owned(), Dispatch::Unknown))) | |
|
388 | .unwrap(); | |
|
389 | } | |
|
383 | } else if options.list_unknown { | |
|
384 | files_sender | |
|
385 | .send(Ok((filename.to_owned(), Dispatch::Unknown))) | |
|
386 | .unwrap(); | |
|
390 | 387 | } |
|
391 | 388 | } else if ignore_fn(&filename) && options.list_ignored { |
|
392 | 389 | files_sender |
@@ -181,8 +181,8 b' impl<G: Graph + Clone> PartialDiscovery<' | |||
|
181 | 181 | common: MissingAncestors::new(graph, vec![]), |
|
182 | 182 | missing: HashSet::new(), |
|
183 | 183 | rng: Rng::from_seed(seed), |
|
184 |
respect_size |
|
|
185 |
randomize |
|
|
184 | respect_size, | |
|
185 | randomize, | |
|
186 | 186 | } |
|
187 | 187 | } |
|
188 | 188 | |
@@ -284,7 +284,7 b' impl<G: Graph + Clone> PartialDiscovery<' | |||
|
284 | 284 | |
|
285 | 285 | /// Did we acquire full knowledge of our Revisions that the peer has? |
|
286 | 286 | pub fn is_complete(&self) -> bool { |
|
287 |
self.undecided.as_ref().map_or(false, |
|
|
287 | self.undecided.as_ref().map_or(false, HashSet::is_empty) | |
|
288 | 288 | } |
|
289 | 289 | |
|
290 | 290 | /// Return the heads of the currently known common set of revisions. |
@@ -332,7 +332,7 b' impl<G: Graph + Clone> PartialDiscovery<' | |||
|
332 | 332 | FastHashMap::default(); |
|
333 | 333 | for &rev in self.undecided.as_ref().unwrap() { |
|
334 | 334 | for p in ParentsIterator::graph_parents(&self.graph, rev)? { |
|
335 |
children.entry(p).or_insert_with( |
|
|
335 | children.entry(p).or_insert_with(Vec::new).push(rev); | |
|
336 | 336 | } |
|
337 | 337 | } |
|
338 | 338 | self.children_cache = Some(children); |
@@ -342,7 +342,7 b' impl<G: Graph + Clone> PartialDiscovery<' | |||
|
342 | 342 | /// Provide statistics about the current state of the discovery process |
|
343 | 343 | pub fn stats(&self) -> DiscoveryStats { |
|
344 | 344 | DiscoveryStats { |
|
345 |
undecided: self.undecided.as_ref().map( |
|
|
345 | undecided: self.undecided.as_ref().map(HashSet::len), | |
|
346 | 346 | } |
|
347 | 347 | } |
|
348 | 348 |
@@ -324,6 +324,8 b' pub fn parse_pattern_file_contents<P: As' | |||
|
324 | 324 | warn: bool, |
|
325 | 325 | ) -> Result<(Vec<IgnorePattern>, Vec<PatternFileWarning>), PatternError> { |
|
326 | 326 | let comment_regex = Regex::new(r"((?:^|[^\\])(?:\\\\)*)#.*").unwrap(); |
|
327 | ||
|
328 | #[allow(clippy::trivial_regex)] | |
|
327 | 329 | let comment_escape_regex = Regex::new(r"\\#").unwrap(); |
|
328 | 330 | let mut inputs: Vec<IgnorePattern> = vec![]; |
|
329 | 331 | let mut warnings: Vec<PatternFileWarning> = vec![]; |
@@ -458,9 +460,7 b' pub fn get_patterns_from_file(' | |||
|
458 | 460 | .into_iter() |
|
459 | 461 | .flat_map(|entry| -> PatternResult<_> { |
|
460 | 462 | let IgnorePattern { |
|
461 | syntax, | |
|
462 | pattern, | |
|
463 | source: _, | |
|
463 | syntax, pattern, .. | |
|
464 | 464 | } = &entry; |
|
465 | 465 | Ok(match syntax { |
|
466 | 466 | PatternSyntax::Include => { |
@@ -504,10 +504,11 b' impl SubInclude {' | |||
|
504 | 504 | normalize_path_bytes(&get_bytes_from_path(source)); |
|
505 | 505 | |
|
506 | 506 | let source_root = get_path_from_bytes(&normalized_source); |
|
507 | let source_root = source_root.parent().unwrap_or(source_root.deref()); | |
|
507 | let source_root = | |
|
508 | source_root.parent().unwrap_or_else(|| source_root.deref()); | |
|
508 | 509 | |
|
509 | 510 | let path = source_root.join(get_path_from_bytes(pattern)); |
|
510 | let new_root = path.parent().unwrap_or(path.deref()); | |
|
511 | let new_root = path.parent().unwrap_or_else(|| path.deref()); | |
|
511 | 512 | |
|
512 | 513 | let prefix = canonical_path(&root_dir, &root_dir, new_root)?; |
|
513 | 514 |
@@ -164,7 +164,7 b" impl<'a> FileMatcher<'a> {" | |||
|
164 | 164 | files: &'a [impl AsRef<HgPath>], |
|
165 | 165 | ) -> Result<Self, DirstateMapError> { |
|
166 | 166 | Ok(Self { |
|
167 |
files: HashSet::from_iter(files.iter().map( |
|
|
167 | files: HashSet::from_iter(files.iter().map(AsRef::as_ref)), | |
|
168 | 168 | dirs: DirsMultiset::from_manifest(files)?, |
|
169 | 169 | }) |
|
170 | 170 | } |
@@ -190,10 +190,10 b" impl<'a> Matcher for FileMatcher<'a> {" | |||
|
190 | 190 | if self.files.is_empty() || !self.dirs.contains(&directory) { |
|
191 | 191 | return VisitChildrenSet::Empty; |
|
192 | 192 | } |
|
193 |
let dirs_as_set = self.dirs.iter().map( |
|
|
193 | let dirs_as_set = self.dirs.iter().map(Deref::deref).collect(); | |
|
194 | 194 | |
|
195 | 195 | let mut candidates: HashSet<&HgPath> = |
|
196 |
self.files.union(&dirs_as_set). |
|
|
196 | self.files.union(&dirs_as_set).cloned().collect(); | |
|
197 | 197 | candidates.remove(HgPath::new(b"")); |
|
198 | 198 | |
|
199 | 199 | if !directory.as_ref().is_empty() { |
@@ -470,7 +470,7 b' fn roots_dirs_and_parents(' | |||
|
470 | 470 | _ => unreachable!(), |
|
471 | 471 | })? |
|
472 | 472 | .iter() |
|
473 |
.map( |
|
|
473 | .map(ToOwned::to_owned), | |
|
474 | 474 | ); |
|
475 | 475 | parents.extend( |
|
476 | 476 | DirsMultiset::from_manifest(&roots) |
@@ -479,7 +479,7 b' fn roots_dirs_and_parents(' | |||
|
479 | 479 | _ => unreachable!(), |
|
480 | 480 | })? |
|
481 | 481 | .iter() |
|
482 |
.map( |
|
|
482 | .map(ToOwned::to_owned), | |
|
483 | 483 | ); |
|
484 | 484 | |
|
485 | 485 | Ok(RootsDirsAndParents { |
@@ -523,7 +523,7 b" fn build_match<'a, 'b>(" | |||
|
523 | 523 | let match_subinclude = move |filename: &HgPath| { |
|
524 | 524 | for prefix in prefixes.iter() { |
|
525 | 525 | if let Some(rel) = filename.relative_to(prefix) { |
|
526 |
if (submatchers |
|
|
526 | if (submatchers[prefix])(rel) { | |
|
527 | 527 | return true; |
|
528 | 528 | } |
|
529 | 529 | } |
@@ -25,6 +25,7 b' pub const NULL_REVISION: Revision = -1;' | |||
|
25 | 25 | /// |
|
26 | 26 | /// This is also equal to `i32::max_value()`, but it's better to spell |
|
27 | 27 | /// it out explicitely, same as in `mercurial.node` |
|
28 | #[allow(clippy::unreadable_literal)] | |
|
28 | 29 | pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff; |
|
29 | 30 | |
|
30 | 31 | /// The simplest expression of what we need of Mercurial DAGs. |
@@ -49,6 +50,10 b' pub trait RevlogIndex {' | |||
|
49 | 50 | /// Total number of Revisions referenced in this index |
|
50 | 51 | fn len(&self) -> usize; |
|
51 | 52 | |
|
53 | fn is_empty(&self) -> bool { | |
|
54 | self.len() == 0 | |
|
55 | } | |
|
56 | ||
|
52 | 57 | /// Return a reference to the Node or `None` if rev is out of bounds |
|
53 | 58 | /// |
|
54 | 59 | /// `NULL_REVISION` is not considered to be out of bounds. |
@@ -208,6 +208,10 b" impl<'a> NodePrefixRef<'a> {" | |||
|
208 | 208 | } |
|
209 | 209 | } |
|
210 | 210 | |
|
211 | pub fn is_empty(&self) -> bool { | |
|
212 | self.len() == 0 | |
|
213 | } | |
|
214 | ||
|
211 | 215 | pub fn is_prefix_of(&self, node: &Node) -> bool { |
|
212 | 216 | if self.is_odd { |
|
213 | 217 | let buf = self.buf; |
@@ -242,13 +246,13 b" impl<'a> NodePrefixRef<'a> {" | |||
|
242 | 246 | } else { |
|
243 | 247 | buf.len() |
|
244 | 248 | }; |
|
245 | for i in 0..until { | |
|
246 |
if |
|
|
247 |
if |
|
|
248 |
|
|
|
249 | for (i, item) in buf.iter().enumerate().take(until) { | |
|
250 | if *item != node.data[i] { | |
|
251 | return if *item & 0xf0 == node.data[i] & 0xf0 { | |
|
252 | Some(2 * i + 1) | |
|
249 | 253 | } else { |
|
250 |
|
|
|
251 | } | |
|
254 | Some(2 * i) | |
|
255 | }; | |
|
252 | 256 | } |
|
253 | 257 | } |
|
254 | 258 | if self.is_odd && buf[until] & 0xf0 != node.data[until] & 0xf0 { |
@@ -218,7 +218,7 b' pub struct Block([u8; BLOCK_SIZE]);' | |||
|
218 | 218 | /// Not derivable for arrays of length >32 until const generics are stable |
|
219 | 219 | impl PartialEq for Block { |
|
220 | 220 | fn eq(&self, other: &Self) -> bool { |
|
221 |
|
|
|
221 | self.0[..] == other.0[..] | |
|
222 | 222 | } |
|
223 | 223 | } |
|
224 | 224 | |
@@ -343,14 +343,11 b' impl NodeTree {' | |||
|
343 | 343 | /// |
|
344 | 344 | /// We keep `readonly` and clone its root block if it isn't empty. |
|
345 | 345 | fn new(readonly: Box<dyn Deref<Target = [Block]> + Send>) -> Self { |
|
346 | let root = readonly | |
|
347 | .last() | |
|
348 | .map(|b| b.clone()) | |
|
349 | .unwrap_or_else(|| Block::new()); | |
|
346 | let root = readonly.last().cloned().unwrap_or_else(Block::new); | |
|
350 | 347 | NodeTree { |
|
351 |
readonly |
|
|
348 | readonly, | |
|
352 | 349 | growable: Vec::new(), |
|
353 |
root |
|
|
350 | root, | |
|
354 | 351 | masked_inner_blocks: 0, |
|
355 | 352 | } |
|
356 | 353 | } |
@@ -461,7 +458,7 b' impl NodeTree {' | |||
|
461 | 458 | ) -> NodeTreeVisitor<'n, 'p> { |
|
462 | 459 | NodeTreeVisitor { |
|
463 | 460 | nt: self, |
|
464 |
prefix |
|
|
461 | prefix, | |
|
465 | 462 | visit: self.len() - 1, |
|
466 | 463 | nybble_idx: 0, |
|
467 | 464 | done: false, |
@@ -486,8 +483,7 b' impl NodeTree {' | |||
|
486 | 483 | let glen = self.growable.len(); |
|
487 | 484 | if idx < ro_len { |
|
488 | 485 | self.masked_inner_blocks += 1; |
|
489 | // TODO OPTIM I think this makes two copies | |
|
490 | self.growable.push(ro_blocks[idx].clone()); | |
|
486 | self.growable.push(ro_blocks[idx]); | |
|
491 | 487 | (glen + ro_len, &mut self.growable[glen], glen + 1) |
|
492 | 488 | } else if glen + ro_len == idx { |
|
493 | 489 | (idx, &mut self.root, glen) |
@@ -674,8 +670,8 b" impl<'n, 'p> Iterator for NodeTreeVisito" | |||
|
674 | 670 | |
|
675 | 671 | Some(NodeTreeVisitItem { |
|
676 | 672 | block_idx: visit, |
|
677 |
nybble |
|
|
678 |
element |
|
|
673 | nybble, | |
|
674 | element, | |
|
679 | 675 | }) |
|
680 | 676 | } |
|
681 | 677 | } |
@@ -68,6 +68,7 b' pub trait SliceExt {' | |||
|
68 | 68 | fn drop_prefix(&self, needle: &Self) -> Option<&Self>; |
|
69 | 69 | } |
|
70 | 70 | |
|
71 | #[allow(clippy::trivially_copy_pass_by_ref)] | |
|
71 | 72 | fn is_not_whitespace(c: &u8) -> bool { |
|
72 | 73 | !(*c as char).is_whitespace() |
|
73 | 74 | } |
@@ -75,7 +76,7 b' fn is_not_whitespace(c: &u8) -> bool {' | |||
|
75 | 76 | impl SliceExt for [u8] { |
|
76 | 77 | fn trim_end(&self) -> &[u8] { |
|
77 | 78 | if let Some(last) = self.iter().rposition(is_not_whitespace) { |
|
78 |
&self[..last |
|
|
79 | &self[..=last] | |
|
79 | 80 | } else { |
|
80 | 81 | &[] |
|
81 | 82 | } |
@@ -151,7 +152,7 b' impl Escaped for u8 {' | |||
|
151 | 152 | |
|
152 | 153 | impl<'a, T: Escaped> Escaped for &'a [T] { |
|
153 | 154 | fn escaped_bytes(&self) -> Vec<u8> { |
|
154 |
self.iter().flat_map( |
|
|
155 | self.iter().flat_map(Escaped::escaped_bytes).collect() | |
|
155 | 156 | } |
|
156 | 157 | } |
|
157 | 158 |
@@ -98,7 +98,7 b" impl<'a> FusedIterator for AncestorsWith" | |||
|
98 | 98 | /// |
|
99 | 99 | /// The path itself isn't included unless it is b"" (meaning the root |
|
100 | 100 | /// directory.) |
|
101 |
pub fn find_dirs |
|
|
101 | pub fn find_dirs(path: &HgPath) -> Ancestors { | |
|
102 | 102 | let mut dirs = Ancestors { next: Some(path) }; |
|
103 | 103 | if !path.is_empty() { |
|
104 | 104 | dirs.next(); // skip itself |
@@ -113,9 +113,7 b" pub fn find_dirs<'a>(path: &'a HgPath) -" | |||
|
113 | 113 | /// |
|
114 | 114 | /// The path itself isn't included unless it is b"" (meaning the root |
|
115 | 115 | /// directory.) |
|
116 |
pub(crate) fn find_dirs_with_base |
|
|
117 | path: &'a HgPath, | |
|
118 | ) -> AncestorsWithBase<'a> { | |
|
116 | pub(crate) fn find_dirs_with_base(path: &HgPath) -> AncestorsWithBase { | |
|
119 | 117 | let mut dirs = AncestorsWithBase { |
|
120 | 118 | next: Some((path, HgPath::new(b""))), |
|
121 | 119 | }; |
@@ -214,9 +212,9 b' pub fn canonical_path(' | |||
|
214 | 212 | if name != root && name.starts_with(&root) { |
|
215 | 213 | let name = name.strip_prefix(&root).unwrap(); |
|
216 | 214 | auditor.audit_path(path_to_hg_path_buf(name)?)?; |
|
217 |
|
|
|
215 | Ok(name.to_owned()) | |
|
218 | 216 | } else if name == root { |
|
219 |
|
|
|
217 | Ok("".into()) | |
|
220 | 218 | } else { |
|
221 | 219 | // Determine whether `name' is in the hierarchy at or beneath `root', |
|
222 | 220 | // by iterating name=name.parent() until it returns `None` (can't |
@@ -208,7 +208,7 b' impl HgPath {' | |||
|
208 | 208 | } |
|
209 | 209 | pub fn join<T: ?Sized + AsRef<Self>>(&self, other: &T) -> HgPathBuf { |
|
210 | 210 | let mut inner = self.inner.to_owned(); |
|
211 |
if inner. |
|
|
211 | if !inner.is_empty() && inner.last() != Some(&b'/') { | |
|
212 | 212 | inner.push(b'/'); |
|
213 | 213 | } |
|
214 | 214 | inner.extend(other.as_ref().bytes()); |
@@ -315,7 +315,7 b' impl HgPath {' | |||
|
315 | 315 | /// This generates fine-grained errors useful for debugging. |
|
316 | 316 | /// To simply check if the path is valid during tests, use `is_valid`. |
|
317 | 317 | pub fn check_state(&self) -> Result<(), HgPathError> { |
|
318 |
if self. |
|
|
318 | if self.is_empty() { | |
|
319 | 319 | return Ok(()); |
|
320 | 320 | } |
|
321 | 321 | let bytes = self.as_bytes(); |
@@ -366,14 +366,14 b' impl fmt::Display for HgPath {' | |||
|
366 | 366 | } |
|
367 | 367 | } |
|
368 | 368 | |
|
369 | #[derive(Eq, Ord, Clone, PartialEq, PartialOrd, Hash)] | |
|
369 | #[derive(Default, Eq, Ord, Clone, PartialEq, PartialOrd, Hash)] | |
|
370 | 370 | pub struct HgPathBuf { |
|
371 | 371 | inner: Vec<u8>, |
|
372 | 372 | } |
|
373 | 373 | |
|
374 | 374 | impl HgPathBuf { |
|
375 | 375 | pub fn new() -> Self { |
|
376 | Self { inner: Vec::new() } | |
|
376 | Default::default() | |
|
377 | 377 | } |
|
378 | 378 | pub fn push(&mut self, byte: u8) { |
|
379 | 379 | self.inner.push(byte); |
@@ -384,9 +384,6 b' impl HgPathBuf {' | |||
|
384 | 384 | pub fn into_vec(self) -> Vec<u8> { |
|
385 | 385 | self.inner |
|
386 | 386 | } |
|
387 | pub fn as_ref(&self) -> &[u8] { | |
|
388 | self.inner.as_ref() | |
|
389 | } | |
|
390 | 387 | } |
|
391 | 388 | |
|
392 | 389 | impl fmt::Debug for HgPathBuf { |
@@ -112,7 +112,7 b' impl PathAuditor {' | |||
|
112 | 112 | // accidentally traverse a symlink into some other filesystem (which |
|
113 | 113 | // is potentially expensive to access). |
|
114 | 114 | for index in 0..parts.len() { |
|
115 |
let prefix = &parts[..index |
|
|
115 | let prefix = &parts[..=index].join(&b'/'); | |
|
116 | 116 | let prefix = HgPath::new(prefix); |
|
117 | 117 | if self.audited_dirs.read().unwrap().contains(prefix) { |
|
118 | 118 | continue; |
@@ -90,10 +90,7 b' impl Index {' | |||
|
90 | 90 | ), |
|
91 | 91 | )); |
|
92 | 92 | } |
|
93 | Ok(Index { | |
|
94 | index: index, | |
|
95 | capi: capi, | |
|
96 | }) | |
|
93 | Ok(Index { index, capi }) | |
|
97 | 94 | } |
|
98 | 95 | |
|
99 | 96 | /// return a reference to the CPython Index object in this Struct |
@@ -158,7 +155,7 b' impl RevlogIndex for Index {' | |||
|
158 | 155 | unsafe { (self.capi.index_length)(self.index.as_ptr()) as usize } |
|
159 | 156 | } |
|
160 | 157 | |
|
161 |
fn node |
|
|
158 | fn node(&self, rev: Revision) -> Option<&Node> { | |
|
162 | 159 | let raw = unsafe { |
|
163 | 160 | (self.capi.index_node)(self.index.as_ptr(), rev as c_int) |
|
164 | 161 | }; |
@@ -89,7 +89,7 b' impl CopyMap {' | |||
|
89 | 89 | py: Python, |
|
90 | 90 | res: (&HgPathBuf, &HgPathBuf), |
|
91 | 91 | ) -> PyResult<Option<PyBytes>> { |
|
92 |
Ok(Some(PyBytes::new(py, res.0.as_ |
|
|
92 | Ok(Some(PyBytes::new(py, res.0.as_bytes()))) | |
|
93 | 93 | } |
|
94 | 94 | fn translate_key_value( |
|
95 | 95 | py: Python, |
@@ -97,8 +97,8 b' impl CopyMap {' | |||
|
97 | 97 | ) -> PyResult<Option<(PyBytes, PyBytes)>> { |
|
98 | 98 | let (k, v) = res; |
|
99 | 99 | Ok(Some(( |
|
100 |
PyBytes::new(py, k.as_ |
|
|
101 |
PyBytes::new(py, v.as_ |
|
|
100 | PyBytes::new(py, k.as_bytes()), | |
|
101 | PyBytes::new(py, v.as_bytes()), | |
|
102 | 102 | ))) |
|
103 | 103 | } |
|
104 | 104 | } |
@@ -128,7 +128,7 b' impl Dirs {' | |||
|
128 | 128 | py: Python, |
|
129 | 129 | res: &HgPathBuf, |
|
130 | 130 | ) -> PyResult<Option<PyBytes>> { |
|
131 |
Ok(Some(PyBytes::new(py, res.as_ |
|
|
131 | Ok(Some(PyBytes::new(py, res.as_bytes()))) | |
|
132 | 132 | } |
|
133 | 133 | } |
|
134 | 134 |
@@ -179,7 +179,7 b' py_class!(pub class DirstateMap |py| {' | |||
|
179 | 179 | "other_parent", |
|
180 | 180 | other_parent |
|
181 | 181 | .iter() |
|
182 |
.map(|v| PyBytes::new(py, v.as_ |
|
|
182 | .map(|v| PyBytes::new(py, v.as_bytes())) | |
|
183 | 183 | .collect::<Vec<PyBytes>>() |
|
184 | 184 | .to_py_object(py), |
|
185 | 185 | )?; |
@@ -348,7 +348,11 b' py_class!(pub class DirstateMap |py| {' | |||
|
348 | 348 | for (key, value) in |
|
349 | 349 | self.inner(py).borrow_mut().build_file_fold_map().iter() |
|
350 | 350 | { |
|
351 | dict.set_item(py, key.as_ref().to_vec(), value.as_ref().to_vec())?; | |
|
351 | dict.set_item( | |
|
352 | py, | |
|
353 | key.as_bytes().to_vec(), | |
|
354 | value.as_bytes().to_vec(), | |
|
355 | )?; | |
|
352 | 356 | } |
|
353 | 357 | Ok(dict) |
|
354 | 358 | } |
@@ -440,8 +444,8 b' py_class!(pub class DirstateMap |py| {' | |||
|
440 | 444 | for (key, value) in self.inner(py).borrow().copy_map.iter() { |
|
441 | 445 | dict.set_item( |
|
442 | 446 | py, |
|
443 |
PyBytes::new(py, key.as_ |
|
|
444 |
PyBytes::new(py, value.as_ |
|
|
447 | PyBytes::new(py, key.as_bytes()), | |
|
448 | PyBytes::new(py, value.as_bytes()), | |
|
445 | 449 | )?; |
|
446 | 450 | } |
|
447 | 451 | Ok(dict) |
@@ -450,7 +454,7 b' py_class!(pub class DirstateMap |py| {' | |||
|
450 | 454 | def copymapgetitem(&self, key: PyObject) -> PyResult<PyBytes> { |
|
451 | 455 | let key = key.extract::<PyBytes>(py)?; |
|
452 | 456 | match self.inner(py).borrow().copy_map.get(HgPath::new(key.data(py))) { |
|
453 |
Some(copy) => Ok(PyBytes::new(py, copy.as_ |
|
|
457 | Some(copy) => Ok(PyBytes::new(py, copy.as_bytes())), | |
|
454 | 458 | None => Err(PyErr::new::<exc::KeyError, _>( |
|
455 | 459 | py, |
|
456 | 460 | String::from_utf8_lossy(key.data(py)), |
@@ -485,7 +489,7 b' py_class!(pub class DirstateMap |py| {' | |||
|
485 | 489 | .get(HgPath::new(key.data(py))) |
|
486 | 490 | { |
|
487 | 491 | Some(copy) => Ok(Some( |
|
488 |
PyBytes::new(py, copy.as_ |
|
|
492 | PyBytes::new(py, copy.as_bytes()).into_object(), | |
|
489 | 493 | )), |
|
490 | 494 | None => Ok(default), |
|
491 | 495 | } |
@@ -549,7 +553,7 b' impl DirstateMap {' | |||
|
549 | 553 | py: Python, |
|
550 | 554 | res: (&HgPathBuf, &DirstateEntry), |
|
551 | 555 | ) -> PyResult<Option<PyBytes>> { |
|
552 |
Ok(Some(PyBytes::new(py, res.0.as_ |
|
|
556 | Ok(Some(PyBytes::new(py, res.0.as_bytes()))) | |
|
553 | 557 | } |
|
554 | 558 | fn translate_key_value( |
|
555 | 559 | py: Python, |
@@ -557,7 +561,7 b' impl DirstateMap {' | |||
|
557 | 561 | ) -> PyResult<Option<(PyBytes, PyObject)>> { |
|
558 | 562 | let (f, entry) = res; |
|
559 | 563 | Ok(Some(( |
|
560 |
PyBytes::new(py, f.as_ |
|
|
564 | PyBytes::new(py, f.as_bytes()), | |
|
561 | 565 | make_dirstate_tuple(py, entry)?, |
|
562 | 566 | ))) |
|
563 | 567 | } |
@@ -62,7 +62,7 b' impl NonNormalEntries {' | |||
|
62 | 62 | py: Python, |
|
63 | 63 | key: &HgPathBuf, |
|
64 | 64 | ) -> PyResult<Option<PyBytes>> { |
|
65 |
Ok(Some(PyBytes::new(py, key.as_ |
|
|
65 | Ok(Some(PyBytes::new(py, key.as_bytes()))) | |
|
66 | 66 | } |
|
67 | 67 | } |
|
68 | 68 |
@@ -236,12 +236,10 b' pub fn status_wrapper(' | |||
|
236 | 236 | |
|
237 | 237 | build_response(py, lookup, status_res, all_warnings) |
|
238 | 238 | } |
|
239 | e => { | |
|
240 | return Err(PyErr::new::<ValueError, _>( | |
|
241 | py, | |
|
242 | format!("Unsupported matcher {}", e), | |
|
243 | )); | |
|
244 | } | |
|
239 | e => Err(PyErr::new::<ValueError, _>( | |
|
240 | py, | |
|
241 | format!("Unsupported matcher {}", e), | |
|
242 | )), | |
|
245 | 243 | } |
|
246 | 244 | } |
|
247 | 245 |
@@ -37,15 +37,15 b' fn parse_dirstate_wrapper(' | |||
|
37 | 37 | for (filename, entry) in &dirstate_map { |
|
38 | 38 | dmap.set_item( |
|
39 | 39 | py, |
|
40 |
PyBytes::new(py, filename.as_ |
|
|
40 | PyBytes::new(py, filename.as_bytes()), | |
|
41 | 41 | make_dirstate_tuple(py, entry)?, |
|
42 | 42 | )?; |
|
43 | 43 | } |
|
44 | 44 | for (path, copy_path) in copies { |
|
45 | 45 | copymap.set_item( |
|
46 | 46 | py, |
|
47 |
PyBytes::new(py, path.as_ |
|
|
48 |
PyBytes::new(py, copy_path.as_ |
|
|
47 | PyBytes::new(py, path.as_bytes()), | |
|
48 | PyBytes::new(py, copy_path.as_bytes()), | |
|
49 | 49 | )?; |
|
50 | 50 | } |
|
51 | 51 | Ok( |
@@ -116,7 +116,7 b' fn pack_dirstate_wrapper(' | |||
|
116 | 116 | for (filename, entry) in &dirstate_map { |
|
117 | 117 | dmap.set_item( |
|
118 | 118 | py, |
|
119 |
PyBytes::new(py, filename.as_ |
|
|
119 | PyBytes::new(py, filename.as_bytes()), | |
|
120 | 120 | make_dirstate_tuple(py, entry)?, |
|
121 | 121 | )?; |
|
122 | 122 | } |
@@ -32,10 +32,7 b" pub fn node_from_py_object<'a>(" | |||
|
32 | 32 | |
|
33 | 33 | /// Clone incoming Python bytes given as `PyBytes` as a `Node`, |
|
34 | 34 | /// doing the necessary checks. |
|
35 | pub fn node_from_py_bytes<'a>( | |
|
36 | py: Python, | |
|
37 | bytes: &'a PyBytes, | |
|
38 | ) -> PyResult<Node> { | |
|
35 | pub fn node_from_py_bytes(py: Python, bytes: &PyBytes) -> PyResult<Node> { | |
|
39 | 36 | <NodeData>::try_from(bytes.data(py)) |
|
40 | 37 | .map_err(|_| { |
|
41 | 38 | PyErr::new::<ValueError, _>( |
@@ -43,5 +40,5 b" pub fn node_from_py_bytes<'a>(" | |||
|
43 | 40 | format!("{}-byte hash required", NODE_BYTES_LENGTH), |
|
44 | 41 | ) |
|
45 | 42 | }) |
|
46 |
.map( |
|
|
43 | .map(Into::into) | |
|
47 | 44 | } |
General Comments 0
You need to be logged in to leave comments.
Login now