Patchwork D12387: amend: fix amend with copies in extras

login
register
mail settings
Submitter phabricator
Date March 19, 2022, 5:06 a.m.
Message ID <differential-rev-PHID-DREV-wdemryopld3q7gn3pcbk-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/50731/
State New
Headers show

Comments

phabricator - March 19, 2022, 5:06 a.m.
martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  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.

REPOSITORY
  rHG Mercurial

BRANCH
  stable

REVISION DETAIL
  https://phab.mercurial-scm.org/D12387

AFFECTED FILES
  mercurial/cmdutil.py
  tests/test-copies-in-changeset.t

CHANGE DETAILS




To: martinvonz, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/tests/test-copies-in-changeset.t b/tests/test-copies-in-changeset.t
--- a/tests/test-copies-in-changeset.t
+++ b/tests/test-copies-in-changeset.t
@@ -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
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -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,