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

Re: [RFC] v2 Tree conflict resolver spec.

From: Daniel Näslund <daniel_at_longitudo.com>
Date: Mon, 8 Feb 2010 15:55:10 +0100

On Sun, Feb 07, 2010 at 12:23:12AM +0000, Julian Foad wrote:
> Can you post an updated RFC that incorporates the responses to my and
> Stefan's comments so far?

Here it is. I've only merged some of the comments from you and Stefan.
The merge part is still rather sketchy.

[[[
Design spec for tree conflict resolution in the commandline client
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The hard part is figuring out what state the wc is in during the
different user cases.

The main difference between update/switch and merge is that we don't
have somewhere to store the incoming changes during a merge. It would be
nice if we could save a THEIRS tree.

### Saving a THEIRS file is one thing but a tree? It could be a large
### tree. On the other hand, a file can be large too...

Contents
=========
Problem definition
Requirements
Terminology
Use cases update/switch
Use cases merge
API changes
User interface

Problem definition
=========================
Users are having problems understanding how to resolve tree conflicts.
For some operations they may not know how to get back to a previous
state. They don't always know how to view the changes causing a
conflict.

Requirements
=====================
It should be easy for the user to understand why the conflict has
happened and how to resolv it.

Update, switch and merge should be reversible. That is; going back to
the former revision in the wc should restore the contents to the
original.

The solution should work for both files and dirs.

The resolver should not handle moves since we have no way to track
those. When I say handle moves I mean "do something about the other end
not affected by this conflict". We will apply give the option to apply
changes elswehere and do renames but we will leave some files behind for
the user to clean up.

### There should be a good way to view what has caused a conflict.
### Perhaps some info from 'svn info'.

The tree conflict resolver interface should be consistent with the
existing resolver. It should provide
{postpone,theirs,mine,diff}-options.

### The user should be able to run the conflict resolver at any time.
### We have to fix libsvn_wc/conflicts.c first. Not really
### specific to this feature.

Terminology
============
In this document, WORKING means the user's version, which possibly has
text, property and/or tree modifications relative to the BASE; it does
not mean the WC-NG database concept that is known as WORKING.

Use cases update/switch
========================
Since we don't know how to follow moves we just leave the half of the
operation not affected by the conflict untouched. The user can remove
it manually. Once we have editor-v2 this would work automatically.

Local add, incoming add
-------------------------
THEIRS: Put new BASE file/dir in WORKING.
MINE: Keep current WORKING file/dir.
RENAME-MINE:
        Move WORKING file/dir to <user-suggest>. Replace WORKING
        file/dir with the BASE-TARGET file/dir.
MERGE Merge BASE file1 onto WORKING file2.
        If any copyfrom info is present (i.e. at least one of the files
        was copied), the user needs to select a copyfrom source:

        WORKING file | BASE file | Options
        --------------------------------------
        has copyfrom | has copyfrom |
        Yes Yes Pick one copyfrom of 2, or none.
        Yes No Use WORKING copyfrom, or none.
        No Yes Use BASE copyfrom, or none.

Local del, incoming del
-------------------------
THEIRS: Nothing to do.
MINE: Nothing to do.
RENAME: Merge BASE-TARGET <moved>
        onto WORKING <moved>.
        ### We need the user to tell us there was a rename until
        ### editor-v2 is here. Until then <moved> must be a user
        ### suggestion.

Local del, incoming edit
-------------------------
THEIRS: Replace the deleted WORKING file/dir with edited BASE file/dir.
MINE: Keep current WORKING file/dir.
ELSEWHERE:
        Merge BASE file/dir onto WORKING <user-suggest>.
        ### editor-v2 will automatically find a move. No need for this
        ### option then?
        ### stsp: I hope to get the local move case working
        ### automatically before 1.7 release

Local edit, incoming del
--------------------------
THEIRS: Delete the file/dir from WORKING and ACTUAL.
MINE: Keep current WORKING file/dir.
MOVE-MY-MODS:
        Schedule BASE add-half for addition. Merge WORKING file/dir to
        add-half. (Must be suggested by user. We can't track add-halfs
        right now.

Use cases merge
=======================
### julianf wrote: How can we most easily implement an extension of "svn
### merge" that achieves a copyfrom-history-sensitive diff (between WC
### items) rather than an unaware diff?

Local add, incoming add
-------------------------
THEIRS: Replace WORKING with BASE. Merge START to END into WORKING.
MINE: Keep current WORKING file/dir.
RENAME-MINE:
        Move WORKING file/dir to <user-suggest>. Merge START to END into
        WORKING.

Local del, incoming del
-------------------------
THEIRS: Nothing to do.
MINE: Nothing to do.
ELSEWHERE:
        MERGE START to END from THEIRS <user-suggest> into WORKING
        <user-suggest>.
        ### This will be handled automatically when we can handle moves.

Local del, incoming edit
-------------------------
### Should we need some way to merge with copyfrom info?
THEIRS: Copy THEIRS to ACTUAL. Add to WORKING.
MINE: Nothing to do.
ELSEWHERE1:
        Merge WORKING add-half onto THEIRS file/dir. Copy THEIRS to
        WORKING delete-half.
        ### This is in case of a move with mods. The user would have to
        ### supply the path to the add-half. Editor-v2 will resolve this
        ### automatically.
ELSEWHERE2:
        Merge THEIRS file/dir onto WORKING add-half.
        ### The add-half would have to be supplied by the user.

Locale edit, incoming del
--------------------------
THEIRS: Remove WORKING file/dir.
MINE: Nothing to do.
RENAME1: Merge START to END from THEIRS add-half onto WORKING.
RENAME2: Merge START to END from WORKING file/dir onto THEIRS add-half.

API changes
==================

We have
--------
1) We already know which operations has caused the conflict. It's in
svn_wc_operation_t. In case some cases will need to differ between sw/up
and merge which I think will be the case.

2) We know which type of tree conflict svn_wc_conflict_reason_t,
                                    svn_wc_conflict_action_t

3) We have conflict choises already svn_wc_conflict_choise_t {
  svn_wc_conflict_choose_postpone
  svn_wc_conflict_choose_base, /* original version */
  svn_wc_conflict_choose_theirs_full, /* incoming version */
  svn_wc_conflict_choose_mine_full, /* own version */
  svn_wc_conflict_choose_theirs_conflict, /* incoming (for conflicted hunks) */
  svn_wc_conflict_choose_mine_conflict, /* own (for conflicted hunks) */
  svn_wc_conflict_choose_merged /* merged version */
}

4) A code structure for invoking interactive commands, displaying diffs
and choosing versions.

We need
--------
1) svn_cl__conflict_handler must use svn_wc_conflict_description2_t for
some additional tree conflict info.

2) Handle the cases we can in svn_cl__conflict_handler, let the other fall
through. (Or return svn_wc_conflict_choose_postpone). I'm thinking of
letting all dir conflicts fall through as a first step.

3) Add some choises to svn_wc_conflict_choise_t.
svn_wc_conflict_choose_{rename,elsewhere,my_moved_mods}?

4) Add calls to eb->conflict_resolver if check_tree_conflict() returns a
conflict in:
libsvn_wc/update_editor.c
  do_entry_deletion()
  add_directory()
  open_directory()
  add_file_with_history()
  open_file()

5) Create code to handle and execute the svn_wc_conflict_choise_t
choises. in libsvn_wc/update_editor.c

6) Test to verify the interactive callback. Some detection tests needs
to use the --non-interactive flag.

7) It would be nice to be able to store the THEIRS tree in the wc db
when we get a tree conflict during a merge operation.

User interface
======================

I will focus on the update stuff for files. These are the options I'm
suggesting. We need to supply paths at a couple of places. Perhaps some
bash-completion stuff would be useful. We're on the limit here of what's
a good CLI. There shouldn't be too much interactivity.

Perhaps something more than diff-full for viewing changes. Something
like what svn info ^/trunk/conflicting_path, svn info wc_path can
provide?

Local add, incoming add
-------------------------
Tree conflict discovered in 'path'
    local add, incoming add upon update
Select: (p) postpone, (df) diff-full,
        (mc) mine-conflict, (tc) theirs-conflict,
        (mr) mine-rename, (m) merge,
        (s) show all options: s

  (e) edit - change merged file in an editor
  (df) diff-full - show all changes made to merged file
  (r) resolved - accept merged version of file

  (dc) display-conflict - show all conflicts (ignoring merged version)
  (mc) mine-conflict - accept my version for all conflicts (same)
  (tc) theirs-conflict - accept their version for all conflicts (same)
  (mr) mine-rename <to-path>
                        - Move my file to <to-path> and put their
                          file at my files old place
  (m) merge - merge their file onto my file. You may be
                          asked to choose copyfrom

  (mf) mine-full - accept my version of entire file (even non-conflicts)
  (tf) theirs-full - accept their version of entire file (same)

  (p) postpone - mark the conflict to be resolved later
  (l) launch - launch external tool to resolve conflict
  (s) show all - show this list

Local del, incoming del
-------------------------
Tree conflict discovered in 'path'
    local del, incoming del upon update
Select: (p) postpone, (df) diff-full,
        (mc) mine-conflict, (tc) theirs-conflict,
        (r) rename, (m) merge,
        (s) show all options: s

  (e) edit - change merged file in an editor
  (df) diff-full - show all changes made to merged file
  (r) resolved - accept merged version of file

  (dc) display-conflict - show all conflicts (ignoring merged version)
  (mc) mine-conflict - accept my version for all conflicts (same)
  (tc) theirs-conflict - accept their version for all conflicts (same)
  (r) rename <from-path> <to-path>
                         - Move my file to <to-path> and put their
                           file at my files old place
  (m) merge - merge their file onto my file. You may be
                          asked to choose copyfrom

  (mf) mine-full - accept my version of entire file (even non-conflicts)
  (tf) theirs-full - accept their version of entire file (same)

  (p) postpone - mark the conflict to be resolved later
  (s) show all - show this list

Local del, incoming edit
--------------------------
Tree conflict discovered in 'path'
    local del, incoming edit upon update
Select: (p) postpone, (df) diff-full,
        (mc) mine-conflict, (tc) theirs-conflict,
        (me) merge-elsewhere,
        (s) show all options: s

  (e) edit - change merged file in an editor
  (df) diff-full - show all changes made to merged file
  (r) resolved - accept merged version of file

  (dc) display-conflict - show all conflicts (ignoring merged version)
  (mc) mine-conflict - accept my version for all conflicts (same)
  (tc) theirs-conflict - accept their version for all conflicts (same)
  (mr) mine-rename <to-path>
                        - Move my file to <to-path> and put their
                          file at my files old place
  (m) merge - merge their file onto my file. You may be
                          asked to choose copyfrom

  (mf) mine-full - accept my version of entire file (even non-conflicts)
  (tf) theirs-full - accept their version of entire file (same)

  (p) postpone - mark the conflict to be resolved later
  (s) show all - show this list

Local edit, incoming del
--------------------------
Tree conflict discovered in 'path'
    local edit, incoming del upon update
Select: (p) postpone, (df) diff-full,
        (mc) mine-conflict, (tc) theirs-conflict,
        (mm) mine-move-mods
        (s) show all options: s

  (e) edit - change merged file in an editor
  (df) diff-full - show all changes made to merged file
  (r) resolved - accept merged version of file

  (dc) display-conflict - show all conflicts (ignoring merged version)
  (mc) mine-conflict - accept my version for all conflicts (same)
  (tc) theirs-conflict - accept their version for all conflicts (same)
  (m) merge <their-file>- merge my file onto their file.
                          asked to choose copyfrom

  (mf) mine-full - accept my version of entire file (even non-conflicts)
  (tf) theirs-full - accept their version of entire file (same)

  (p) postpone - mark the conflict to be resolved later
  (s) show all - show this list
]]]

cheers,
Daniel
Received on 2010-02-08 15:55:51 CET

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