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