456 /// merge two copies-mapping together, minor and major |
456 /// merge two copies-mapping together, minor and major |
457 /// |
457 /// |
458 /// In case of conflict, value from "major" will be picked, unless in some |
458 /// In case of conflict, value from "major" will be picked, unless in some |
459 /// cases. See inline documentation for details. |
459 /// cases. See inline documentation for details. |
460 fn merge_copies_dict<A: Fn(Revision, Revision) -> bool>( |
460 fn merge_copies_dict<A: Fn(Revision, Revision) -> bool>( |
461 minor: TimeStampedPathCopies, |
461 mut minor: TimeStampedPathCopies, |
462 major: TimeStampedPathCopies, |
462 mut major: TimeStampedPathCopies, |
463 changes: &ChangedFiles, |
463 changes: &ChangedFiles, |
464 oracle: &mut AncestorOracle<A>, |
464 oracle: &mut AncestorOracle<A>, |
465 ) -> TimeStampedPathCopies { |
465 ) -> TimeStampedPathCopies { |
466 // This closure exist as temporary help while multiple developper are |
466 // This closure exist as temporary help while multiple developper are |
467 // actively working on this code. Feel free to re-inline it once this |
467 // actively working on this code. Feel free to re-inline it once this |
473 compare_value(changes, oracle, dest, src_minor, src_major) |
473 compare_value(changes, oracle, dest, src_minor, src_major) |
474 }; |
474 }; |
475 if minor.is_empty() { |
475 if minor.is_empty() { |
476 major |
476 major |
477 } else if major.is_empty() { |
477 } else if major.is_empty() { |
|
478 minor |
|
479 } else if minor.len() * 2 < major.len() { |
|
480 // Lets says we are merging two TimeStampedPathCopies instance A and B. |
|
481 // |
|
482 // If A contains N items, the merge result will never contains more |
|
483 // than N values differents than the one in A |
|
484 // |
|
485 // If B contains M items, with M > N, the merge result will always |
|
486 // result in a minimum of M - N value differents than the on in |
|
487 // A |
|
488 // |
|
489 // As a result, if N < (M-N), we know that simply iterating over A will |
|
490 // yield less difference than iterating over the difference |
|
491 // between A and B. |
|
492 // |
|
493 // This help performance a lot in case were a tiny |
|
494 // TimeStampedPathCopies is merged with a much larger one. |
|
495 for (dest, src_minor) in minor { |
|
496 let src_major = major.get(&dest); |
|
497 match src_major { |
|
498 None => major.insert(dest, src_minor), |
|
499 Some(src_major) => { |
|
500 match cmp_value(&dest, &src_minor, src_major) { |
|
501 MergePick::Any | MergePick::Major => None, |
|
502 MergePick::Minor => major.insert(dest, src_minor), |
|
503 } |
|
504 } |
|
505 }; |
|
506 } |
|
507 major |
|
508 } else if major.len() * 2 < minor.len() { |
|
509 // This use the same rational than the previous block. |
|
510 // (Check previous block documentation for details.) |
|
511 for (dest, src_major) in major { |
|
512 let src_minor = minor.get(&dest); |
|
513 match src_minor { |
|
514 None => minor.insert(dest, src_major), |
|
515 Some(src_minor) => { |
|
516 match cmp_value(&dest, src_minor, &src_major) { |
|
517 MergePick::Any | MergePick::Minor => None, |
|
518 MergePick::Major => minor.insert(dest, src_major), |
|
519 } |
|
520 } |
|
521 }; |
|
522 } |
478 minor |
523 minor |
479 } else { |
524 } else { |
480 let mut override_minor = Vec::new(); |
525 let mut override_minor = Vec::new(); |
481 let mut override_major = Vec::new(); |
526 let mut override_major = Vec::new(); |
482 |
527 |