Index: subversion/tests/cmdline/svntest/actions.py
===================================================================
--- subversion/tests/cmdline/svntest/actions.py	(revision 32499)
+++ subversion/tests/cmdline/svntest/actions.py	(working copy)
@@ -608,14 +608,26 @@
 
   # Verify actual output against expected output.
   if output_tree:
-    tree.compare_trees ("output", actual_output, output_tree)
+    try:
+      tree.compare_trees ("output", actual_output, output_tree)
+    except:
+      print "\nActual output tree:"
+      #tree.dump_tree(actual_output, verbose=True)
+      tree.dump_tree_script(actual_output, len(wc_dir_name) + len(os.sep))
+      raise
 
   # Create a tree by scanning the working copy, and verify it
   if disk_tree:
     actual_disk = tree.build_tree_from_wc (wc_dir_name, check_props)
-    tree.compare_trees ("disk", actual_disk, disk_tree,
-                        singleton_handler_a, a_baton,
-                        singleton_handler_b, b_baton)
+    try:
+      tree.compare_trees ("disk", actual_disk, disk_tree,
+                          singleton_handler_a, a_baton,
+                          singleton_handler_b, b_baton)
+    except:
+      print "\nActual disk tree:"
+      tree.dump_tree(actual_disk)
+      tree.dump_tree_script(actual_disk)
+      raise
 
   # Verify via 'status' command too, if possible.
   if status_tree:
@@ -841,8 +853,13 @@
     raise Failure
 
   myskiptree = tree.build_tree_from_skipped(out)
-  tree.compare_trees("skip", myskiptree, skip_tree,
-                     extra_skip, None, missing_skip, None)
+  try:
+    tree.compare_trees("skip", myskiptree, skip_tree,
+                       extra_skip, None, missing_skip, None)
+  except:
+    print "\nActual skip tree:"
+    tree.dump_tree_script(myskiptree, len(dir) + len(os.sep))
+    raise
 
   actual = tree.build_tree_from_checkout(out, 0)
   verify_update (actual, dir,
@@ -1059,6 +1076,9 @@
                         singleton_handler_b, b_baton)
   except tree.SVNTreeError:
     verify.display_trees(None, 'STATUS OUTPUT TREE', output_tree, actual)
+    print "\nActual status tree:"
+    #tree.dump_tree(actual, "  ", verbose=True)
+    tree.dump_tree_script(actual, len(wc_dir_name) + len(os.sep))
     raise
 
 
@@ -1479,123 +1499,14 @@
   return "<<<<<<< .working\n" + wc_text + "=======\n" + \
          merged_text + ">>>>>>> .merge-right.r" + str(merged_rev) + "\n"
 
-def set_up_tree_conflicts(sbox, do_copy=False):
-  """Edit and delete files in two working copies so that tree conflicts
-  will appear.  See notes/tree-conflicts/use-cases.txt for background.
 
-  For update testing, wc 2 is a duplicate of wc 1 (with the same URL), so
-  DO_COPY should be False.
 
-  For switch testing, the URL of wc 2 should be a copy of the first URL,
-  so DO_COPY should be True.
-  """
 
-  wc_dir = sbox.wc_dir
-  j = os.path.join
-  G = j(wc_dir, 'A', 'D', 'G')
 
-  if do_copy:
-    # Create wc 2 as a copy of wc 1.
-    A_url  = sbox.repo_url + '/A'
-    A2_url = sbox.repo_url + '/A2'
-    main.run_svn(None, 'cp', A_url, A2_url, '-m', 'copy A to A2')
-    main.run_svn(None, 'up', wc_dir)
-    A = j(wc_dir, 'A')
-    A2 = j(wc_dir, 'A2')
-    G2 = j(wc_dir, 'A2', 'D', 'G')
-  else:
-    # Create wc 2 as a duplicate of wc 1.
-    wc_dir_2 =  sbox.add_wc_path('2')
-    duplicate_dir(wc_dir, wc_dir_2)
-    main.run_svn(None, 'up', wc_dir_2)
-    G2 = j(wc_dir_2, 'A', 'D', 'G')
 
-  # Replace the files in /A/D/H of wc 1 to break the common ancestry.
-  # TODO: first implement ancestry-checking.
 
-  # Use cases 1 and 4, except they call for "move" rather than "delete"
-  # Action: Edited
-  main.file_append(j(G, 'pi'), "Edited in wc 1.\n")
-  # Reason: Deleted
-  main.run_svn(None, 'del', j(G2, 'pi'))
-
-  # Use cases 2 and 5, except they call for "move" rather than "delete"
-  # Action: Deleted
-  main.run_svn(None, 'del', j(G, 'rho'))
-  # Reason: Edited
-  main.file_append(j(G2, 'rho'), "Edited in wc 2.\n")
-
-  # Use cases 3 and 6, except they call for "move" rather than "delete"
-  # Action: Deleted
-  main.run_svn(None, 'del', j(G, 'tau'))
-  # Reason: Deleted
-  main.run_svn(None, 'del', j(G2, 'tau'))
-
-  if do_copy:
-    main.run_svn(None, 'ci', '-m', 'Changes in wc 1.', A)
-    return None
-  else:
-    main.run_svn(None, 'ci', '-m', 'Changes in wc 1.', wc_dir)
-    return wc_dir_2
-
-def set_up_tree_conflicts_for_merge(sbox):
-  """Edit and delete files in two working copies so that tree conflicts
-  will appear.  See notes/tree-conflict/use-cases.txt for background.
-  
-  Some files are in a leaf dir others are in a parent dir, to make sure
-  the global list of tree conflicts works correctly.
-  """
-
-  wc_dir = sbox.wc_dir
-  j = os.path.join
-  A = j(wc_dir, 'A')
-  D = j(wc_dir, 'A', 'D')
-  G = j(wc_dir, 'A', 'D', 'G')
-
-  main.file_write(j(D, 'sigma'), "This is the file 'sigma'.\n")
-  main.file_write(j(D, 'theta'), "This is the file 'theta'.\n")
-  main.run_svn(None, 'add', j(D, 'sigma'), j(D, 'theta'))
-  main.run_svn(None, 'ci', '-m', 'Create extra test files.', wc_dir)
-  
-  # Create wc 2 as a copy of wc 1.
-  A_url  = sbox.repo_url + '/A'
-  A2_url = sbox.repo_url + '/A2'
-  main.run_svn(None, 'cp', A_url, A2_url, '-m', 'copy A to A2')
-  main.run_svn(None, 'up', wc_dir)
-  A2 = j(wc_dir, 'A2')
-  D2 = j(wc_dir, 'A2', 'D')
-  G2 = j(wc_dir, 'A2', 'D', 'G')
-
-  # Use case 4
-  # Action: Edited
-  main.file_append(j(G, 'pi'), "Edited in wc 1.\n")
-  main.file_append(j(D, 'gamma'), "Edited in wc 1.\n")
-  # Reason: Deleted
-  main.run_svn(None, 'del', j(G2, 'pi'))
-  main.run_svn(None, 'del', j(D2, 'gamma'))
-
-  # Use case 5
-  # Action: Deleted
-  main.run_svn(None, 'del', j(G, 'rho'))
-  main.run_svn(None, 'del', j(D, 'sigma'))
-  # Reason: Edited
-  main.file_append(j(G2, 'rho'), "Edited in wc 2.\n")
-  main.file_append(j(D2, 'sigma'), "Edited in wc 2.\n")
-
-  # Use case 6
-  # Action: Deleted
-  main.run_svn(None, 'del', j(G, 'tau'))
-  main.run_svn(None, 'del', j(D, 'theta'))
-  # Reason: Deleted
-  main.run_svn(None, 'del', j(G2, 'tau'))
-  main.run_svn(None, 'del', j(D2, 'theta'))
-
-  main.run_svn(None, 'ci', '-m', 'Changes in wc 1.', A)
-  main.run_svn(None, 'ci', '-m', 'Changes in wc 2.', A2)
-  return None
-
-def make_tc_test_trees(base):
-  """Helper function for deep tree conflicts.  Create a set of trees,
+def make_deep_trees(base):
+  """Helper function for deep trees conflicts.  Create a set of trees,
   each in its own "container" dir.  After tree conflicts are created,
   the tree-conflict status in each container can be tested separately.
   """
@@ -1622,12 +1533,73 @@
   main.file_append(beta, "This is the file 'beta'.\n")
   main.file_append(gamma, "This is the file 'gamma'.\n")
 
+
+def add_deep_trees(sbox, base_dir_name):
+  """Prepare a "deep_trees" within a given directory.
+
+  The directory <sbox.wc_dir>/<base_dir_name> is created and a deep_tree
+  is created within. The items are only added, a commit has to be
+  called separately, if needed.
+
+  <base_dir_name> will thus be a container for the set of containers
+  mentioned in make_deep_trees().
+  """
+  j = os.path.join
+  base = j(sbox.wc_dir, base_dir_name)
+  make_deep_trees(base)
   main.run_svn(None, 'add', base)
 
-def tc_leaf_del(base):
-  """Helper function for deep tree conflicts.  Delete files and empty dirs."""
+
+Item = wc.StateItem
+
+# initial deep trees state
+deep_trees_virginal_state = wc.State('', {
+  'F/alpha'         : Item("This is the file 'alpha'.\n"),
+  'D/D1'            : Item(),
+  'DF/D1/beta'      : Item("This is the file 'beta'.\n"),
+  'DD/D1/D2'        : Item(),
+  'DDF/D1/D2/gamma' : Item("This is the file 'gamma'.\n"),
+  'DDD/D1/D2/D3'    : Item(),
+  })
+
+
+# Many actions on deep trees and their resulting states...
+
+def deep_trees_leaf_edit(base):
+  """Helper function for deep trees conflicts.  Append text to files,
+	create new files in empty directories."""
   j = os.path.join
   F   = j(base, 'F', 'alpha')
+  DF  = j(base, 'DF', 'D1', 'beta')
+  DDF = j(base, 'DDF', 'D1', 'D2', 'gamma')
+  main.file_append(F, "More text for file alpha.\n")
+  main.file_append(DF, "More text for file beta.\n")
+  main.file_append(DDF, "More text for file gamma.\n")
+
+  D   = j(base, 'D', 'D1', 'delta')
+  DD  = j(base, 'DD', 'D1', 'D2', 'epsilon')
+  DDD = j(base, 'DDD', 'D1', 'D2', 'D3', 'zeta')
+  main.file_append(D, "This is the file 'delta'.\n")
+  main.file_append(DD, "This is the file 'epsilon'.\n")
+  main.file_append(DDD, "This is the file 'zeta'.\n")
+  main.run_svn(None, 'add', D, DD, DDD)
+
+# deep trees state after a call to deep_trees_leaf_edit
+deep_trees_after_leaf_edit = wc.State('', {
+  'F/alpha'           : Item("This is the file 'alpha'.\nMore text for file alpha.\n"),
+  'D/D1/delta'        : Item("This is the file 'delta'.\n"),
+  'DF/D1/beta'        : Item("This is the file 'beta'.\nMore text for file beta.\n"),
+  'DD/D1/D2/epsilon'  : Item("This is the file 'epsilon'.\n"),
+  'DDF/D1/D2/gamma'   : Item("This is the file 'gamma'.\nMore text for file gamma.\n"),
+  'DDD/D1/D2/D3/zeta' : Item("This is the file 'zeta'.\n"),
+  })
+
+
+def deep_trees_leaf_del(base):
+  """Helper function for deep trees conflicts.  Delete files and empty
+  dirs."""
+  j = os.path.join
+  F   = j(base, 'F', 'alpha')
   D   = j(base, 'D', 'D1')
   DF  = j(base, 'DF', 'D1', 'beta')
   DD  = j(base, 'DD', 'D1', 'D2')
@@ -1635,70 +1607,487 @@
   DDD = j(base, 'DDD', 'D1', 'D2', 'D3')
   main.run_svn(None, 'rm', F, D, DF, DD, DDF, DDD)
 
-def tc_tree_del(base):
-  """Helper function for deep tree conflicts.  Delete top-level dirs."""
+# deep trees state after a call to deep_trees_leaf_del
+deep_trees_after_leaf_del = wc.State('', {
+  'F'               : Item(),
+  'D'               : Item(),
+  'DF/D1'           : Item(),
+  'DD/D1'           : Item(),
+  'DDF/D1/D2'       : Item(),
+  'DDD/D1/D2'       : Item(),
+  })
+
+
+def deep_trees_tree_del(base):
+  """Helper function for deep trees conflicts.  Delete top-level dirs."""
   j = os.path.join
+  F   = j(base, 'F', 'alpha')
   D   = j(base, 'D', 'D1')
   DF  = j(base, 'DF', 'D1')
   DD  = j(base, 'DD', 'D1')
   DDF = j(base, 'DDF', 'D1')
   DDD = j(base, 'DDD', 'D1')
-  main.run_svn(None, 'rm', D, DF, DD, DDF, DDD)
+  main.run_svn(None, 'rm', F, D, DF, DD, DDF, DDD)
+
+# deep trees state after a call to deep_trees_tree_del
+deep_trees_after_tree_del = wc.State('', {
+  'F'                 : Item(),
+  'D'                 : Item(),
+  'DF'                : Item(),
+  'DD'                : Item(),
+  'DDF'               : Item(),
+  'DDD'               : Item(),
+  })
+
+
+
+
+class DeepTreesTestCase:
+  """Describes one tree-conflicts test case.
+  See deep_trees_run_tests_scheme_for_update(), ..._switch(), ..._merge().
   
-def tc_text_append(base):
-  """Helper function for deep tree conflicts.  Append text to files."""
+  The name field is the subdirectory name in which the test should be run.
+
+  The local_action and incoming_action are the functions to run
+  to construct the local changes and incoming changes, respectively.
+  See deep_trees_leaf_edit, deep_trees_tree_del, etc.
+
+  The expected_* and error_re_string arguments are described in functions
+  run_and_verify_[update|switch|merge]
+
+  Note: expected_skip is only used in merge, i.e. using
+  deep_trees_run_tests_scheme_for_merge.
+  """
+
+  def __init__(self, name, local_action, incoming_action,
+                expected_output = None, expected_disk = None,
+                expected_status = None, expected_skip = None,
+                error_re_string = None):
+    self.name = name
+    self.local_action = local_action
+    self.incoming_action = incoming_action
+    self.expected_output = expected_output
+    self.expected_disk = expected_disk
+    self.expected_status = expected_status
+    self.expected_skip = expected_skip
+    self.error_re_string = error_re_string
+
+
+
+def deep_trees_run_tests_scheme_for_update(sbox, greater_scheme):
+  """
+  Runs a given list of tests for conflicts occuring at an update operation.
+
+  This function wants to save time and perform a number of different
+  test cases using just a single repository and performing just one commit
+  for all test cases instead of one for each test case.
+
+   1) Each test case is initialized in a separate subdir. Each subdir
+      again contains one set of "deep_trees", being separate container
+      dirs for different depths of trees (F, D, DF, DD, DDF, DDD).
+
+   2) A commit is performed across all test cases and depths.
+      (our initial state, -r2)
+
+   3) In each test case subdir (e.g. "local_tree_del_incoming_leaf_edit"),
+      its *incoming* action is performed (e.g. "deep_trees_leaf_edit"), in
+      each of the different depth trees (F, D, DF, ... DDD).
+
+   4) A commit is performed across all test cases and depths:
+      our "incoming" state is "stored away in the repository for now",
+      -r3.
+
+   5) All test case dirs and contained deep_trees are time-warped
+      (updated) back to -r2, the initial state containing deep_trees.
+
+   6) In each test case subdir (e.g. "local_tree_del_incoming_leaf_edit"),
+      its *local* action is performed (e.g. "deep_trees_leaf_del"), in
+      each of the different depth trees (F, D, DF, ... DDD).
+
+   7) An update to -r3 is performed across all test cases and depths.
+      This causes tree-conflicts between the "local" state in the working
+      copy and the "incoming" state from the repository, -r3.
+
+  The sbox parameter is just the sbox passed to a test function. No need
+  to call sbox.build(), since it is called (once) within this function.
+
+  The "table" greater_scheme models all of the different test cases
+  that should be run using a single repository.
+
+  greater_scheme is a list of DeepTreesTestCase items, which define complete
+  test setups, so that they can be performed as described above.
+  """
+
   j = os.path.join
-  alpha = j(F, 'alpha')
-  beta  = j(DF, 'D1', 'beta')
-  gamma = j(DDF, 'D1', 'D2', 'gamma')
-  main.file_append(alpha, "More text for file alpha.\n")
-  main.file_append(beta, "More text for file beta.\n")
-  main.file_append(gamma, "More text for file gamma\n")
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # 1) create directories
+
+  for test_case in greater_scheme:
+    try:
+      add_deep_trees(sbox, test_case.name)
+    except:
+      print "ERROR IN: Tests scheme for update: " \
+          + "while setting up deep trees in '%s'" % test_case.name
+      raise
+
+
+  # 2) commit initial state
+
+  main.run_svn(None, 'commit', '-m', 'initial state', wc_dir)
+
   
-def set_up_deep_tree_conflicts_up(sbox, local_actions, incoming_actions):
-  """Run functions local_actions and incoming_actions on a working copy
-  directory so that tree conflicts will appear.  These may includes
-  conflicts between a dir and its descendants.
+  # 3) apply incoming changes
 
-  After this setup, reveal the tree conflicts by updating the 'local' dir.
+  for test_case in greater_scheme:
+    try:
+      test_case.incoming_action(j(sbox.wc_dir, test_case.name))
+    except:
+      print "ERROR IN: Tests scheme for update: " \
+          + "while performing incoming action in '%s'" % test_case.name
+      raise
+
+
+  # 4) commit incoming changes
+
+  main.run_svn(None, 'commit', '-m', 'incoming changes', wc_dir)
+
+
+  # 5) time-warp back to -r2
+
+  main.run_svn(None, 'update', '-r2', wc_dir)
+
+
+  # 6) apply local changes
+
+  for test_case in greater_scheme:
+    try:
+      test_case.local_action(j(wc_dir, test_case.name))
+    except:
+      print "ERROR IN: Tests scheme for update: " \
+          + "while performing local action in '%s'" % test_case.name
+      raise
+
+  # 7) update to -r3, conflicting with incoming changes.
+  #    A lot of different things are expected.
+  #    Do separate update operations for each test case.
+
+  for test_case in greater_scheme:
+    try:
+      base = j(wc_dir, test_case.name)
+
+      x_out = test_case.expected_output
+      if x_out != None:
+        x_out = x_out.copy()
+        x_out.wc_dir = base
+
+      x_disk = test_case.expected_disk
+      
+      x_status = test_case.expected_status
+      if x_status != None:
+        x_status.copy()
+        x_status.wc_dir = base
+
+      run_and_verify_update(base, x_out, x_disk, x_status,
+                            error_re_string = test_case.error_re_string)
+    except:
+      print "ERROR IN: tests scheme for update: while verifying in '%s'" % test_case.name
+      raise
+
+
+
+def deep_trees_run_tests_scheme_for_switch(sbox, greater_scheme):
   """
+  Runs a given list of tests for conflicts occuring at a switch operation.
 
-  wc_dir = sbox.wc_dir
+  This function wants to save time and perform a number of different
+  test cases using just a single repository and performing just one commit
+  for all test cases instead of one for each test case.
+
+   1) Each test case is initialized in a separate subdir. Each subdir
+      again contains two subdirs: one "local" and one "incoming" for
+      the switch operation. These contain a set of deep_trees each.
+
+   2) A commit is performed across all test cases and depths.
+      (our initial state, -r2)
+
+   3) In each test case subdir's incoming subdir, the
+      incoming actions are performed.
+
+   4) A commit is performed across all test cases and depths. (-r3)
+
+   5) In each test case subdir's local subdir, the local actions are
+      performed. They remain uncommitted in the working copy.
+
+   6) In each test case subdir's local dir, a switch is performed to its
+      corresponding incoming dir.
+      This causes conflicts between the "local" state in the working
+      copy and the "incoming" state from the incoming subdir (still -r3).
+
+  The sbox parameter is just the sbox passed to a test function. No need
+  to call sbox.build(), since it is called (once) within this function.
+
+  The "table" greater_scheme models all of the different test cases
+  that should be run using a single repository.
+
+  greater_scheme is a list of DeepTreesTestCase items, which define complete
+  test setups, so that they can be performed as described above.
+  """
+
   j = os.path.join
-  local = j(wc_dir, 'local')
-  make_tc_test_trees(local)
-  main.run_svn(None, 'ci', '-m', 'Set up deep test dirs.', wc_dir) # -r2
 
-  # Apply the incoming actions.
-  incoming_actions(local)
-  main.run_svn(None, 'ci', '-m', 'Commit incoming actions.', wc_dir) # -r3
+  sbox.build()
+  wc_dir = sbox.wc_dir
 
-  # Roll back the WC so that the local actions will conflict.
-  main.run_svn(None, 'up', wc_dir, '-r2')
-  local_actions(local)  
+  # 1) Create directories.
 
-def set_up_deep_tree_conflicts_sw(sbox, local_actions, incoming_actions):
-  """Run functions local_actions and incoming_actions on working copy
-  directories so that tree conflicts will appear.  These may includes
-  conflicts between a dir and its descendants.
+  for test_case in greater_scheme:
+    try:
+      base = j(sbox.wc_dir, test_case.name)
+      os.makedirs(base)
+      make_deep_trees(j(base, "local"))
+      make_deep_trees(j(base, "incoming"))
+      main.run_svn(None, 'add', base)
+    except:
+      print "ERROR IN: Tests scheme for switch: " \
+          + "while setting up deep trees in '%s'" % test_case.name
+      raise
 
-  After this setup, reveal the tree conflicts by switching the 'local'
-  dir to the 'incoming' URL, or by merging the 'incoming' URL (r2:3)
-  into the 'local' dir.
+
+  # 2) Commit initial state (-r2).
+
+  main.run_svn(None, 'commit', '-m', 'initial state', wc_dir)
+
+  
+  # 3) Apply incoming changes
+
+  for test_case in greater_scheme:
+    try:
+      test_case.incoming_action(j(sbox.wc_dir, test_case.name, "incoming"))
+    except:
+      print "ERROR IN: Tests scheme for switch: " \
+          + "while performing incoming action in '%s'" % test_case.name
+      raise
+
+
+  # 4) Commit all changes (-r3).
+
+  main.run_svn(None, 'commit', '-m', 'incoming changes', wc_dir)
+
+
+  # 5) Apply local changes in their according subdirs.
+
+  for test_case in greater_scheme:
+    try:
+      test_case.local_action(j(sbox.wc_dir, test_case.name, "local"))
+    except:
+      print "ERROR IN: Tests scheme for switch: " \
+          + "while performing local action in '%s'" % test_case.name
+      raise
+
+
+  # 6) switch the local dir to the incoming url, conflicting with incoming
+  #    changes. A lot of different things are expected.
+  #    Do separate switch operations for each test case.
+
+  for test_case in greater_scheme:
+    try:
+      local = j(wc_dir, test_case.name, "local")
+      incoming = sbox.repo_url + "/" + test_case.name + "/incoming"
+
+      x_out = test_case.expected_output
+      if x_out != None:
+        x_out = x_out.copy()
+        x_out.wc_dir = local
+
+      x_disk = test_case.expected_disk
+      
+      x_status = test_case.expected_status
+      if x_status != None:
+        x_status.copy()
+        x_status.wc_dir = local
+
+      run_and_verify_switch(local, local, incoming, x_out, x_disk, x_status,
+                            error_re_string = test_case.error_re_string)
+    except:
+      print "ERROR IN: tests scheme for switch: while verifying in '%s'" % test_case.name
+      raise
+
+
+def deep_trees_run_tests_scheme_for_merge(sbox, greater_scheme,
+                                          do_commit_local_changes):
   """
+  Runs a given list of tests for conflicts occuring at a merge operation.
 
-  wc_dir = sbox.wc_dir
+  This function wants to save time and perform a number of different
+  test cases using just a single repository and performing just one commit
+  for all test cases instead of one for each test case.
+
+   1) Each test case is initialized in a separate subdir. Each subdir
+      initially contains another subdir, called "incoming", which
+      contains a set of deep_trees.
+
+   2) A commit is performed across all test cases and depths.
+      (a pre-initial state, -r2)
+
+   3) In each test case subdir, the "incoming" subdir is copied to "local",
+      via the `svn copy' command. Each test case's subdir now has two sub-
+      dirs: "local" and "incoming", initial states for the merge operation.
+
+   4) An update is performed across all test cases and depths, so that the
+      copies made in 3) are pulled into the wc.
+
+   5) In each test case's "incoming" subdir, the incoming action is
+      performed.
+
+   6) A commit is performed across all test cases and depths, to commit
+      the incoming changes.
+      If do_commit_local_changes is True, this becomes step 7 (swap steps).
+
+   7) In each test case's "local" subdir, the local_action is performed.
+      If do_commit_local_changes is True, this becomes step 6 (swap steps).
+      Then, in effect, the local changes are committed as well.
+
+   8) In each test case subdir, the "incoming" subdir is merged into the
+      "local" subdir.
+      This causes conflicts between the "local" state in the working
+      copy and the "incoming" state from the incoming subdir (still -r3).
+
+  The sbox parameter is just the sbox passed to a test function. No need
+  to call sbox.build(), since it is called (once) within this function.
+
+  The "table" greater_scheme models all of the different test cases
+  that should be run using a single repository.
+
+  greater_scheme is a list of DeepTreesTestCase items, which define complete
+  test setups, so that they can be performed as described above.
+  """
+
   j = os.path.join
-  local = j(wc_dir, 'local')
-  incoming = j(wc_dir, 'incoming')
-  make_tc_test_trees(local)
-  make_tc_test_trees(incoming)
-  main.run_svn(None, 'ci', '-m', 'Set up deep test dirs.', wc_dir) # -r2
 
-  incoming_actions(incoming)
-  main.run_svn(None, 'ci', '-m', 'Commit incoming actions.', incoming) # -r3
+  sbox.build()
+  wc_dir = sbox.wc_dir
 
-  local_actions(local)
-  main.run_svn(None, 'ci', '-m', 'Commit local actions.', local) # -r4
+  # 1) Create directories.
+  for test_case in greater_scheme:
+    try:
+      base = j(sbox.wc_dir, test_case.name)
+      os.makedirs(base)
+      make_deep_trees(j(base, "incoming"))
+      main.run_svn(None, 'add', base)
+    except:
+      print "ERROR IN: Tests scheme for merge: " \
+          + "while setting up deep trees in '%s'" % test_case.name
+      raise
 
-  main.run_svn(None, 'up', wc_dir)
+
+  # 2) Commit pre-initial state (-r2).
+
+  main.run_svn(None, 'commit', '-m', 'pre-initial state', wc_dir)
+
+  
+  # 3) Copy "incoming" to "local".
+  for test_case in greater_scheme:
+    try:
+      base_url = sbox.repo_url + "/" + test_case.name
+      incoming_url = base_url + "/incoming"
+      local_url = base_url + "/local"
+      main.run_svn(None, 'cp', incoming_url, local_url, '-m',
+                   'copy incoming to local')
+    except:
+      print "ERROR IN: Tests scheme for merge: " \
+          + "while copying deep trees in '%s'" % test_case.name
+      raise
+
+  # 4) Update to load all of the "/local" subdirs into the working copies.
+
+  try:
+    main.run_svn(None, 'up', sbox.wc_dir)
+  except:
+    print "ERROR IN: Tests scheme for merge: " \
+          + "while updating local subdirs"
+    raise
+
+
+  # 5) Perform incoming actions
+  for test_case in greater_scheme:
+    try:
+      test_case.incoming_action(j(sbox.wc_dir, test_case.name, "incoming"))
+    except:
+      print "ERROR IN: Tests scheme for merge: " \
+          + "while performing incoming action in '%s'" % test_case.name
+      raise
+
+
+  # 6) or 7) Commit all incoming actions
+
+  if not do_commit_local_changes:
+    try:
+      main.run_svn(None, 'ci', '-m', 'Committing incoming actions',
+                   sbox.wc_dir)
+    except:
+      print "ERROR IN: Tests scheme for merge: " \
+          + "while committing incoming actions"
+      raise
+
+
+  # 7) or 6) Perform all local actions.
+  
+  for test_case in greater_scheme:
+    try:
+      test_case.local_action(j(sbox.wc_dir, test_case.name, "local"))
+    except:
+      print "ERROR IN: Tests scheme for merge: " \
+          + "while performing local action in '%s'" % test_case.name
+      raise
+  
+
+  # 6) or 7) Commit all incoming actions
+
+  if do_commit_local_changes:
+    try:
+      main.run_svn(None, 'ci', '-m', 'Committing incoming and local actions', 
+                   sbox.wc_dir)
+    except:
+      print "ERROR IN: Tests scheme for merge: " \
+          + "while committing incoming and local actions"
+      raise
+
+
+  # 8) Merge all "incoming" subdirs to their respective "local" subdirs.
+  #    This creates conflicts between the local changes in the "local" wc
+  #    subdirs and the incoming states committed in the "incoming" subdirs.
+
+  for test_case in greater_scheme:
+    try:
+      local = j(sbox.wc_dir, test_case.name, "local")
+      incoming = sbox.repo_url + "/" + test_case.name + "/incoming"
+
+      x_out = test_case.expected_output
+      if x_out != None:
+        x_out = x_out.copy()
+        x_out.wc_dir = local
+
+      x_disk = test_case.expected_disk
+      
+      x_status = test_case.expected_status
+      if x_status != None:
+        x_status.copy()
+        x_status.wc_dir = local
+
+      x_skip = test_case.expected_skip
+      if x_skip != None:
+        x_skip.copy()
+        x_skip.wc_dir = local
+
+      run_and_verify_merge(local, None, None, incoming,
+                           x_out, x_disk, x_status, x_skip,
+                           error_re_string = test_case.error_re_string,
+                           dry_run = False)
+    except:
+      print "ERROR IN: tests scheme for merge: while verifying in '%s'" % test_case.name
+      raise
+
+
Index: subversion/tests/cmdline/switch_tests.py
===================================================================
--- subversion/tests/cmdline/switch_tests.py	(revision 32499)
+++ subversion/tests/cmdline/switch_tests.py	(working copy)
@@ -2111,93 +2111,357 @@
 
 #----------------------------------------------------------------------
 
-def tree_conflicts_in_switched_files(sbox):
-  "tree conflicts in switched files"
+# Detect tree conflicts among files and directories,
+# edited or deleted in a deep directory structure.
+#
+# See use cases 1-3 in notes/tree-conflicts/use-cases.txt for background.
+# Note that we do not try to track renames.  The only difference from
+# the behavior of Subversion 1.4 and 1.5 is the conflicted status of the
+# parent directory.
+#
+def tree_conflicts_on_switch(sbox):
+  "tree conflicts on switch (tc use cases 1 to 3)"
 
-  # Detect simple tree conflicts among files edited and renamed in a single
-  # directory.  See use cases 1-3 in notes/tree-conflicts/use-cases.txt for
-  # background.
+  # Each case is constructed and then appended to the table, which
+  # is initially empty:
+  greater_scheme = [];
+
+  # convenience definitions
+  leaf_edit = svntest.actions.deep_trees_leaf_edit
+  tree_del = svntest.actions.deep_trees_tree_del
+  leaf_del = svntest.actions.deep_trees_leaf_del
+
+  state_after_leaf_edit = svntest.actions.deep_trees_after_leaf_edit
+  state_after_leaf_del = svntest.actions.deep_trees_after_leaf_del
+  state_after_tree_del = svntest.actions.deep_trees_after_tree_del
+
+  j = os.path.join
+
+  DeepTreesTestCase = svntest.actions.DeepTreesTestCase
+
+
+  # use case 1, as in notes/tree-conflicts/use-cases.txt
+  # 1.1) local tree delete, incoming leaf edit
+
+  expected_output = svntest.wc.State('', {
+    'D'                 : Item(status='C '),
+    'D/D1'              : Item(),
+    'D/D1/delta'        : Item(status='A '),
+    'F'                 : Item(status='C '),
+    'F/alpha'           : Item(status='U '),
+    'DD'                : Item(status='C '),
+    'DD/D1'             : Item(status='C '),
+    'DD/D1/D2'          : Item(),
+    'DD/D1/D2/epsilon'  : Item(status='A '),
+    'DF'                : Item(status='C '),
+    'DF/D1'             : Item(status='C '),
+    'DF/D1/beta'        : Item(status='U '),
+    'DDD'               : Item(status='C '),
+    'DDD/D1'            : Item(status='C '),
+    'DDD/D1/D2'         : Item(status='C '),
+    'DDD/D1/D2/D3'      : Item(),
+    'DDD/D1/D2/D3/zeta' : Item(status='A '),
+    'DDF'               : Item(status='C '),
+    'DDF/D1'            : Item(status='C '),
+    'DDF/D1/D2'         : Item(status='C '),
+    'DDF/D1/D2/gamma'   : Item(status='U '),
+    })
+
+  expected_disk = state_after_leaf_edit
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status='  ', wc_rev='3'),
+    'D'                 : Item(status='C ', wc_rev='3'),
+    'D/D1'              : Item(status='D ', wc_rev='3'),
+    'D/D1/delta'        : Item(status='  ', wc_rev='3'),
+    'F'                 : Item(status='C ', wc_rev='3'),
+    'F/alpha'           : Item(status='D ', wc_rev='3'),
+    'DD'                : Item(status='C ', wc_rev='3'),
+    'DD/D1'             : Item(status='D ', wc_rev='3'),
+    'DD/D1/D2'          : Item(status='D ', wc_rev='3'),
+    'DD/D1/D2/epsilon'  : Item(status='  ', wc_rev='3'),
+    'DF'                : Item(status='C ', wc_rev='3'),
+    'DF/D1'             : Item(status='D ', wc_rev='3'),
+    'DF/D1/beta'        : Item(status='D ', wc_rev='3'),
+    'DDD'               : Item(status='C ', wc_rev='3'),
+    'DDD/D1'            : Item(status='D ', wc_rev='3'),
+    'DDD/D1/D2'         : Item(status='D ', wc_rev='3'),
+    'DDD/D1/D2/D3'      : Item(status='D ', wc_rev='3'),
+    'DDD/D1/D2/D3/zeta' : Item(status='  ', wc_rev='3'),
+    'DDF'               : Item(status='C ', wc_rev='3'),
+    'DDF/D1'            : Item(status='D ', wc_rev='3'),
+    'DDF/D1/D2'         : Item(status='D ', wc_rev='3'),
+    'DDF/D1/D2/gamma'   : Item(status='D ', wc_rev='3'),
+    })
+
+  greater_scheme += [ DeepTreesTestCase("local_tree_del_incoming_leaf_edit",
+                                        tree_del,
+                                        leaf_edit,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status) ]
+
+
+  # 1.2) local tree delete, incoming leaf delete
+
+  expected_output = svntest.wc.State('', {
+    'D'                 : Item(status='C '),
+    'D/D1'              : Item(status='D '),
+    'F'                 : Item(status='C '),
+    'F/alpha'           : Item(status='D '),
+    'DD'                : Item(status='C '),
+    'DD/D1'             : Item(status='C '),
+    'DD/D1/D2'          : Item(status='D '),
+    'DF'                : Item(status='C '),
+    'DF/D1'             : Item(status='C '),
+    'DF/D1/beta'        : Item(status='D '),
+    'DDD'               : Item(status='C '),
+    'DDD/D1'            : Item(status='C '),
+    'DDD/D1/D2'         : Item(status='C '),
+    'DDD/D1/D2/D3'      : Item(status='D '),
+    'DDF'               : Item(status='C '),
+    'DDF/D1'            : Item(status='C '),
+    'DDF/D1/D2'         : Item(status='C '),
+    'DDF/D1/D2/gamma'   : Item(status='D '),
+    })
+
+  expected_disk = state_after_leaf_del
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status='  ', wc_rev='3'),
+    'D'                 : Item(status='C ', wc_rev='3'),
+    'F'                 : Item(status='C ', wc_rev='3'),
+    'DD'                : Item(status='C ', wc_rev='3'),
+    'DD/D1'             : Item(status='D ', wc_rev='3'),
+    'DF'                : Item(status='C ', wc_rev='3'),
+    'DF/D1'             : Item(status='D ', wc_rev='3'),
+    'DDD'               : Item(status='C ', wc_rev='3'),
+    'DDD/D1'            : Item(status='D ', wc_rev='3'),
+    'DDD/D1/D2'         : Item(status='D ', wc_rev='3'),
+    'DDF'               : Item(status='C ', wc_rev='3'),
+    'DDF/D1'            : Item(status='D ', wc_rev='3'),
+    'DDF/D1/D2'         : Item(status='D ', wc_rev='3'),
+    })
+
+  greater_scheme += [ DeepTreesTestCase("local_tree_del_incoming_leaf_del",
+                                        tree_del,
+                                        leaf_del,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status) ]
+
+
+  # use case 2, as in notes/tree-conflicts/use-cases.txt
+  # 2.1) local leaf edit, incoming tree delete
+
+  # NOTE: When trying to test a complete deep_trees set at once, the
+  #       switch operation bails out on the first encountered error and
+  #       does not actually test any other subtrees.
+  #
+  #       In order to get reliable checks for all of the subdirs in a
+  #       deep_trees setup, each of the subdirs has to be checked on its
+  #       own.
   
-  # We do not try to track renames.  The only difference from the behavior
-  # of Subversion 1.4/1.5 is the conflicted status of the directory.
+  # Separate action functions for each subdir:
 
-  sbox.build()
-  wc_dir = sbox.wc_dir
-  A = os.path.join(wc_dir, 'A')
+  def leaf_edit_F(base):
+    F   = j(base, 'F', 'alpha')
+    svntest.main.file_append(F, "More text for file alpha.\n")
 
-  # Set up tree conflicts in wc 2
-  svntest.actions.set_up_tree_conflicts(sbox, True)
-  A2 = os.path.join(sbox.wc_dir, 'A2')
+  def leaf_edit_D(base):
+    D   = j(base, 'D', 'D1', 'delta')
+    svntest.main.file_append(D, "This is the file 'delta'.\n")
+    svntest.main.run_svn(None, 'add', D)
 
-  # Switch wc 2 to url 1
-  expected_output = svntest.wc.State(wc_dir, {
-    'A2/D/G'       : Item(status='C '),
-    'A2/D/G/pi'    : Item(status='U '),
-    'A2/D/G/rho'   : Item(status='D '),
-    'A2/D/G/tau'   : Item(status='D '),
+  def leaf_edit_DF(base):
+    DF  = j(base, 'DF', 'D1', 'beta')
+    svntest.main.file_append(DF, "More text for file beta.\n")
+
+  def leaf_edit_DD(base):
+    DD  = j(base, 'DD', 'D1', 'D2', 'epsilon')
+    svntest.main.file_append(DD, "This is the file 'epsilon'.\n")
+    svntest.main.run_svn(None, 'add', DD)
+
+  def leaf_edit_DDF(base):
+    DDF = j(base, 'DDF', 'D1', 'D2', 'gamma')
+    svntest.main.file_append(DDF, "More text for file gamma.\n")
+
+  def leaf_edit_DDD(base):
+    DDD = j(base, 'DDD', 'D1', 'D2', 'D3', 'zeta')
+    svntest.main.file_append(DDD, "This is the file 'zeta'.\n")
+    svntest.main.run_svn(None, 'add', DDD)
+
+  def tree_del_F(base):
+    F   = j(base, 'F', 'alpha')
+    svntest.main.run_svn(None, 'rm', F)
+
+  def tree_del_D(base):
+    D   = j(base, 'D', 'D1')
+    svntest.main.run_svn(None, 'rm', D)
+
+  def tree_del_DF(base):
+    DF  = j(base, 'DF', 'D1')
+    svntest.main.run_svn(None, 'rm', DF)
+
+  def tree_del_DD(base):
+    DD  = j(base, 'DD', 'D1')
+    svntest.main.run_svn(None, 'rm', DD)
+
+  def tree_del_DDF(base):
+    DDF = j(base, 'DDF', 'D1')
+    svntest.main.run_svn(None, 'rm', DDF)
+
+  def tree_del_DDD(base):
+    DDD = j(base, 'DDD', 'D1')
+    svntest.main.run_svn(None, 'rm', DDD)
+
+  # Now, set up a distinct DeepTreesTestCase for each container dir.
+
+  error_re_string = "Won't delete locally modified directory"
+
+  expected_output = svntest.wc.State('', {
+    'F'                 : Item(status='C '),
+    'F/alpha'           : Item(status='D '),
     })
 
-  expected_disk = svntest.main.greek_state.copy()
-  expected_disk.add({
-    'A2'           : Item(),
-    'A2/mu'        : Item("This is the file 'mu'.\n"),
-    'A2/B'         : Item(),
-    'A2/B/lambda'  : Item("This is the file 'lambda'.\n"),
-    'A2/B/E'       : Item(),
-    'A2/B/E/alpha' : Item("This is the file 'alpha'.\n"),
-    'A2/B/E/beta'  : Item("This is the file 'beta'.\n"),
-    'A2/B/F'       : Item(),
-    'A2/C'         : Item(),
-    'A2/D'         : Item(),
-    'A2/D/gamma'   : Item("This is the file 'gamma'.\n"),
-    'A2/D/G'       : Item(),
-    'A2/D/G/pi'    : Item("This is the file 'pi'.\nEdited in wc 1.\n"),
-    'A2/D/G/rho'   : Item("This is the file 'rho'.\nEdited in wc 2.\n"),
-    'A2/D/H'       : Item(),
-    'A2/D/H/chi'   : Item("This is the file 'chi'.\n"),
-    'A2/D/H/psi'   : Item("This is the file 'psi'.\n"),
-    'A2/D/H/omega' : Item("This is the file 'omega'.\n"),
-  })
-  expected_disk.tweak('A/D/G/pi',
-                      contents="This is the file 'pi'.\nEdited in wc 1.\n")
-  expected_disk.remove('A/D/G/rho',
-                       'A/D/G/tau')
+  expected_disk = svntest.actions.deep_trees_virginal_state.copy()
+  expected_disk.tweak('F/alpha', contents="This is the file 'alpha'.\nMore text for file alpha.\n")
 
-  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
-  expected_status.add({
-    'A2'           : Item(wc_rev=3),
-    'A2/mu'        : Item(wc_rev=3),
-    'A2/B'         : Item(wc_rev=3),
-    'A2/B/lambda'  : Item(wc_rev=3),
-    'A2/B/E'       : Item(wc_rev=3),
-    'A2/B/E/alpha' : Item(wc_rev=3),
-    'A2/B/E/beta'  : Item(wc_rev=3),
-    'A2/B/F'       : Item(wc_rev=3),
-    'A2/C'         : Item(wc_rev=3),
-    'A2/D'         : Item(wc_rev=3),
-    'A2/D/gamma'   : Item(wc_rev=3),
-    'A2/D/G'       : Item(wc_rev=3),
-    'A2/D/G/pi'    : Item(wc_rev=3),
-    'A2/D/H'       : Item(wc_rev=3),
-    'A2/D/H/chi'   : Item(wc_rev=3),
-    'A2/D/H/psi'   : Item(wc_rev=3),
-    'A2/D/H/omega' : Item(wc_rev=3),
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status='  ', wc_rev='3'),
+    'F'                 : Item(status='C ', wc_rev='3'),
+    'DDF'               : Item(status='  ', wc_rev='3'),
+    'DDF/D1'            : Item(status='  ', wc_rev='3'),
+    'DDF/D1/D2'         : Item(status='  ', wc_rev='3'),
+    'DDF/D1/D2/gamma'   : Item(status='  ', wc_rev='3'),
+    'D'                 : Item(status='  ', wc_rev='3'),
+    'D/D1'              : Item(status='  ', wc_rev='3'),
+    'DD'                : Item(status='  ', wc_rev='3'),
+    'DD/D1'             : Item(status='  ', wc_rev='3'),
+    'DD/D1/D2'          : Item(status='  ', wc_rev='3'),
+    'DF'                : Item(status='  ', wc_rev='3'),
+    'DF/D1'             : Item(status='  ', wc_rev='3'),
+    'DF/D1/beta'        : Item(status='  ', wc_rev='3'),
+    'DDD'               : Item(status='  ', wc_rev='3'),
+    'DDD/D1'            : Item(status='  ', wc_rev='3'),
+    'DDD/D1/D2'         : Item(status='  ', wc_rev='3'),
+    'DDD/D1/D2/D3'      : Item(status='  ', wc_rev='3'),
+    })
+
+  greater_scheme += [ DeepTreesTestCase("local_leaf_edit_incoming_tree_del_F",
+                                        leaf_edit_F,
+                                        tree_del_F,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status) ]
+
+  greater_scheme += [ DeepTreesTestCase("local_leaf_edit_incoming_tree_del_D",
+                                        leaf_edit_D,
+                                        tree_del_D,
+                                        error_re_string = error_re_string) ]
+
+  greater_scheme += [ DeepTreesTestCase("local_leaf_edit_incoming_tree_del_DF",
+                                        leaf_edit_DF,
+                                        tree_del_DF,
+                                        error_re_string = error_re_string) ]
+
+  greater_scheme += [ DeepTreesTestCase("local_leaf_edit_incoming_tree_del_DD",
+                                        leaf_edit_DD,
+                                        tree_del_DD,
+                                        error_re_string = error_re_string) ]
+
+  greater_scheme += [ DeepTreesTestCase("local_leaf_edit_incoming_tree_del_DDF",
+                                        leaf_edit_DDF,
+                                        tree_del_DDF,
+                                        error_re_string = error_re_string) ]
+
+  greater_scheme += [ DeepTreesTestCase("local_leaf_edit_incoming_tree_del_DDD",
+                                        leaf_edit_DDD,
+                                        tree_del_DDD,
+                                        error_re_string = error_re_string) ]
+
+
+  # 2.2) local leaf delete, incoming tree delete
+
+  expected_output = svntest.wc.State('', {
+    'D'                 : Item(status='C '),
+    'D/D1'              : Item(status='D '),
+    'F'                 : Item(status='C '),
+    'F/alpha'           : Item(status='D '),
+    'DD'                : Item(),
+    'DD/D1'             : Item(status='D '),
+    'DF'                : Item(),
+    'DF/D1'             : Item(status='D '),
+    'DDD'               : Item(),
+    'DDD/D1'            : Item(status='D '),
+    'DDF'               : Item(),
+    'DDF/D1'            : Item(status='D '),
+    })
+
+  expected_disk = state_after_tree_del
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status='  ', wc_rev='3'),
+    'D'                 : Item(status='C ', wc_rev='3'),
+    'F'                 : Item(status='C ', wc_rev='3'),
+    'DD'                : Item(status='  ', wc_rev='3'),
+    'DF'                : Item(status='  ', wc_rev='3'),
+    'DDD'               : Item(status='  ', wc_rev='3'),
+    'DDF'               : Item(status='  ', wc_rev='3'),
+    })
+
+  greater_scheme += [ DeepTreesTestCase("local_leaf_del_incoming_tree_del",
+                                        leaf_del,
+                                        tree_del,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status) ]
+
+
+  # use case 3, as in notes/tree-conflicts/use-cases.txt
+  # local tree delete, incoming tree delete
+
+  expected_output = svntest.wc.State('', {
+    'D'                 : Item(status='C '),
+    'D/D1'              : Item(status='D '),
+    'F'                 : Item(status='C '),
+    'F/alpha'           : Item(status='D '),
+    'DD'                : Item(status='C '),
+    'DD/D1'             : Item(status='D '),
+    'DF'                : Item(status='C '),
+    'DF/D1'             : Item(status='D '),
+    'DDD'               : Item(status='C '),
+    'DDD/D1'            : Item(status='D '),
+    'DDF'               : Item(status='C '),
+    'DDF/D1'            : Item(status='D '),
   })
-  expected_status.tweak(status='  ')
-  expected_status.tweak('A2', switched='S')
-  expected_status.tweak('A2/D/G', status='C ')
-  expected_status.tweak('A2/D/G/pi', status='D ')
-  expected_status.tweak('A/D/G/pi', wc_rev=3)
-  expected_status.remove('A/D/G/rho',
-                         'A/D/G/tau')
 
-  svntest.actions.run_and_verify_switch(wc_dir, A2, 
-                                        sbox.repo_url + '/A',
+  expected_disk = state_after_tree_del
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status='  ', wc_rev='3'),
+    'F'                 : Item(status='C ', wc_rev='3'),
+    'D'                 : Item(status='C ', wc_rev='3'),
+    'DF'                : Item(status='C ', wc_rev='3'),
+    'DD'                : Item(status='C ', wc_rev='3'),
+    'DDF'               : Item(status='C ', wc_rev='3'),
+    'DDD'               : Item(status='C ', wc_rev='3'),
+    })
+
+
+  greater_scheme += [ DeepTreesTestCase("local_tree_del_incoming_tree_del",
+                                        tree_del,
+                                        tree_del,
                                         expected_output,
                                         expected_disk,
-                                        expected_status)
+                                        expected_status) ]
 
 
+  # now run the whole bunch of them.
+  svntest.actions.deep_trees_run_tests_scheme_for_switch(sbox, greater_scheme)
+
+
+
 ########################################################################
 # Run the tests
 
@@ -2232,7 +2496,7 @@
               switch_urls_with_spaces,
               switch_to_dir_with_peg_rev2,
               switch_to_root,
-              tree_conflicts_in_switched_files,
+              tree_conflicts_on_switch,
              ]
 
 if __name__ == '__main__':
Index: subversion/tests/cmdline/update_tests.py
===================================================================
--- subversion/tests/cmdline/update_tests.py	(revision 32499)
+++ subversion/tests/cmdline/update_tests.py	(working copy)
@@ -3862,50 +3862,251 @@
 
 #----------------------------------------------------------------------
 
-def tree_conflicts_in_updated_files(sbox):
-  "tree conflicts in updated files"
+# Detect tree conflicts among files and directories,
+# edited or deleted in a deep directory structure.
+#
+# See use cases 1-3 in notes/tree-conflicts/use-cases.txt for background.
+#
+def tree_conflicts_on_update(sbox):
+  "tree conflicts on update (tc use cases 1 to 3)"
 
-  # Detect simple tree conflicts among files edited or deleted in a single
-  # directory.
+  # Each case is constructed and then appended to this table, which
+  # is initially empty:
+  greater_scheme = [];
 
-  # See use cases 1-3 in notes/tree-conflicts/use-cases.txt for background.
-  # Note that we do not try to track renames.  The only difference from
-  # the behavior of Subversion 1.4 and 1.5 is the conflicted status of the
-  # parent directory.
+  # convenience definitions
+  leaf_edit = svntest.actions.deep_trees_leaf_edit
+  tree_del = svntest.actions.deep_trees_tree_del
+  leaf_del = svntest.actions.deep_trees_leaf_del
 
-  sbox.build()
-  wc_dir = sbox.wc_dir
+  state_after_leaf_edit = svntest.actions.deep_trees_after_leaf_edit
+  state_after_leaf_del = svntest.actions.deep_trees_after_leaf_del
+  state_after_tree_del = svntest.actions.deep_trees_after_tree_del
 
-  # Set up tree conflicts in wc 2
-  wc_dir_2 = svntest.actions.set_up_tree_conflicts(sbox)
+  DeepTreesTestCase = svntest.actions.DeepTreesTestCase
 
-  # Update in wc 2
-  expected_output = wc.State(wc_dir_2, {
-    'A/D/G'       : Item(status='C '),
-    'A/D/G/pi'    : Item(status='U '),
-    'A/D/G/rho'   : Item(status='D '),
-    'A/D/G/tau'   : Item(status='D '),
+
+  # use case 1, as in notes/tree-conflicts/use-cases.txt
+  # 1.1) local tree delete, incoming leaf edit
+
+  expected_output = wc.State('', {
+    'F'                 : Item(status='C '),
+    'F/alpha'           : Item(status='U '),
+    'D'                 : Item(status='C '),
+    'D/D1/delta'        : Item(status='A '),
+    'DF'                : Item(status='C '),
+    'DF/D1'             : Item(status='C '),
+    'DF/D1/beta'        : Item(status='U '),
+    'DD'                : Item(status='C '),
+    'DD/D1'             : Item(status='C '),
+    'DD/D1/D2/epsilon'  : Item(status='A '),
+    'DDF'               : Item(status='C '),
+    'DDF/D1'            : Item(status='C '),
+    'DDF/D1/D2'         : Item(status='C '),
+    'DDF/D1/D2/gamma'   : Item(status='U '),
+    'DDD'               : Item(status='C '),
+    'DDD/D1'            : Item(status='C '),
+    'DDD/D1/D2'         : Item(status='C '),
+    'DDD/D1/D2/D3/zeta' : Item(status='A '),
     })
 
-  expected_disk = svntest.main.greek_state.copy()
-  expected_disk.tweak('A/D/G/pi',
-                      contents="This is the file 'pi'.\nEdited in wc 1.\n")
-  expected_disk.tweak('A/D/G/rho',
-                      contents="This is the file 'rho'.\nEdited in wc 2.\n")
-  expected_disk.remove('A/D/G/tau')
+  expected_disk = state_after_leaf_edit
 
-  expected_status = svntest.actions.get_virginal_state(wc_dir_2, 2)
-  expected_status.tweak('A/D/G',     status='C ')
-  expected_status.tweak('A/D/G/pi',  status='D ')
-  expected_status.remove('A/D/G/rho',
-                         'A/D/G/tau')
+  expected_status = wc.State('', {
+    ''                  : Item(status='  ', wc_rev='3'),
+    'F'                 : Item(status='C ', wc_rev='3'),
+    'F/alpha'           : Item(status='D ', wc_rev='3'),
+    'D'                 : Item(status='C ', wc_rev='3'),
+    'D/D1'              : Item(status='D ', wc_rev='3'),
+    'D/D1/delta'        : Item(status='  ', wc_rev='3'),
+    'DF'                : Item(status='C ', wc_rev='3'),
+    'DF/D1'             : Item(status='D ', wc_rev='3'),
+    'DF/D1/beta'        : Item(status='D ', wc_rev='3'),
+    'DD'                : Item(status='C ', wc_rev='3'),
+    'DD/D1'             : Item(status='D ', wc_rev='3'),
+    'DD/D1/D2'          : Item(status='D ', wc_rev='3'),
+    'DD/D1/D2/epsilon'  : Item(status='  ', wc_rev='3'),
+    'DDF'               : Item(status='C ', wc_rev='3'),
+    'DDF/D1'            : Item(status='D ', wc_rev='3'),
+    'DDF/D1/D2'         : Item(status='D ', wc_rev='3'),
+    'DDF/D1/D2/gamma'   : Item(status='D ', wc_rev='3'),
+    'DDD'               : Item(status='C ', wc_rev='3'),
+    'DDD/D1'            : Item(status='D ', wc_rev='3'),
+    'DDD/D1/D2'         : Item(status='D ', wc_rev='3'),
+    'DDD/D1/D2/D3'      : Item(status='D ', wc_rev='3'),
+    'DDD/D1/D2/D3/zeta' : Item(status='  ', wc_rev='3'),
+    })
 
-  svntest.actions.run_and_verify_update(wc_dir_2,
+  greater_scheme += [ DeepTreesTestCase("local_tree_del_incoming_leaf_edit",
+                                        tree_del,
+                                        leaf_edit,
                                         expected_output,
                                         expected_disk,
-                                        expected_status)
+                                        expected_status) ]
 
 
+  # 1.2) local tree delete, incoming leaf delete
+
+  expected_output = wc.State('', {
+    'F'                 : Item(status='C '),
+    'F/alpha'           : Item(status='D '),
+    'D'                 : Item(status='C '),
+    'D/D1'              : Item(status='D '),
+    'DF'                : Item(status='C '),
+    'DF/D1'             : Item(status='C '),
+    'DF/D1/beta'        : Item(status='D '),
+    'DD'                : Item(status='C '),
+    'DD/D1'             : Item(status='C '),
+    'DD/D1/D2'          : Item(status='D '),
+    'DDF'               : Item(status='C '),
+    'DDF/D1'            : Item(status='C '),
+    'DDF/D1/D2'         : Item(status='C '),
+    'DDF/D1/D2/gamma'   : Item(status='D '),
+    'DDD'               : Item(status='C '),
+    'DDD/D1'            : Item(status='C '),
+    'DDD/D1/D2'         : Item(status='C '),
+    'DDD/D1/D2/D3'      : Item(status='D '),
+    })
+
+  expected_disk = state_after_leaf_del
+
+  expected_status = wc.State('', {
+    ''                  : Item(status='  ', wc_rev='3'),
+    'F'                 : Item(status='C ', wc_rev='3'),
+    'D'                 : Item(status='C ', wc_rev='3'),
+    'DF'                : Item(status='C ', wc_rev='3'),
+    'DF/D1'             : Item(status='D ', wc_rev='3'),
+    'DD'                : Item(status='C ', wc_rev='3'),
+    'DD/D1'             : Item(status='D ', wc_rev='3'),
+    'DDF'               : Item(status='C ', wc_rev='3'),
+    'DDF/D1'            : Item(status='D ', wc_rev='3'),
+    'DDF/D1/D2'         : Item(status='D ', wc_rev='3'),
+    'DDD'               : Item(status='C ', wc_rev='3'),
+    'DDD/D1'            : Item(status='D ', wc_rev='3'),
+    'DDD/D1/D2'         : Item(status='D ', wc_rev='3'),
+    })
+
+  greater_scheme += [ DeepTreesTestCase("local_tree_del_incoming_leaf_del",
+                                        tree_del,
+                                        leaf_del,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status) ]
+
+
+  # use case 2, as in notes/tree-conflicts/use-cases.txt
+  # 2.1) local leaf edit, incoming tree delete
+
+  expected_output = wc.State('', {
+    'F'                 : Item(status='C '),
+    'F/alpha'           : Item(status='D '),
+    'D/D1'              : Item(status='D '),
+    'DF/D1'             : Item(status='D '),
+    'DD/D1'             : Item(status='D '),
+    'DDF/D1'            : Item(status='D '),
+    'DDD/D1'            : Item(status='D '),
+    })
+
+  expected_disk = state_after_leaf_edit
+
+  expected_status = wc.State('', {
+    ''                  : Item(status='  ', wc_rev='3'),
+    'F'                 : Item(status='C ', wc_rev='3'),
+    'D'                 : Item(status='  ', wc_rev='3'),
+    'DF'                : Item(status='  ', wc_rev='3'),
+    'DD'                : Item(status='  ', wc_rev='3'),
+    'DDF'               : Item(status='  ', wc_rev='3'),
+    'DDD'               : Item(status='  ', wc_rev='3'),
+    })
+
+  greater_scheme += [ DeepTreesTestCase("local_leaf_edit_incoming_tree_del",
+                                        leaf_edit,
+                                        tree_del,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status) ]
+
+
+  # 2.2) local leaf delete, incoming tree delete
+
+  expected_output = wc.State('', {
+    'D'                 : Item(status='C '),
+    'D/D1'              : Item(status='D '),
+    'F'                 : Item(status='C '),
+    'F/alpha'           : Item(status='D '),
+    'DD'                : Item(),
+    'DD/D1'             : Item(status='D '),
+    'DF'                : Item(),
+    'DF/D1'             : Item(status='D '),
+    'DDD'               : Item(),
+    'DDD/D1'            : Item(status='D '),
+    'DDF'               : Item(),
+    'DDF/D1'            : Item(status='D '),
+    })
+
+  expected_disk = state_after_tree_del
+
+  expected_status = wc.State('', {
+    ''                  : Item(status='  ', wc_rev='3'),
+    'F'                 : Item(status='C ', wc_rev='3'),
+    'DD'                : Item(status='  ', wc_rev='3'),
+    'DF'                : Item(status='  ', wc_rev='3'),
+    'DDD'               : Item(status='  ', wc_rev='3'),
+    'DDF'               : Item(status='  ', wc_rev='3'),
+    'D'                 : Item(status='C ', wc_rev='3'),
+    })
+
+  greater_scheme += [ DeepTreesTestCase("local_leaf_del_incoming_tree_del",
+                                        leaf_del,
+                                        tree_del,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status) ]
+
+
+  # use case 3, as in notes/tree-conflicts/use-cases.txt
+  # local tree delete, incoming tree delete
+
+  expected_output = wc.State('', {
+    'F'                 : Item(status='C '),
+    'F/alpha'           : Item(status='D '),
+    'D'                 : Item(status='C '),
+    'D/D1'              : Item(status='D '),
+    'DF'                : Item(status='C '),
+    'DF/D1'             : Item(status='D '),
+    'DD'                : Item(status='C '),
+    'DD/D1'             : Item(status='D '),
+    'DDF'               : Item(status='C '),
+    'DDF/D1'            : Item(status='D '),
+    'DDD'               : Item(status='C '),
+    'DDD/D1'            : Item(status='D '),
+    })
+
+  expected_disk = state_after_tree_del
+
+  expected_status = wc.State('', {
+    ''                  : Item(status='  ', wc_rev='3'),
+    'F'                 : Item(status='C ', wc_rev='3'),
+    'D'                 : Item(status='C ', wc_rev='3'),
+    'DF'                : Item(status='C ', wc_rev='3'),
+    'DD'                : Item(status='C ', wc_rev='3'),
+    'DDF'               : Item(status='C ', wc_rev='3'),
+    'DDD'               : Item(status='C ', wc_rev='3'),
+    })
+
+  greater_scheme += [ DeepTreesTestCase("local_tree_del_incoming_tree_del",
+                                        tree_del,
+                                        tree_del,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status) ]
+
+
+  # now run the whole bunch of them.
+  svntest.actions.deep_trees_run_tests_scheme_for_update(sbox, greater_scheme)
+
+
+
 #######################################################################
 # Run the tests
 
@@ -3959,7 +4160,7 @@
               update_accept_conflicts,
               eof_in_interactive_conflict_resolver,
               update_uuid_changed,
-              tree_conflicts_in_updated_files,
+              tree_conflicts_on_update,
              ]
 
 if __name__ == '__main__':
Index: subversion/tests/cmdline/svntest/tree.py
===================================================================
--- subversion/tests/cmdline/svntest/tree.py	(revision 32499)
+++ subversion/tests/cmdline/svntest/tree.py	(working copy)
@@ -207,6 +207,40 @@
     else:
       print >> stream, "    Children:  None (node is probably a file)"
 
+  def print_script(self, stream = sys.stdout, strip = 0):
+    "Python-script-print the meta data for this node."
+    
+    path = self.path
+    if len(path) > len(root_node_name) and path.startswith(root_node_name):
+      path = path[(len(root_node_name)+1):]
+    if len(path) > strip:
+      path = path[strip:]
+
+    line = "%-20s: Item(" % ("'%s'" % path)
+    comma = False
+
+    mime_type = self.props.get("svn:mime-type")
+    if not mime_type or mime_type.startswith("text/"):
+      if self.children is None and not self.contents is None:
+        line += "contents=\"\"\"%s\"\"\"" % self.contents
+        comma = True
+
+    for name in self.atts:
+      if comma:
+        line += ", "
+      line += "%s='%s'" % (name, self.atts[name])
+      comma = True
+
+#    for name in self.props:
+#      if comma:
+#        line += ", "
+#      line += "%s='%s'" % (name, self.props[name])
+#      comma = True
+
+    line += "),"
+    print >> stream, line
+
+
   def __str__(self):
     import StringIO
     s = StringIO.StringIO()
@@ -555,7 +589,7 @@
 
 # Visually show a tree's structure
 
-def dump_tree(n,indent=""):
+def dump_tree(n,indent="",verbose=False):
   "Print out a nice representation of the tree's structure."
 
   # Code partially stolen from Dave Beazley
@@ -569,17 +603,41 @@
   else:
     print "%s%s" % (indent, n.name)
 
+  if verbose:
+    n.pprint()
+
   indent = indent.replace("-", " ")
   indent = indent.replace("+", " ")
   for i in range(len(tmp_children)):
     c = tmp_children[i]
     if i == len(tmp_children
                 )-1:
-      dump_tree(c,indent + "  +-- ")
+      dump_tree(c,indent + "  +-- ",verbose)
     else:
-      dump_tree(c,indent + "  |-- ")
+      dump_tree(c,indent + "  |-- ",verbose)
 
+def dump_tree_script(n, strip=0):
+  "Print out a python script representation of the tree's structure."
 
+  # Code partially stolen from Dave Beazley
+  if n.children is None:
+    tmp_children = []
+  else:
+    tmp_children = n.children
+
+  if n.name != root_node_name:
+    if strip < len(n.path):
+      n.print_script(strip = strip)
+
+  for i in range(len(tmp_children)):
+    c = tmp_children[i]
+    if i == len(tmp_children
+                )-1:
+      dump_tree_script(c, strip=strip)
+    else:
+      dump_tree_script(c, strip=strip)
+
+
 ###################################################################
 ###################################################################
 # PARSERS that return trees made of SVNTreeNodes....
Index: subversion/tests/cmdline/merge_tests.py
===================================================================
--- subversion/tests/cmdline/merge_tests.py	(revision 32499)
+++ subversion/tests/cmdline/merge_tests.py	(working copy)
@@ -12548,6 +12548,8 @@
                                        None, None, None, None, None, 1)
   os.chdir(saved_cwd)
 
+
+#----------------------------------------------------------------------
 # Helper for text output.
 def verify_lines(lines, regexes):
   """Return True if each of the given regular expressions matches
@@ -12581,107 +12583,10 @@
                           actions_and_victims)):
     raise svntest.Failure("Wrong tree-conflict result")
 
-# This test involves tree conflicts.
-def tree_conflicts_in_merged_files(sbox):
-  "tree conflicts in merged files"
 
-  # Detect simple tree conflicts among files edited or deleted in a single
-  # directory.
 
-  # See use cases 4-6 in notes/tree-conflicts/use-cases.txt for background.
-  # Note that we do not try to track renames.  The only difference from
-  # the behavior of Subversion 1.4 and 1.5 is the conflicted status of the
-  # parent directory.
+#----------------------------------------------------------------------
 
-  sbox.build()
-  wc_dir = sbox.wc_dir
-
-  # Set up tree conflicts in wc 2
-  wc_dir_2 = svntest.actions.set_up_tree_conflicts_for_merge(sbox)
-  j = os.path.join
-  A2 = j(wc_dir, 'A2')
-  D2 = j(wc_dir, 'A2', 'D')
-  G2 = j(wc_dir, 'A2', 'D', 'G')
-  svntest.main.run_svn(None, 'ci', '-m', 'Changes in wc 2.', A2)
-
-  # Merge a revision from url 1 into wc 2
-  expected_output = wc.State(A2, {
-    'D'         : Item(status='C '),
-    'D/sigma'   : Item(status='D '),
-    'D/G'       : Item(status='C '),
-    'D/G/rho'   : Item(status='D '),
-    })
-
-  expected_disk = wc.State('', {
-    'mu'        : Item("This is the file 'mu'.\n"),
-    'B'         : Item(),
-    'B/lambda'  : Item("This is the file 'lambda'.\n"),
-    'B/E'       : Item(),
-    'B/E/alpha' : Item("This is the file 'alpha'.\n"),
-    'B/E/beta'  : Item("This is the file 'beta'.\n"),
-    'B/F'       : Item(),
-    'C'         : Item(),
-    'D'         : Item(),
-    'D/sigma'   : Item("This is the file 'sigma'.\nEdited in wc 2.\n"),
-    'D/G'       : Item(),
-    'D/G/rho'   : Item("This is the file 'rho'.\nEdited in wc 2.\n"),
-    'D/H'       : Item(),
-    'D/H/chi'   : Item("This is the file 'chi'.\n"),
-    'D/H/psi'   : Item("This is the file 'psi'.\n"),
-    'D/H/omega' : Item("This is the file 'omega'.\n"),
-    })
-
-  expected_status = wc.State(A2, {
-    ''          : Item(),
-    'mu'        : Item(),
-    'B'         : Item(),
-    'B/lambda'  : Item(),
-    'B/E'       : Item(),
-    'B/E/alpha' : Item(),
-    'B/E/beta'  : Item(),
-    'B/F'       : Item(),
-    'C'         : Item(),
-    'D'         : Item(),
-    'D/sigma'   : Item(),
-    'D/G'       : Item(),
-    'D/G/rho'   : Item(),
-    'D/H'       : Item(),
-    'D/H/chi'   : Item(),
-    'D/H/psi'   : Item(),
-    'D/H/omega' : Item(),
-    })
-  expected_status.tweak(status='  ', wc_rev=3)
-  expected_status.tweak('', status=' M')
-  expected_status.tweak('D', 'D/G', status='C ')
-  expected_status.tweak('D/sigma', 'D/G/rho', status='D ', wc_rev=5)
-
-  expected_skip = wc.State(A2, {
-    'D/gamma'   : Item(),
-    'D/theta'   : Item(),
-    'D/G/pi'    : Item(),
-    'D/G/tau'   : Item(),
-    })
-
-  svntest.actions.run_and_verify_merge(A2, 3, 4,
-                                       sbox.repo_url + '/A',
-                                       expected_output,
-                                       expected_disk,
-                                       expected_status,
-                                       expected_skip)
-
-  # Make sure all victims have been found.
-  verify_tree_conflict_info(D2,
-                            [('edit',   'gamma'),  # use case 4
-                             ('delete', 'sigma'),  # use case 5
-                             ('delete', 'theta'),  # use case 6
-                             ])
-  verify_tree_conflict_info(G2,
-                            [('edit',   'pi'),   # use case 4
-                             ('delete', 'rho'),  # use case 5
-                             ('delete', 'tau'),  # use case 6
-                             ])
-
-
 # This test involves tree conflicts.
 def tree_conflicts_and_obstructions(sbox):
   "tree conflicts and obstructions"
@@ -12752,6 +12657,646 @@
                             [('add', 'alpha-moved')])
 
 
+#----------------------------------------------------------------------
+
+# Detect tree conflicts among files and directories,
+# edited or deleted in a deep directory structure.
+#
+# See use cases 4-6 in notes/tree-conflicts/use-cases.txt for background.
+# Note that we do not try to track renames.  The only difference from
+# the behavior of Subversion 1.4 and 1.5 is the conflicted status of the
+# parent directory.
+#
+def tree_conflicts_on_merge_local_ci(sbox):
+  "tree conflicts on merge, local commit (tc 4-6)"
+
+  # Each case is constructed and then appended to the table, which
+  # is initially empty:
+  greater_scheme = [];
+
+  # convenience definitions
+  leaf_edit = svntest.actions.deep_trees_leaf_edit
+  tree_del = svntest.actions.deep_trees_tree_del
+  leaf_del = svntest.actions.deep_trees_leaf_del
+
+  state_after_leaf_edit = svntest.actions.deep_trees_after_leaf_edit
+  state_after_leaf_del = svntest.actions.deep_trees_after_leaf_del
+  state_after_tree_del = svntest.actions.deep_trees_after_tree_del
+
+  j = os.path.join
+
+  DeepTreesTestCase = svntest.actions.DeepTreesTestCase
+
+
+  # use case 1, as in notes/tree-conflicts/use-cases.txt
+  # 1.1) local tree delete, incoming leaf edit
+
+  expected_output = svntest.wc.State('', {
+    'F'                 : Item(status='C '),
+    'D'                 : Item(status='C '),
+    'DF'                : Item(status='C '),
+    'DD'                : Item(status='C '),
+    'DDF'               : Item(status='C '),
+    'DDD'               : Item(status='C '),
+    })
+
+  expected_disk = state_after_tree_del
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status=' M', wc_rev='7'),
+    'F'                 : Item(status='C ', wc_rev='7'),
+    'D'                 : Item(status='C ', wc_rev='7'),
+    'DF'                : Item(status='C ', wc_rev='7'),
+    'DD'                : Item(status='C ', wc_rev='7'),
+    'DDF'               : Item(status='C ', wc_rev='7'),
+    'DDD'               : Item(status='C ', wc_rev='7'),
+    })
+
+  expected_skip = svntest.wc.State('', {
+    'F/alpha'           : Item(),
+    'DF/D1/beta'        : Item(),
+    'DDF/D1/D2/gamma'   : Item(),
+    'D/D1/delta'        : Item(),
+    'DD/D1/D2/epsilon'  : Item(),
+    'DDD/D1/D2/D3/zeta' : Item(),
+    })
+
+  greater_scheme += [ DeepTreesTestCase("local_tree_del_incoming_leaf_edit",
+                                        tree_del,
+                                        leaf_edit,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        expected_skip) ]
+
+  # 1.2) local tree delete, incoming leaf delete
+
+  expected_output = svntest.wc.State('', {
+    'F'                 : Item(status='C '),
+    'D'                 : Item(status='C '),
+    'DF'                : Item(status='C '),
+    'DD'                : Item(status='C '),
+    'DDF'               : Item(status='C '),
+    'DDD'               : Item(status='C '),
+    })
+
+  expected_disk = state_after_tree_del
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status=' M', wc_rev='7'),
+    'F'                 : Item(status='C ', wc_rev='7'),
+    'D'                 : Item(status='C ', wc_rev='7'),
+    'DF'                : Item(status='C ', wc_rev='7'),
+    'DD'                : Item(status='C ', wc_rev='7'),
+    'DDF'               : Item(status='C ', wc_rev='7'),
+    'DDD'               : Item(status='C ', wc_rev='7'),
+    })
+
+  expected_skip = svntest.wc.State('', {
+    'F/alpha'           : Item(),
+    'DF/D1/beta'        : Item(),
+    'DDF/D1/D2/gamma'   : Item(),
+    'D/D1'              : Item(),
+    'DD/D1/D2'          : Item(),
+    'DDD/D1/D2/D3'      : Item(),
+    })
+
+  greater_scheme += [ DeepTreesTestCase("local_tree_del_incoming_leaf_del",
+                                        tree_del,
+                                        leaf_del,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        expected_skip) ]
+
+
+
+
+  # use case 2, as in notes/tree-conflicts/use-cases.txt
+  # 2.1) local leaf edit, incoming tree delete
+
+  expected_output = svntest.wc.State('', {
+    'D'                 : Item(),
+    'D/D1'              : Item(status='D '),
+    'F'                 : Item(status='C '),
+    'F/alpha'           : Item(status='D '),
+    'DD'                : Item(),
+    'DD/D1'             : Item(status='D '),
+    'DF'                : Item(),
+    'DF/D1'             : Item(status='D '),
+    'DDD'               : Item(),
+    'DDD/D1'            : Item(status='D '),
+    'DDF'               : Item(),
+    'DDF/D1'            : Item(status='D '),
+    })
+
+  expected_disk = svntest.wc.State('', {
+    'DF'                : Item(),
+    'DF/D1'             : Item(),
+    'DDF'               : Item(),
+    'DDF/D1'            : Item(),
+    'DDF/D1/D2'         : Item(),
+    'F'                 : Item(),
+    'F/alpha'           : Item(contents="This is the file 'alpha'.\nMore text for file alpha.\n"),
+    'DDD'               : Item(),
+    'DDD/D1'            : Item(),
+    'DDD/D1/D2'         : Item(),
+    'DDD/D1/D2/D3'      : Item(),
+    'DD'                : Item(),
+    'DD/D1'             : Item(),
+    'DD/D1/D2'          : Item(),
+    'D'                 : Item(),
+    'D/D1'              : Item(),
+    })
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status=' M', wc_rev='7'),
+    'D'                 : Item(status='  ', wc_rev='7'),
+    'D/D1'              : Item(status='D ', wc_rev='7'),
+    'D/D1/delta'        : Item(status='D ', wc_rev='8'),
+    'F'                 : Item(status='C ', wc_rev='7'),
+    'F/alpha'           : Item(status='D ', wc_rev='8'),
+    'DD'                : Item(status='  ', wc_rev='7'),
+    'DD/D1'             : Item(status='D ', wc_rev='7'),
+    'DD/D1/D2'          : Item(status='D ', wc_rev='7'),
+    'DD/D1/D2/epsilon'  : Item(status='D ', wc_rev='8'),
+    'DF'                : Item(status='  ', wc_rev='7'),
+    'DF/D1'             : Item(status='D ', wc_rev='7'),
+    'DF/D1/beta'        : Item(status='D ', wc_rev='8'),
+    'DDD'               : Item(status='  ', wc_rev='7'),
+    'DDD/D1'            : Item(status='D ', wc_rev='7'),
+    'DDD/D1/D2'         : Item(status='D ', wc_rev='7'),
+    'DDD/D1/D2/D3'      : Item(status='D ', wc_rev='7'),
+    'DDD/D1/D2/D3/zeta' : Item(status='D ', wc_rev='8'),
+    'DDF'               : Item(status='  ', wc_rev='7'),
+    'DDF/D1'            : Item(status='D ', wc_rev='7'),
+    'DDF/D1/D2'         : Item(status='D ', wc_rev='7'),
+    'DDF/D1/D2/gamma'   : Item(status='D ', wc_rev='8'),
+    })
+
+  expected_skip = svntest.wc.State('', {})
+
+  greater_scheme += [ DeepTreesTestCase("local_leaf_edit_incoming_tree_del",
+                                        leaf_edit,
+                                        tree_del,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        expected_skip) ]
+
+
+  # 2.2) local leaf del, incoming tree delete
+
+  expected_output = svntest.wc.State('', {
+    'D'                 : Item(status='C '),
+    'F'                 : Item(status='C '),
+    'DD'                : Item(),
+    'DD/D1'             : Item(status='D '),
+    'DF'                : Item(),
+    'DF/D1'             : Item(status='D '),
+    'DDD'               : Item(),
+    'DDD/D1'            : Item(status='D '),
+    'DDF'               : Item(),
+    'DDF/D1'            : Item(status='D '),
+    })
+
+
+  expected_disk = svntest.wc.State('', {
+    'F'                 : Item(),
+    'D'                 : Item(),
+    'DF/D1'             : Item(),
+    'DD/D1'             : Item(),
+    'DDF/D1/D2'         : Item(),
+    'DDD/D1/D2'         : Item(),
+    })
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status=' M', wc_rev='7'),
+    'D'                 : Item(status='C ', wc_rev='7'),
+    'F'                 : Item(status='C ', wc_rev='7'),
+    'DD'                : Item(status='  ', wc_rev='7'),
+    'DD/D1'             : Item(status='D ', wc_rev='7'),
+    'DF'                : Item(status='  ', wc_rev='7'),
+    'DF/D1'             : Item(status='D ', wc_rev='7'),
+    'DDD'               : Item(status='  ', wc_rev='7'),
+    'DDD/D1'            : Item(status='D ', wc_rev='7'),
+    'DDD/D1/D2'         : Item(status='D ', wc_rev='7'),
+    'DDF'               : Item(status='  ', wc_rev='7'),
+    'DDF/D1'            : Item(status='D ', wc_rev='7'),
+    'DDF/D1/D2'         : Item(status='D ', wc_rev='7'),
+    })
+
+  expected_skip = svntest.wc.State('', {
+    'F/alpha'           : Item(),
+    'D/D1'              : Item(),
+    })
+
+  greater_scheme += [ DeepTreesTestCase("local_leaf_del_incoming_tree_del",
+                                        leaf_del,
+                                        tree_del,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        expected_skip) ]
+
+
+  # use case 3, as in notes/tree-conflicts/use-cases.txt
+  # local tree delete, incoming tree delete
+
+  expected_output = svntest.wc.State('', {
+    'F'                 : Item(status='C '),
+    'D'                 : Item(status='C '),
+    'DF'                : Item(status='C '),
+    'DD'                : Item(status='C '),
+    'DDF'               : Item(status='C '),
+    'DDD'               : Item(status='C '),
+    })
+
+  expected_disk = state_after_tree_del
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status=' M', wc_rev='7'),
+    'D'                 : Item(status='C ', wc_rev='7'),
+    'F'                 : Item(status='C ', wc_rev='7'),
+    'DD'                : Item(status='C ', wc_rev='7'),
+    'DF'                : Item(status='C ', wc_rev='7'),
+    'DDD'               : Item(status='C ', wc_rev='7'),
+    'DDF'               : Item(status='C ', wc_rev='7'),
+    })
+
+  expected_skip = svntest.wc.State('', {
+    'D/D1'              : Item(),
+    'F/alpha'           : Item(),
+    'DD/D1'             : Item(),
+    'DF/D1'             : Item(),
+    'DDD/D1'            : Item(),
+    'DDF/D1'            : Item(),
+    })
+
+  greater_scheme += [ DeepTreesTestCase("local_tree_del_incoming_tree_del",
+                                        tree_del,
+                                        tree_del,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        expected_skip) ]
+
+
+  # now run the whole bunch of them.
+  svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox, greater_scheme,
+                                                        True)
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+def tree_conflicts_on_merge_no_local_ci(sbox):
+  "tree conflicts on merge, NO local commit (tc 4-6)"
+
+  # Each case is constructed and then appended to the table, which
+  # is initially empty:
+  greater_scheme = [];
+
+  # convenience definitions
+  leaf_edit = svntest.actions.deep_trees_leaf_edit
+  tree_del = svntest.actions.deep_trees_tree_del
+  leaf_del = svntest.actions.deep_trees_leaf_del
+
+  state_after_leaf_edit = svntest.actions.deep_trees_after_leaf_edit
+  state_after_leaf_del = svntest.actions.deep_trees_after_leaf_del
+  state_after_tree_del = svntest.actions.deep_trees_after_tree_del
+
+  j = os.path.join
+
+  DeepTreesTestCase = svntest.actions.DeepTreesTestCase
+
+
+  # use case 1, as in notes/tree-conflicts/use-cases.txt
+  # 1.1) local tree delete, incoming leaf edit
+
+  expected_output = svntest.wc.State('', {
+    'F'                 : Item(status='C '),
+    'D'                 : Item(status='C '),
+    'D/D1'              : Item(),
+    'D/D1/delta'        : Item(status='A '),
+    'DF'                : Item(status='C '),
+    'DF/D1'             : Item(status='C '),
+    'DD'                : Item(status='C '),
+    'DD/D1'             : Item(status='C '),
+    'DD/D1/D2'          : Item(),
+    'DD/D1/D2/epsilon'  : Item(status='A '),
+    'DDF'               : Item(status='C '),
+    'DDF/D1'            : Item(status='C '),
+    'DDF/D1/D2'         : Item(status='C '),
+    'DDD'               : Item(status='C '),
+    'DDD/D1'            : Item(status='C '),
+    'DDD/D1/D2'         : Item(status='C '),
+    'DDD/D1/D2/D3'      : Item(),
+    'DDD/D1/D2/D3/zeta' : Item(status='A '),
+    })
+
+  expected_disk = svntest.wc.State('', {
+    'F'                 : Item(),
+    'D/D1/delta'        : Item(contents="This is the file 'delta'.\n"),
+    'DF/D1'             : Item(),
+    'DD/D1/D2/epsilon'  : Item(contents="This is the file 'epsilon'.\n"),
+    'DDF/D1/D2'         : Item(),
+    'DDD/D1/D2/D3/zeta' : Item(contents="This is the file 'zeta'.\n"),
+    })
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status=' M', wc_rev='7'),
+    'F'                 : Item(status='C ', wc_rev='7'),
+    'F/alpha'           : Item(status='D ', wc_rev='7'),
+    'DD'                : Item(status='C ', wc_rev='7'),
+    'DD/D1'             : Item(status='D ', wc_rev='7'),
+    'DD/D1/D2'          : Item(status='D ', wc_rev='7'),
+    'DD/D1/D2/epsilon'  : Item(status='A ', copied='+', wc_rev='-'),
+    'DF'                : Item(status='C ', wc_rev='7'),
+    'DF/D1'             : Item(status='D ', wc_rev='7'),
+    'DF/D1/beta'        : Item(status='D ', wc_rev='7'),
+    'DDD'               : Item(status='C ', wc_rev='7'),
+    'DDD/D1'            : Item(status='D ', wc_rev='7'),
+    'DDD/D1/D2'         : Item(status='D ', wc_rev='7'),
+    'DDD/D1/D2/D3'      : Item(status='D ', wc_rev='7'),
+    'DDD/D1/D2/D3/zeta' : Item(status='A ', copied='+', wc_rev='-'),
+    'DDF'               : Item(status='C ', wc_rev='7'),
+    'DDF/D1'            : Item(status='D ', wc_rev='7'),
+    'DDF/D1/D2'         : Item(status='D ', wc_rev='7'),
+    'DDF/D1/D2/gamma'   : Item(status='D ', wc_rev='7'),
+    'D'                 : Item(status='C ', wc_rev='7'),
+    'D/D1'              : Item(status='D ', wc_rev='7'),
+    'D/D1/delta'        : Item(status='A ', copied='+', wc_rev='-'),
+    })
+
+  alpha_beta_gamma = svntest.wc.State('', {
+    'F/alpha'           : Item(),
+    'DF/D1/beta'        : Item(),
+    'DDF/D1/D2/gamma'   : Item(),
+    })
+
+  expected_skip = alpha_beta_gamma
+
+  greater_scheme += [ DeepTreesTestCase(
+                               "local_tree_del_incoming_leaf_edit",
+                               tree_del,
+                               leaf_edit,
+                               expected_output,
+                               expected_disk,
+                               expected_status,
+                               expected_skip,
+                             ) ]
+
+  # 1.2) local tree delete, incoming leaf delete
+
+  expected_output = svntest.wc.State('', {
+    'F'                 : Item(status='C '),
+    'D'                 : Item(status='C '),
+    'D/D1'              : Item(status='D '),
+    'DF'                : Item(status='C '),
+    'DF/D1'             : Item(status='C '),
+    'DD'                : Item(status='C '),
+    'DD/D1'             : Item(status='C '),
+    'DD/D1/D2'          : Item(status='D '),
+    'DDF'               : Item(status='C '),
+    'DDF/D1'            : Item(status='C '),
+    'DDF/D1/D2'         : Item(status='C '),
+    'DDD'               : Item(status='C '),
+    'DDD/D1'            : Item(status='C '),
+    'DDD/D1/D2'         : Item(status='C '),
+    'DDD/D1/D2/D3'      : Item(status='D '),
+    })
+
+  expected_disk = svntest.wc.State('', {
+    'F'                 : Item(),
+    'D/D1'              : Item(),
+    'DF/D1'             : Item(),
+    'DD/D1/D2'          : Item(),
+    'DDF/D1/D2'         : Item(),
+    'DDD/D1/D2/D3'      : Item(),
+    })
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status=' M', wc_rev='7'),
+    'F'                 : Item(status='C ', wc_rev='7'),
+    'F/alpha'           : Item(status='D ', wc_rev='7'),
+    'D'                 : Item(status='C ', wc_rev='7'),
+    'D/D1'              : Item(status='D ', wc_rev='7'),
+    'DF'                : Item(status='C ', wc_rev='7'),
+    'DF/D1'             : Item(status='D ', wc_rev='7'),
+    'DF/D1/beta'        : Item(status='D ', wc_rev='7'),
+    'DD'                : Item(status='C ', wc_rev='7'),
+    'DD/D1'             : Item(status='D ', wc_rev='7'),
+    'DD/D1/D2'          : Item(status='D ', wc_rev='7'),
+    'DDF'               : Item(status='C ', wc_rev='7'),
+    'DDF/D1'            : Item(status='D ', wc_rev='7'),
+    'DDF/D1/D2'         : Item(status='D ', wc_rev='7'),
+    'DDF/D1/D2/gamma'   : Item(status='D ', wc_rev='7'),
+    'DDD'               : Item(status='C ', wc_rev='7'),
+    'DDD/D1'            : Item(status='D ', wc_rev='7'),
+    'DDD/D1/D2'         : Item(status='D ', wc_rev='7'),
+    'DDD/D1/D2/D3'      : Item(status='D ', wc_rev='7'),
+    })
+
+  expected_skip = alpha_beta_gamma
+
+  greater_scheme += [ DeepTreesTestCase(
+                               "local_tree_del_incoming_leaf_del",
+                               tree_del,
+                               leaf_del,
+                               expected_output,
+                               expected_disk,
+                               expected_status,
+                               expected_skip,
+                             ) ]
+
+
+
+
+  # use case 2, as in notes/tree-conflicts/use-cases.txt
+  # 2.1) local leaf edit, incoming tree delete
+
+  expected_output = svntest.wc.State('', {
+    'F'                 : Item(status='C '),
+    'F/alpha'           : Item(status='D '),
+    })
+
+  expected_disk = state_after_leaf_edit
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status=' M', wc_rev='7'),
+    'D'                 : Item(status='  ', wc_rev='7'),
+    'D/D1'              : Item(status=' M', wc_rev='7'),
+    'D/D1/delta'        : Item(status='A ', wc_rev='0'),
+    'F'                 : Item(status='C ', wc_rev='7'),
+    'F/alpha'           : Item(status='D ', wc_rev='7'),
+    'DD'                : Item(status='  ', wc_rev='7'),
+    'DD/D1'             : Item(status=' M', wc_rev='7'),
+    'DD/D1/D2'          : Item(status='  ', wc_rev='7'),
+    'DD/D1/D2/epsilon'  : Item(status='A ', wc_rev='0'),
+    'DF'                : Item(status='  ', wc_rev='7'),
+    'DF/D1'             : Item(status=' M', wc_rev='7'),
+    'DF/D1/beta'        : Item(status='M ', wc_rev='7'),
+    'DDD'               : Item(status='  ', wc_rev='7'),
+    'DDD/D1'            : Item(status=' M', wc_rev='7'),
+    'DDD/D1/D2'         : Item(status='  ', wc_rev='7'),
+    'DDD/D1/D2/D3'      : Item(status='  ', wc_rev='7'),
+    'DDD/D1/D2/D3/zeta' : Item(status='A ', wc_rev='0'),
+    'DDF'               : Item(status='  ', wc_rev='7'),
+    'DDF/D1'            : Item(status=' M', wc_rev='7'),
+    'DDF/D1/D2'         : Item(status='  ', wc_rev='7'),
+    'DDF/D1/D2/gamma'   : Item(status='M ', wc_rev='7'),
+    })
+
+  expected_skip = svntest.wc.State('', {
+    'D/D1'              : Item(),
+    'DF/D1'             : Item(),
+    'DD/D1'             : Item(),
+    'DDF/D1'            : Item(),
+    'DDD/D1'            : Item(),
+    })
+
+  greater_scheme += [ DeepTreesTestCase(
+                               "local_leaf_edit_incoming_tree_del",
+                               leaf_edit,
+                               tree_del,
+                               expected_output,
+                               expected_disk,
+                               expected_status,
+                               expected_skip,
+                             ) ]
+
+
+  # 2.2) local leaf del, incoming tree delete
+
+  expected_output = svntest.wc.State('', {
+    'D'                 : Item(status='C '),
+    'D/D1'              : Item(status='D '),
+    'F'                 : Item(status='C '),
+    'DD'                : Item(),
+    'DD/D1'             : Item(status='D '),
+    'DF'                : Item(),
+    'DF/D1'             : Item(status='D '),
+    'DDD'               : Item(),
+    'DDD/D1'            : Item(status='D '),
+    'DDF'               : Item(),
+    'DDF/D1'            : Item(status='D '),
+    })
+
+
+  expected_disk = svntest.wc.State('', {
+    'F'                 : Item(),
+    'D/D1'              : Item(),
+    'DF/D1'             : Item(),
+    'DD/D1/D2'          : Item(),
+    'DDF/D1/D2'         : Item(),
+    'DDD/D1/D2/D3'      : Item(),
+    })
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status=' M', wc_rev='7'),
+    'F'                 : Item(status='C ', wc_rev='7'),
+    'F/alpha'           : Item(status='D ', wc_rev='7'),
+    'DD'                : Item(status='  ', wc_rev='7'),
+    'DD/D1'             : Item(status='D ', wc_rev='7'),
+    'DD/D1/D2'          : Item(status='D ', wc_rev='7'),
+    'DF'                : Item(status='  ', wc_rev='7'),
+    'DF/D1'             : Item(status='D ', wc_rev='7'),
+    'DF/D1/beta'        : Item(status='D ', wc_rev='7'),
+    'DDD'               : Item(status='  ', wc_rev='7'),
+    'DDD/D1'            : Item(status='D ', wc_rev='7'),
+    'DDD/D1/D2'         : Item(status='D ', wc_rev='7'),
+    'DDD/D1/D2/D3'      : Item(status='D ', wc_rev='7'),
+    'DDF'               : Item(status='  ', wc_rev='7'),
+    'DDF/D1'            : Item(status='D ', wc_rev='7'),
+    'DDF/D1/D2'         : Item(status='D ', wc_rev='7'),
+    'DDF/D1/D2/gamma'   : Item(status='D ', wc_rev='7'),
+    'D'                 : Item(status='C ', wc_rev='7'),
+    'D/D1'              : Item(status='D ', wc_rev='7'),
+    })
+
+  expected_skip = svntest.wc.State('', {
+    'F/alpha'           : Item(),
+    })
+
+  greater_scheme += [ DeepTreesTestCase(
+                               "local_leaf_del_incoming_tree_del",
+                               leaf_del,
+                               tree_del,
+                               expected_output,
+                               expected_disk,
+                               expected_status,
+                               expected_skip,
+                             ) ]
+
+
+  # use case 3, as in notes/tree-conflicts/use-cases.txt
+  # local tree delete, incoming tree delete
+
+  expected_output = svntest.wc.State('', {
+    'D'                 : Item(status='C '),
+    'D/D1'              : Item(status='D '),
+    'F'                 : Item(status='C '),
+    'DD'                : Item(status='C '),
+    'DD/D1'             : Item(status='D '),
+    'DF'                : Item(status='C '),
+    'DF/D1'             : Item(status='D '),
+    'DDD'               : Item(status='C '),
+    'DDD/D1'            : Item(status='D '),
+    'DDF'               : Item(status='C '),
+    'DDF/D1'            : Item(status='D '),
+    })
+
+  expected_disk = svntest.wc.State('', {
+    'F'                 : Item(),
+    'D/D1'              : Item(),
+    'DF/D1'             : Item(),
+    'DD/D1/D2'          : Item(),
+    'DDF/D1/D2'         : Item(),
+    'DDD/D1/D2/D3'      : Item(),
+    })
+
+  expected_status = svntest.wc.State('', {
+    ''                  : Item(status=' M', wc_rev='7'),
+    'DDF'               : Item(status='C ', wc_rev='7'),
+    'DDF/D1'            : Item(status='D ', wc_rev='7'),
+    'DDF/D1/D2'         : Item(status='D ', wc_rev='7'),
+    'DDF/D1/D2/gamma'   : Item(status='D ', wc_rev='7'),
+    'D'                 : Item(status='C ', wc_rev='7'),
+    'D/D1'              : Item(status='D ', wc_rev='7'),
+    'F'                 : Item(status='C ', wc_rev='7'),
+    'F/alpha'           : Item(status='D ', wc_rev='7'),
+    'DD'                : Item(status='C ', wc_rev='7'),
+    'DD/D1'             : Item(status='D ', wc_rev='7'),
+    'DD/D1/D2'          : Item(status='D ', wc_rev='7'),
+    'DF'                : Item(status='C ', wc_rev='7'),
+    'DF/D1'             : Item(status='D ', wc_rev='7'),
+    'DF/D1/beta'        : Item(status='D ', wc_rev='7'),
+    'DDD'               : Item(status='C ', wc_rev='7'),
+    'DDD/D1'            : Item(status='D ', wc_rev='7'),
+    'DDD/D1/D2'         : Item(status='D ', wc_rev='7'),
+    'DDD/D1/D2/D3'      : Item(status='D ', wc_rev='7'),
+    })
+
+  expected_skip = svntest.wc.State('', {
+    'F/alpha'           : Item(),
+    })
+
+  greater_scheme += [ DeepTreesTestCase(
+                               "local_tree_del_incoming_tree_del",
+                               tree_del,
+                               tree_del,
+                               expected_output,
+                               expected_disk,
+                               expected_status,
+                               expected_skip,
+                             ) ]
+
+
+  # now run the whole bunch of them.
+  svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox, greater_scheme,
+                                                        False)
+
+
+
 ########################################################################
 # Run the tests
 
@@ -12925,8 +13470,9 @@
                          server_has_mergeinfo),
               XFail(SkipUnless(subtrees_with_empty_mergeinfo,
                                server_has_mergeinfo)),
-              tree_conflicts_in_merged_files,
               tree_conflicts_and_obstructions,
+              tree_conflicts_on_merge_local_ci,
+              tree_conflicts_on_merge_no_local_ci,
              ]
 
 if __name__ == '__main__':



