D12418: copies: add config to preserve old copies (issue5457)
martinvonz (Martin von Zweigbergk)
phabricator at mercurial-scm.org
Wed Mar 30 04:19:22 UTC 2022
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
More information about the Mercurial-devel
mailing list