##// END OF EJS Templates
amend: fix amending rename commit with diverged topologies (issue4405)...
Ryan McElroy -
r23071:652ab726 stable
parent child Browse files
Show More
@@ -19,9 +19,15 b' def _dirname(f):'
19 return f[:s]
19 return f[:s]
20
20
21 def _findlimit(repo, a, b):
21 def _findlimit(repo, a, b):
22 """Find the earliest revision that's an ancestor of a or b but not both,
22 """
23 Find the last revision that needs to be checked to ensure that a full
24 transitive closure for file copies can be properly calculated.
25 Generally, this means finding the earliest revision number that's an
26 ancestor of a or b but not both, except when a or b is a direct descendent
27 of the other, in which case we can return the minimum revnum of a and b.
23 None if no such revision exists.
28 None if no such revision exists.
24 """
29 """
30
25 # basic idea:
31 # basic idea:
26 # - mark a and b with different sides
32 # - mark a and b with different sides
27 # - if a parent's children are all on the same side, the parent is
33 # - if a parent's children are all on the same side, the parent is
@@ -73,7 +79,29 b' def _findlimit(repo, a, b):'
73
79
74 if not hascommonancestor:
80 if not hascommonancestor:
75 return None
81 return None
76 return limit
82
83 # Consider the following flow (see test-commit-amend.t under issue4405):
84 # 1/ File 'a0' committed
85 # 2/ File renamed from 'a0' to 'a1' in a new commit (call it 'a1')
86 # 3/ Move back to first commit
87 # 4/ Create a new commit via revert to contents of 'a1' (call it 'a1-amend')
88 # 5/ Rename file from 'a1' to 'a2' and commit --amend 'a1-msg'
89 #
90 # During the amend in step five, we will be in this state:
91 #
92 # @ 3 temporary amend commit for a1-amend
93 # |
94 # o 2 a1-amend
95 # |
96 # | o 1 a1
97 # |/
98 # o 0 a0
99 #
100 # When findlimit is called, a and b are revs 3 and 0, so limit will be 2,
101 # yet the filelog has the copy information in rev 1 and we will not look
102 # back far enough unless we also look at the a and b as candidates.
103 # This only occurs when a is a descendent of b or visa-versa.
104 return min(limit, a, b)
77
105
78 def _chain(src, dst, a, b):
106 def _chain(src, dst, a, b):
79 '''chain two sets of copies a->b'''
107 '''chain two sets of copies a->b'''
@@ -854,3 +854,61 b' Test that amend with --edit invokes edit'
854 HG: changed foo
854 HG: changed foo
855 $ hg parents --template "{desc}\n"
855 $ hg parents --template "{desc}\n"
856 editor should be invoked
856 editor should be invoked
857
858 Check for issue4405
859 -------------------
860
861 Setup the repo with a file that gets moved in a second commit.
862 $ hg init repo
863 $ cd repo
864 $ touch a0
865 $ hg add a0
866 $ hg commit -m a0
867 $ hg mv a0 a1
868 $ hg commit -m a1
869 $ hg up -q 0
870 $ hg log -G --template '{rev} {desc}'
871 o 1 a1
872 |
873 @ 0 a0
874
875
876 Now we branch the repro, but re-use the file contents, so we have a divergence
877 in the file revlog topology and the changelog topology.
878 $ hg revert --rev 1 --all
879 removing a0
880 adding a1
881 $ hg ci -qm 'a1-amend'
882 $ hg log -G --template '{rev} {desc}'
883 @ 2 a1-amend
884 |
885 | o 1 a1
886 |/
887 o 0 a0
888
889
890 The way mercurial does amends is to create a temporary commit (rev 3) and then
891 fold the new and old commits together into another commit (rev 4). During this
892 process, findlimit is called to check how far back to look for the transitive
893 closure of file copy information, but due to the divergence of the filelog
894 and changelog graph topologies, before findlimit was fixed, it returned a rev
895 which was not far enough back in this case.
896 $ hg mv a1 a2
897 $ hg status --copies --rev 0
898 A a2
899 a0
900 R a0
901 $ hg ci --amend -q
902 $ hg log -G --template '{rev} {desc}'
903 @ 4 a1-amend
904 |
905 | o 1 a1
906 |/
907 o 0 a0
908
909
910 Before the fix, the copy information was lost.
911 $ hg status --copies --rev 0
912 A a2
913 a0
914 R a0
General Comments 0
You need to be logged in to leave comments. Login now