diff --git a/rust/hg-core/src/copy_tracing.rs b/rust/hg-core/src/copy_tracing.rs index c244c13761ac1d4956ac50a6e28677fee9350acb_cnVzdC9oZy1jb3JlL3NyYy9jb3B5X3RyYWNpbmcucnM=..19884e678792b912d0f12cff15bfb21822f51e3f_cnVzdC9oZy1jb3JlL3NyYy9jb3B5X3RyYWNpbmcucnM= 100644 --- a/rust/hg-core/src/copy_tracing.rs +++ b/rust/hg-core/src/copy_tracing.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use std::collections::HashSet; -use im_rc::ordmap::OrdMap; +use im_rc::ordmap::{DiffItem, OrdMap}; pub type PathCopies = HashMap<HgPathBuf, HgPathBuf>; @@ -8,7 +8,7 @@ pub type PathCopies = HashMap<HgPathBuf, HgPathBuf>; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] struct TimeStampedPathCopy { /// revision at which the copy information was added rev: Revision, @@ -202,9 +202,28 @@ changes: &ChangedFiles, is_ancestor: &impl Fn(Revision, Revision) -> bool, ) -> TimeStampedPathCopies { - let mut result = minor.clone(); - for (dest, src_major) in major.into_iter() { - let overwrite; - if let Some(src_minor) = minor.get(&dest) { - { + if minor.is_empty() { + return major; + } else if major.is_empty() { + return minor; + } + let mut override_minor = Vec::new(); + let mut override_major = Vec::new(); + + let mut to_major = |k: &HgPathBuf, v: &TimeStampedPathCopy| { + override_major.push((k.clone(), v.clone())) + }; + let mut to_minor = |k: &HgPathBuf, v: &TimeStampedPathCopy| { + override_minor.push((k.clone(), v.clone())) + }; + + for d in minor.diff(&major) { + match d { + DiffItem::Add(k, v) => to_minor(k, v), + DiffItem::Remove(k, v) => to_major(k, v), + DiffItem::Update { old, new } => { + let (dest, src_major) = new; + let (_, src_minor) = old; + let mut pick_minor = || (to_major(dest, src_minor)); + let mut pick_major = || (to_minor(dest, src_major)); if src_major.path == src_minor.path { @@ -210,7 +229,7 @@ if src_major.path == src_minor.path { - // we have the same value, no need to battle; + // we have the same value, but from other source; if src_major.rev == src_minor.rev { // If the two entry are identical, `minor.diff(major)` // should not have yield it. unreachable!() } else if is_ancestor(src_major.rev, src_minor.rev) { @@ -212,7 +231,7 @@ if src_major.rev == src_minor.rev { // If the two entry are identical, `minor.diff(major)` // should not have yield it. unreachable!() } else if is_ancestor(src_major.rev, src_minor.rev) { - overwrite = false; + pick_minor(); } else { @@ -218,6 +237,6 @@ } else { - overwrite = true; + pick_major(); } } else if src_major.rev == src_minor.rev { // We cannot get copy information for both p1 and p2 in the // same rev. So this is the same value. @@ -220,6 +239,6 @@ } } else if src_major.rev == src_minor.rev { // We cannot get copy information for both p1 and p2 in the // same rev. So this is the same value. - overwrite = false; + unreachable!(); } else if src_major.path.is_none() @@ -225,6 +244,6 @@ } else if src_major.path.is_none() - && changes.salvaged.contains(&dest) + && changes.salvaged.contains(dest) { // If the file is "deleted" in the major side but was // salvaged by the merge, we // keep the minor side alive @@ -227,6 +246,6 @@ { // If the file is "deleted" in the major side but was // salvaged by the merge, we // keep the minor side alive - overwrite = false; + pick_minor(); } else if src_minor.path.is_none() @@ -232,6 +251,6 @@ } else if src_minor.path.is_none() - && changes.salvaged.contains(&dest) + && changes.salvaged.contains(dest) { // If the file is "deleted" in the minor side but was // salvaged by the merge, // unconditionnaly preserve the major side. @@ -234,9 +253,9 @@ { // If the file is "deleted" in the minor side but was // salvaged by the merge, // unconditionnaly preserve the major side. - overwrite = true; - } else if changes.merged.contains(&dest) { + pick_major(); + } else if changes.merged.contains(dest) { // If the file was actively merged, copy information from // each side might conflict. // The major side will win such conflict. @@ -240,7 +259,7 @@ // If the file was actively merged, copy information from // each side might conflict. // The major side will win such conflict. - overwrite = true; + pick_major(); } else if is_ancestor(src_major.rev, src_minor.rev) { // If the minor side is strictly newer than the major side, // it should be kept. @@ -244,7 +263,7 @@ } else if is_ancestor(src_major.rev, src_minor.rev) { // If the minor side is strictly newer than the major side, // it should be kept. - overwrite = false; + pick_minor(); } else if src_major.path.is_some() { // without any special case, the "major" value win other // the "minor" one. @@ -248,7 +267,7 @@ } else if src_major.path.is_some() { // without any special case, the "major" value win other // the "minor" one. - overwrite = true; + pick_major(); } else if is_ancestor(src_minor.rev, src_major.rev) { // the "major" rev is a direct ancestors of "minor", any // different value should overwrite @@ -252,6 +271,6 @@ } else if is_ancestor(src_minor.rev, src_major.rev) { // the "major" rev is a direct ancestors of "minor", any // different value should overwrite - overwrite = true; + pick_major(); } else { // major version is None (so the file was deleted on that @@ -256,6 +275,6 @@ } else { // major version is None (so the file was deleted on that - // branch) annd that branch + // branch) and that branch // is independant (neither minor nor major is an ancestors // of the other one.) We preserve the // new information about the new file. @@ -259,6 +278,6 @@ // is independant (neither minor nor major is an ancestors // of the other one.) We preserve the // new information about the new file. - overwrite = false; + pick_minor(); } } @@ -263,3 +282,16 @@ } } + }; + } + + let updates; + let mut result; + if override_major.is_empty() { + result = major + } else if override_minor.is_empty() { + result = minor + } else { + if override_minor.len() < override_major.len() { + updates = override_minor; + result = minor; } else { @@ -265,4 +297,4 @@ } else { - // minor had not value - overwrite = true; + updates = override_major; + result = major; } @@ -268,6 +300,6 @@ } - if overwrite { - result.insert(dest, src_major); + for (k, v) in updates { + result.insert(k, v); } } result