You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2011/04/07 12:18:28 UTC

svn commit: r1089806 - in /subversion/trunk/subversion: libsvn_wc/update_editor.c tests/cmdline/checkout_tests.py tests/cmdline/switch_tests.py tests/cmdline/tree_conflict_tests.py tests/cmdline/update_tests.py

Author: rhuijben
Date: Thu Apr  7 10:18:28 2011
New Revision: 1089806

URL: http://svn.apache.org/viewvc?rev=1089806&view=rev
Log:
Allow the update editor to proceed under instead of skip added directories
when encountering a tree conflict. This automatically resolves issue #3608.

When the tree conflict is against a local addition, a shadowed base node
will be added under it, which changes the addition in a replacement.

When the tree conflict is against an unversioned obstruction this patch
marks all the incomming nodes as deleted, because we have no way to describe
this kind of obstruction properly/in another way yet. (Design in progress)

* subversion/libsvn_wc/update_editor.c
  (add_directory): Don't skip the node and everything below when we find a
    tree conflict. When the conflict is generated against an unversioned
    node delete the new directory.

* subversion/tests/cmdline/checkout_tests.py
  (checkout_with_obstructions,
   forced_checkout_of_dir_with_file_obstructions,
   co_with_obstructing_local_adds): Update expected results.

* subversion/tests/cmdline/switch_tests.py
  (bad_intermediate_urls,
   forced_switch_failures,
   switch_with_obstructing_local_adds): Update expected results.

* subversion/tests/cmdline/tree_conflict_tests.py
  (up_add_onto_add_revert): Remove XFail marker.

* subversion/tests/cmdline/update_tests.py
  (obstructed_update_alters_wc_props,
   forced_update_failures,
   update_with_obstructing_additions): Update expected results.

Modified:
    subversion/trunk/subversion/libsvn_wc/update_editor.c
    subversion/trunk/subversion/tests/cmdline/checkout_tests.py
    subversion/trunk/subversion/tests/cmdline/switch_tests.py
    subversion/trunk/subversion/tests/cmdline/tree_conflict_tests.py
    subversion/trunk/subversion/tests/cmdline/update_tests.py

Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1089806&r1=1089805&r2=1089806&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Thu Apr  7 10:18:28 2011
@@ -2202,25 +2202,10 @@ add_directory(const char *path,
             }
         }
 
-      /* We can't properly handle add vs. add with mismatching
-       * node kinds before single db. */
-      if (local_is_non_dir)
-        {
-          db->already_notified = TRUE;
-          do_notification(eb, db->local_abspath, svn_node_dir,
-                          svn_wc_notify_update_obstruction, pool);
-          return svn_error_createf(
-                   SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
-                   _("Failed to add directory '%s': a non-directory object "
-                     "of the same name already exists"),
-                   svn_dirent_local_style(db->local_abspath,
-                                          pool));
-        }
-
       /* Do tree conflict checking if
        *  - if there is a local copy.
        *  - if this is a switch operation
-       *  - the node kinds mismatch (when single db is here)
+       *  - the node kinds mismatch
        *
        * During switch, local adds at the same path as incoming adds get
        * "lost" in that switching back to the original will no longer have the
@@ -2228,10 +2213,6 @@ add_directory(const char *path,
        *
        * Allow pulling absent/exluded/not_present nodes back in.
        *
-       * ### This code is already gearing up to single db with respect to
-       * add-vs.-add conflicts with mismatching node kinds. But before single
-       * db, we cannot deal with mismatching node kinds properly.
-       *
        * ### We would also like to be checking copyfrom infos to not flag tree
        * conflicts on two copies with identical history. But at the time of
        * writing, add_directory() does not get any copyfrom information. */
@@ -2257,6 +2238,11 @@ add_directory(const char *path,
            * conflict, so merge it with the incoming add. */
           db->add_existed = TRUE;
         }
+      else
+        {
+          /* Add the node as deleted */
+          db->shadowed = TRUE;
+        }
     }
   else if (kind != svn_node_none)
     {
@@ -2267,20 +2253,8 @@ add_directory(const char *path,
        * if unversioned obstructions are allowed. */
       if (! (kind == svn_node_dir && eb->allow_unver_obstructions))
         {
-          /* ### Instead of skipping, this should bring in the BASE node
-           * and mark some sort of obstruction-conflict. Come, o single-db! */
-          db->skip_this = TRUE;
-
-          /* If we are skipping an add, we need to tell the WC that
-           * there's a node supposed to be here which we don't have. */
-          SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db, db->local_abspath,
-                                                  db->new_relpath,
-                                                  eb->repos_root,
-                                                  eb->repos_uuid,
-                                                  *eb->target_revision,
-                                                  svn_wc__db_kind_dir,
-                                                  NULL, NULL, pool));
-          SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
+          /* Bring in the node as deleted */ /* ### Obstructed Conflict */
+          db->shadowed = TRUE;
 
           /* Mark a conflict */
           SVN_ERR(create_tree_conflict(&tree_conflict, eb,
@@ -2300,14 +2274,10 @@ add_directory(const char *path,
       SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db, db->local_abspath,
                                               tree_conflict, pool));
 
-      SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
-
-      db->skip_this = TRUE;
       db->already_notified = TRUE;
 
       do_notification(eb, db->local_abspath, svn_node_unknown,
                       svn_wc_notify_tree_conflict, pool);
-      return SVN_NO_ERROR;
     }
 
 
@@ -2329,6 +2299,12 @@ add_directory(const char *path,
     /* If there is no conflict we take over any added directory */
     SVN_ERR(svn_wc__db_temp_op_remove_working(eb->db, db->local_abspath, pool));
 
+  /* ### We can't record an unversioned obstruction yet, so 
+     ### we record a delete instead, which will allow resolving the conflict
+     ### to theirs with 'svn revert'. */
+  if (db->shadowed && db->obstruction_found)
+    SVN_ERR(svn_wc__db_temp_op_delete(eb->db, db->local_abspath, pool));
+
   /* If this add was obstructed by dir scheduled for addition without
      history let close_file() handle the notification because there
      might be properties to deal with.  If PATH was added inside a locally

Modified: subversion/trunk/subversion/tests/cmdline/checkout_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/checkout_tests.py?rev=1089806&r1=1089805&r2=1089806&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/checkout_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/checkout_tests.py Thu Apr  7 10:18:28 2011
@@ -177,6 +177,25 @@ def checkout_with_obstructions(sbox):
   expected_output = svntest.wc.State(wc_dir, {
     'iota'              : Item(status='  ', treeconflict='C'),
     'A'                 : Item(status='  ', treeconflict='C'),
+    # And the updates below the tree conflict
+    'A/D'               : Item(status='  ', treeconflict='A'),
+    'A/D/gamma'         : Item(status='  ', treeconflict='A'),
+    'A/D/G'             : Item(status='  ', treeconflict='A'),
+    'A/D/G/rho'         : Item(status='  ', treeconflict='A'),
+    'A/D/G/pi'          : Item(status='  ', treeconflict='A'),
+    'A/D/G/tau'         : Item(status='  ', treeconflict='A'),
+    'A/D/H'             : Item(status='  ', treeconflict='A'),
+    'A/D/H/chi'         : Item(status='  ', treeconflict='A'),
+    'A/D/H/omega'       : Item(status='  ', treeconflict='A'),
+    'A/D/H/psi'         : Item(status='  ', treeconflict='A'),
+    'A/B'               : Item(status='  ', treeconflict='A'),
+    'A/B/E'             : Item(status='  ', treeconflict='A'),
+    'A/B/E/beta'        : Item(status='  ', treeconflict='A'),
+    'A/B/E/alpha'       : Item(status='  ', treeconflict='A'),
+    'A/B/F'             : Item(status='  ', treeconflict='A'),
+    'A/B/lambda'        : Item(status='  ', treeconflict='A'),
+    'A/C'               : Item(status='  ', treeconflict='A'),
+    'A/mu'              : Item(status='  ', treeconflict='A'),
   })
 
   expected_disk = svntest.main.greek_state.copy()
@@ -189,13 +208,17 @@ def checkout_with_obstructions(sbox):
 
   # svn status
   expected_status = actions.get_virginal_state(wc_dir, 1)
-  expected_status.tweak('A', 'iota', status='? ', wc_rev=None,
+  expected_status.tweak('iota', status='? ', wc_rev=None,
     treeconflict='C')
+  # A is tree conflicted and obstructed
+  # Currently we record that as deleted
+  expected_status.tweak('A', status='D ', treeconflict='C')
   expected_status.tweak('A/D', 'A/D/G', 'A/D/G/rho', 'A/D/G/pi', 'A/D/G/tau',
     'A/D/H', 'A/D/H/chi', 'A/D/H/omega', 'A/D/H/psi', 'A/D/gamma', 'A/B',
     'A/B/E', 'A/B/E/beta', 'A/B/E/alpha', 'A/B/F', 'A/B/lambda', 'A/C',
-    wc_rev=None)
-  expected_status.tweak('A/mu', status='? ', wc_rev=None)
+    status='D ')
+  # A/mu exists on disk, but is deleted
+  expected_status.tweak('A/mu', status='D ')
 
   actions.run_and_verify_unquiet_status(wc_dir, expected_status)
 
@@ -203,29 +226,11 @@ def checkout_with_obstructions(sbox):
   # Now see to it that we can recover from the obstructions.
   # rm -rf A iota
   svntest.main.safe_rmtree( os.path.join(wc_dir, 'A') )
+  svntest.main.run_svn(None, 'revert', '-R', os.path.join(wc_dir, 'A'))
   os.remove( os.path.join(wc_dir, 'iota') )
 
   # svn up
   expected_output = svntest.wc.State(wc_dir, {
-    'A'                 : Item(status='A '),
-    'A/D'               : Item(status='A '),
-    'A/D/gamma'         : Item(status='A '),
-    'A/D/G'             : Item(status='A '),
-    'A/D/G/rho'         : Item(status='A '),
-    'A/D/G/pi'          : Item(status='A '),
-    'A/D/G/tau'         : Item(status='A '),
-    'A/D/H'             : Item(status='A '),
-    'A/D/H/chi'         : Item(status='A '),
-    'A/D/H/omega'       : Item(status='A '),
-    'A/D/H/psi'         : Item(status='A '),
-    'A/B'               : Item(status='A '),
-    'A/B/E'             : Item(status='A '),
-    'A/B/E/beta'        : Item(status='A '),
-    'A/B/E/alpha'       : Item(status='A '),
-    'A/B/F'             : Item(status='A '),
-    'A/B/lambda'        : Item(status='A '),
-    'A/C'               : Item(status='A '),
-    'A/mu'              : Item(status='A '),
     'iota'              : Item(status='A '),
   })
 
@@ -318,6 +323,25 @@ def forced_checkout_of_dir_with_file_obs
   expected_output = svntest.wc.State(wc_dir_other, {
     'iota'              : Item(status='A '),
     'A'                 : Item(status='  ', treeconflict='C'),
+    # And what happens below A
+    'A/mu'              : Item(status='  ', treeconflict='A'),
+    'A/D'               : Item(status='  ', treeconflict='A'),
+    'A/D/G'             : Item(status='  ', treeconflict='A'),
+    'A/D/G/tau'         : Item(status='  ', treeconflict='A'),
+    'A/D/G/pi'          : Item(status='  ', treeconflict='A'),
+    'A/D/G/rho'         : Item(status='  ', treeconflict='A'),
+    'A/D/H'             : Item(status='  ', treeconflict='A'),
+    'A/D/H/psi'         : Item(status='  ', treeconflict='A'),
+    'A/D/H/omega'       : Item(status='  ', treeconflict='A'),
+    'A/D/H/chi'         : Item(status='  ', treeconflict='A'),
+    'A/D/gamma'         : Item(status='  ', treeconflict='A'),
+    'A/C'               : Item(status='  ', treeconflict='A'),
+    'A/B'               : Item(status='  ', treeconflict='A'),
+    'A/B/E'             : Item(status='  ', treeconflict='A'),
+    'A/B/E/beta'        : Item(status='  ', treeconflict='A'),
+    'A/B/E/alpha'       : Item(status='  ', treeconflict='A'),
+    'A/B/F'             : Item(status='  ', treeconflict='A'),
+    'A/B/lambda'        : Item(status='  ', treeconflict='A'),
   })
 
   expected_disk = svntest.main.greek_state.copy()
@@ -337,31 +361,14 @@ def forced_checkout_of_dir_with_file_obs
 
   # svn up wc_dir_other
   expected_output = svntest.wc.State(wc_dir_other, {
-    'A'                 : Item(status='A '),
-    'A/mu'              : Item(status='A '),
-    'A/D'               : Item(status='A '),
-    'A/D/G'             : Item(status='A '),
-    'A/D/G/tau'         : Item(status='A '),
-    'A/D/G/pi'          : Item(status='A '),
-    'A/D/G/rho'         : Item(status='A '),
-    'A/D/H'             : Item(status='A '),
-    'A/D/H/psi'         : Item(status='A '),
-    'A/D/H/omega'       : Item(status='A '),
-    'A/D/H/chi'         : Item(status='A '),
-    'A/D/gamma'         : Item(status='A '),
-    'A/C'               : Item(status='A '),
-    'A/B'               : Item(status='A '),
-    'A/B/E'             : Item(status='A '),
-    'A/B/E/beta'        : Item(status='A '),
-    'A/B/E/alpha'       : Item(status='A '),
-    'A/B/F'             : Item(status='A '),
-    'A/B/lambda'        : Item(status='A '),
   })
 
   expected_disk = svntest.main.greek_state.copy()
 
   expected_status = actions.get_virginal_state(wc_dir_other, 1)
 
+  svntest.main.run_svn(None, 'revert', '-R', os.path.join(wc_dir_other, 'A'))
+
   actions.run_and_verify_update(wc_dir_other, expected_output, expected_disk,
     expected_status, None, None, None, None, None, False, wc_dir_other)
 
@@ -914,6 +921,9 @@ def co_with_obstructing_local_adds(sbox)
 
   expected_output = wc.State(wc_dir, {
     'A/D/M'         : Item(status='  ', treeconflict='C'),
+    'A/D/M/rho'     : Item(status='  ', treeconflict='A'),
+    'A/D/M/pi'      : Item(status='  ', treeconflict='A'),
+    'A/D/M/tau'     : Item(status='  ', treeconflict='A'),
     })
   expected_disk = wc.State('', {
     'gamma'     : Item("This is the file 'gamma'.\n"),
@@ -947,7 +957,7 @@ def co_with_obstructing_local_adds(sbox)
                                           None, None, None, None,
                                           '--force')
 
-  expected_status.tweak('A/D/M', treeconflict='C')
+  expected_status.tweak('A/D/M', treeconflict='C', status='R ')
   expected_status.tweak(
     'A/D',
     'A/D/G',
@@ -967,6 +977,9 @@ def co_with_obstructing_local_adds(sbox)
     'A/D/H/chi'      : Item(status='  ', wc_rev=4),
     'A/D/H/psi'      : Item(status='  ', wc_rev=4),
     'A/D/H/omega'    : Item(status='  ', wc_rev=4),
+    'A/D/M/pi'       : Item(status='D ', wc_rev=4),
+    'A/D/M/rho'      : Item(status='D ', wc_rev=4),
+    'A/D/M/tau'      : Item(status='D ', wc_rev=4),
     })
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 

Modified: subversion/trunk/subversion/tests/cmdline/switch_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/switch_tests.py?rev=1089806&r1=1089805&r2=1089806&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/switch_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/switch_tests.py Thu Apr  7 10:18:28 2011
@@ -881,7 +881,8 @@ def bad_intermediate_urls(sbox):
     'A/D/G/tau', 'A/D/H', 'A/D/H/psi', 'A/D/H/omega', 'A/D/H/chi',
     'A/D/gamma', 'A/mu', 'A/C')
   expected_status.add({
-    'A/Z'               : Item(status='? ', treeconflict='C'),
+    # Obstructed node is currently turned into a delete to allow resolving.
+    'A/Z'               : Item(status='D ', treeconflict='C', wc_rev=2),
   })
 
   actions.run_and_verify_switch(wc_dir, wc_dir, url_A_C, expected_output,
@@ -898,10 +899,10 @@ def bad_intermediate_urls(sbox):
   # check that we can recover from the tree conflict
   # rm A/Z
   os.remove(A_Z)
+  svntest.main.run_svn(None, 'revert', A_Z)
 
   # svn up
   expected_output = svntest.wc.State(wc_dir, {
-    'A/Z'               : Item(status='A '),
   })
 
   expected_disk.tweak('A/Z', contents=None)
@@ -1450,6 +1451,9 @@ def forced_switch_failures(sbox):
     'A/C/G/tau'         : Item(status='A '),
     'A/C/gamma'         : Item(status='A '),
     'A/C/H'             : Item(status='  ', treeconflict='C'),
+    'A/C/H/psi'         : Item(status='  ', treeconflict='A'),
+    'A/C/H/omega'       : Item(status='  ', treeconflict='A'),
+    'A/C/H/chi'         : Item(status='  ', treeconflict='A'),
   })
 
   expected_disk = svntest.main.greek_state.copy()
@@ -1469,7 +1473,10 @@ def forced_switch_failures(sbox):
     'A/C/G/rho'         : Item(status='  ', wc_rev='1'),
     'A/C/G/tau'         : Item(status='  ', wc_rev='1'),
     'A/C/G/pi'          : Item(status='  ', wc_rev='1'),
-    'A/C/H'             : Item(status='? ', treeconflict='C'),
+    'A/C/H'             : Item(status='D ', treeconflict='C', wc_rev='1'),
+    'A/C/H/psi'         : Item(status='D ', wc_rev='1'),
+    'A/C/H/omega'       : Item(status='D ', wc_rev='1'),
+    'A/C/H/chi'         : Item(status='D ', wc_rev='1'),
     'A/C/gamma'         : Item(status='  ', wc_rev='1'),
   })
   expected_status.tweak('A/C', switched='S')
@@ -1563,16 +1570,15 @@ def forced_switch_failures(sbox):
   # rm A/C/H
   os.remove(A_C_H)
 
+  # Resolve the tree conflict on A_C_H
+  svntest.main.run_svn(None, 'resolved', A_C_H)
+
   # A/B/F is switched to A/D/G
   # A/C is switched to A/D
   # A/D/G is switched to A/D/H
   # svn up
   expected_output = svntest.wc.State(wc_dir, {
-    'A/C/H'             : Item(status='A '),
-    'A/C/H/omega'       : Item(status='A '),
-    'A/C/H/chi'         : Item(status='A '),
     'A/C/H/I'           : Item(status='A '),
-    'A/C/H/psi'         : Item(status='A '),
     'A/D/G/omega'       : Item(status='A '),
     'A/D/G/I'           : Item(status='A '),
     'A/D/G/psi'         : Item(status='A '),
@@ -1616,6 +1622,8 @@ def forced_switch_failures(sbox):
   expected_status.tweak('A/B/F/pi', 'A/C/H', treeconflict=None)
   expected_status.tweak('A/D/G', switched='S')
 
+  svntest.main.run_svn(None, 'revert', '-R', os.path.join(wc_dir, 'A/C/H'))
+
   actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
     expected_status, None, None, None, None, None, False, wc_dir)
 
@@ -1658,6 +1666,9 @@ def switch_with_obstructing_local_adds(s
   expected_output = svntest.wc.State(sbox.wc_dir, {
     "A/B/F/gamma"   : Item(status='  ', treeconflict='C'),
     "A/B/F/G"       : Item(status='  ', treeconflict='C'),
+    'A/B/F/G/tau'   : Item(status='  ', treeconflict='A'),
+    'A/B/F/G/rho'   : Item(status='  ', treeconflict='A'),
+    'A/B/F/G/pi'    : Item(status='  ', treeconflict='A'),
     "A/B/F/H"       : Item(status='A '),
     "A/B/F/H/chi"   : Item(status='A '),
     "A/B/F/H/omega" : Item(status='A '),
@@ -1681,10 +1692,11 @@ def switch_with_obstructing_local_adds(s
   expected_status.tweak('A/B/F', switched='S')
   expected_status.add({
     'A/B/F/gamma'     : Item(status='R ', treeconflict='C', wc_rev='1'),
-    'A/B/F/G'         : Item(status='A ', treeconflict='C', wc_rev='0'),
-    'A/B/F/G/pi'      : Item(status='A ', wc_rev='0'),
-    'A/B/F/G/tau'     : Item(status='A ', wc_rev='0'),
+    'A/B/F/G'         : Item(status='R ', treeconflict='C', wc_rev='1'),
+    'A/B/F/G/pi'      : Item(status='R ', wc_rev='1'),
+    'A/B/F/G/tau'     : Item(status='R ', wc_rev='1'),
     'A/B/F/G/upsilon' : Item(status='A ', wc_rev='0'),
+    'A/B/F/G/rho'     : Item(status='D ', wc_rev='1'),
     'A/B/F/H'         : Item(status='  ', wc_rev='1'),
     'A/B/F/H/chi'     : Item(status='  ', wc_rev='1'),
     'A/B/F/H/omega'   : Item(status='  ', wc_rev='1'),

Modified: subversion/trunk/subversion/tests/cmdline/tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/tree_conflict_tests.py?rev=1089806&r1=1089805&r2=1089806&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/tree_conflict_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/tree_conflict_tests.py Thu Apr  7 10:18:28 2011
@@ -977,7 +977,6 @@ def query_absent_tree_conflicted_dir(sbo
 
 #----------------------------------------------------------------------
 
-@XFail()
 @Issue(3608)
 def up_add_onto_add_revert(sbox):
   "issue #3608: reverting an add onto add conflict"

Modified: subversion/trunk/subversion/tests/cmdline/update_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/update_tests.py?rev=1089806&r1=1089805&r2=1089806&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/update_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/update_tests.py Thu Apr  7 10:18:28 2011
@@ -816,7 +816,7 @@ def obstructed_update_alters_wc_props(sb
 
   expected_status = actions.get_virginal_state(wc_dir, 2)
   expected_status.add({
-    'A/foo'             : Item(status='? ', treeconflict='C'),
+    'A/foo'             : Item(status='D ', treeconflict='C', wc_rev=2),
   })
 
   actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
@@ -827,10 +827,11 @@ def obstructed_update_alters_wc_props(sb
   #print "Removing obstruction"
   os.unlink(obstruction_path)
 
+  svntest.main.run_svn(None, 'revert', obstruction_path)
+
   # Update the -- now unobstructed -- WC again.
   #print "Updating WC again"
   expected_output = svntest.wc.State(wc_dir, {
-    'A/foo' : Item(status='A '),
     })
 
   expected_disk = svntest.main.greek_state.copy()
@@ -2260,7 +2261,7 @@ def forced_update_failures(sbox):
 
   expected_status = actions.get_virginal_state(wc_dir_backup, 1)
   expected_status.add({
-    'A/C/I'             : Item(status='? ', treeconflict='C'),
+    'A/C/I'             : Item(status='D ', treeconflict='C', wc_rev=2),
     'A/B/F/nu'          : Item(status='? ', treeconflict='C'),
   })
   expected_status.tweak('A/C', 'A/B/F', wc_rev='2')
@@ -2273,9 +2274,10 @@ def forced_update_failures(sbox):
   os.remove(backup_A_C_I)
   svntest.main.safe_rmtree(backup_A_B_F_nu)
 
+  svntest.main.run_svn(None, 'revert', backup_A_C_I)
+
   # svn up wc_dir_backup
   expected_output = svntest.wc.State(wc_dir_backup, {
-    'A/C/I'             : Item(status='A '),
     'A/B/F/nu'          : Item(status='A '),
   })
 
@@ -2857,7 +2859,10 @@ def update_with_obstructing_additions(sb
 
   # Try to update M's Parent.
   expected_output = wc.State(A_path, {
-    'M'   : Item(status='  ', treeconflict='C'),
+    'M'      : Item(status='  ', treeconflict='C'),
+    'M/rho'  : Item(status='  ', treeconflict='A'),
+    'M/pi'   : Item(status='  ', treeconflict='A'),
+    'M/tau'  : Item(status='  ', treeconflict='A'),
     })
 
   expected_disk = svntest.main.greek_state.copy()
@@ -2901,7 +2906,7 @@ def update_with_obstructing_additions(sb
     'A/D/H/I/K'     : Item(status='  ', wc_rev=4),
     'A/D/H/I/K/xi'  : Item(status='  ', wc_rev=4),
     'A/D/H/I/L'     : Item(status='  ', wc_rev=4),
-    'A/M'           : Item(status='A ', copied='+', wc_rev='-',
+    'A/M'           : Item(status='R ', copied='+', wc_rev='-',
                            treeconflict='C'),
     'A/M/I'         : Item(status='  ', copied='+', wc_rev='-'),
     'A/M/I/J'       : Item(status='  ', copied='+', wc_rev='-'),
@@ -2913,6 +2918,11 @@ def update_with_obstructing_additions(sb
     'A/M/psi'       : Item(status='  ', copied='+', wc_rev='-'),
     'A/M/omega'     : Item(status='  ', copied='+', wc_rev='-'),
     'omicron'       : Item(status='A ', copied='+', wc_rev='-'),
+
+    # Inserted under the tree conflict
+    'A/M/pi'            : Item(status='D ', wc_rev='4'),
+    'A/M/rho'           : Item(status='D ', wc_rev='4'),
+    'A/M/tau'           : Item(status='D ', wc_rev='4'),
     })
 
   svntest.actions.run_and_verify_update(wc_dir, expected_output,
@@ -2923,12 +2933,6 @@ def update_with_obstructing_additions(sb
   # Resolve the tree conflict.
   svntest.main.run_svn(None, 'resolve', '--accept', 'working', M_path)
 
-  # --force shouldn't help either.
-  svntest.actions.run_and_verify_update(wc_dir, expected_output,
-                                        expected_disk, expected_status,
-                                        None, None, None, None, None, False,
-                                        M_path, '--force')
-
   # Try to update omicron's parent, non-recusively so as not to
   # try and update M first.
   expected_output = wc.State(wc_dir, {
@@ -2938,6 +2942,7 @@ def update_with_obstructing_additions(sb
   expected_status.tweak('', 'iota', status='  ', wc_rev=4)
   expected_status.tweak('omicron', status='R ', copied='+', wc_rev='-',
                         treeconflict='C')
+  expected_status.tweak('A/M', treeconflict=None)
 
   svntest.actions.run_and_verify_update(wc_dir, expected_output,
                                         expected_disk, expected_status,