amend: fix amend with copies in extras stable
authorMartin von Zweigbergk <martinvonz@google.com>
Fri, 18 Mar 2022 21:15:54 -0700
branchstable
changeset 48976 877d7e1a4223
parent 48975 e3c75d65d589
child 48977 bd752712ccaf
amend: fix amend with copies in extras If copy information is stored only in the commit extras and not in filelogs, then they get lost on amend if the file wasn't also modified in the working copy. That's because we create `filectx` object from the old commit in those cases, and the `.copysource()` of such objects read only from the filelog. This patch fixes it by always creating a new `memfilectx` in these cases, passing the calculated copy information to it. Differential Revision: https://phab.mercurial-scm.org/D12387
mercurial/cmdutil.py
tests/test-copies-in-changeset.t
--- a/mercurial/cmdutil.py	Fri Mar 18 21:37:22 2022 -0700
+++ b/mercurial/cmdutil.py	Fri Mar 18 21:15:54 2022 -0700
@@ -2906,7 +2906,14 @@
         filestoamend = {f for f in wctx.files() if matcher(f)}
 
         changes = len(filestoamend) > 0
-        if changes:
+        changeset_copies = (
+            repo.ui.config(b'experimental', b'copies.read-from')
+            != b'filelog-only'
+        )
+        # If there are changes to amend or if copy information needs to be read
+        # from the changeset extras, we cannot take the fast path of using
+        # filectxs from the old commit.
+        if changes or changeset_copies:
             # Recompute copies (avoid recording a -> b -> a)
             copied = copies.pathcopies(base, wctx, matcher)
             if old.p2:
@@ -2927,19 +2934,19 @@
 
             def filectxfn(repo, ctx_, path):
                 try:
+                    # Return None for removed files.
+                    if path in wctx.removed():
+                        return None
+
                     # If the file being considered is not amongst the files
-                    # to be amended, we should return the file context from the
+                    # to be amended, we should use the file context from the
                     # old changeset. This avoids issues when only some files in
                     # the working copy are being amended but there are also
                     # changes to other files from the old changeset.
-                    if path not in filestoamend:
-                        return old.filectx(path)
-
-                    # Return None for removed files.
-                    if path in wctx.removed():
-                        return None
-
-                    fctx = wctx[path]
+                    if path in filestoamend:
+                        fctx = wctx[path]
+                    else:
+                        fctx = old.filectx(path)
                     flags = fctx.flags()
                     mctx = context.memfilectx(
                         repo,
--- a/tests/test-copies-in-changeset.t	Fri Mar 18 21:37:22 2022 -0700
+++ b/tests/test-copies-in-changeset.t	Fri Mar 18 21:15:54 2022 -0700
@@ -324,7 +324,7 @@
   $ hg ci --amend -m 'new description'
   saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-*-amend.hg (glob)
   $ hg showcopies
-  a -> l (no-extra !)
+  a -> l
   $ cd ..
 
 Test rebasing a commit with copy information