[PATCH] amend: fix amending rename commit with obsolescence markers

Ryan McElroy rm at fb.com
Fri Oct 17 21:38:37 CDT 2014


# HG changeset patch
# User Ryan McElroy <rmcelroy at fb.com>
# Date 1413466506 25200
#      Thu Oct 16 06:35:06 2014 -0700
# Node ID 90fe3166419ec665f31cdc657a8ebe753d7f168d
# Parent  48c0b101a9de1fdbd638daa858da845cd05a6be7
amend: fix amending rename commit with obsolescence markers

This addresses the bug described in issue4405: when obsolescence markers are
enabled, amending a commit with a file move can lead to the copy information
being lost.

diff --git a/mercurial/copies.py b/mercurial/copies.py
--- a/mercurial/copies.py
+++ b/mercurial/copies.py
@@ -73,7 +73,32 @@
 
     if not hascommonancestor:
         return None
-    return limit
+
+    # Consider the following flow (tested in test-rename-amend.t):
+    # 1/ File 'a' committed
+    # 2/ File renamed from 'a' to 'b' in a new commit
+    # 3/ Commit messaged updated with amend
+    # 4/ File renamed from 'b' to 'c' and commit (2) amended
+    #
+    # When obsolescence markers are enabled, this would create a graph like:
+    # @  4 mv b c
+    # |
+    # | x  3 temporary amend commit for 60e352014901
+    # | |
+    # | x  2 change message
+    # |/
+    # | x  1 mv a b
+    # |/
+    # o  0 add a
+    #
+    # During the second amend (step 4), limit is calculated to be 3, which does
+    # not look back far enough to reconstruct the full transitive closure of the
+    # renames.
+    #
+    # In this case, a is rev 4 and b is rev 0; taking the minimum of these three
+    # ensures that we always look back far enough when we have obsolescence
+    # markers enabled.
+    return min(limit, a, b)
 
 def _chain(src, dst, a, b):
     '''chain two sets of copies a->b'''
diff --git a/tests/test-rename-amend.t b/tests/test-rename-amend.t
new file mode 100644
--- /dev/null
+++ b/tests/test-rename-amend.t
@@ -0,0 +1,37 @@
+Enable obsolescence markers
+  $ cat > obs.py << EOF
+  > import mercurial.obsolete
+  > mercurial.obsolete._enabled = True
+  > EOF
+  $ cat >> $HGRCPATH <<EOF
+  > [extensions]
+  > EOF
+  $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH
+
+Set up test repo
+  $ hg init repo
+  $ cd repo
+  $ echo a > a
+  $ hg add a
+  $ hg commit -m a
+  $ hg mv a b
+  $ hg commit -m 'mv a b'
+  $ hg st -C --change .
+  A b
+    a
+  R a
+
+Change the commit message
+  $ hg commit --amend -m 'change commit message'
+  $ hg st -C --change .
+  A b
+    a
+  R a
+
+Move again
+  $ hg mv b c
+  $ hg commit --amend -m 'mv b c'
+  $ hg st -C --change .
+  A c
+    a
+  R a


More information about the Mercurial-devel mailing list