On Fri, Jan 25, 2013 at 12:32 PM, Paul Burba <ptburba_at_gmail.com> wrote:
> On Fri, Jan 25, 2013 at 12:11 PM, Paul Burba <ptburba_at_gmail.com> wrote:
>> On Thu, Jan 24, 2013 at 5:16 PM, Julian Foad <julianfoad_at_btopenworld.com> wrote:
>>> Summary: I plan to make 'svn merge' act on --accept=theirs|mine|etc. per file, rather than (as it does now) postponing all conflicts until after the whole merge and then resolving them.
>>>
>>>
>>> I have been investigating the way "--accept=foo" resolves conflicts, for blocker issue #4238 "merge -cA,B with --accept option aborts if rA conflicts" [1]. Postponing all resolution until the end of the whole merge (as we do now) is not good enough in this scenario. A similar scenario can occur during an automatic merge when the merge code internally decides to do a multi-revision-range merge.
>>
>> Minor nit: The internal split you speak of here isn't tied solely to
>> automatic merges. Cherry-picks can provoke that behavior just as
>> easily. For example:
>>
>> svn merge SRC TGT -cY
>> svn merge SRC TGT -rX:Z
>>
>> Where X < (Y-1) < Y < Z
>>
>> The second merge will be split into two parts: X:(Y-1), Y:Z
>>
>> I mention this only because the issue #4238 scenario of
>>
>> svn merge -cM,N
>>
>> Could just as easily be,
>>
>> svn merge -rW:X,Y:Z
>>
>> and either one of those ranges could be split into multiple merges.
>>
>>> We need to be able to resolve conflicts at least after each phase (revision range) of merge.
>>>
>>> For the manual '-cA,B' example the client ('svn') could simply call svn_client_merge once for each specified revision or range, resolving any conflicts after each. That is not feasible for the ranges decided internally during an automatic merge, because the client doesn't have a way to discover those ranges in advance. (And the merge code architecture is such that it discovers those ranges incrementally as it goes.)
>>
>> I just realized another problem for automatic (implied) or cherry-pick
>> (explicit) ranges in which a given range is split into multiple merges
>> under the covers: We record mergeinfo based on the requested merge
>> range, even if only part of the range is merged before we hit a
>> conflict and abort. This prevents the remainder of the range from
>> being merged if the conflict is resolved and the merge repeated.
>>
>> A simple example (borrowing the WC from the issue #4238 test prior to
>> the merge):
>>
>> ### Copy a file:
>>
>>>svn copy iota_at_1 iota-new
>> A iota-new
>>
>>>svn ci -m "" -q
>>
>> ### Merge a rev from the middle of all eligible revs and commit:
>>
>>>svn mergeinfo --show-revs eligible ^^/iota iota-new
>> r2
>> r3
>> r4
>>
>>>svn merge ^^/iota iota-new -c3 --accept theirs-conflict
>> --- Merging r3 into 'iota-new':
>> C iota-new
>> --- Recording mergeinfo for merge of r3 into 'iota-new':
>> U iota-new
>> Summary of conflicts:
>> Text conflicts: 1
>> Resolved conflicted state of 'iota-new'
>>
>>>svn ci -m ""
>> Sending iota-new
>> Transmitting file data .
>> Committed revision 6.
>>
>>>svn up -q
>>
>> ### The expected mergeinfo:
>>
>>>svn pl -vR
>> Properties on 'iota-new':
>> svn:mergeinfo
>> /iota:3
>>
>> ### Do a merge which covers a range of revs which the previously merged
>> ### rev is a proper subset of (nothing new here, this is just the "internally
>> ### decided" range split Julian spoke of.
>>
>>>svn merge ^^/iota iota-new
>> --- Merging r2 into 'iota-new':
>> C iota-new
>> --- Recording mergeinfo for merge of r2 through r6 into 'iota-new':
>> U iota-new
>> Summary of conflicts:
>> Text conflicts: 1
>> Conflict discovered in file 'iota-new'.
>> Select: (p) postpone, (df) diff-full, (e) edit, (m) merge,
>> (mc) mine-conflict, (tc) theirs-conflict, (s) show all options: p
>> ..\..\..\subversion\svn\util.c:553: (apr_err=155015)
>> ..\..\..\subversion\svn\merge-cmd.c:138: (apr_err=155015)
>> ..\..\..\subversion\libsvn_client\merge.c:11611: (apr_err=155015)
>> ..\..\..\subversion\libsvn_client\merge.c:11582: (apr_err=155015)
>> ..\..\..\subversion\libsvn_client\merge.c:9057: (apr_err=155015)
>> ..\..\..\subversion\libsvn_client\merge.c:4715: (apr_err=155015)
>> svn: E155015: One or more conflicts were produced while merging r1:2 into
>> '\iota-new' --
>> resolve all conflicts and rerun the merge to apply the remaining
>> unmerged revisions
>>
>>>svn st
>> CM iota-new
>> ? iota-new.merge-left.r1
>> ? iota-new.merge-right.r2
>> ? iota-new.working
>> Summary of conflicts:
>> Text conflicts: 1
>>
>> ### Obviously we only merged r2 before things blew up, but
>> ### not according to the resulting mergeinfo :
>>
>>>svn pl -vR
>> Properties on 'iota-new':
>> svn:mergeinfo
>> /iota:2-6
>>
>> ### Obviously this means if we resolve the conflict...
>>
>>>svn resolved -R .
>> Resolved conflicted state of 'iota-new'
>>
>> ### ...and repeat the merge, then r4 stubbornly remains un-merged:
>>
>>>svn merge ^^/iota iota-new
>>
>> ### Even if we explicitly ask for r4:
>>
>>>svn merge ^^/iota iota-new -c4
>>
>> ### We have to disable merge tracking and use a cherry-pick to DTRT
>> ### (i.e. get r4 applied) which is, to put it charitably, less than optimal:
>>
>>>svn merge ^^/iota iota-new -c4 --ignore-ancestry
>> --- Merging r4 into 'iota-new':
>> C iota-new
>> Summary of conflicts:
>> Text conflicts: 1
>> Conflict discovered in file 'iota-new'.
>> Select: (p) postpone, (df) diff-full, (e) edit, (m) merge,
>> (mc) mine-conflict, (tc) theirs-conflict, (s) show all options: p
>>
>>>
>>
>> FWIW this isn't a regression from 1.7. I'll file an issue and add a
>> test shortly.
>
> Issue: http://subversion.tigris.org/issues/show_bug.cgi?id=4306
> Test: http://svn.apache.org/viewvc?view=revision&revision=1438602
Turns out only file merges were susceptible (which explains why we
haven't had lots of complaints about this previously). Fixed in
http://svn.apache.org/viewvc?view=revision&revision=1438683
--
Paul T. Burba
CollabNet, Inc. -- www.collab.net -- Enterprise Cloud Development
Skype: ptburba
Received on 2013-01-25 21:21:47 CET