Show More
@@ -363,7 +363,7 b' def _combine_changeset_copies(' | |||
|
363 | 363 | |
|
364 | 364 | if rustmod is not None: |
|
365 | 365 | final_copies = rustmod.combine_changeset_copies( |
|
366 |
list(revs), children_count, targetrev, revinfo |
|
|
366 | list(revs), children_count, targetrev, revinfo | |
|
367 | 367 | ) |
|
368 | 368 | else: |
|
369 | 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 | 284 | struct ActionsIterator<'a> { |
|
325 | 285 | changes: &'a ChangedFiles<'a>, |
|
326 | 286 | parent: Parent, |
@@ -419,15 +379,13 b' impl TwoWayPathMap {' | |||
|
419 | 379 | /// * ChangedFiles |
|
420 | 380 | /// isancestors(low_rev, high_rev): callback to check if a revision is an |
|
421 | 381 | /// ancestor of another |
|
422 |
pub fn combine_changeset_copies< |
|
|
382 | pub fn combine_changeset_copies<D>( | |
|
423 | 383 | revs: Vec<Revision>, |
|
424 | 384 | mut children_count: HashMap<Revision, usize>, |
|
425 | 385 | target_rev: Revision, |
|
426 | 386 | rev_info: RevInfoMaker<D>, |
|
427 | is_ancestor: &A, | |
|
428 | 387 | ) -> PathCopies { |
|
429 | 388 | let mut all_copies = HashMap::new(); |
|
430 | let mut oracle = AncestorOracle::new(is_ancestor); | |
|
431 | 389 | |
|
432 | 390 | let mut path_map = TwoWayPathMap::default(); |
|
433 | 391 | |
@@ -450,7 +408,6 b' pub fn combine_changeset_copies<A: Fn(Re' | |||
|
450 | 408 | // combine it with data for that revision |
|
451 | 409 | let vertex_copies = add_from_changes( |
|
452 | 410 | &mut path_map, |
|
453 | &mut oracle, | |
|
454 | 411 | &parent_copies, |
|
455 | 412 | &changes, |
|
456 | 413 | Parent::FirstParent, |
@@ -471,7 +428,6 b' pub fn combine_changeset_copies<A: Fn(Re' | |||
|
471 | 428 | // combine it with data for that revision |
|
472 | 429 | let vertex_copies = add_from_changes( |
|
473 | 430 | &mut path_map, |
|
474 | &mut oracle, | |
|
475 | 431 | &parent_copies, |
|
476 | 432 | &changes, |
|
477 | 433 | Parent::SecondParent, |
@@ -491,7 +447,6 b' pub fn combine_changeset_copies<A: Fn(Re' | |||
|
491 | 447 | vertex_copies, |
|
492 | 448 | copies, |
|
493 | 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 | 504 | /// Combine ChangedFiles with some existing PathCopies information and return |
|
550 | 505 | /// the result |
|
551 | fn add_from_changes<A: Fn(Revision, Revision) -> bool>( | |
|
506 | fn add_from_changes( | |
|
552 | 507 | path_map: &mut TwoWayPathMap, |
|
553 | oracle: &mut AncestorOracle<A>, | |
|
554 | 508 | base_copies: &InternalPathCopies, |
|
555 | 509 | changes: &ChangedFiles, |
|
556 | 510 | parent: Parent, |
@@ -582,7 +536,6 b' fn add_from_changes<A: Fn(Revision, Revi' | |||
|
582 | 536 | } |
|
583 | 537 | Entry::Occupied(mut slot) => { |
|
584 | 538 | let ttpc = slot.get_mut(); |
|
585 | oracle.record_overwrite(ttpc.rev, current_rev); | |
|
586 | 539 | ttpc.overwrite(current_rev, entry); |
|
587 | 540 | } |
|
588 | 541 | } |
@@ -595,7 +548,6 b' fn add_from_changes<A: Fn(Revision, Revi' | |||
|
595 | 548 | // InternalPathCopies object. |
|
596 | 549 | let deleted = path_map.tokenize(deleted_path); |
|
597 | 550 | copies.entry(deleted).and_modify(|old| { |
|
598 | oracle.record_overwrite(old.rev, current_rev); | |
|
599 | 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 | 561 | /// In case of conflict, value from "major" will be picked, unless in some |
|
610 | 562 | /// cases. See inline documentation for details. |
|
611 | fn merge_copies_dict<A: Fn(Revision, Revision) -> bool>( | |
|
563 | fn merge_copies_dict( | |
|
612 | 564 | path_map: &TwoWayPathMap, |
|
613 | 565 | current_merge: Revision, |
|
614 | 566 | mut minor: InternalPathCopies, |
|
615 | 567 | mut major: InternalPathCopies, |
|
616 | 568 | changes: &ChangedFiles, |
|
617 | oracle: &mut AncestorOracle<A>, | |
|
618 | 569 | ) -> InternalPathCopies { |
|
619 | 570 | // This closure exist as temporary help while multiple developper are |
|
620 | 571 | // actively working on this code. Feel free to re-inline it once this |
|
621 | 572 | // code is more settled. |
|
622 | let cmp_value = |oracle: &mut AncestorOracle<A>, | |
|
623 | dest: &PathToken, | |
|
624 | src_minor: &CopySource, | |
|
625 | src_major: &CopySource| { | |
|
626 | compare_value( | |
|
627 |
|
|
|
628 |
|
|
|
629 |
|
|
|
630 |
or |
|
|
631 |
|
|
|
632 | src_minor, | |
|
633 | src_major, | |
|
634 | ) | |
|
635 | }; | |
|
573 | let cmp_value = | |
|
574 | |dest: &PathToken, src_minor: &CopySource, src_major: &CopySource| { | |
|
575 | compare_value( | |
|
576 | path_map, | |
|
577 | current_merge, | |
|
578 | changes, | |
|
579 | dest, | |
|
580 | src_minor, | |
|
581 | src_major, | |
|
582 | ) | |
|
583 | }; | |
|
636 | 584 | if minor.is_empty() { |
|
637 | 585 | major |
|
638 | 586 | } else if major.is_empty() { |
@@ -661,10 +609,8 b' fn merge_copies_dict<A: Fn(Revision, Rev' | |||
|
661 | 609 | } |
|
662 | 610 | Some(src_major) => { |
|
663 | 611 | let (pick, overwrite) = |
|
664 |
cmp_value( |
|
|
612 | cmp_value(&dest, &src_minor, src_major); | |
|
665 | 613 | if overwrite { |
|
666 | oracle.record_overwrite(src_minor.rev, current_merge); | |
|
667 | oracle.record_overwrite(src_major.rev, current_merge); | |
|
668 | 614 | let src = match pick { |
|
669 | 615 | MergePick::Major => CopySource::new_from_merge( |
|
670 | 616 | current_merge, |
@@ -704,10 +650,8 b' fn merge_copies_dict<A: Fn(Revision, Rev' | |||
|
704 | 650 | } |
|
705 | 651 | Some(src_minor) => { |
|
706 | 652 | let (pick, overwrite) = |
|
707 |
cmp_value( |
|
|
653 | cmp_value(&dest, src_minor, &src_major); | |
|
708 | 654 | if overwrite { |
|
709 | oracle.record_overwrite(src_minor.rev, current_merge); | |
|
710 | oracle.record_overwrite(src_major.rev, current_merge); | |
|
711 | 655 | let src = match pick { |
|
712 | 656 | MergePick::Major => CopySource::new_from_merge( |
|
713 | 657 | current_merge, |
@@ -769,10 +713,8 b' fn merge_copies_dict<A: Fn(Revision, Rev' | |||
|
769 | 713 | let (dest, src_major) = new; |
|
770 | 714 | let (_, src_minor) = old; |
|
771 | 715 | let (pick, overwrite) = |
|
772 |
cmp_value( |
|
|
716 | cmp_value(dest, src_minor, src_major); | |
|
773 | 717 | if overwrite { |
|
774 | oracle.record_overwrite(src_minor.rev, current_merge); | |
|
775 | oracle.record_overwrite(src_major.rev, current_merge); | |
|
776 | 718 | let src = match pick { |
|
777 | 719 | MergePick::Major => CopySource::new_from_merge( |
|
778 | 720 | current_merge, |
@@ -840,11 +782,10 b' enum MergePick {' | |||
|
840 | 782 | |
|
841 | 783 | /// decide which side prevails in case of conflicting values |
|
842 | 784 | #[allow(clippy::if_same_then_else)] |
|
843 | fn compare_value<A: Fn(Revision, Revision) -> bool>( | |
|
785 | fn compare_value( | |
|
844 | 786 | path_map: &TwoWayPathMap, |
|
845 | 787 | current_merge: Revision, |
|
846 | 788 | changes: &ChangedFiles, |
|
847 | oracle: &mut AncestorOracle<A>, | |
|
848 | 789 | dest: &PathToken, |
|
849 | 790 | src_minor: &CopySource, |
|
850 | 791 | src_major: &CopySource, |
@@ -1,5 +1,4 b'' | |||
|
1 | 1 | use cpython::ObjectProtocol; |
|
2 | use cpython::PyBool; | |
|
3 | 2 | use cpython::PyBytes; |
|
4 | 3 | use cpython::PyDict; |
|
5 | 4 | use cpython::PyList; |
@@ -26,32 +25,10 b' pub fn combine_changeset_copies_wrapper(' | |||
|
26 | 25 | children_count: PyDict, |
|
27 | 26 | target_rev: Revision, |
|
28 | 27 | rev_info: PyObject, |
|
29 | is_ancestor: PyObject, | |
|
30 | 28 | ) -> PyResult<PyDict> { |
|
31 | 29 | let revs: PyResult<_> = |
|
32 | 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 | 32 | // Wrap the `rev_info_maker` python callback as a Rust closure |
|
56 | 33 | // |
|
57 | 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 | 81 | children_count?, |
|
105 | 82 | target_rev, |
|
106 | 83 | rev_info_maker, |
|
107 | &is_ancestor_wrap, | |
|
108 | 84 | ); |
|
109 | 85 | let out = PyDict::new(py); |
|
110 | 86 | for (dest, source) in res.into_iter() { |
@@ -134,8 +110,7 b' pub fn init_module(py: Python, package: ' | |||
|
134 | 110 | revs: PyList, |
|
135 | 111 | children: PyDict, |
|
136 | 112 | target_rev: Revision, |
|
137 |
rev_info: PyObject |
|
|
138 | is_ancestor: PyObject | |
|
113 | rev_info: PyObject | |
|
139 | 114 | ) |
|
140 | 115 | ), |
|
141 | 116 | )?; |
General Comments 0
You need to be logged in to leave comments.
Login now