You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Julian Foad <ju...@btopenworld.com> on 2013/01/24 23:16:16 UTC

[RFC] Run the conflict resolver callback per file during merge - issue #4238

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.


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 suppose the client could run the merge, let the merge abort if it finds any conflicts during a phase, resolve those conflicts, and then run the same merge again, repeating until the merge is complete.  That may work if the merge code can be run again and again... but it isn't set up to do so in general.  (For one thing, local mods aren't tolerated in all cases, and obviously there will be local mods after the first phase has run.  I bet there would be other problems too.)

I think a good enough solution for 1.8 is this:

  * With --accept=postpone, if any conflicts are raised during a merge phase (one revision range), then abort the merge after that phase.  (The details are not relevant to this mail thread.)

  * Otherwise, the user requested a specific conflict resolution.  At the moment, we run the merge with a per-node resolver callback installed that always chooses 'postpone' but also collects a list of the conflicted paths, and then we run 'resolve' on those paths afterwards.  Instead, let 
the resolver callback be active during the merge, resolving each 
conflict on a node immediately after that conflict has been raised, according to '--accept'.

  * By resolving a conflict so soon, we can avoid notifying the merge result as 'C' for conflict and instead notify 'U' or 'G' for that node, and avoid "Resolved conflict on 'foo'" lines.  I think that is better.

  * After the merge, there might still be some postponed conflicts, depending on whether the implementation of the chosen --accept was capable of handling every conflict that occurred.  We might want to consider doing something like running the interactive resolver afterwards if this happens, but I think not.

The main alternative I can think of to this plan would be to design a way to store multiple 
conflicts (of the same kind) per node and so be able to postpone all conflicts from multiple phases of merge.  We have decided before that that
 is too difficult and I still think so.

So, can you see any problems with the above approach?

I think we were doing this at one stage during development.  I assume we stopped because (a) for interactive resolution, postponing that stage until after the merge avoids network timeouts due to waiting for the user; and (b) we wanted to test the ability to postpone all conflicts and/or there seemed to be no reason to make the '--accept=' case work differently from the interactive case.

- Julian


[1] <http://subversion.tigris.org/issues/show_bug.cgi?id=4238>

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


Re: [RFC] Run the conflict resolver callback per file during merge - issue #4238

Posted by Julian Foad <ju...@btopenworld.com>.
I (Julian Foad) 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 think a good enough solution for 1.8 is this:
[...]
>   * [...] let the resolver callback be active during the merge, resolving each 
> conflict on a node immediately after that conflict has been raised, according to 
> '--accept'.

A note:

The issue can only occur for 'merge', and never for 'update' or 'switch' because those never need a multi-revision-range merge.

Another thought:

This solution deliberately leaves interactive resolution as a separate case.  We do need to ensure that there is some workable solution available for interactive users hitting the same case (the problem case is: two successive changes to the same node, that both conflict).

Ultimately I can't think of any alternative to running the merge one phase (rev range) at a time, resolving any conflicts produced during that phase at the end of that phase.  When we achieve that, then the --accept=theirs kinds of resolution might as well work the same way, but I don't see us achieving that before 1.8, so I think we'll do something cruder; not sure what.

- Julian

Re: [RFC] Run the conflict resolver callback per file during merge - issue #4238

Posted by Paul Burba <pt...@gmail.com>.
On Fri, Jan 25, 2013 at 12:32 PM, Paul Burba <pt...@gmail.com> wrote:
> On Fri, Jan 25, 2013 at 12:11 PM, Paul Burba <pt...@gmail.com> wrote:
>> On Thu, Jan 24, 2013 at 5:16 PM, Julian Foad <ju...@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@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

Re: [RFC] Run the conflict resolver callback per file during merge - issue #4238

Posted by Paul Burba <pt...@gmail.com>.
On Fri, Jan 25, 2013 at 12:11 PM, Paul Burba <pt...@gmail.com> wrote:
> On Thu, Jan 24, 2013 at 5:16 PM, Julian Foad <ju...@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@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

-- 
Paul T. Burba
CollabNet, Inc. -- www.collab.net -- Enterprise Cloud Development
Skype: ptburba

Re: [RFC] Run the conflict resolver callback per file during merge - issue #4238

Posted by Paul Burba <pt...@gmail.com>.
On Thu, Jan 24, 2013 at 5:16 PM, Julian Foad <ju...@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@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.

> I suppose the client could run the merge, let the merge abort if it finds any conflicts during a phase, resolve those conflicts, and then run the same merge again, repeating until the merge is complete.  That may work if the merge code can be run again and again... but it isn't set up to do so in general.  (For one thing, local mods aren't tolerated in all cases, and obviously there will be local mods after the first phase has run.  I bet there would be other problems too.)

Look no further than the above example :-\

> I think a good enough solution for 1.8 is this:
>
>   * With --accept=postpone, if any conflicts are raised during a merge phase (one revision range), then abort the merge after that phase.  (The details are not relevant to this mail thread.)
>
>   * Otherwise, the user requested a specific conflict resolution.  At the moment, we run the merge with a per-node resolver callback installed that always chooses 'postpone' but also collects a list of the conflicted paths, and then we run 'resolve' on those paths afterwards.  Instead, let
> the resolver callback be active during the merge, resolving each
> conflict on a node immediately after that conflict has been raised, according to '--accept'.
>
>   * By resolving a conflict so soon, we can avoid notifying the merge result as 'C' for conflict and instead notify 'U' or 'G' for that node, and avoid "Resolved conflict on 'foo'" lines.  I think that is better.
>
>   * After the merge, there might still be some postponed conflicts, depending on whether the implementation of the chosen --accept was capable of handling every conflict that occurred.  We might want to consider doing something like running the interactive resolver afterwards if this happens, but I think not.
>
> The main alternative I can think of to this plan would be to design a way to store multiple
> conflicts (of the same kind) per node and so be able to postpone all conflicts from multiple phases of merge.  We have decided before that that
>  is too difficult and I still think so.
>
> So, can you see any problems with the above approach?

Other than noted above no.

-- 
Paul T. Burba
CollabNet, Inc. -- www.collab.net -- Enterprise Cloud Development
Skype: ptburba

> I think we were doing this at one stage during development.  I assume we stopped because (a) for interactive resolution, postponing that stage until after the merge avoids network timeouts due to waiting for the user; and (b) we wanted to test the ability to postpone all conflicts and/or there seemed to be no reason to make the '--accept=' case work differently from the interactive case.
>
> - Julian
>
>
> [1] <http://subversion.tigris.org/issues/show_bug.cgi?id=4238>
>
> --
> Certified & Supported Apache Subversion Downloads: http://www.wandisco.com/subversion/download

Re: [RFC] Run the conflict resolver callback per file during merge - issue #4238

Posted by Julian Foad <ju...@btopenworld.com>.
I (Julian Foad) wrote on 2012-01-25:

> Stefan Sperling wrote:
>>  I filed the issue. I think I had in mind that we'd store multiple
>>  conflicts, but I'm not quite sure.
>> 
>>  I agree with your plans to deal with the non-interactive --accept case.

In r1440193 I did that, closing issue #4238.

>>  I have one concern about the interactive case where no --accept option
>>  was passed, which we might want to consider addressing as well for 1.8.
>> 
>>  Currently, 'svn merge' errors out as follows if one of the ranges 
>> merged  in a multi-range merge conflicts.
> ...
>>  That's fine and expected. It is the same as the --accept=postpone
>>  behaviour you are proposing.
>> 
>>  But it seems what's missing is to continue the merge in case no
>>  conflicts are left after the resolver returns. Consider:
>> 
>>    $ svn merge -c3,4 ^/trunk 
>>    --- Merging r3 into '.':
>>    C    alpha
> ...
>>    Conflict discovered in file 'alpha'.
> ...
>>    Select: (p) postpone, (df) diff-full, (e) edit, (m) merge, (r) resolved,
>>            (mc) mine-conflict, (tc) theirs-conflict, (s) show all options: r
>>    Resolved conflicted state of 'alpha'
> ...
>>    svn: E155015: One or more conflicts were produced while merging r2:3 into
>>    '/tmp/svn-sandbox/branch' --
>>    resolve all conflicts and rerun the merge to apply the remaining
>>    unmerged revisions
>> 
>>  So the conflict has been resolved, but 'svn merge' stops anyway.
>>  I think it should continue merging further ranges instead.
>> 
>>  I don't think we should continue the merge in case any conflicts are
>>  left in the working copy, of course
> 
> OK, that all sounds good.  I'll try to make it happen.

I'll tackle that next.

- Julian

Re: [RFC] Run the conflict resolver callback per file during merge - issue #4238

Posted by Julian Foad <ju...@btopenworld.com>.
Stefan Sperling wrote:

> I filed the issue. I think I had in mind that we'd store multiple
> conflicts, but I'm not quite sure.
> 
> I agree with your plans to deal with the non-interactive --accept case.
> 
> I have one concern about the interactive case where no --accept option
> was passed, which we might want to consider addressing as well for 1.8.
> 
> Currently, 'svn merge' errors out as follows if one of the ranges merged
> in a multi-range merge conflicts.
...
> That's fine and expected. It is the same as the --accept=postpone
> behaviour you are proposing.
> 
> But it seems what's missing is to continue the merge in case no
> conflicts are left after the resolver returns. Consider:
> 
>   $ svn merge -c3,4 ^/trunk 
>   --- Merging r3 into '.':
>   C    alpha
...
>   Conflict discovered in file 'alpha'.
...
>   Select: (p) postpone, (df) diff-full, (e) edit, (m) merge, (r) resolved,
>           (mc) mine-conflict, (tc) theirs-conflict, (s) show all options: r
>   Resolved conflicted state of 'alpha'
...
>   svn: E155015: One or more conflicts were produced while merging r2:3 into
>   '/tmp/svn-sandbox/branch' --
>   resolve all conflicts and rerun the merge to apply the remaining
>   unmerged revisions
> 
> So the conflict has been resolved, but 'svn merge' stops anyway.
> I think it should continue merging further ranges instead.
> 
> I don't think we should continue the merge in case any conflicts are
> left in the working copy, of course

OK, that all sounds good.  I'll try to make it happen.

- Julian

Re: [RFC] Run the conflict resolver callback per file during merge - issue #4238

Posted by Stefan Sperling <st...@elego.de>.
On Thu, Jan 24, 2013 at 10:16:16PM +0000, Julian Foad 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.
> 
> 
> We need to be able to resolve conflicts at least after each phase (revision range) of merge.

I filed the issue. I think I had in mind that we'd store multiple
conflicts, but I'm not quite sure.

I agree with your plans to deal with the non-interactive --accept case.

I have one concern about the interactive case where no --accept option
was passed, which we might want to consider addressing as well for 1.8.

Currently, 'svn merge' errors out as follows if one of the ranges merged
in a multi-range merge conflicts.

  $ svn merge -c3,4 ^/trunk
  --- Merging r3 into '.':
  C    alpha
  --- Recording mergeinfo for merge of r3 into '.':
   U   .
  Summary of conflicts:
    Text conflicts: 1
  Conflict discovered in file 'alpha'.
  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/libsvn_client/merge.c:10904: (apr_err=155015)
  subversion/libsvn_client/merge.c:10868: (apr_err=155015)
  subversion/libsvn_client/merge.c:9071: (apr_err=155015)
  subversion/libsvn_client/merge.c:8763: (apr_err=155015)
  subversion/libsvn_client/merge.c:4714: (apr_err=155015)
  svn: E155015: One or more conflicts were produced while merging r2:3 into
  '/tmp/svn-sandbox/branch' --
  resolve all conflicts and rerun the merge to apply the remaining
  unmerged revisions

That's fine and expected. It is the same as the --accept=postpone
behaviour you are proposing.

But it seems what's missing is to continue the merge in case no
conflicts are left after the resolver returns. Consider:

  $ svn merge -c3,4 ^/trunk 
  --- Merging r3 into '.':
  C    alpha
  --- Recording mergeinfo for merge of r3 into '.':
   U   .
  Summary of conflicts:
    Text conflicts: 1
  Conflict discovered in file 'alpha'.
  Select: (p) postpone, (df) diff-full, (e) edit, (m) merge,
          (mc) mine-conflict, (tc) theirs-conflict, (s) show all options: m
  Merging 'alpha'.
  Conflicting section found during merge:
  (1) their version (at line 1)         |(2) your version (at line 1)          
  --------------------------------------+--------------------------------------
  foo                                   |moo                                   
  --------------------------------------+--------------------------------------
  Select: (1) use their version, (2) use your version,
          (e1) edit their version and use the result,
          (e2) edit your version and use the result,
          (eb) edit both versions and use the result,
          (p) postpone this conflicting section leaving conflict markers,
          (a) abort file merge and return to main menu: 2
  Merge of 'alpha' completed.
  Select: (p) postpone, (df) diff-full, (e) edit, (m) merge, (r) resolved,
          (mc) mine-conflict, (tc) theirs-conflict, (s) show all options: r
  Resolved conflicted state of 'alpha'
  subversion/svn/util.c:553: (apr_err=155015)
  subversion/libsvn_client/merge.c:10904: (apr_err=155015)
  subversion/libsvn_client/merge.c:10868: (apr_err=155015)
  subversion/libsvn_client/merge.c:9071: (apr_err=155015)
  subversion/libsvn_client/merge.c:8763: (apr_err=155015)
  subversion/libsvn_client/merge.c:4714: (apr_err=155015)
  svn: E155015: One or more conflicts were produced while merging r2:3 into
  '/tmp/svn-sandbox/branch' --
  resolve all conflicts and rerun the merge to apply the remaining
  unmerged revisions

So the conflict has been resolved, but 'svn merge' stops anyway.
I think it should continue merging further ranges instead.

I don't think we should continue the merge in case any conflicts are
left in the working copy, of course.