Show More
@@ -363,7 +363,7 b' def _combine_changeset_copies(' | |||||
363 |
|
363 | |||
364 | if rustmod is not None: |
|
364 | if rustmod is not None: | |
365 | final_copies = rustmod.combine_changeset_copies( |
|
365 | final_copies = rustmod.combine_changeset_copies( | |
366 |
list(revs), children_count, targetrev, revinfo |
|
366 | list(revs), children_count, targetrev, revinfo | |
367 | ) |
|
367 | ) | |
368 | else: |
|
368 | else: | |
369 | isancestor = cached_is_ancestor(isancestor) |
|
369 | isancestor = cached_is_ancestor(isancestor) |
@@ -281,46 +281,6 b" impl<'a> ChangedFiles<'a> {" | |||||
281 | } |
|
281 | } | |
282 | } |
|
282 | } | |
283 |
|
283 | |||
284 | /// A struct responsible for answering "is X ancestors of Y" quickly |
|
|||
285 | /// |
|
|||
286 | /// The structure will delegate ancestors call to a callback, and cache the |
|
|||
287 | /// result. |
|
|||
288 | #[derive(Debug)] |
|
|||
289 | struct AncestorOracle<'a, A: Fn(Revision, Revision) -> bool> { |
|
|||
290 | inner: &'a A, |
|
|||
291 | pairs: HashMap<(Revision, Revision), bool>, |
|
|||
292 | } |
|
|||
293 |
|
||||
294 | impl<'a, A: Fn(Revision, Revision) -> bool> AncestorOracle<'a, A> { |
|
|||
295 | fn new(func: &'a A) -> Self { |
|
|||
296 | Self { |
|
|||
297 | inner: func, |
|
|||
298 | pairs: HashMap::default(), |
|
|||
299 | } |
|
|||
300 | } |
|
|||
301 |
|
||||
302 | fn record_overwrite(&mut self, anc: Revision, desc: Revision) { |
|
|||
303 | self.pairs.insert((anc, desc), true); |
|
|||
304 | } |
|
|||
305 |
|
||||
306 | /// returns `true` if `anc` is an ancestors of `desc`, `false` otherwise |
|
|||
307 | fn is_overwrite(&mut self, anc: Revision, desc: Revision) -> bool { |
|
|||
308 | if anc > desc { |
|
|||
309 | false |
|
|||
310 | } else if anc == desc { |
|
|||
311 | true |
|
|||
312 | } else { |
|
|||
313 | if let Some(b) = self.pairs.get(&(anc, desc)) { |
|
|||
314 | *b |
|
|||
315 | } else { |
|
|||
316 | let b = (self.inner)(anc, desc); |
|
|||
317 | self.pairs.insert((anc, desc), b); |
|
|||
318 | b |
|
|||
319 | } |
|
|||
320 | } |
|
|||
321 | } |
|
|||
322 | } |
|
|||
323 |
|
||||
324 | struct ActionsIterator<'a> { |
|
284 | struct ActionsIterator<'a> { | |
325 | changes: &'a ChangedFiles<'a>, |
|
285 | changes: &'a ChangedFiles<'a>, | |
326 | parent: Parent, |
|
286 | parent: Parent, | |
@@ -419,15 +379,13 b' impl TwoWayPathMap {' | |||||
419 | /// * ChangedFiles |
|
379 | /// * ChangedFiles | |
420 | /// isancestors(low_rev, high_rev): callback to check if a revision is an |
|
380 | /// isancestors(low_rev, high_rev): callback to check if a revision is an | |
421 | /// ancestor of another |
|
381 | /// ancestor of another | |
422 |
pub fn combine_changeset_copies< |
|
382 | pub fn combine_changeset_copies<D>( | |
423 | revs: Vec<Revision>, |
|
383 | revs: Vec<Revision>, | |
424 | mut children_count: HashMap<Revision, usize>, |
|
384 | mut children_count: HashMap<Revision, usize>, | |
425 | target_rev: Revision, |
|
385 | target_rev: Revision, | |
426 | rev_info: RevInfoMaker<D>, |
|
386 | rev_info: RevInfoMaker<D>, | |
427 | is_ancestor: &A, |
|
|||
428 | ) -> PathCopies { |
|
387 | ) -> PathCopies { | |
429 | let mut all_copies = HashMap::new(); |
|
388 | let mut all_copies = HashMap::new(); | |
430 | let mut oracle = AncestorOracle::new(is_ancestor); |
|
|||
431 |
|
389 | |||
432 | let mut path_map = TwoWayPathMap::default(); |
|
390 | let mut path_map = TwoWayPathMap::default(); | |
433 |
|
391 | |||
@@ -450,7 +408,6 b' pub fn combine_changeset_copies<A: Fn(Re' | |||||
450 | // combine it with data for that revision |
|
408 | // combine it with data for that revision | |
451 | let vertex_copies = add_from_changes( |
|
409 | let vertex_copies = add_from_changes( | |
452 | &mut path_map, |
|
410 | &mut path_map, | |
453 | &mut oracle, |
|
|||
454 | &parent_copies, |
|
411 | &parent_copies, | |
455 | &changes, |
|
412 | &changes, | |
456 | Parent::FirstParent, |
|
413 | Parent::FirstParent, | |
@@ -471,7 +428,6 b' pub fn combine_changeset_copies<A: Fn(Re' | |||||
471 | // combine it with data for that revision |
|
428 | // combine it with data for that revision | |
472 | let vertex_copies = add_from_changes( |
|
429 | let vertex_copies = add_from_changes( | |
473 | &mut path_map, |
|
430 | &mut path_map, | |
474 | &mut oracle, |
|
|||
475 | &parent_copies, |
|
431 | &parent_copies, | |
476 | &changes, |
|
432 | &changes, | |
477 | Parent::SecondParent, |
|
433 | Parent::SecondParent, | |
@@ -491,7 +447,6 b' pub fn combine_changeset_copies<A: Fn(Re' | |||||
491 | vertex_copies, |
|
447 | vertex_copies, | |
492 | copies, |
|
448 | copies, | |
493 | &changes, |
|
449 | &changes, | |
494 | &mut oracle, |
|
|||
495 | )), |
|
450 | )), | |
496 | }; |
|
451 | }; | |
497 | } |
|
452 | } | |
@@ -548,9 +503,8 b' fn get_and_clean_parent_copies(' | |||||
548 |
|
503 | |||
549 | /// Combine ChangedFiles with some existing PathCopies information and return |
|
504 | /// Combine ChangedFiles with some existing PathCopies information and return | |
550 | /// the result |
|
505 | /// the result | |
551 | fn add_from_changes<A: Fn(Revision, Revision) -> bool>( |
|
506 | fn add_from_changes( | |
552 | path_map: &mut TwoWayPathMap, |
|
507 | path_map: &mut TwoWayPathMap, | |
553 | oracle: &mut AncestorOracle<A>, |
|
|||
554 | base_copies: &InternalPathCopies, |
|
508 | base_copies: &InternalPathCopies, | |
555 | changes: &ChangedFiles, |
|
509 | changes: &ChangedFiles, | |
556 | parent: Parent, |
|
510 | parent: Parent, | |
@@ -582,7 +536,6 b' fn add_from_changes<A: Fn(Revision, Revi' | |||||
582 | } |
|
536 | } | |
583 | Entry::Occupied(mut slot) => { |
|
537 | Entry::Occupied(mut slot) => { | |
584 | let ttpc = slot.get_mut(); |
|
538 | let ttpc = slot.get_mut(); | |
585 | oracle.record_overwrite(ttpc.rev, current_rev); |
|
|||
586 | ttpc.overwrite(current_rev, entry); |
|
539 | ttpc.overwrite(current_rev, entry); | |
587 | } |
|
540 | } | |
588 | } |
|
541 | } | |
@@ -595,7 +548,6 b' fn add_from_changes<A: Fn(Revision, Revi' | |||||
595 | // InternalPathCopies object. |
|
548 | // InternalPathCopies object. | |
596 | let deleted = path_map.tokenize(deleted_path); |
|
549 | let deleted = path_map.tokenize(deleted_path); | |
597 | copies.entry(deleted).and_modify(|old| { |
|
550 | copies.entry(deleted).and_modify(|old| { | |
598 | oracle.record_overwrite(old.rev, current_rev); |
|
|||
599 | old.mark_delete(current_rev); |
|
551 | old.mark_delete(current_rev); | |
600 | }); |
|
552 | }); | |
601 | } |
|
553 | } | |
@@ -608,31 +560,27 b' fn add_from_changes<A: Fn(Revision, Revi' | |||||
608 | /// |
|
560 | /// | |
609 | /// In case of conflict, value from "major" will be picked, unless in some |
|
561 | /// In case of conflict, value from "major" will be picked, unless in some | |
610 | /// cases. See inline documentation for details. |
|
562 | /// cases. See inline documentation for details. | |
611 | fn merge_copies_dict<A: Fn(Revision, Revision) -> bool>( |
|
563 | fn merge_copies_dict( | |
612 | path_map: &TwoWayPathMap, |
|
564 | path_map: &TwoWayPathMap, | |
613 | current_merge: Revision, |
|
565 | current_merge: Revision, | |
614 | mut minor: InternalPathCopies, |
|
566 | mut minor: InternalPathCopies, | |
615 | mut major: InternalPathCopies, |
|
567 | mut major: InternalPathCopies, | |
616 | changes: &ChangedFiles, |
|
568 | changes: &ChangedFiles, | |
617 | oracle: &mut AncestorOracle<A>, |
|
|||
618 | ) -> InternalPathCopies { |
|
569 | ) -> InternalPathCopies { | |
619 | // This closure exist as temporary help while multiple developper are |
|
570 | // This closure exist as temporary help while multiple developper are | |
620 | // actively working on this code. Feel free to re-inline it once this |
|
571 | // actively working on this code. Feel free to re-inline it once this | |
621 | // code is more settled. |
|
572 | // code is more settled. | |
622 | let cmp_value = |oracle: &mut AncestorOracle<A>, |
|
573 | let cmp_value = | |
623 | dest: &PathToken, |
|
574 | |dest: &PathToken, src_minor: &CopySource, src_major: &CopySource| { | |
624 | src_minor: &CopySource, |
|
575 | compare_value( | |
625 | src_major: &CopySource| { |
|
576 | path_map, | |
626 | compare_value( |
|
577 | current_merge, | |
627 |
|
|
578 | changes, | |
628 |
|
|
579 | dest, | |
629 |
|
|
580 | src_minor, | |
630 |
or |
|
581 | src_major, | |
631 |
|
|
582 | ) | |
632 | src_minor, |
|
583 | }; | |
633 | src_major, |
|
|||
634 | ) |
|
|||
635 | }; |
|
|||
636 | if minor.is_empty() { |
|
584 | if minor.is_empty() { | |
637 | major |
|
585 | major | |
638 | } else if major.is_empty() { |
|
586 | } else if major.is_empty() { | |
@@ -661,10 +609,8 b' fn merge_copies_dict<A: Fn(Revision, Rev' | |||||
661 | } |
|
609 | } | |
662 | Some(src_major) => { |
|
610 | Some(src_major) => { | |
663 | let (pick, overwrite) = |
|
611 | let (pick, overwrite) = | |
664 |
cmp_value( |
|
612 | cmp_value(&dest, &src_minor, src_major); | |
665 | if overwrite { |
|
613 | if overwrite { | |
666 | oracle.record_overwrite(src_minor.rev, current_merge); |
|
|||
667 | oracle.record_overwrite(src_major.rev, current_merge); |
|
|||
668 | let src = match pick { |
|
614 | let src = match pick { | |
669 | MergePick::Major => CopySource::new_from_merge( |
|
615 | MergePick::Major => CopySource::new_from_merge( | |
670 | current_merge, |
|
616 | current_merge, | |
@@ -704,10 +650,8 b' fn merge_copies_dict<A: Fn(Revision, Rev' | |||||
704 | } |
|
650 | } | |
705 | Some(src_minor) => { |
|
651 | Some(src_minor) => { | |
706 | let (pick, overwrite) = |
|
652 | let (pick, overwrite) = | |
707 |
cmp_value( |
|
653 | cmp_value(&dest, src_minor, &src_major); | |
708 | if overwrite { |
|
654 | if overwrite { | |
709 | oracle.record_overwrite(src_minor.rev, current_merge); |
|
|||
710 | oracle.record_overwrite(src_major.rev, current_merge); |
|
|||
711 | let src = match pick { |
|
655 | let src = match pick { | |
712 | MergePick::Major => CopySource::new_from_merge( |
|
656 | MergePick::Major => CopySource::new_from_merge( | |
713 | current_merge, |
|
657 | current_merge, | |
@@ -769,10 +713,8 b' fn merge_copies_dict<A: Fn(Revision, Rev' | |||||
769 | let (dest, src_major) = new; |
|
713 | let (dest, src_major) = new; | |
770 | let (_, src_minor) = old; |
|
714 | let (_, src_minor) = old; | |
771 | let (pick, overwrite) = |
|
715 | let (pick, overwrite) = | |
772 |
cmp_value( |
|
716 | cmp_value(dest, src_minor, src_major); | |
773 | if overwrite { |
|
717 | if overwrite { | |
774 | oracle.record_overwrite(src_minor.rev, current_merge); |
|
|||
775 | oracle.record_overwrite(src_major.rev, current_merge); |
|
|||
776 | let src = match pick { |
|
718 | let src = match pick { | |
777 | MergePick::Major => CopySource::new_from_merge( |
|
719 | MergePick::Major => CopySource::new_from_merge( | |
778 | current_merge, |
|
720 | current_merge, | |
@@ -840,11 +782,10 b' enum MergePick {' | |||||
840 |
|
782 | |||
841 | /// decide which side prevails in case of conflicting values |
|
783 | /// decide which side prevails in case of conflicting values | |
842 | #[allow(clippy::if_same_then_else)] |
|
784 | #[allow(clippy::if_same_then_else)] | |
843 | fn compare_value<A: Fn(Revision, Revision) -> bool>( |
|
785 | fn compare_value( | |
844 | path_map: &TwoWayPathMap, |
|
786 | path_map: &TwoWayPathMap, | |
845 | current_merge: Revision, |
|
787 | current_merge: Revision, | |
846 | changes: &ChangedFiles, |
|
788 | changes: &ChangedFiles, | |
847 | oracle: &mut AncestorOracle<A>, |
|
|||
848 | dest: &PathToken, |
|
789 | dest: &PathToken, | |
849 | src_minor: &CopySource, |
|
790 | src_minor: &CopySource, | |
850 | src_major: &CopySource, |
|
791 | src_major: &CopySource, |
@@ -1,5 +1,4 b'' | |||||
1 | use cpython::ObjectProtocol; |
|
1 | use cpython::ObjectProtocol; | |
2 | use cpython::PyBool; |
|
|||
3 | use cpython::PyBytes; |
|
2 | use cpython::PyBytes; | |
4 | use cpython::PyDict; |
|
3 | use cpython::PyDict; | |
5 | use cpython::PyList; |
|
4 | use cpython::PyList; | |
@@ -26,32 +25,10 b' pub fn combine_changeset_copies_wrapper(' | |||||
26 | children_count: PyDict, |
|
25 | children_count: PyDict, | |
27 | target_rev: Revision, |
|
26 | target_rev: Revision, | |
28 | rev_info: PyObject, |
|
27 | rev_info: PyObject, | |
29 | is_ancestor: PyObject, |
|
|||
30 | ) -> PyResult<PyDict> { |
|
28 | ) -> PyResult<PyDict> { | |
31 | let revs: PyResult<_> = |
|
29 | let revs: PyResult<_> = | |
32 | revs.iter(py).map(|r| Ok(r.extract(py)?)).collect(); |
|
30 | revs.iter(py).map(|r| Ok(r.extract(py)?)).collect(); | |
33 |
|
31 | |||
34 | // Wrap the `is_ancestor` python callback as a Rust closure |
|
|||
35 | // |
|
|||
36 | // No errors are expected from the Python side, and they will should only |
|
|||
37 | // happens in case of programing error or severe data corruption. Such |
|
|||
38 | // errors will raise panic and the rust-cpython harness will turn them into |
|
|||
39 | // Python exception. |
|
|||
40 | let is_ancestor_wrap = |anc: Revision, desc: Revision| -> bool { |
|
|||
41 | is_ancestor |
|
|||
42 | .call(py, (anc, desc), None) |
|
|||
43 | .expect( |
|
|||
44 | "rust-copy-tracing: python call to `is_ancestor` \ |
|
|||
45 | failed", |
|
|||
46 | ) |
|
|||
47 | .cast_into::<PyBool>(py) |
|
|||
48 | .expect( |
|
|||
49 | "rust-copy-tracing: python call to `is_ancestor` \ |
|
|||
50 | returned unexpected non-Bool value", |
|
|||
51 | ) |
|
|||
52 | .is_true() |
|
|||
53 | }; |
|
|||
54 |
|
||||
55 | // Wrap the `rev_info_maker` python callback as a Rust closure |
|
32 | // Wrap the `rev_info_maker` python callback as a Rust closure | |
56 | // |
|
33 | // | |
57 | // No errors are expected from the Python side, and they will should only |
|
34 | // No errors are expected from the Python side, and they will should only | |
@@ -104,7 +81,6 b' pub fn combine_changeset_copies_wrapper(' | |||||
104 | children_count?, |
|
81 | children_count?, | |
105 | target_rev, |
|
82 | target_rev, | |
106 | rev_info_maker, |
|
83 | rev_info_maker, | |
107 | &is_ancestor_wrap, |
|
|||
108 | ); |
|
84 | ); | |
109 | let out = PyDict::new(py); |
|
85 | let out = PyDict::new(py); | |
110 | for (dest, source) in res.into_iter() { |
|
86 | for (dest, source) in res.into_iter() { | |
@@ -134,8 +110,7 b' pub fn init_module(py: Python, package: ' | |||||
134 | revs: PyList, |
|
110 | revs: PyList, | |
135 | children: PyDict, |
|
111 | children: PyDict, | |
136 | target_rev: Revision, |
|
112 | target_rev: Revision, | |
137 |
rev_info: PyObject |
|
113 | rev_info: PyObject | |
138 | is_ancestor: PyObject |
|
|||
139 | ) |
|
114 | ) | |
140 | ), |
|
115 | ), | |
141 | )?; |
|
116 | )?; |
General Comments 0
You need to be logged in to leave comments.
Login now