I'm investigating a discrepancy that shows up, when 'symmetric merge' is 
enabled [1], in the notifications printed by some merges.  Merge_tests 78 fails 
because the expected notification for the last merge is:

--- Merging r6 through r9 into 'H_COPY':
U    H_COPY/psi
D    H_COPY/nu
--- Recording mergeinfo for merge of r6 through r9 into 'H_COPY':
 U   H_COPY

but the first line of that changes to:

--- Merging r7 through r9 into 'H_COPY':

while the rest stays the same.  In this instance the difference is probably 
harmless since r6 is a no-op in the merge source, but we need to check whether 
this is a symptom of a wider problem.


NEW TEST FOR THIS ISSUE

I have simplified the recipe into a new test, merge_tests-130 in 
the attached patch [2].  I removed the '--force' option, and this changes 
things such that the merge prints a separate notification for the subtree.  
Also 
in that patch are some debug prints in the merge code which help to 
trace the source of the problem.  A diagram of the test scenario:

  #                        merge -c4 A/D/H/nu@4 H_COPY/nu
  #                        |  merge A/D/H H_COPY
  #                        |  |
  # A/D/H      A---------------
  #     +-psi  +---------M-----
  #     +-nu     A---M-D
  # H_COPY         C----------G
  #     +-psi      +----------+
  #     +-nu       +-------G--+
  #            1 2 3 4 5 6 wc wc
  #
  # Key: Add Mod Del Copy merGe

The difference in outputs ('-': existing 1.7 merge, '+': symmetric merge):

 I: CMD: svn merge ^/A/D/H H_COPY
 I: DBG: merge.c:8568: 1: ...130/H_COPY: 3-6
 I: DBG: merge.c:8568: 1: .../H_COPY/nu: 3,5-6
 I: DBG: merge.c:8568: 2: ...130/H_COPY: 3-6
 I: DBG: merge.c:8568: 2: .../H_COPY/nu: 3,5-6
 I: DBG: merge.c:8568: 3: ...130/H_COPY: 3-6
-I: DBG: merge.c:8568: 3: .../H_COPY/nu: 3-6
+I: DBG: merge.c:8568: 3: .../H_COPY/nu: 3,5-6
-I: --- Merging r3 through r6 into 'H_COPY':
+I: --- Merging r4 through r6 into 'H_COPY':
 I: U    H_COPY/psi
-I: --- Merging r3 through r6 into 'H_COPY/nu':
+I: --- Merging r5 through r6 into 'H_COPY/nu':
 I:    C H_COPY/nu
 I: --- Recording mergeinfo for merge of r3 through r6 into 'H_COPY':
 I:  U   H_COPY
 I: --- Recording mergeinfo for merge of r3 through r6 into 'H_COPY/nu':
 I:  G   H_COPY/nu
 I: --- Eliding mergeinfo from 'H_COPY/nu':
 I:  U   H_COPY/nu
 I: Summary of conflicts:
 I:   Tree conflicts: 1

The immediate cause of the discrepancy is that the symmetric merge code 
passes the YCA revision as the beginning of the range to be merged, 
whereas the existing merge code passes revision '1' as the beginning of 
the range to be merged.  At the beginning of the main loop in do_merge():

- source = {loc1 = "/A/D/H@1", loc2 = "/A/D/H@6", ancestral = TRUE}
+ source = {loc1 = "/A/D/H@2", loc2 = "/A/D/H@6", ancestral = TRUE}

The underlying problem -- the reason why the merge code doesn't resolve these 
two requests to the same result -- is deeper, involving the function 
fix_deleted_subtree_ranges().  That function yields

  (child 'H_COPY/nu')->remaining_ranges = 3-6

for the 1.7 merge and

  (child 'H_COPY/nu')->remaining_ranges = 3,5-6

for the symmetric merge.

Revision 4 has already been merged to 'H_COPY/nu', so it should not be merged 
again; but that doesn't mean 'remaining_ranges = 3-6' is wrong.  
fix_deleted_subtree_ranges() is designed to set a subtree's remaining range to 
match its parent's remaining range if the subtree doesn't need a separate 
editor drive.  The function appears to be concluding in the first case that the 
subtree doesn't need a separate editor drive (since, over the range 3-6, the 
net result is simply to delete the subtree), but in the second case that it 
does and should be split into two sub-ranges.

I'm not sure whether one of those conclusions is right and the other wrong; 
maybe both are OK.  I'm not sure why there are two different conclusions.


TREE CONFLICT

Another issue I have identified here is that, in either case, a tree conflict 
is flagged unnecessarily on 'nu'.  (That doesn't happen in merge_tests-78 
because that test passes the '--force' flag.)

In the 1.7 case, the merge reports that it is merging 'r3 through r6', and the 
conflict details are reported as:

  $ svn info H_COPY/nu
  Tree conflict: local edit, incoming delete upon merge
    Source  left: (file) ^/A/D/H/nu@1
    Source right: (file) ^/A/D/H/nu@6

First, we notice that the reported 'left' and 'right' details don't match up 
with the description as an incoming 'delete'.  I recall that's a long-standing 
error in the conflict reporting.

The working file to be deleted ('H_COPY/nu' with r4 merged in to it) has 
content that doesn't match the expected pre-delete content (A/D/H/nu@2, because 
the revs to be merged are 3-6).  I haven't checked the detection code yet, but 
if that's why the conflict is flagged, then clearly the tree-conflict logic 
that says 'the content should match that at the beginning of the range being 
merged' is incompatible with the logic of fix_deleted_subtree_ranges() which 
says 'there is no need to calculate the exact ranges to be merged if the end 
result is just a delete'.

In the symmetric merge case, the merge reports that it is merging 'r5 through 
r6', and the conflict details are:

  Tree conflict: local edit, incoming delete upon merge
    Source  left: (file) ^/A/D/H/nu@2
    Source right: (file) ^/A/D/H/nu@6

I don't know why that's flagging a conflict there -- do we flag a conflict just 
because it has local mod, regardless that it may have the expected content?


CONCLUSIONS SO FAR


  * There's a deficiency in fix_deleted_subtree_ranges() -- it should at least 
give consistent results with these two different input ranges.

  * As a temporary or diagnostic measure we might be able to make 'symmetric 
merge' give the same result by making it pass the oldest possible revision (1) 
instead of the YCA revision (2) as the beginning of the range to consider.

  * There's a deficiency in conflict detection.


I will continue to investigate all of this, but any assistance is very welcome.

- Julian

[1] Patch to enable symmetric merge: attachment 'use-symmetric-merge-1.patch'.

[2] New test and debug prints: attachment 'deleted-subtree-ranges-1.patch'.



--
Certified & Supported Apache Subversion Downloads: 
http://www.wandisco.com/subversion/download

Attachment: deleted-subtree-ranges-1.patch
Description: Binary data

Attachment: use-symmetric-merge-1.patch
Description: Binary data

Reply via email to