This file describes handling of all add-vs.-add tree conflict situations
on 2010-jul-20 (previously 2010-jul-01, r959735). Maybe someone will update it
and put another date here some day, maybe not.

Add-vs.-add tree conflicts handling introduces a new meaning for
svn_wc__db_status_not_present. Apart from the usual "node deleted and
committed and parent not updated yet", a not_present BASE_NODE can also mean:
This node was intended to be added during update/switch/checkout, but there
was an unversioned obstruction in the local working copy at that path. A tree
conflict with reason == svn_wc_conflict_reason_unversioned is flagged on such
nodes. If such a tree conflict with _reason_unversioned is found on a
not_present node during update/checkout/switch, and if furthermore there is no
unversioned obstruction in the WC anymore (the user moved it away), then
complete_directory() automatically removes the tree conflict, after which the
running update/switch/checkout will pull that node in.


All add vs. add cases:
----------------------
(see a legend below)

all add-vs.-add   | incoming ADD of a           | incoming COPY of a          |
tree conflict     | file    | symlink | dir (2) | file    | symlink | dir (2) |
situations        |co up sw |co up sw |co up sw |co up sw |co up sw |co up sw |
------------------+---------+---------+---------+---------+---------+---------+
locally      file |?C*?C*?C*|?C*?C*?C*|?C+?C+?C+|?C*?C*?C*|?C*?C*?C*|?C+?C+?C+|
UNVER-    symlink |?C*?C*?C*|?C*?C*?C*|?C+?C+?C+|?C*?C*?C*|?C*?C*?C*|?C+?C+?C+|
SIONED        dir |?C*?C*?C*|?C*?C*?C*|?C+?C+?C+|?C*?C*?C*|?C*?C*?C*|?C+?C+?C+|
------------------+---------+---------+---------+---------+---------+---------+
locally      file |Ex Ex RC*|RC*RC*RC*|:( :( :( |Ex RC*RC*|RC*RC*RC*|:( :( :( |
ADDED     symlink |RC*RC*RC*|Ex Ex RC*|:( :( :( |RC*RC*RC*|Ex RC*RC*|:( :( :( |
          (2) dir |:( :( :( |:( :( :( |Ex Ex Ex |:( :( :( |:( :( :( |Ex Ex Ex |
------------------+---------+---------+---------+---------+---------+---------+
DIFFERENT    file |RC*RC*RC*|RC*RC*RC*|:( :( :( |RC*RC*RC*|RC*RC*RC*|:( :( :( |
COPY      symlink |RC*RC*RC*|RC*RC*RC*|:( :( :( |RC*RC*RC*|RC*RC*RC*|:( :( :( |
of a      (2) dir |:( :( :( |:( :( :( |AC AC AC |:( :( :( |:( :( :( |AC AC AC |
------------------+---------+---------+---------+---------+---------+---------+
IDENTICAL    file |                             |RC*Ex*RC*|         |         |
COPY of   symlink |         (see above)         |         |RC*Ex*RC*|         |
a (1)     (2) dir |                             |         |         |AC AC AC |

           
"*" The cases changed in r959735 marked with a * on their right.
"+" The cases most recently changed are marked with a + on their right.

(1) Where both local and incoming are copies and both copies are from the
exact same copyfrom URL@REV, the node kinds must also match. The colums
against incoming simple-add are identical to "different copy" and omitted.

(2) Since we can only deal with replace-by-different-kind properly after we
moved to single-db, some of these rows/columns are still ':(' or 'AC'.


In the table above, each cell shows three letter pairs for,
checkout, update, switch operations, respectively.

The letter pairs are:
  RC = tree conflict where local add/copy becomes a schedule-replace,
       i.e. status reports:
       'R     C'    -> that's why this is called 'RC'
       '      > local add, incoming add upon update|switch'
       Resolving is easy. 'svn revert' gives theirs, 'svn commit' replaces
       theirs with mine. (this is new!)

  ?C = tree conflict against locally unversioned, adds a not_present BASE
       node. Status reports
       '?     C'
       '      > local unversioned, incoming add upon update|switch'
       Resolving is easy. Just move away the obstruction and run 'update'.
       The tree conflict is removed automagically. (this is new!)

  Ex = "Existed": local add and incoming add are seen as identical, there
       will be a text/prop merge and possibly a text conflict.

  :( = svn bails with an error, interrupting the operation. The parent is
       left '!' == incomplete. Removing the obstruction and running the
       operation again fixes the node as expected.

  AC = Though a tree conflict is flagged, the node is skipped and the working
       copy is left in a state where it doesn't notice that the incoming add
       is still missing. After a revert, it is necessary to update back to an
       older revision and then again back to HEAD to restore the file.
       This is the old behaviour for all caught add-vs-add tree conflicts.
       i.e. status reports
          'A     C'
       or 'A  +  C',
          '      > local add, incoming add upon update|switch'

So "Ex Ex RC*" would mean:
 "During checkout and update, the local add is merged with the incoming add.
  During switch, an easily resolvable tree conflict is flagged.
  r959735 only changes the 'switch' behavior."

A note on checkout: It *is* possible to checkout a URL onto a working copy of
the same URL, which can have local adds scheduled. Then, checkout presumably
is like an update -- almost. Note the incoming copy columns during checkout
saying 'Ex' and 'RC' in some wrong places. That's because during checkout,
add_file() gets no copy_from info and the incoming action always looks like a
simple add. #TODO: we should discuss this non-feature.
Note that tree conflicts from a checkout wrongly say "upon update".

Notably, earlier servers provide no copy_from info to add_file() either, so
'update' then acts the same way as 'checkout' -- fails to flag same-kind tree
conflicts with local-add vs. incoming-copy, and fails to not flag conflicts on
matching copies. #TODO: we should discuss this, too.

The reasoning with 'switch' is that when 'switch' merges a local add
with an incoming add, it is "lost" in the sense that switching back wants to
simply delete that node, not re-schedule it for addition. So switch should
*always* flag tree conflicts, never merge local adds away, so that the user is
(hopefully not annoyed but) made aware of the situation.

