You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2016/12/03 10:09:55 UTC

svn commit: r1772445 [4/6] - in /subversion/branches/authzperf: ./ build/ac-macros/ notes/ subversion/bindings/javahl/native/ subversion/bindings/swig/perl/libsvn_swig_perl/ subversion/bindings/swig/ruby/test/ subversion/include/ subversion/include/pri...

Modified: subversion/branches/authzperf/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_wc/wc_db_update_move.c?rev=1772445&r1=1772444&r2=1772445&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_wc/wc_db_update_move.c Sat Dec  3 10:09:54 2016
@@ -21,13 +21,15 @@
  * ====================================================================
  */
 
-/* This file implements an editor and an edit driver which are used
- * to resolve an "incoming edit, local move-away" tree conflict resulting
- * from an update (or switch).
+/* This implements editors and an edit drivers which are used to resolve
+ * "incoming edit, local move-away" and "incoming move, local edit" tree
+ * conflict resulting from an update (or switch).
  *
  * Our goal is to be able to resolve this conflict such that the end
  * result is just the same as if the user had run the update *before*
- * the local move.
+ * the local (or incoming) move.
+ *
+ * -- Updating local moves --
  *
  * When an update (or switch) produces incoming changes for a locally
  * moved-away subtree, it updates the base nodes of the moved-away tree
@@ -72,6 +74,34 @@
  *     representing a replacement, but this editor only reads from the
  *     single-op-depth layer of it, and makes no changes of any kind
  *     within the source tree.
+ *
+ * -- Updating incoming moves --
+ *
+ * When an update (or switch) produces an incoming move, it deletes the
+ * moved node at the old location from the BASE tree and adds a node at
+ * the new location to the BASE tree. If the old location contains local
+ * changes, a tree conflict is raised, and the former BASE tree which
+ * the local changes were based on (the tree conflict victim) is re-added
+ * as a copy which contains these local changes.
+ *
+ * The driver sees two NODES trees: The op-root of the copy, and the
+ * WORKING layer on top of this copy which represents the local changes.
+ * The driver will compare the two NODES trees and drive an editor to
+ * change the move destination's WORKING tree so that it now contains
+ * the local changes seen in the copy of the victim's tree.
+ *
+ * We require that no local changes exist at the destination, in order
+ * to avoid tree conflicts where the "incoming" and "local" change both
+ * originated in the working copy, because the resolver code cannot handle
+ * such tree conflicts at present.
+ * 
+ * The whole drive occurs as one single wc.db transaction.  At the end
+ * of the transaction the destination NODES table should have a WORKING
+ * layer that is equivalent to the WORKING layer found in the copied victim
+ * tree, and there should be workqueue items to make any required changes
+ * to working files/directories in the move destination, and there should be
+ * tree-conflicts in the move destination where it was not possible to
+ * update the working files/directories.
  */
 
 #define SVN_WC__I_AM_WC_DB
@@ -491,7 +521,7 @@ create_node_tree_conflict(svn_skel_t **c
   update_move_baton_t *umb = nmb->umb;
   const char *dst_repos_relpath;
   const char *dst_root_relpath = svn_relpath_prefix(nmb->dst_relpath,
-                                                    nmb->umb->dst_op_depth,
+                                                    umb->dst_op_depth,
                                                     scratch_pool);
 
   dst_repos_relpath =
@@ -500,8 +530,6 @@ create_node_tree_conflict(svn_skel_t **c
                                                        nmb->dst_relpath),
                              scratch_pool);
 
-
-
   return svn_error_trace(
             create_tree_conflict(conflict_p, umb->wcroot, dst_local_relpath,
                                  svn_relpath_prefix(dst_local_relpath,
@@ -737,6 +765,111 @@ tc_editor_add_directory(node_move_baton_
 }
 
 static svn_error_t *
+copy_working_node(const char *src_relpath,
+                  const char *dst_relpath,
+                  svn_wc__db_wcroot_t *wcroot,
+                  apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  const char *dst_parent_relpath = svn_relpath_dirname(dst_relpath,
+                                                       scratch_pool);
+
+  /* Add a WORKING row for the new node, based on the source. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt,wcroot->sdb,
+                                    STMT_INSERT_WORKING_NODE_COPY_FROM));
+  SVN_ERR(svn_sqlite__bindf(stmt, "issdst", wcroot->wc_id, src_relpath,
+                            dst_relpath, relpath_depth(dst_relpath),
+                            dst_parent_relpath, presence_map,
+                            svn_wc__db_status_normal));
+  SVN_ERR(svn_sqlite__step_done(stmt));
+
+  /* Copy properties over.  ### This loses changelist association. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_ACTUAL_NODE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, src_relpath));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (have_row)
+    {
+      apr_size_t props_size;
+      const char *properties;
+
+      properties = svn_sqlite__column_blob(stmt, 1, &props_size,
+                                           scratch_pool);
+      SVN_ERR(svn_sqlite__reset(stmt));
+      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                        STMT_INSERT_ACTUAL_NODE));
+      SVN_ERR(svn_sqlite__bindf(stmt, "issbs",
+                                wcroot->wc_id, dst_relpath,
+                                svn_relpath_dirname(dst_relpath,
+                                                    scratch_pool),
+                                properties, props_size, NULL));
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tc_editor_incoming_add_directory(node_move_baton_t *nmb,
+                                 const char *dst_relpath,
+                                 svn_node_kind_t old_kind,
+                                 apr_hash_t *props,
+                                 const char *src_relpath,
+                                 apr_pool_t *scratch_pool)
+{
+  update_move_baton_t *b = nmb->umb;
+  const char *dst_abspath;
+  svn_node_kind_t wc_kind;
+  svn_skel_t *work_item = NULL;
+  svn_skel_t *conflict = NULL;
+  svn_wc_conflict_reason_t reason = svn_wc_conflict_reason_unversioned;
+
+  SVN_ERR(mark_parent_edited(nmb, scratch_pool));
+  if (nmb->skip)
+    return SVN_NO_ERROR;
+
+  dst_abspath = svn_dirent_join(b->wcroot->abspath, dst_relpath, scratch_pool);
+
+  /* Check for unversioned tree-conflict */
+  SVN_ERR(svn_io_check_path(dst_abspath, &wc_kind, scratch_pool));
+
+  if (wc_kind == old_kind)
+    wc_kind = svn_node_none; /* Node will be gone once we install */
+
+  if (wc_kind != svn_node_none && wc_kind != old_kind) /* replace */
+    {
+      SVN_ERR(create_node_tree_conflict(&conflict, nmb, dst_relpath,
+                                        old_kind, svn_node_dir,
+                                        reason,
+                                        (old_kind == svn_node_none)
+                                          ? svn_wc_conflict_action_add
+                                          : svn_wc_conflict_action_replace,
+                                        NULL,
+                                        scratch_pool, scratch_pool));
+      nmb->skip = TRUE;
+    }
+  else
+    {
+      SVN_ERR(copy_working_node(src_relpath, dst_relpath, b->wcroot,
+                                scratch_pool));
+      SVN_ERR(svn_wc__wq_build_dir_install(&work_item, b->db, dst_abspath,
+                                           scratch_pool, scratch_pool));
+    }
+
+  SVN_ERR(update_move_list_add(b->wcroot, dst_relpath, b->db,
+                               (old_kind == svn_node_none)
+                                  ? svn_wc_notify_update_add
+                                  : svn_wc_notify_update_replace,
+                               svn_node_dir,
+                               svn_wc_notify_state_inapplicable,
+                               svn_wc_notify_state_inapplicable,
+                               conflict, work_item, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
 tc_editor_add_file(node_move_baton_t *nmb,
                    const char *relpath,
                    svn_node_kind_t old_kind,
@@ -824,6 +957,85 @@ tc_editor_add_file(node_move_baton_t *nm
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+tc_editor_incoming_add_file(node_move_baton_t *nmb,
+                            const char *dst_relpath,
+                            svn_node_kind_t old_kind,
+                            const svn_checksum_t *checksum,
+                            apr_hash_t *props,
+                            const char *src_relpath,
+                            const char *content_abspath,
+                            apr_pool_t *scratch_pool)
+{
+  update_move_baton_t *b = nmb->umb;
+  svn_wc_conflict_reason_t reason = svn_wc_conflict_reason_unversioned;
+  svn_node_kind_t wc_kind;
+  const char *dst_abspath;
+  svn_skel_t *work_items = NULL;
+  svn_skel_t *work_item = NULL;
+  svn_skel_t *conflict = NULL;
+
+  SVN_ERR(mark_parent_edited(nmb, scratch_pool));
+  if (nmb->skip)
+    {
+      SVN_ERR(svn_io_remove_file2(content_abspath, TRUE, scratch_pool));
+      return SVN_NO_ERROR;
+    }
+
+  dst_abspath = svn_dirent_join(b->wcroot->abspath, dst_relpath, scratch_pool);
+
+  /* Check for unversioned tree-conflict */
+  SVN_ERR(svn_io_check_path(dst_abspath, &wc_kind, scratch_pool));
+
+  if (wc_kind != svn_node_none && wc_kind != old_kind) /* replace */
+    {
+      SVN_ERR(create_node_tree_conflict(&conflict, nmb, dst_relpath,
+                                        old_kind, svn_node_file,
+                                        reason,
+                                        (old_kind == svn_node_none)
+                                          ? svn_wc_conflict_action_add
+                                          : svn_wc_conflict_action_replace,
+                                        NULL,
+                                        scratch_pool, scratch_pool));
+      nmb->skip = TRUE;
+      SVN_ERR(svn_io_remove_file2(content_abspath, TRUE, scratch_pool));
+    }
+  else
+    {
+      const char *src_abspath;
+
+      SVN_ERR(copy_working_node(src_relpath, dst_relpath, b->wcroot,
+                                scratch_pool));
+
+      /* Update working file. */
+      src_abspath = svn_dirent_join(b->wcroot->abspath, src_relpath,
+                                    scratch_pool);
+      SVN_ERR(svn_wc__wq_build_file_install(&work_item, b->db, dst_abspath,
+                                            src_abspath,
+                                            FALSE /* FIXME: use_commit_times?*/,
+                                            TRUE  /* record_file_info */,
+                                            scratch_pool, scratch_pool));
+      work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+
+      /* Queue removal of temporary content copy. */
+      SVN_ERR(svn_wc__wq_build_file_remove(&work_item, b->db,
+                                           b->wcroot->abspath, src_abspath,
+                                           scratch_pool, scratch_pool));
+    
+      work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+    }
+
+  SVN_ERR(update_move_list_add(b->wcroot, dst_relpath, b->db,
+                               (old_kind == svn_node_none)
+                                  ? svn_wc_notify_update_add
+                                  : svn_wc_notify_update_replace,
+                               svn_node_file,
+                               svn_wc_notify_state_inapplicable,
+                               svn_wc_notify_state_inapplicable,
+                               conflict, work_items, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
 /* All the info we need about one version of a working node. */
 typedef struct working_node_version_t
 {
@@ -860,6 +1072,11 @@ create_conflict_markers(svn_skel_t **wor
 
   part = svn_relpath_skip_ancestor(original_version->path_in_repos,
                                    repos_relpath);
+  if (part == NULL)
+    part = svn_relpath_skip_ancestor(conflicted_version->path_in_repos,
+                                     repos_relpath);
+  SVN_ERR_ASSERT(part != NULL);
+
   conflicted_version->path_in_repos
     = svn_relpath_join(conflicted_version->path_in_repos, part, scratch_pool);
   original_version->path_in_repos = repos_relpath;
@@ -873,6 +1090,13 @@ create_conflict_markers(svn_skel_t **wor
                     conflicted_version,
                     scratch_pool, scratch_pool));
         }
+      else if (operation == svn_wc_operation_merge)
+        {
+          SVN_ERR(svn_wc__conflict_skel_set_op_merge(
+                    conflict_skel, original_version,
+                    conflicted_version,
+                    scratch_pool, scratch_pool));
+        }
       else
         {
           SVN_ERR(svn_wc__conflict_skel_set_op_switch(
@@ -1197,15 +1421,15 @@ tc_editor_alter_file(node_move_baton_t *
 }
 
 static svn_error_t *
-tc_editor_merge_local_file_change(node_move_baton_t *nmb,
-                                  const char *dst_relpath,
-                                  const char *src_relpath,
-                                  const svn_checksum_t *src_checksum,
-                                  const svn_checksum_t *dst_checksum,
-                                  apr_hash_t *dst_props,
-                                  apr_hash_t *src_props,
-                                  svn_boolean_t do_text_merge,
-                                  apr_pool_t *scratch_pool)
+tc_editor_update_incoming_moved_file(node_move_baton_t *nmb,
+                                     const char *dst_relpath,
+                                     const char *src_relpath,
+                                     const svn_checksum_t *src_checksum,
+                                     const svn_checksum_t *dst_checksum,
+                                     apr_hash_t *dst_props,
+                                     apr_hash_t *src_props,
+                                     svn_boolean_t do_text_merge,
+                                     apr_pool_t *scratch_pool)
 {
   update_move_baton_t *b = nmb->umb;
   working_node_version_t old_version, new_version;
@@ -1213,28 +1437,107 @@ tc_editor_merge_local_file_change(node_m
                                             dst_relpath,
                                             scratch_pool);
   svn_skel_t *conflict_skel = NULL;
-  apr_hash_t *actual_props;
-  apr_array_header_t *propchanges;
   enum svn_wc_merge_outcome_t merge_outcome;
-  svn_wc_notify_state_t prop_state, content_state;
+  svn_wc_notify_state_t prop_state = svn_wc_notify_state_unchanged;
+  svn_wc_notify_state_t content_state = svn_wc_notify_state_unchanged;
   svn_skel_t *work_item, *work_items = NULL;
   svn_node_kind_t dst_kind_on_disk;
-  svn_boolean_t obstructed = FALSE;
+  const char *dst_repos_relpath;
+  svn_boolean_t tree_conflict = FALSE;
+  svn_node_kind_t dst_db_kind;
+  svn_error_t *err;
 
   SVN_ERR(mark_node_edited(nmb, scratch_pool));
   if (nmb->skip)
     return SVN_NO_ERROR;
 
+  err = svn_wc__db_base_get_info_internal(NULL, &dst_db_kind, NULL,
+                                          &dst_repos_relpath,
+                                          NULL, NULL, NULL, NULL, NULL, NULL,
+                                          NULL, NULL, NULL, NULL, NULL,
+                                          b->wcroot, dst_relpath,
+                                          scratch_pool, scratch_pool);
+  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+    {
+      const char *dst_parent_relpath;
+      const char *dst_parent_repos_relpath;
+      const char *src_abspath;
+
+      /* If the file cannot be found, it was either deleted at the
+       * move destination, or it was moved after its parent was moved.
+       * We cannot deal with this problem right now. Instead, we will
+       * raise a new tree conflict at the location where this file should
+       * have been, and let another run of the resolver deal with the
+       * new conflict later on. */
+
+      svn_error_clear(err);
+
+      /* Create a WORKING node for this file at the move destination. */
+      SVN_ERR(copy_working_node(src_relpath, dst_relpath, b->wcroot,
+                                scratch_pool));
+
+      /* Raise a tree conflict at the new WORKING node. */
+      dst_db_kind = svn_node_none;
+      SVN_ERR(create_node_tree_conflict(&conflict_skel, nmb, dst_relpath,
+                                        svn_node_file, dst_db_kind,
+                                        svn_wc_conflict_reason_edited,
+                                        svn_wc_conflict_action_delete,
+                                        NULL, scratch_pool, scratch_pool));
+      dst_parent_relpath = svn_relpath_dirname(dst_relpath, scratch_pool);
+      SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, NULL,
+                                                &dst_parent_repos_relpath,
+                                                NULL, NULL, NULL, NULL, NULL,
+                                                NULL, NULL, NULL, NULL, NULL,
+                                                NULL, b->wcroot,
+                                                dst_parent_relpath,
+                                                scratch_pool, scratch_pool));
+      dst_repos_relpath = svn_relpath_join(dst_parent_repos_relpath,
+                                           svn_relpath_basename(dst_relpath,
+                                                                scratch_pool),
+                                           scratch_pool);
+      tree_conflict = TRUE;
+
+      /* Schedule a copy of the victim's file content to the new node's path. */
+      src_abspath = svn_dirent_join(b->wcroot->abspath, src_relpath,
+                                    scratch_pool);
+      SVN_ERR(svn_wc__wq_build_file_install(&work_item, b->db,
+                                            dst_abspath,
+                                            src_abspath,
+                                            FALSE /*FIXME: use_commit_times?*/,
+                                            TRUE  /* record_file_info */,
+                                            scratch_pool, scratch_pool));
+      work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+    }
+  else
+    SVN_ERR(err);
+
+  if ((dst_db_kind == svn_node_none || dst_db_kind != svn_node_file) &&
+      conflict_skel == NULL)
+    {
+      SVN_ERR(create_node_tree_conflict(&conflict_skel, nmb, dst_relpath,
+                                        svn_node_file, dst_db_kind,
+                                        dst_db_kind == svn_node_none
+                                          ? svn_wc_conflict_reason_missing
+                                          : svn_wc_conflict_reason_obstructed,
+                                        svn_wc_conflict_action_edit,
+                                        NULL,
+                                        scratch_pool, scratch_pool));
+      tree_conflict = TRUE;
+    }
+
   SVN_ERR(svn_io_check_path(dst_abspath, &dst_kind_on_disk, scratch_pool));
-  if (dst_kind_on_disk != svn_node_none && dst_kind_on_disk != svn_node_file)
+  if ((dst_kind_on_disk == svn_node_none || dst_kind_on_disk != svn_node_file)
+      && conflict_skel == NULL)
     {
       SVN_ERR(create_node_tree_conflict(&conflict_skel, nmb, dst_relpath,
-                                        svn_node_file, svn_node_file,
-                                        svn_wc_conflict_reason_obstructed,
+                                        svn_node_file, dst_kind_on_disk,
+                                        dst_kind_on_disk == svn_node_none
+                                          ? svn_wc_conflict_reason_missing
+                                          : svn_wc_conflict_reason_obstructed,
                                         svn_wc_conflict_action_edit,
                                         NULL,
                                         scratch_pool, scratch_pool));
-      obstructed = TRUE;
+      tree_conflict = TRUE;
     }
 
   old_version.location_and_kind = b->old_version;
@@ -1245,71 +1548,74 @@ tc_editor_merge_local_file_change(node_m
   new_version.checksum = dst_checksum;
   new_version.props = dst_props;
 
-  SVN_ERR(update_working_props(&prop_state, &conflict_skel, &propchanges,
-                               &actual_props, b, dst_relpath,
-                               &old_version, &new_version,
-                               scratch_pool, scratch_pool));
-
-  if (!obstructed && do_text_merge)
+  /* Merge properties and text content if there is no tree conflict. */
+  if (conflict_skel == NULL)
     {
-      const char *old_pristine_abspath;
-      const char *src_abspath;
+      apr_hash_t *actual_props;
+      apr_array_header_t *propchanges;
 
-      /*
-       * Run a 3-way merge to update the file at its post-move location, using
-       * the pre-move file's pristine text as the merge base, the post-move
-       * content as the merge-left version, and the current content of the
-       * working file at the pre-move location as the merge-right version.
-       */
-      SVN_ERR(svn_wc__db_pristine_get_path(&old_pristine_abspath,
-                                           b->db, b->wcroot->abspath,
-                                           src_checksum,
-                                           scratch_pool, scratch_pool));
-      src_abspath = svn_dirent_join(b->wcroot->abspath, src_relpath,
-                                    scratch_pool);
-      SVN_ERR(svn_wc__internal_merge(&work_item, &conflict_skel,
-                                     &merge_outcome, b->db,
-                                     old_pristine_abspath,
-                                     src_abspath,
-                                     dst_abspath,
-                                     dst_abspath,
-                                     NULL, NULL, NULL, /* diff labels */
-                                     actual_props,
-                                     FALSE, /* dry-run */
-                                     NULL, /* diff3-cmd */
-                                     NULL, /* merge options */
-                                     propchanges,
-                                     b->cancel_func, b->cancel_baton,
-                                     scratch_pool, scratch_pool));
+      SVN_ERR(update_working_props(&prop_state, &conflict_skel, &propchanges,
+                                   &actual_props, b, dst_relpath,
+                                   &old_version, &new_version,
+                                   scratch_pool, scratch_pool));
+      if (do_text_merge)
+        {
+          const char *old_pristine_abspath;
+          const char *src_abspath;
+          const char *label_left;
+          const char *label_target;
 
-      work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+          /*
+           * Run a 3-way merge to update the file at its post-move location,
+           * using the pre-move file's pristine text as the merge base, the
+           * post-move content as the merge-right version, and the current
+           * content of the working file at the pre-move location as the
+           * merge-left version.
+           */
+          SVN_ERR(svn_wc__db_pristine_get_path(&old_pristine_abspath,
+                                               b->db, b->wcroot->abspath,
+                                               src_checksum,
+                                               scratch_pool, scratch_pool));
+          src_abspath = svn_dirent_join(b->wcroot->abspath, src_relpath,
+                                        scratch_pool);
+          label_left = apr_psprintf(scratch_pool, ".r%ld",
+                                    b->old_version->peg_rev);
+          label_target = apr_psprintf(scratch_pool, ".r%ld",
+                                      b->new_version->peg_rev);
+          SVN_ERR(svn_wc__internal_merge(&work_item, &conflict_skel,
+                                         &merge_outcome, b->db,
+                                         old_pristine_abspath,
+                                         src_abspath,
+                                         dst_abspath,
+                                         dst_abspath,
+                                         label_left,
+                                         _(".working"),
+                                         label_target,
+                                         actual_props,
+                                         FALSE, /* dry-run */
+                                         NULL, /* diff3-cmd */
+                                         NULL, /* merge options */
+                                         propchanges,
+                                         b->cancel_func, b->cancel_baton,
+                                         scratch_pool, scratch_pool));
 
-      if (merge_outcome == svn_wc_merge_conflict)
-        content_state = svn_wc_notify_state_conflicted;
-      else
-        content_state = svn_wc_notify_state_merged;
+          work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+
+          if (merge_outcome == svn_wc_merge_conflict)
+            content_state = svn_wc_notify_state_conflicted;
+          else
+            content_state = svn_wc_notify_state_merged;
+        }
     }
-  else
-    content_state = svn_wc_notify_state_unchanged;
 
   /* If there are any conflicts to be stored, convert them into work items
    * too. */
   if (conflict_skel)
     {
-      const char *dst_repos_relpath;
-
-      SVN_ERR(svn_wc__db_depth_get_info(NULL, NULL, NULL,
-                                        &dst_repos_relpath, NULL, NULL,
-                                        NULL, NULL, NULL, NULL, NULL, NULL,
-                                        NULL,
-                                        b->wcroot, dst_relpath,
-                                        b->dst_op_depth,
-                                        scratch_pool, scratch_pool));
-
       SVN_ERR(create_conflict_markers(&work_item, dst_abspath, b->db,
                                       dst_repos_relpath, conflict_skel,
                                       b->operation, &old_version, &new_version,
-                                      svn_node_file, !obstructed,
+                                      svn_node_file, !tree_conflict,
                                       scratch_pool, scratch_pool));
 
       work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
@@ -1456,6 +1762,93 @@ tc_editor_delete(node_move_baton_t *nmb,
   return SVN_NO_ERROR;
 }
 
+/* Handle node deletion for an incoming move. */
+static svn_error_t *
+tc_incoming_editor_delete(node_move_baton_t *nmb,
+                          const char *relpath,
+                          svn_node_kind_t old_kind,
+                          svn_node_kind_t new_kind,
+                          apr_pool_t *scratch_pool)
+{
+  update_move_baton_t *b = nmb->umb;
+  svn_sqlite__stmt_t *stmt;
+  const char *local_abspath;
+  svn_boolean_t is_modified, is_all_deletes;
+  svn_skel_t *work_items = NULL;
+  svn_skel_t *conflict = NULL;
+
+  SVN_ERR(mark_parent_edited(nmb, scratch_pool));
+  if (nmb->skip)
+    return SVN_NO_ERROR;
+
+  /* Check before retracting delete to catch delete-delete
+     conflicts. This catches conflicts on the node itself; deleted
+     children are caught as local modifications below.*/
+  if (nmb->shadowed)
+    {
+      SVN_ERR(mark_tc_on_op_root(nmb,
+                                 old_kind, new_kind,
+                                 svn_wc_conflict_action_delete,
+                                 scratch_pool));
+      return SVN_NO_ERROR;
+    }
+
+  local_abspath = svn_dirent_join(b->wcroot->abspath, relpath, scratch_pool);
+  SVN_ERR(svn_wc__node_has_local_mods(&is_modified, &is_all_deletes,
+                                      nmb->umb->db, local_abspath, FALSE,
+                                      NULL, NULL, scratch_pool));
+  if (is_modified)
+    {
+      svn_wc_conflict_reason_t reason;
+
+      /* No conflict means no NODES rows at the relpath op-depth
+         so it's easy to convert the modified tree into a copy.
+
+         Note the following assumptions for relpath:
+            * it is not shadowed
+            * it is not the/an op-root. (or we can't make us a copy)
+       */
+
+      SVN_ERR(svn_wc__db_op_make_copy_internal(b->wcroot, relpath, FALSE,
+                                               NULL, NULL, scratch_pool));
+
+      reason = svn_wc_conflict_reason_edited;
+
+      SVN_ERR(create_node_tree_conflict(&conflict, nmb, relpath,
+                                        old_kind, new_kind, reason,
+                                        (new_kind == svn_node_none)
+                                          ? svn_wc_conflict_action_delete
+                                          : svn_wc_conflict_action_replace,
+                                        NULL,
+                                        scratch_pool, scratch_pool));
+      nmb->skip = TRUE;
+    }
+  else
+    {
+      /* Delete the WORKING node at DST_RELPATH. */
+      SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+                                 STMT_INSERT_DELETE_FROM_NODE_RECURSIVE));
+      SVN_ERR(svn_sqlite__bindf(stmt, "isdd",
+                                b->wcroot->wc_id, relpath,
+                                0, relpath_depth(relpath)));
+      SVN_ERR(svn_sqlite__step_done(stmt));
+    }
+
+  /* Only notify if add_file/add_dir is not going to notify */
+  if (conflict || (new_kind == svn_node_none))
+    SVN_ERR(update_move_list_add(b->wcroot, relpath, b->db,
+                                 svn_wc_notify_update_delete,
+                                 new_kind,
+                                 svn_wc_notify_state_inapplicable,
+                                 svn_wc_notify_state_inapplicable,
+                                 conflict, work_items, scratch_pool));
+  else if (work_items)
+    SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_items,
+                                       scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
 /*
  * Driver code.
  *
@@ -1747,28 +2140,30 @@ suitable_for_move(svn_wc__db_wcroot_t *w
   while (have_row)
     {
       svn_revnum_t node_revision = svn_sqlite__column_revnum(stmt, 2);
-      const char *relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      const char *relpath;
 
       svn_pool_clear(iterpool);
 
-      relpath = svn_relpath_skip_ancestor(local_relpath, relpath);
+      relpath = svn_relpath_skip_ancestor(local_relpath, child_relpath);
       relpath = svn_relpath_join(repos_relpath, relpath, iterpool);
 
-      if (revision != node_revision)
+      if (strcmp(relpath, svn_sqlite__column_text(stmt, 1, NULL)))
         return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
                                  svn_sqlite__reset(stmt),
-                                 _("Cannot apply update because move source "
-                                   "%s' is a mixed-revision working copy"),
-                                 path_for_error_message(wcroot, local_relpath,
+                                 _("Cannot apply update because '%s' is a "
+                                   "switched path (please switch it back to "
+                                   "its original URL and try again)"),
+                                 path_for_error_message(wcroot, child_relpath,
                                                         scratch_pool));
 
-      if (strcmp(relpath, svn_sqlite__column_text(stmt, 1, NULL)))
+      if (revision != node_revision)
         return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
                                  svn_sqlite__reset(stmt),
-                                 _("Cannot apply update because move source "
-                                   "'%s' is a switched subtree"),
-                                 path_for_error_message(wcroot,
-                                                        local_relpath,
+                                 _("Cannot apply update because '%s' is a "
+                                   "mixed-revision working copy (please "
+                                   "update and try again)"),
+                                 path_for_error_message(wcroot, local_relpath,
                                                         scratch_pool));
 
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -2035,87 +2430,126 @@ get_working_info(apr_hash_t **props,
   return SVN_NO_ERROR;
 }
 
-/* ### Drive TC_EDITOR so as to ...
- */
+/* Apply changes found in the victim node at SRC_RELPATH to the incoming
+ * move at DST_RELPATH. */
 static svn_error_t *
-walk_local_changes(node_move_baton_t *nmb,
-                   svn_wc__db_wcroot_t *wcroot,
-                   const char *src_relpath,
-                   const char *dst_relpath,
-                   apr_pool_t *scratch_pool)
+update_incoming_moved_node(node_move_baton_t *nmb,
+                           svn_wc__db_wcroot_t *wcroot,
+                           const char *src_relpath,
+                           const char *dst_relpath,
+                           apr_pool_t *scratch_pool)
 {
   update_move_baton_t *b = nmb->umb;
-  svn_node_kind_t src_kind, dst_kind;
-  const svn_checksum_t *src_checksum, *dst_checksum;
-  apr_hash_t *src_props, *dst_props;
-  apr_array_header_t *src_children, *dst_children;
+  svn_node_kind_t orig_kind, working_kind;
+  const char *victim_relpath = src_relpath;
+  const svn_checksum_t *orig_checksum, *working_checksum;
+  apr_hash_t *orig_props, *working_props;
+  apr_array_header_t *orig_children, *working_children;
 
   if (b->cancel_func)
     SVN_ERR(b->cancel_func(b->cancel_baton));
 
-  SVN_ERR(get_working_info(&src_props, &src_checksum, &src_children,
-                           &src_kind, src_relpath, wcroot, scratch_pool,
-                           scratch_pool));
-
-  SVN_ERR(get_info(&dst_props, &dst_checksum, &dst_children, &dst_kind,
-                   dst_relpath, b->dst_op_depth,
-                   wcroot, scratch_pool, scratch_pool));
+  /* Compare the tree conflict victim's copied layer (the "original") with
+   * the working layer, i.e. look for changes layered on top of the copy. */
+  SVN_ERR(get_info(&orig_props, &orig_checksum, &orig_children, &orig_kind,
+                   victim_relpath, b->src_op_depth, wcroot, scratch_pool,
+                   scratch_pool));
+  SVN_ERR(get_working_info(&working_props, &working_checksum,
+                           &working_children, &working_kind, victim_relpath,
+                           wcroot, scratch_pool, scratch_pool));
 
-  if (src_kind == svn_node_none
-      || (dst_kind != svn_node_none && src_kind != dst_kind))
+  if (working_kind == svn_node_none
+      || (orig_kind != svn_node_none && orig_kind != working_kind))
     {
-      SVN_ERR(tc_editor_delete(nmb, dst_relpath, dst_kind, src_kind,
-                               scratch_pool));
+      SVN_ERR(tc_incoming_editor_delete(nmb, dst_relpath, orig_kind,
+                                        working_kind, scratch_pool));
     }
 
   if (nmb->skip)
     return SVN_NO_ERROR;
 
-  if (src_kind != svn_node_none && src_kind != dst_kind)
+  if (working_kind != svn_node_none && orig_kind != working_kind)
     {
-      if (src_kind == svn_node_file || src_kind == svn_node_symlink)
+      if (working_kind == svn_node_file || working_kind == svn_node_symlink)
         {
-          SVN_ERR(tc_editor_add_file(nmb, dst_relpath, dst_kind,
-                                     src_checksum, src_props,
-                                     scratch_pool));
+          const char *victim_abspath;
+          const char *wctemp_abspath;
+          svn_stream_t *working_stream;
+          svn_stream_t *temp_stream;
+          const char *temp_abspath;
+          svn_error_t *err;
+
+          /* Copy the victim's content to a safe place and add it from there. */
+          SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&wctemp_abspath, b->db,
+                                                 b->wcroot->abspath,
+                                                 scratch_pool,
+                                                 scratch_pool));
+          victim_abspath = svn_dirent_join(b->wcroot->abspath,
+                                           victim_relpath, scratch_pool);
+          SVN_ERR(svn_stream_open_readonly(&working_stream, victim_abspath,
+                                           scratch_pool, scratch_pool));
+          SVN_ERR(svn_stream_open_unique(&temp_stream, &temp_abspath,
+                                         wctemp_abspath, svn_io_file_del_none,
+                                         scratch_pool, scratch_pool));
+          err = svn_stream_copy3(working_stream, temp_stream, 
+                                 b->cancel_func, b->cancel_baton,
+                                 scratch_pool);
+          if (err && err->apr_err == SVN_ERR_CANCELLED)
+            {
+              svn_error_t *err2;
+
+              err2 = svn_io_remove_file2(temp_abspath, TRUE, scratch_pool);
+              return svn_error_compose_create(err, err2);
+            }
+          else
+            SVN_ERR(err);
+
+          SVN_ERR(tc_editor_incoming_add_file(nmb, dst_relpath, orig_kind,
+                                              working_checksum, working_props,
+                                              victim_relpath, temp_abspath,
+                                              scratch_pool));
         }
-      else if (src_kind == svn_node_dir)
+      else if (working_kind == svn_node_dir)
         {
-          SVN_ERR(tc_editor_add_directory(nmb, dst_relpath, dst_kind,
-                                          src_props, scratch_pool));
+          SVN_ERR(tc_editor_incoming_add_directory(nmb, dst_relpath,
+                                                   orig_kind, working_props,
+                                                   victim_relpath,
+                                                   scratch_pool));
         }
     }
-  else if (src_kind != svn_node_none)
+  else if (working_kind != svn_node_none)
     {
       svn_boolean_t props_equal;
 
-      SVN_ERR(props_match(&props_equal, src_props, dst_props, scratch_pool));
+      SVN_ERR(props_match(&props_equal, orig_props, working_props,
+                          scratch_pool));
 
-      if (src_kind == svn_node_file || src_kind == svn_node_symlink)
+      if (working_kind == svn_node_file || working_kind == svn_node_symlink)
         {
           svn_boolean_t is_modified;
 
           SVN_ERR(svn_wc__internal_file_modified_p(&is_modified, b->db,
                                                    svn_dirent_join(
                                                      b->wcroot->abspath,
-                                                     src_relpath,
+                                                     victim_relpath,
                                                      scratch_pool),
                                                    FALSE /* exact_comparison */,
                                                    scratch_pool));
           if (!props_equal || is_modified)
-            SVN_ERR(tc_editor_merge_local_file_change(nmb, dst_relpath,
-                                                      src_relpath,
-                                                      src_checksum,
-                                                      dst_checksum,
-                                                      dst_props, src_props,
-                                                      is_modified,
-                                                      scratch_pool));
+            SVN_ERR(tc_editor_update_incoming_moved_file(nmb, dst_relpath,
+                                                         victim_relpath,
+                                                         working_checksum,
+                                                         orig_checksum,
+                                                         orig_props,
+                                                         working_props,
+                                                         is_modified,
+                                                         scratch_pool));
         }
-      else if (src_kind == svn_node_dir)
+      else if (working_kind == svn_node_dir)
         {
           if (!props_equal)
             SVN_ERR(tc_editor_alter_directory(nmb, dst_relpath,
-                                              dst_props, src_props,
+                                              orig_props, working_props,
                                               scratch_pool));
         }
     }
@@ -2123,15 +2557,15 @@ walk_local_changes(node_move_baton_t *nm
   if (nmb->skip)
     return SVN_NO_ERROR;
 
-  if (src_kind == svn_node_dir)
+  if (working_kind == svn_node_dir)
     {
       apr_pool_t *iterpool = svn_pool_create(scratch_pool);
       int i = 0, j = 0;
 
-      while (i < src_children->nelts || j < dst_children->nelts)
+      while (i < orig_children->nelts || j < working_children->nelts)
         {
           const char *child_name;
-          svn_boolean_t src_only = FALSE, dst_only = FALSE;
+          svn_boolean_t orig_only = FALSE, working_only = FALSE;
           node_move_baton_t cnmb = { 0 };
 
           cnmb.pb = nmb;
@@ -2139,30 +2573,30 @@ walk_local_changes(node_move_baton_t *nm
           cnmb.shadowed = nmb->shadowed;
 
           svn_pool_clear(iterpool);
-          if (i >= src_children->nelts)
+          if (i >= orig_children->nelts)
             {
-              dst_only = TRUE;
-              child_name = APR_ARRAY_IDX(dst_children, j, const char *);
+              working_only = TRUE;
+              child_name = APR_ARRAY_IDX(working_children, j, const char *);
             }
-          else if (j >= dst_children->nelts)
+          else if (j >= working_children->nelts)
             {
-              src_only = TRUE;
-              child_name = APR_ARRAY_IDX(src_children, i, const char *);
+              orig_only = TRUE;
+              child_name = APR_ARRAY_IDX(orig_children, i, const char *);
             }
           else
             {
-              const char *src_name = APR_ARRAY_IDX(src_children, i,
-                                                   const char *);
-              const char *dst_name = APR_ARRAY_IDX(dst_children, j,
-                                                   const char *);
-              int cmp = strcmp(src_name, dst_name);
+              const char *orig_name = APR_ARRAY_IDX(orig_children, i,
+                                                    const char *);
+              const char *working_name = APR_ARRAY_IDX(working_children, j,
+                                                       const char *);
+              int cmp = strcmp(orig_name, working_name);
 
               if (cmp > 0)
-                dst_only = TRUE;
+                working_only = TRUE;
               else if (cmp < 0)
-                src_only = TRUE;
+                orig_only = TRUE;
 
-              child_name = dst_only ? dst_name : src_name;
+              child_name = working_only ? working_name : orig_name;
             }
 
           cnmb.src_relpath = svn_relpath_join(src_relpath, child_name,
@@ -2170,17 +2604,12 @@ walk_local_changes(node_move_baton_t *nm
           cnmb.dst_relpath = svn_relpath_join(dst_relpath, child_name,
                                               iterpool);
 
-          if (!cnmb.shadowed)
-            SVN_ERR(check_node_shadowed(&cnmb.shadowed, wcroot,
-                                        cnmb.dst_relpath, b->dst_op_depth,
-                                        iterpool));
-
-          SVN_ERR(walk_local_changes(&cnmb, wcroot, cnmb.src_relpath,
-                                     cnmb.dst_relpath, iterpool));
+          SVN_ERR(update_incoming_moved_node(&cnmb, wcroot, cnmb.src_relpath,
+                                             cnmb.dst_relpath, iterpool));
 
-          if (!dst_only)
+          if (!working_only)
             ++i;
-          if (!src_only)
+          if (!orig_only)
             ++j;
 
           if (nmb->skip) /* Does parent now want a skip? */
@@ -2191,9 +2620,9 @@ walk_local_changes(node_move_baton_t *nm
   return SVN_NO_ERROR;
 }
 
-/* The body of svn_wc__db_merge_local_changes(). */
+/* The body of svn_wc__db_update_incoming_move(). */
 static svn_error_t *
-merge_local_changes(svn_revnum_t *old_rev,
+update_incoming_move(svn_revnum_t *old_rev,
                     svn_revnum_t *new_rev,
                     svn_wc__db_t *db,
                     svn_wc__db_wcroot_t *wcroot,
@@ -2211,46 +2640,81 @@ merge_local_changes(svn_revnum_t *old_re
   svn_wc_conflict_version_t new_version;
   apr_int64_t repos_id;
   node_move_baton_t nmb = { 0 };
+  svn_boolean_t is_modified;
 
   SVN_ERR_ASSERT(svn_relpath_skip_ancestor(dst_relpath, local_relpath) == NULL);
 
-  /* In case of 'merge' the source is in the BASE tree (+ local mods) and the
-   * destination is a copied tree. For update/switch the source is a copied
-   * tree (copied from the pre-update BASE revision when the tree conflict
-   * was raised), and the destination is in the BASE tree. */
-  if (operation == svn_wc_operation_merge)
-    {
-      umb.src_op_depth = 0;
-      umb.dst_op_depth = relpath_depth(dst_relpath);
-    }
-  else
-    {
-      umb.src_op_depth = relpath_depth(local_relpath);
-      umb.dst_op_depth = 0;
-    }
+  /* For incoming moves during update/switch, the move source is a copied
+   * tree which was copied from the pre-update BASE revision while raising
+   * the tree conflict, when the update attempted to delete the move source.
+   * This copy is our "original" state (SRC of the diff) and the local changes
+   * on top of this copy at the top-most WORKING layer are used to drive the
+   * editor (DST of the diff).
+   *
+   * The move destination, where changes are applied to, is now in the BASE
+   * tree at DST_RELPATH. This repository-side move is the "incoming change"
+   * recorded for any tree conflicts created during the editor drive.
+   * We assume this path contains no local changes, and create local changes
+   * in DST_RELPATH corresponding to changes contained in the conflict victim.
+   * 
+   * DST_OP_DEPTH is used to infer the "op-root" of the incoming move. This
+   * "op-root" is virtual because all nodes belonging to the incoming move
+   * live in the BASE tree. It is used for constructing repository paths
+   * when new tree conflicts need to be raised.
+   */
+  umb.src_op_depth = relpath_depth(local_relpath); /* SRC of diff */
+  umb.dst_op_depth = relpath_depth(dst_relpath); /* virtual DST op-root */
 
   SVN_ERR(verify_write_lock(wcroot, local_relpath, scratch_pool));
   SVN_ERR(verify_write_lock(wcroot, dst_relpath, scratch_pool));
 
-  SVN_ERR(svn_wc__db_depth_get_info(NULL, &new_version.node_kind,
-                                    &new_version.peg_rev,
-                                    &new_version.path_in_repos, &repos_id,
-                                    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                    NULL,
-                                    wcroot, local_relpath, umb.src_op_depth,
-                                    scratch_pool, scratch_pool));
+  /* Make sure there are no local modifications in the move destination. */
+  SVN_ERR(svn_wc__node_has_local_mods(&is_modified, NULL, db,
+                                      svn_dirent_join(wcroot->abspath,
+                                                      dst_relpath,
+                                                      scratch_pool),
+                                      TRUE, cancel_func, cancel_baton,
+                                      scratch_pool));
+  if (is_modified)
+    return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+                             _("Cannot merge local changes from '%s' because "
+                               "'%s' already contains other local changes "
+                               "(please commit or revert these other changes "
+                               "and try again)"),
+                             svn_dirent_local_style(
+                               svn_dirent_join(wcroot->abspath, local_relpath,
+                                               scratch_pool),
+                               scratch_pool),
+                             svn_dirent_local_style(
+                               svn_dirent_join(wcroot->abspath, dst_relpath,
+                                               scratch_pool),
+                               scratch_pool));
+
+  /* Check for switched subtrees and mixed-revision working copy. */
+  SVN_ERR(suitable_for_move(wcroot, dst_relpath, scratch_pool));
+
+  /* Read version info from the updated incoming post-move location. */
+  SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &new_version.node_kind,
+                                            &new_version.peg_rev,
+                                            &new_version.path_in_repos,
+                                            &repos_id,
+                                            NULL, NULL, NULL, NULL, NULL,
+                                            NULL, NULL, NULL, NULL, NULL,
+                                            wcroot, dst_relpath,
+                                            scratch_pool, scratch_pool));
 
   SVN_ERR(svn_wc__db_fetch_repos_info(&new_version.repos_url,
                                       &new_version.repos_uuid,
                                       wcroot, repos_id,
                                       scratch_pool));
 
+  /* Read version info from the victim's location. */
   SVN_ERR(svn_wc__db_depth_get_info(NULL, &old_version.node_kind,
                                     &old_version.peg_rev,
                                     &old_version.path_in_repos, &repos_id,
                                     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                    NULL,
-                                    wcroot, dst_relpath, umb.dst_op_depth,
+                                    NULL, wcroot,
+                                    local_relpath, umb.src_op_depth,
                                     scratch_pool, scratch_pool));
 
   SVN_ERR(svn_wc__db_fetch_repos_info(&old_version.repos_url,
@@ -2268,9 +2732,6 @@ merge_local_changes(svn_revnum_t *old_re
   umb.cancel_func = cancel_func;
   umb.cancel_baton = cancel_baton;
 
-  if (umb.src_op_depth == 0)
-    SVN_ERR(suitable_for_move(wcroot, local_relpath, scratch_pool));
-
   /* Create a new, and empty, list for notification information. */
   SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
                                       STMT_CREATE_UPDATE_MOVE_LIST));
@@ -2284,27 +2745,27 @@ merge_local_changes(svn_revnum_t *old_re
   /* nmb.edited = FALSE; */
   /* nmb.skip_children = FALSE; */
 
-  /* We walk the move source, comparing each node with the equivalent node at
-   * the move destination and applying any local changes to nodes at the move
-   destination. */
-  SVN_ERR(walk_local_changes(&nmb, wcroot, local_relpath, dst_relpath,
-                             scratch_pool));
+  /* We walk the conflict victim, comparing each node with the equivalent node
+   * at the WORKING layer, applying any local changes to nodes at the move
+   * destination. */
+  SVN_ERR(update_incoming_moved_node(&nmb, wcroot, local_relpath, dst_relpath,
+                                     scratch_pool));
 
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
-svn_wc__db_merge_local_changes(svn_wc__db_t *db,
-                               const char *local_abspath,
-                               const char *dest_abspath,
-                               svn_wc_operation_t operation,
-                               svn_wc_conflict_action_t action,
-                               svn_wc_conflict_reason_t reason,
-                               svn_cancel_func_t cancel_func,
-                               void *cancel_baton,
-                               svn_wc_notify_func2_t notify_func,
-                               void *notify_baton,
-                               apr_pool_t *scratch_pool)
+svn_wc__db_update_incoming_move(svn_wc__db_t *db,
+                                const char *local_abspath,
+                                const char *dest_abspath,
+                                svn_wc_operation_t operation,
+                                svn_wc_conflict_action_t action,
+                                svn_wc_conflict_reason_t reason,
+                                svn_cancel_func_t cancel_func,
+                                void *cancel_baton,
+                                svn_wc_notify_func2_t notify_func,
+                                void *notify_baton,
+                                apr_pool_t *scratch_pool)
 {
   svn_wc__db_wcroot_t *wcroot;
   svn_revnum_t old_rev, new_rev;
@@ -2321,11 +2782,11 @@ svn_wc__db_merge_local_changes(svn_wc__d
   dest_relpath
     = svn_dirent_skip_ancestor(wcroot->abspath, dest_abspath);
 
-  SVN_WC__DB_WITH_TXN(merge_local_changes(&old_rev, &new_rev, db, wcroot,
-                                          local_relpath, dest_relpath,
-                                          operation, action, reason,
-                                          cancel_func, cancel_baton,
-                                          scratch_pool),
+  SVN_WC__DB_WITH_TXN(update_incoming_move(&old_rev, &new_rev, db, wcroot,
+                                           local_relpath, dest_relpath,
+                                           operation, action, reason,
+                                           cancel_func, cancel_baton,
+                                           scratch_pool),
                       wcroot);
 
   /* Send all queued up notifications. */

Modified: subversion/branches/authzperf/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/svn/cl.h?rev=1772445&r1=1772444&r2=1772445&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/svn/cl.h (original)
+++ subversion/branches/authzperf/subversion/svn/cl.h Sat Dec  3 10:09:54 2016
@@ -385,17 +385,16 @@ svn_cl__print_conflict_stats(svn_cl__con
  */
 svn_error_t *
 svn_cl__resolve_conflict(svn_boolean_t *resolved,
-                         svn_cl__accept_t *accept_which,
                          svn_boolean_t *quit,
                          svn_boolean_t *external_failed,
                          svn_boolean_t *printed_summary,
                          svn_client_conflict_t *conflict,
+                         svn_cl__accept_t accept_which,
                          const char *editor_cmd,
                          apr_hash_t *config,
                          const char *path_prefix,
                          svn_cmdline_prompt_baton_t *pb,
                          svn_cl__conflict_stats_t *conflict_stats,
-                         svn_client_conflict_option_id_t option_id,
                          svn_client_ctx_t *ctx,
                          apr_pool_t *scratch_pool);
 
@@ -406,7 +405,6 @@ svn_cl__resolve_conflict(svn_boolean_t *
 svn_error_t *
 svn_cl__walk_conflicts(apr_array_header_t *targets,
                        svn_cl__conflict_stats_t *conflict_stats,
-                       svn_boolean_t is_resolve_cmd,
                        svn_cl__opt_state_t *opt_state,
                        svn_client_ctx_t *ctx,
                        apr_pool_t *scratch_pool);