[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: new conflict callback API

From: Julian Foad <julianfoad_at_btopenworld.com>
Date: Wed, 23 May 2012 13:47:04 +0100 (BST)

Hi Stefan.

I'm just about starting to get the idea that I think you're talking about, but I'm still having a hard time seeing how a state machine in the library would need more than one state transition for any chosen resolution, or why it would need to control information-display requests.

I think it would help if we could see how these ideas work, step by step, for some non-trivial use case.

Stefan Sperling wrote:
> On Thu, May 17, 2012 at 11:09:48AM +0100, Julian Foad wrote:
>>  Let's take a closer look at what the user (through the client
>>  application) needs to be able to do.
> Thanks for your comments. I think we're about to each consensus
> on this. We just have a slight misunderstanding to clear up, and
> need to agree on whether the main resolution logic should be
> implemented by clients themselves, or in the library.
>>>  /* The set of all conflict choices for all kinds of conflicts. */
>>>  enum svn_client_resolution_choice_t {
>>>    svn_client_resolution_choice_theirs_conflict,
>>>    svn_client_resolution_choice_mine_conflict,
>> "theirs-conflict" and "mine-conflict" are good options for an
>> interactive 3-way merge tool to offer the user while showing the user
>> which sections of the file do have conflicts and which don't.  It's not
>> an option I'd like to choose outside a 3-way merge tool.  In terms of
>> tree conflicts, the same applies: I'd only be comfortable with this
>> option when it's presented in a 3-way directory-merge window that's
>> showing me which children are conflicting and which are not.  After
>> pressing this button in the 3-way (file or dir) merge tool, I wouldn't
>> expect the tool to immediately close and Subversion library to
>> immediately finalize my choice, instead I'd expect to be able to review
>> and edit the result and then finally confirm.
> Agreed.

You agree that those options shouldn't be found outside a 3-way merge tool that's displaying the conflicts in question?  So what are they doing in this list?

>>>    [...]
>>>    svn_client_resolution_choice_diff_full,
>> "diff-full" isn't a resolution choice, it's the user asking to see
>> more information before choosing.
> There seems to be a slight misunderstanding here.
> I don't intend the values of this enum to represent "final"
> resolution choices.

OK, I'm glad to learn this was partly me misunderstanding your intentions.

> Rather, each choice allows the conflict
> resolver to make progress in the resolution process. Some
> options may result in a "final" resolution state where the
> conflict is resolved. Other options may simply allow the user
> to request information or carry out other actions that are
> in the set of permitted options of the current resolver state.

Perhaps you could give an example of one part of this state machine, that's sufficiently complex that a state machine is a useful way of achieving it.  What's an example of when an information-display request such as "show me a diff between base and theirs" needs to be tied into the state machine?

> In technical terms, I think of the new resolver as a state machine,
> where each conflict choice triggers a state transition. The set of
> final states may either resolve the conflict or postpone resolution.
> Maybe we need a different name than svn_client_resolution_choice_t to
> avoid this misunderstanding? Note that it isn't called
> svn_client_final_resolution_choice_t :)
> Wherever you say "not a resolution" below, my above response applies.
>> We need to get away from the mode
>> of operation of the existing interactive resolver loop where the user
>> interacts my means of question-and-answer.  That question-and-answer
>> loop should be in the presentation layer (svn), not in the library.
> Here I disagree. The loop we have today is a small state machine
> that runs within the 'svn' client. We need this loop in one form
> or another, either in the client or in the library. Today it is in
> the client, so each client has to reimplement this loop with a set of
> possible states and transitions. You seem to favour this model but I
> don't see any advantage in keeping it.
> I want to put as many aspects of the resolution process as possible
> into the library so that each client uses the same state machine to
> resolve conflicts. This makes it easier to work with several clients
> simultaneously because terminology and logic will be the same for all
> clients during the conflict resolution process. And it allows clients
> to implement conflict resolution dialogs with much less effort.
>>>    svn_client_resolution_choice_edit_file,
>> "edit-file" isn't a resolution choice that the library can then
>> "execute" in a black-box manner.  Instead, the user wants the GUI to
>> help him/her prepare the final result with the aid of an editor, and
>> then the user may choose to confirm that resulting file as the final
>> resolved result.  The resolution needs to be communicated to the Svn
>> lib in the form of a file, not "he chose 'edit' as the resolution".
> Yes, the library will receive a file.
> However, it will also have an internal resolver state that makes the
> acceptance of such a file a valid resolution choice. For example, it
> probably makes no sense to provide a file when resolving a directory
> vs. directory tree conflict. If the resolver knows the set of valid
> options for the conflict in question, it can reject such invalid input
> from clients. Your opinion seems to be that the decision about whether
> a choice is valid or not belongs into the client. I say that leads to
> unnecessary complexity and variance between client implementations.
>>>    [...]
>>>    svn_client_resolution_choice_scan_log_for_moves,
>> Not a resolution.  Instead, there should be a way for the GUI to get the
>> suggestion(s) of what moves might be applicable, and to offer those as
>> suggestions to the user, and then for the user to select maybe one of
>> the choices or maybe another resolution.
> Again, this is a good description of what I intend to do. It seems
> we're on the same page but you misunderstood my intentions.
>>>    svn_client_resolution_choice_specify_local_target_for_incoming_move,
>>>    svn_client_resolution_choice_merge_edits_into_local_file,
>>>    [...]
>>>  };
>> A GUI wants the user to be in control.  The first obvious thing is the
>> user should be able to select which file/dir to resolve next.  If the
>> GUI wants to have a button that enters a loop that iterates over all
>> conflicts sequentially, that's it's business and we should make it
>> possible to do that, but we should not implement this loop in the Svn
>> lib.
> I realised after comments from Bert and Mark that we need to run the
> main loop of the resolution process within the client, not within the
> library. So I've ditched the callback-table idea in favour of a set of
> functions that receive a resolver state object which is opaque to the
> client (I'll elaborate on that in a different post). This way, the library
> can keep state and reject invalid or nonsense choices it receives
> from the client, and clients are in control of the overall flow.
>> The overall process the user goes through to resolve a particular
>> conflict needs to include a reviewing phase, an editing phase, and
>> finally a confirmation that the result is as the user wants it.  How
>> does this fit with the idea of there being a point where the user
>> chooses a resolution such as "choose edit-file"?
> It fits because "choose edit-file" is just a state transition,
> rather than a final choice.
>> While in the reviewing phase of resolving any particular conflict, the
>> user should be able to bring up, on demand, a diff between 'mine' and
>> 'base' or 'mine:theirs' or 'base:theirs' or whatever he/she chooses,
>> jump to the location in their editor where the next text conflict
>> occurs, review the log messages on the source and/or target branch,
>> and so on.  And all of this in parallel, in separate, non-modal
>> windows.
> Indeed, clients should be allowed to do all that. Do you think we even
> need to design the API such that clients can resolve multiple conflicts
> in parallel?


> Or should we restrict clients to handle one conflict at
> a time?


> This restriction might make it easier to implement the resolver.
> We could also make this restriction initially and lift it later.

You can only lift such a restriction if the initial architecture was designed for parallel resolving.

>> To enable this, the application needs access to the metadata
>> [...] like this:
>>    svn_node_kind_t node_kind;
>>    svn_wc_conflict_kind_t kind;
>>    svn_wc_conflict_action_t action;
>>    svn_wc_conflict_reason_t reason;
>>    svn_wc_operation_t operation;
>>    const svn_wc_conflict_version_t *src_left_version;
>>    const svn_wc_conflict_version_t *src_right_version;
>> ... which is an extract from svn_wc_conflict_description2_t.[...]
> This is the kind of data the resolver can use to determine a set of
> valid states and transitions for conflict resolution.
> The client will drive the state machine so just giving it an
> svn_wc_conflict_description2_t struct an insufficient client<->library
> interface. At the very least, we must also force clients to pass back
> in any state the resolver needs to keep.
> Does all that make sense?

Well, I'm not convinced yet.

- Julian
Received on 2012-05-23 14:47:41 CEST

This is an archived mail posted to the Subversion Dev mailing list.