martinvonz created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches.
REVISION SUMMARY The scenario in issue 5457 gets reported every now and then by our users (Google developers). This patch adds a fix for it by preserving existing copies even if the source file no longer exists. That's a bit of hack, but it's effective and much simpler than the other alternatives we've considered (such as storing the copy information in obsmarkers, which would mean that copy tracing would have to follow both graphs). The fix only works when copies are stored in changeset extras or sidedata because the filelog record needs to have the old file nodeid, which doesn't exist in the parent manifest. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D12418 AFFECTED FILES mercurial/commit.py mercurial/configitems.py mercurial/copies.py mercurial/metadata.py tests/test-copies.t CHANGE DETAILS diff --git a/tests/test-copies.t b/tests/test-copies.t --- a/tests/test-copies.t +++ b/tests/test-copies.t @@ -754,6 +754,7 @@ > [experimental] > evolution.createmarkers = True > evolution.allowunstable = True + > copies.keep-old = True > EOF $ newrepo $ echo a > a @@ -769,11 +770,17 @@ $ hg mv b c $ hg ci --amend -m "added c" 1 new orphan changesets +#if no-filelog no-compatibility $ hg rebase -s 'desc("modified b")' -d . rebasing 2:e3e0011b43ad "modified b" (changeset !) rebasing 2:2612b8963c3f "modified b" (no-changeset !) + merging c and b to c +#else + $ hg rebase -s 'desc("modified b")' -d . + rebasing 2:2612b8963c3f "modified b" file 'b' was deleted in local [dest] but was modified in other [source]. You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved. What do you want to do? u unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') [240] +#endif diff --git a/mercurial/metadata.py b/mercurial/metadata.py --- a/mercurial/metadata.py +++ b/mercurial/metadata.py @@ -639,6 +639,9 @@ p1copies[dst] = src elif src in p2 and p2[src].filenode() == srcnode: p2copies[dst] = src + else: + # This case should only happen with experimental.copies.keep-old + p1copies[dst] = src return p1copies, p2copies diff --git a/mercurial/copies.py b/mercurial/copies.py --- a/mercurial/copies.py +++ b/mercurial/copies.py @@ -53,10 +53,11 @@ # between 5 and 6, so it includes all cases in its result. # Cases 1, 3, and 5 are then removed by _filter(). + keep_old = src.repo().ui.configbool(b'experimental', b'copies.keep-old') for k, v in list(t.items()): if k == v: # case 3 del t[k] - elif v not in src: # case 5 + elif not keep_old and v not in src: # case 5 # remove copies from files that didn't exist del t[k] elif k not in dst: # case 1 diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -943,6 +943,11 @@ ) coreconfigitem( b'experimental', + b'copies.keep-old', + default=False, +) +coreconfigitem( + b'experimental', b'crecordtest', default=None, ) diff --git a/mercurial/commit.py b/mercurial/commit.py --- a/mercurial/commit.py +++ b/mercurial/commit.py @@ -390,7 +390,7 @@ meta[b"copy"] = cfname meta[b"copyrev"] = hex(cnode) fparent1, fparent2 = repo.nullid, newfparent - else: + elif not repo.ui.configbool(b'experimental', b'copies.keep-old'): repo.ui.warn( _( b"warning: can't find ancestor for '%s' " To: martinvonz, #hg-reviewers Cc: mercurial-patches, mercurial-devel _______________________________________________ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel