subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1659238 [3/21] - in /subversion/branches/fsx-1.10: ./ build/generator/ build/generator/templates/ subversion/bindings/swig/ subversion/include/ subversion/include/private/ subversion/libsvn_delta/ subversion/libsvn_fs_base/ subversion/libs...
Date Thu, 12 Feb 2015 12:21:32 GMT
Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.c?rev=1659238&r1=1659237&r2=1659238&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.c Thu Feb 12 12:21:31 2015
@@ -1469,144 +1469,46 @@ merge_showing_conflicts(const char **cho
   return SVN_NO_ERROR;
 }
 
-/* Resolve the text conflict on DB/LOCAL_ABSPATH in the manner specified
- * by CHOICE.
- *
- * Set *WORK_ITEMS to new work items that will make the on-disk changes
- * needed to complete the resolution (but not to mark it as resolved).
- * Set *IS_RESOLVED to true if the conflicts are resolved; otherwise
- * (which is only if CHOICE is 'postpone') to false.
+/* Prepare to delete an artifact file at ARTIFACT_FILE_ABSPATH in the
+ * working copy at DB/WRI_ABSPATH.
  *
- * LEFT_ABSPATH, RIGHT_ABSPATH, and DETRANSLATED_TARGET are the
- * input files to the 3-way merge that will be performed if CHOICE is
- * 'theirs-conflict' or 'mine-conflict'.  LEFT_ABSPATH is also the file
- * that will be used if CHOICE is 'base', and RIGHT_ABSPATH if CHOICE is
- * 'theirs-full'.  MERGED_ABSPATH will be used if CHOICE is 'merged'.
- *
- * DETRANSLATED_TARGET is the detranslated version of 'mine' (see
- * detranslate_wc_file() above).  MERGE_OPTIONS are passed to the
- * diff3 implementation in case a 3-way merge has to be carried out.
+ * Set *WORK_ITEMS to a new work item that, when run, will delete the
+ * artifact file; or to NULL if there is no file to delete.
  *
- * ### This is redundantly similar to resolve_text_conflict_on_node().
+ * Set *FILE_FOUND to TRUE if the artifact file is found on disk and its
+ * node kind is 'file'; otherwise do not change *FILE_FOUND.  FILE_FOUND
+ * may be NULL if not required.
  */
 static svn_error_t *
-eval_text_conflict_func_result(svn_skel_t **work_items,
-                               svn_boolean_t *is_resolved,
+remove_artifact_file_if_exists(svn_skel_t **work_items,
+                               svn_boolean_t *file_found,
                                svn_wc__db_t *db,
-                               const char *local_abspath,
-                               svn_wc_conflict_choice_t choice,
-                               const apr_array_header_t *merge_options,
-                               const char *left_abspath,
-                               const char *right_abspath,
-                               const char *merged_file,
-                               const char *detranslated_target,
-                               svn_cancel_func_t cancel_func,
-                               void *cancel_baton,
+                               const char *wri_abspath,
+                               const char *artifact_file_abspath,
                                apr_pool_t *result_pool,
                                apr_pool_t *scratch_pool)
 {
-  const char *install_from_abspath = NULL;
-  svn_boolean_t remove_source = FALSE;
-
   *work_items = NULL;
-
-  switch (choice)
+  if (artifact_file_abspath)
     {
-      /* If the callback wants to use one of the fulltexts
-         to resolve the conflict, so be it.*/
-      case svn_wc_conflict_choose_base:
-        {
-          install_from_abspath = left_abspath;
-          *is_resolved = TRUE;
-          break;
-        }
-      case svn_wc_conflict_choose_theirs_full:
-        {
-          install_from_abspath = right_abspath;
-          *is_resolved = TRUE;
-          break;
-        }
-      case svn_wc_conflict_choose_mine_full:
-        {
-          install_from_abspath = detranslated_target;
-          *is_resolved = TRUE;
-          break;
-        }
-      case svn_wc_conflict_choose_theirs_conflict:
-      case svn_wc_conflict_choose_mine_conflict:
-        {
-          svn_diff_conflict_display_style_t style
-            = choice == svn_wc_conflict_choose_theirs_conflict
-                ? svn_diff_conflict_display_latest
-                : svn_diff_conflict_display_modified;
-
-          SVN_ERR(merge_showing_conflicts(&install_from_abspath,
-                                          db, local_abspath,
-                                          style, merge_options,
-                                          left_abspath,
-                                          detranslated_target,
-                                          right_abspath,
-                                          /* ### why not same as other caller? */
-                                          svn_io_file_del_none,
-                                          cancel_func, cancel_baton,
-                                          scratch_pool, scratch_pool));
-          remove_source = TRUE;
-          *is_resolved = TRUE;
-          break;
-        }
+      svn_node_kind_t node_kind;
 
-        /* For the case of 3-way file merging, we don't
-           really distinguish between these return values;
-           if the callback claims to have "generally
-           resolved" the situation, we still interpret
-           that as "OK, we'll assume the merged version is
-           good to use". */
-      case svn_wc_conflict_choose_merged:
-        {
-          install_from_abspath = merged_file;
-          *is_resolved = TRUE;
-          break;
-        }
-      case svn_wc_conflict_choose_postpone:
-      default:
+      SVN_ERR(svn_io_check_path(artifact_file_abspath, &node_kind,
+                                scratch_pool));
+      if (node_kind == svn_node_file)
         {
-          /* Assume conflict remains. */
-          *is_resolved = FALSE;
-          return SVN_NO_ERROR;
+          SVN_ERR(svn_wc__wq_build_file_remove(work_items,
+                                               db, wri_abspath,
+                                               artifact_file_abspath,
+                                               result_pool, scratch_pool));
+          if (file_found)
+            *file_found = TRUE;
         }
     }
 
-  SVN_ERR_ASSERT(install_from_abspath != NULL);
-
-  {
-    svn_skel_t *work_item;
-
-    SVN_ERR(svn_wc__wq_build_file_install(&work_item,
-                                          db, local_abspath,
-                                          install_from_abspath,
-                                          FALSE /* use_commit_times */,
-                                          FALSE /* record_fileinfo */,
-                                          result_pool, scratch_pool));
-    *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
-
-    SVN_ERR(svn_wc__wq_build_sync_file_flags(&work_item, db, local_abspath,
-                                             result_pool, scratch_pool));
-    *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
-
-    if (remove_source)
-      {
-        SVN_ERR(svn_wc__wq_build_file_remove(&work_item,
-                                             db, local_abspath,
-                                             install_from_abspath,
-                                             result_pool, scratch_pool));
-        *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
-      }
-  }
-
   return SVN_NO_ERROR;
 }
 
-
 /* Create a new file in the same directory as LOCAL_ABSPATH, with the
    same basename as LOCAL_ABSPATH, with a ".edited" extension, and set
    *WORK_ITEM to a new work item that will copy and translate from the file
@@ -1649,89 +1551,168 @@ save_merge_result(svn_skel_t **work_item
 }
 
 
-/* Call the conflict resolver callback for a text conflict, and resolve
- * the conflict if the callback tells us to do so.  (Do not mark the
- * conflict as resolved.)
- *
- * Assume that there is a text conflict on the path DB/LOCAL_ABSPATH,
- * and CDESC is the conflict description.
- *
- * Call CONFLICT_FUNC with CONFLICT_BATON to find out whether and how
- * it wants to resolve the conflict.
- *
- * If the callback returns a resolution other than 'postpone', then
- * perform that requested resolution and prepare to mark the conflict
- * as resolved ... ?? by adding work items to *WORK_ITEMS ??.
- *
- * MERGE_OPTIONS is used if the resolver callback requests a merge.
- *
- * Return *WORK_ITEMS that will do the on-disk work required to complete
- * the resolution (but not to mark the conflict as resolved), and set
- * *WAS_RESOLVED to true, if it was resolved.  Set *WORK_ITEMS to NULL
- * and *WAS_RESOLVED to FALSE otherwise.
+
+/* Resolve the text conflict in CONFLICT, which is currently recorded
+ * on DB/LOCAL_ABSPATH in the manner specified by CHOICE.
+ *
+ * Set *WORK_ITEMS to new work items that will make the on-disk changes
+ * needed to complete the resolution (but not to mark it as resolved).
+ *
+ * Set *FOUND_ARTIFACT to true if conflict markers are removed; otherwise
+ * (which is only if CHOICE is 'postpone') to false.
+ *
+ * CHOICE, MERGED_FILE and SAVE_MERGED are typically values provided by
+ * the conflict resolver.
+ *
+ * MERGE_OPTIONS allows customizing the diff handling when using
+ * per hunk conflict resolving.
  */
 static svn_error_t *
-resolve_text_conflict(svn_skel_t **work_items,
-                      svn_boolean_t *was_resolved,
-                      svn_wc__db_t *db,
-                      const char *local_abspath,
-                      svn_wc_conflict_description2_t *cdesc,
-                      const apr_array_header_t *merge_options,
-                      svn_wc_conflict_resolver_func2_t conflict_func,
-                      void *conflict_baton,
-                      svn_cancel_func_t cancel_func,
-                      void *cancel_baton,
-                      apr_pool_t *result_pool,
-                      apr_pool_t *scratch_pool)
+build_text_conflict_resolve_items(svn_skel_t **work_items,
+                                  svn_boolean_t *found_artifact,
+                                  svn_wc__db_t *db,
+                                  const char *local_abspath,
+                                  const svn_skel_t *conflict,
+                                  svn_wc_conflict_choice_t choice,
+                                  const char *merged_file,
+                                  svn_boolean_t save_merged,
+                                  const apr_array_header_t *merge_options,
+                                  svn_cancel_func_t cancel_func,
+                                  void *cancel_baton,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool)
 {
-  svn_wc_conflict_result_t *result;
+  const char *mine_abspath;
+  const char *their_old_abspath;
+  const char *their_abspath;
   svn_skel_t *work_item;
+  const char *install_from_abspath = NULL;
+  svn_boolean_t remove_source = FALSE;
 
   *work_items = NULL;
-  *was_resolved = FALSE;
 
-  /* Give the conflict resolution callback a chance to clean
-     up the conflicts before we mark the file 'conflicted' */
+  if (found_artifact)
+    *found_artifact = FALSE;
 
-  SVN_ERR(conflict_func(&result, cdesc, conflict_baton, scratch_pool,
-                        scratch_pool));
-  if (result == NULL)
-    return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
-                            _("Conflict callback violated API:"
-                              " returned no results"));
-
-  if (result->save_merged)
-    {
-      SVN_ERR(save_merge_result(work_items,
-                                db, local_abspath,
-                                /* Look for callback's own
-                                    merged-file first: */
-                                result->merged_file
-                                  ? result->merged_file
-                                  : cdesc->merged_file,
-                                result_pool, scratch_pool));
-    }
+  SVN_ERR(svn_wc__conflict_read_text_conflict(&mine_abspath,
+                                              &their_old_abspath,
+                                              &their_abspath,
+                                              db, local_abspath,
+                                              conflict,
+                                              scratch_pool, scratch_pool));
+
+  if (save_merged)
+    SVN_ERR(save_merge_result(work_items,
+                              db, local_abspath,
+                              merged_file
+                                ? merged_file
+                                : local_abspath,
+                              result_pool, scratch_pool));
 
-  if (result->choice != svn_wc_conflict_choose_postpone)
+  if (choice == svn_wc_conflict_choose_postpone)
+    return SVN_NO_ERROR;
+
+  switch (choice)
     {
-      SVN_ERR(eval_text_conflict_func_result(&work_item,
-                                             was_resolved,
-                                             db, local_abspath,
-                                             result->choice,
-                                             merge_options,
-                                             cdesc->base_abspath,
-                                             cdesc->their_abspath,
-                                             /* ### Sure this is an abspath? */
-                                             result->merged_file
-                                               ? result->merged_file
-                                               : cdesc->merged_file,
-                                             cdesc->my_abspath,
-                                             cancel_func, cancel_baton,
-                                             result_pool, scratch_pool));
+      /* If the callback wants to use one of the fulltexts
+         to resolve the conflict, so be it.*/
+      case svn_wc_conflict_choose_base:
+        {
+          install_from_abspath = their_old_abspath;
+          break;
+        }
+      case svn_wc_conflict_choose_theirs_full:
+        {
+          install_from_abspath = their_abspath;
+          break;
+        }
+      case svn_wc_conflict_choose_mine_full:
+        {
+          install_from_abspath = mine_abspath;
+          break;
+        }
+      case svn_wc_conflict_choose_theirs_conflict:
+      case svn_wc_conflict_choose_mine_conflict:
+        {
+          svn_diff_conflict_display_style_t style
+            = choice == svn_wc_conflict_choose_theirs_conflict
+                ? svn_diff_conflict_display_latest
+                : svn_diff_conflict_display_modified;
+
+          SVN_ERR(merge_showing_conflicts(&install_from_abspath,
+                                          db, local_abspath,
+                                          style, merge_options,
+                                          their_old_abspath,
+                                          mine_abspath,
+                                          their_abspath,
+                                          /* ### why not same as other caller? */
+                                          svn_io_file_del_none,
+                                          cancel_func, cancel_baton,
+                                          scratch_pool, scratch_pool));
+          remove_source = TRUE;
+          break;
+        }
+
+        /* For the case of 3-way file merging, we don't
+           really distinguish between these return values;
+           if the callback claims to have "generally
+           resolved" the situation, we still interpret
+           that as "OK, we'll assume the merged version is
+           good to use". */
+      case svn_wc_conflict_choose_merged:
+        {
+          install_from_abspath = merged_file
+                                  ? merged_file
+                                  : local_abspath;
+          break;
+        }
+      case svn_wc_conflict_choose_postpone:
+        {
+          /* Assume conflict remains. */
+          return SVN_NO_ERROR;
+        }
+      default:
+        SVN_ERR_ASSERT(choice == svn_wc_conflict_choose_postpone);
+    }
+
+  SVN_ERR_ASSERT(install_from_abspath != NULL);
+
+  /* ### It would be nice if we could somehow pass RECORD_FILEINFO
+         as true in some easy cases. */
+  SVN_ERR(svn_wc__wq_build_file_install(&work_item,
+                                        db, local_abspath,
+                                        install_from_abspath,
+                                        FALSE /* use_commit_times */,
+                                        FALSE /* record_fileinfo */,
+                                        result_pool, scratch_pool));
+  *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
+
+  if (remove_source)
+    {
+      SVN_ERR(svn_wc__wq_build_file_remove(&work_item,
+                                           db, local_abspath,
+                                           install_from_abspath,
+                                           result_pool, scratch_pool));
       *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
     }
-  else
-    *was_resolved = FALSE;
+
+  SVN_ERR(remove_artifact_file_if_exists(&work_item, found_artifact,
+                                         db, local_abspath,
+                                         their_old_abspath,
+                                         result_pool, scratch_pool));
+  *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
+
+  SVN_ERR(remove_artifact_file_if_exists(&work_item, found_artifact,
+                                         db, local_abspath,
+                                         their_abspath,
+                                         result_pool, scratch_pool));
+  *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
+
+  SVN_ERR(remove_artifact_file_if_exists(&work_item, found_artifact,
+                                         db, local_abspath,
+                                         mine_abspath,
+                                         result_pool, scratch_pool));
+  *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
 
   return SVN_NO_ERROR;
 }
@@ -1865,6 +1846,19 @@ read_tree_conflict_desc(svn_wc_conflict_
   return SVN_NO_ERROR;
 }
 
+/* Forward definition */
+static svn_error_t *
+resolve_tree_conflict_on_node(svn_boolean_t *did_resolve,
+                              svn_wc__db_t *db,
+                              const char *local_abspath,
+                              const svn_skel_t *conflict,
+                              svn_wc_conflict_choice_t conflict_choice,
+                              apr_hash_t *resolve_later,
+                              svn_wc_notify_func2_t notify_func,
+                              void *notify_baton,
+                              svn_cancel_func_t cancel_func,
+                              void *cancel_baton,
+                              apr_pool_t *scratch_pool);
 
 svn_error_t *
 svn_wc__conflict_invoke_resolver(svn_wc__db_t *db,
@@ -1984,6 +1978,7 @@ svn_wc__conflict_invoke_resolver(svn_wc_
       svn_boolean_t was_resolved;
       svn_wc_conflict_description2_t *desc;
       apr_hash_t *props;
+      svn_wc_conflict_result_t *result;
 
       SVN_ERR(svn_wc__db_read_props(&props, db, local_abspath,
                                     scratch_pool, scratch_pool));
@@ -1995,27 +1990,37 @@ svn_wc__conflict_invoke_resolver(svn_wc_
                                       operation, left_version, right_version,
                                       scratch_pool, scratch_pool));
 
-      SVN_ERR(resolve_text_conflict(&work_items, &was_resolved,
-                                    db, local_abspath, desc,
-                                    merge_options,
-                                    resolver_func, resolver_baton,
-                                    cancel_func, cancel_baton,
-                                    scratch_pool, scratch_pool));
 
-      if (was_resolved)
-        {
-          if (work_items)
-            {
-              SVN_ERR(svn_wc__db_wq_add(db, local_abspath, work_items,
-                                        scratch_pool));
-              SVN_ERR(svn_wc__wq_run(db, local_abspath,
-                                     cancel_func, cancel_baton,
-                                     scratch_pool));
-            }
-          SVN_ERR(svn_wc__mark_resolved_text_conflict(db, local_abspath,
-                                                      cancel_func,
-                                                      cancel_baton,
-                                                      scratch_pool));
+      work_items = NULL;
+      was_resolved = FALSE;
+
+      /* Give the conflict resolution callback a chance to clean
+         up the conflicts before we mark the file 'conflicted' */
+
+      SVN_ERR(resolver_func(&result, desc, resolver_baton, scratch_pool,
+                            scratch_pool));
+      if (result == NULL)
+        return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+                                _("Conflict callback violated API:"
+                                  " returned no results"));
+
+      SVN_ERR(build_text_conflict_resolve_items(&work_items, &was_resolved,
+                                                db, local_abspath,
+                                                conflict_skel, result->choice,
+                                                result->merged_file,
+                                                result->save_merged,
+                                                merge_options,
+                                                cancel_func, cancel_baton,
+                                                scratch_pool, scratch_pool));
+
+      if (result->choice != svn_wc_conflict_choose_postpone)
+        {
+          SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath,
+                                              TRUE, FALSE, FALSE,
+                                              work_items, scratch_pool));
+          SVN_ERR(svn_wc__wq_run(db, local_abspath,
+                                 cancel_func, cancel_baton,
+                                 scratch_pool));
         }
     }
 
@@ -2023,6 +2028,7 @@ svn_wc__conflict_invoke_resolver(svn_wc_
     {
       svn_wc_conflict_result_t *result;
       svn_wc_conflict_description2_t *desc;
+      svn_boolean_t resolved;
 
       SVN_ERR(read_tree_conflict_desc(&desc,
                                       db, local_abspath, conflict_skel,
@@ -2033,9 +2039,21 @@ svn_wc__conflict_invoke_resolver(svn_wc_
       SVN_ERR(resolver_func(&result, desc, resolver_baton, scratch_pool,
                             scratch_pool));
 
-      /* Ignore the result. We cannot apply it here since this code runs
-       * during an update or merge operation. Tree conflicts are always
-       * postponed and resolved after the operation has completed. */
+      if (result == NULL)
+        return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+                                _("Conflict callback violated API:"
+                                  " returned no results"));
+
+      /* Pass retry hash to avoid erroring out on cases where update
+         can continue safely. ### Need notify handling */
+      if (result->choice != svn_wc_conflict_choose_postpone)
+        SVN_ERR(resolve_tree_conflict_on_node(&resolved,
+                                              db, local_abspath, conflict_skel,
+                                              result->choice,
+                                              apr_hash_make(scratch_pool),
+                                              NULL, NULL, /* ### notify */
+                                              cancel_func, cancel_baton,
+                                              scratch_pool));
     }
 
   return SVN_NO_ERROR;
@@ -2108,8 +2126,8 @@ read_prop_conflict_descs(apr_array_heade
       return SVN_NO_ERROR;
     }
 
-  SVN_ERR(svn_wc__db_base_get_props(&base_props, db, local_abspath,
-                                    result_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_read_pristine_props(&base_props, db, local_abspath,
+                                         result_pool, scratch_pool));
   iterpool = svn_pool_create(scratch_pool);
   for (hi = apr_hash_first(scratch_pool, conflicted_props);
        hi;
@@ -2300,190 +2318,6 @@ svn_wc__read_conflicts(const apr_array_h
 
 /*** Resolving a conflict automatically ***/
 
-/* Prepare to delete an artifact file at ARTIFACT_FILE_ABSPATH in the
- * working copy at DB/WRI_ABSPATH.
- *
- * Set *WORK_ITEMS to a new work item that, when run, will delete the
- * artifact file; or to NULL if there is no file to delete.
- *
- * Set *FILE_FOUND to TRUE if the artifact file is found on disk and its
- * node kind is 'file'; otherwise do not change *FILE_FOUND.  FILE_FOUND
- * may be NULL if not required.
- */
-static svn_error_t *
-remove_artifact_file_if_exists(svn_skel_t **work_items,
-                               svn_boolean_t *file_found,
-                               svn_wc__db_t *db,
-                               const char *wri_abspath,
-                               const char *artifact_file_abspath,
-                               apr_pool_t *result_pool,
-                               apr_pool_t *scratch_pool)
-{
-  *work_items = NULL;
-  if (artifact_file_abspath)
-    {
-      svn_node_kind_t node_kind;
-
-      SVN_ERR(svn_io_check_path(artifact_file_abspath, &node_kind,
-                                scratch_pool));
-      if (node_kind == svn_node_file)
-        {
-          SVN_ERR(svn_wc__wq_build_file_remove(work_items,
-                                               db, wri_abspath,
-                                               artifact_file_abspath,
-                                               result_pool, scratch_pool));
-          if (file_found)
-            *file_found = TRUE;
-        }
-    }
-
-  return SVN_NO_ERROR;
-}
-
-/*
- * Resolve the text conflict found in DB/LOCAL_ABSPATH according
- * to CONFLICT_CHOICE.
- *
- * It is not an error if there is no text conflict. If a text conflict
- * existed and was resolved, set *DID_RESOLVE to TRUE, else set it to FALSE.
- *
- * Note: When there are no conflict markers to remove there is no existing
- * text conflict; just a database containing old information, which we should
- * remove to avoid checking all the time. Resolving a text conflict by
- * removing all the marker files is a fully supported scenario since
- * Subversion 1.0.
- *
- * ### This is redundantly similar to eval_text_conflict_func_result().
- */
-static svn_error_t *
-resolve_text_conflict_on_node(svn_boolean_t *did_resolve,
-                              svn_wc__db_t *db,
-                              const char *local_abspath,
-                              svn_wc_conflict_choice_t conflict_choice,
-                              const char *merged_file,
-                              svn_cancel_func_t cancel_func,
-                              void *cancel_baton,
-                              apr_pool_t *scratch_pool)
-{
-  const char *conflict_old = NULL;
-  const char *conflict_new = NULL;
-  const char *conflict_working = NULL;
-  const char *auto_resolve_src;
-  svn_skel_t *work_item;
-  svn_skel_t *work_items = NULL;
-  svn_skel_t *conflicts;
-  svn_wc_operation_t operation;
-  svn_boolean_t text_conflicted;
-
-  *did_resolve = FALSE;
-
-  SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath,
-                                   scratch_pool, scratch_pool));
-  if (!conflicts)
-    return SVN_NO_ERROR;
-
-  SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, &text_conflicted,
-                                     NULL, NULL, db, local_abspath, conflicts,
-                                     scratch_pool, scratch_pool));
-  if (!text_conflicted)
-    return SVN_NO_ERROR;
-
-  SVN_ERR(svn_wc__conflict_read_text_conflict(&conflict_working,
-                                              &conflict_old,
-                                              &conflict_new,
-                                              db, local_abspath, conflicts,
-                                              scratch_pool, scratch_pool));
-
-  /* Handle automatic conflict resolution before the temporary files are
-   * deleted, if necessary. */
-  switch (conflict_choice)
-    {
-    case svn_wc_conflict_choose_base:
-      auto_resolve_src = conflict_old;
-      break;
-    case svn_wc_conflict_choose_mine_full:
-      auto_resolve_src = conflict_working;
-      break;
-    case svn_wc_conflict_choose_theirs_full:
-      auto_resolve_src = conflict_new;
-      break;
-    case svn_wc_conflict_choose_merged:
-      auto_resolve_src = merged_file;
-      break;
-    case svn_wc_conflict_choose_theirs_conflict:
-    case svn_wc_conflict_choose_mine_conflict:
-      {
-        if (conflict_old && conflict_working && conflict_new)
-          {
-            svn_diff_conflict_display_style_t style
-              = conflict_choice == svn_wc_conflict_choose_theirs_conflict
-                  ? svn_diff_conflict_display_latest
-                  : svn_diff_conflict_display_modified;
-
-            SVN_ERR(merge_showing_conflicts(&auto_resolve_src,
-                                            db, local_abspath,
-                                            style,
-                                            NULL /*merge_options*/,
-                                            conflict_old,
-                                            conflict_working,
-                                            conflict_new,
-                                            /* ### why not same as other caller? */
-                                            svn_io_file_del_on_pool_cleanup,
-                                            cancel_func, cancel_baton,
-                                            scratch_pool, scratch_pool));
-          }
-        else
-          auto_resolve_src = NULL;
-        break;
-      }
-    default:
-      return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
-                              _("Invalid 'conflict_result' argument"));
-    }
-
-  if (auto_resolve_src)
-    {
-      SVN_ERR(svn_wc__wq_build_file_copy_translated(
-                &work_item, db, local_abspath,
-                auto_resolve_src, local_abspath, scratch_pool, scratch_pool));
-      work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
-
-      SVN_ERR(svn_wc__wq_build_sync_file_flags(&work_item, db,
-                                               local_abspath,
-                                               scratch_pool, scratch_pool));
-      work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
-    }
-
-  /* Legacy behavior: Only report text conflicts as resolved when at least
-     one conflict marker file exists.
-
-     If not the UI shows the conflict as already resolved
-     (and in this case we just remove the in-db conflict) */
-
-  SVN_ERR(remove_artifact_file_if_exists(&work_item, did_resolve,
-                                         db, local_abspath, conflict_old,
-                                         scratch_pool, scratch_pool));
-  work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
-
-  SVN_ERR(remove_artifact_file_if_exists(&work_item, did_resolve,
-                                         db, local_abspath, conflict_new,
-                                         scratch_pool, scratch_pool));
-  work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
-
-  SVN_ERR(remove_artifact_file_if_exists(&work_item, did_resolve,
-                                         db, local_abspath, conflict_working,
-                                         scratch_pool, scratch_pool));
-  work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
-
-  SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath,
-                                      TRUE, FALSE, FALSE,
-                                      work_items, scratch_pool));
-  SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
-                         scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
 /*
  * Resolve the property conflicts found in DB/LOCAL_ABSPATH according
  * to CONFLICT_CHOICE.
@@ -2681,6 +2515,7 @@ static svn_error_t *
 resolve_tree_conflict_on_node(svn_boolean_t *did_resolve,
                               svn_wc__db_t *db,
                               const char *local_abspath,
+                              const svn_skel_t *conflicts,
                               svn_wc_conflict_choice_t conflict_choice,
                               apr_hash_t *resolve_later,
                               svn_wc_notify_func2_t notify_func,
@@ -2691,18 +2526,12 @@ resolve_tree_conflict_on_node(svn_boolea
 {
   svn_wc_conflict_reason_t reason;
   svn_wc_conflict_action_t action;
-  svn_skel_t *conflicts;
   svn_wc_operation_t operation;
   svn_boolean_t tree_conflicted;
   const char *src_op_root_abspath;
 
   *did_resolve = FALSE;
 
-  SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath,
-                                   scratch_pool, scratch_pool));
-  if (!conflicts)
-    return SVN_NO_ERROR;
-
   SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, NULL,
                                      &tree_conflicted, db, local_abspath,
                                      conflicts, scratch_pool, scratch_pool));
@@ -2745,7 +2574,9 @@ resolve_tree_conflict_on_node(svn_boolea
               if (err)
                 {
                   const char *dup_abspath;
-                  if (err && err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE)
+
+                  if (!resolve_later
+                      || err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE)
                     return svn_error_trace(err);
 
                   svn_error_clear(err);
@@ -2778,15 +2609,18 @@ resolve_tree_conflict_on_node(svn_boolea
           if (conflict_choice == svn_wc_conflict_choose_mine_conflict)
             {
               err = svn_wc__db_update_moved_away_conflict_victim(
-                        db, local_abspath,
-                        notify_func, notify_baton,
+                        db, local_abspath, src_op_root_abspath,
+                        operation, action, reason,
                         cancel_func, cancel_baton,
+                        notify_func, notify_baton,
                         scratch_pool);
 
               if (err)
                 {
                   const char *dup_abspath;
-                  if (err && err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE)
+
+                  if (!resolve_later
+                      || err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE)
                     return svn_error_trace(err);
 
                   svn_error_clear(err);
@@ -2890,14 +2724,28 @@ svn_wc__mark_resolved_text_conflict(svn_
                                     void *cancel_baton,
                                     apr_pool_t *scratch_pool)
 {
-  svn_boolean_t ignored_result;
+  svn_skel_t *work_items;
+  svn_skel_t *conflict;
 
-  return svn_error_trace(resolve_text_conflict_on_node(
-                           &ignored_result,
-                           db, local_abspath,
-                           svn_wc_conflict_choose_merged, NULL,
-                           cancel_func, cancel_baton,
-                           scratch_pool));
+  SVN_ERR(svn_wc__db_read_conflict(&conflict, db, local_abspath,
+                                   scratch_pool, scratch_pool));
+
+  if (!conflict)
+    return SVN_NO_ERROR;
+
+  SVN_ERR(build_text_conflict_resolve_items(&work_items, NULL,
+                                            db, local_abspath, conflict,
+                                            svn_wc_conflict_choose_merged,
+                                            NULL, FALSE, NULL,
+                                            cancel_func, cancel_baton,
+                                            scratch_pool, scratch_pool));
+
+  SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath, TRUE, FALSE, FALSE,
+                                      work_items, scratch_pool));
+
+  return svn_error_trace(svn_wc__wq_run(db, local_abspath,
+                                        cancel_func, cancel_baton,
+                                        scratch_pool));
 }
 
 svn_error_t *
@@ -2933,6 +2781,35 @@ struct conflict_status_walker_baton
   apr_hash_t *resolve_later;
 };
 
+/* Implements svn_wc_notify_func2_t to collect new conflicts caused by
+   resolving a tree conflict. */
+static void
+tree_conflict_collector(void *baton,
+                        const svn_wc_notify_t *notify,
+                        apr_pool_t *pool)
+{
+  struct conflict_status_walker_baton *cswb = baton;
+
+  if (cswb->notify_func)
+    cswb->notify_func(cswb->notify_baton, notify, pool);
+
+  if (cswb->resolve_later
+      && (notify->action == svn_wc_notify_tree_conflict
+          || notify->prop_state == svn_wc_notify_state_conflicted
+          || notify->content_state == svn_wc_notify_state_conflicted))
+    {
+      if (!svn_hash_gets(cswb->resolve_later, notify->path))
+        {
+          const char *dup_path;
+
+          dup_path = apr_pstrdup(apr_hash_pool_get(cswb->resolve_later),
+                                 notify->path);
+
+          svn_hash_sets(cswb->resolve_later, dup_path, dup_path);
+        }
+    }
+}
+
 /* Implements svn_wc_status4_t to walk all conflicts to resolve.
  */
 static svn_error_t *
@@ -2948,12 +2825,16 @@ conflict_status_walker(void *baton,
   apr_pool_t *iterpool;
   int i;
   svn_boolean_t resolved = FALSE;
+  svn_skel_t *conflict;
 
   if (!status->conflicted)
     return SVN_NO_ERROR;
 
   iterpool = svn_pool_create(scratch_pool);
 
+  SVN_ERR(svn_wc__db_read_conflict(&conflict, db, local_abspath,
+                                   scratch_pool, scratch_pool));
+
   SVN_ERR(svn_wc__read_conflicts(&conflicts, db, local_abspath, TRUE,
                                  scratch_pool, iterpool));
 
@@ -2962,16 +2843,22 @@ conflict_status_walker(void *baton,
       const svn_wc_conflict_description2_t *cd;
       svn_boolean_t did_resolve;
       svn_wc_conflict_choice_t my_choice = cswb->conflict_choice;
-      const char *merged_file = NULL;
+      svn_wc_conflict_result_t *result = NULL;
+      svn_skel_t *work_items;
 
       cd = APR_ARRAY_IDX(conflicts, i, const svn_wc_conflict_description2_t *);
 
+      if ((cd->kind == svn_wc_conflict_kind_property && !cswb->resolve_prop)
+          || (cd->kind == svn_wc_conflict_kind_text && !cswb->resolve_text)
+          || (cd->kind == svn_wc_conflict_kind_tree && !cswb->resolve_tree))
+        {
+          continue; /* Easy out. Don't call resolver func and ignore result */
+        }
+
       svn_pool_clear(iterpool);
 
       if (my_choice == svn_wc_conflict_choose_unspecified)
         {
-          svn_wc_conflict_result_t *result;
-
           if (!cswb->conflict_func)
             return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
                                     _("No conflict-callback and no "
@@ -2981,8 +2868,6 @@ conflict_status_walker(void *baton,
                                       iterpool, iterpool));
 
           my_choice = result->choice;
-          merged_file = result->merged_file;
-          /* ### Bug: ignores result->save_merged */
         }
 
 
@@ -2996,11 +2881,11 @@ conflict_status_walker(void *baton,
               break;
             SVN_ERR(resolve_tree_conflict_on_node(&did_resolve,
                                                   db,
-                                                  local_abspath,
+                                                  local_abspath, conflict,
                                                   my_choice,
                                                   cswb->resolve_later,
-                                                  cswb->notify_func,
-                                                  cswb->notify_baton,
+                                                  tree_conflict_collector,
+                                                  cswb,
                                                   cswb->cancel_func,
                                                   cswb->cancel_baton,
                                                   iterpool));
@@ -3013,17 +2898,26 @@ conflict_status_walker(void *baton,
             if (!cswb->resolve_text)
               break;
 
-            SVN_ERR(resolve_text_conflict_on_node(&did_resolve,
-                                                  db,
-                                                  local_abspath,
-                                                  my_choice,
-                                                  merged_file,
-                                                  cswb->cancel_func,
-                                                  cswb->cancel_baton,
-                                                  iterpool));
-
-            if (did_resolve)
-              resolved = TRUE;
+            SVN_ERR(build_text_conflict_resolve_items(
+                                        &work_items,
+                                        &resolved,
+                                        db, local_abspath, conflict,
+                                        my_choice,
+                                        result ? result->merged_file
+                                               : NULL,
+                                        result ? result->save_merged
+                                               : FALSE,
+                                        NULL /* merge_options */,
+                                        cswb->cancel_func,
+                                        cswb->cancel_baton,
+                                        iterpool, iterpool));
+
+            SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath,
+                                                TRUE, FALSE, FALSE,
+                                                work_items, iterpool));
+            SVN_ERR(svn_wc__wq_run(db, local_abspath,
+                                   cswb->cancel_func, cswb->cancel_baton,
+                                   iterpool));
             break;
 
           case svn_wc_conflict_kind_property:
@@ -3041,7 +2935,9 @@ conflict_status_walker(void *baton,
                                                   local_abspath,
                                                   cd->property_name,
                                                   my_choice,
-                                                  merged_file,
+                                                  result
+                                                    ? result->merged_file
+                                                    : NULL,
                                                   cswb->cancel_func,
                                                   cswb->cancel_baton,
                                                   iterpool));
@@ -3129,7 +3025,9 @@ svn_wc__resolve_conflicts(svn_wc_context
   cswb.notify_func = notify_func;
   cswb.notify_baton = notify_baton;
 
-  cswb.resolve_later = apr_hash_make(scratch_pool);
+  cswb.resolve_later = (depth != svn_depth_empty)
+                          ? apr_hash_make(scratch_pool)
+                          : NULL;
 
   if (notify_func)
     notify_func(notify_baton,
@@ -3149,7 +3047,7 @@ svn_wc__resolve_conflicts(svn_wc_context
                            cancel_func, cancel_baton,
                            scratch_pool);
 
-  while (!err && apr_hash_count(cswb.resolve_later))
+  while (!err && cswb.resolve_later && apr_hash_count(cswb.resolve_later))
     {
       apr_hash_index_t *hi;
       svn_boolean_t cleared_one = FALSE;
@@ -3160,17 +3058,19 @@ svn_wc__resolve_conflicts(svn_wc_context
       else
         iterpool = svn_pool_create(scratch_pool);
 
-      for (hi = apr_hash_first(scratch_pool, cswb.resolve_later);
-          hi && !err;
-          hi = apr_hash_next(hi))
+      hi = apr_hash_first(scratch_pool, cswb.resolve_later);
+      cswb.resolve_later = apr_hash_make(scratch_pool);
+
+      for (; hi && !err; hi = apr_hash_next(hi))
         {
           tc_abspath = apr_hash_this_key(hi);
           svn_pool_clear(iterpool);
 
-          svn_hash_sets(cswb.resolve_later, tc_abspath, NULL);
+          /* ### TODO: Check if tc_abspath falls within selected depth */
 
-          err = svn_wc_walk_status(wc_ctx, tc_abspath, depth, FALSE, FALSE,
-                                   TRUE, NULL, conflict_status_walker, &cswb,
+          err = svn_wc_walk_status(wc_ctx, tc_abspath, svn_depth_empty,
+                                   FALSE, FALSE, TRUE, NULL,
+                                   conflict_status_walker, &cswb,
                                    cancel_func, cancel_baton,
                                    iterpool);
 

Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/status.c?rev=1659238&r1=1659237&r2=1659238&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_wc/status.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_wc/status.c Thu Feb 12 12:21:31 2015
@@ -36,7 +36,6 @@
 #include "svn_string.h"
 #include "svn_error.h"
 #include "svn_dirent_uri.h"
-#include "svn_path.h"
 #include "svn_io.h"
 #include "svn_config.h"
 #include "svn_time.h"
@@ -47,9 +46,6 @@
 
 #include "wc.h"
 #include "props.h"
-#include "entries.h"
-#include "translate.h"
-#include "tree_conflicts.h"
 
 #include "private/svn_sorts_private.h"
 #include "private/svn_wc_private.h"

Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/token-map.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/token-map.h?rev=1659238&r1=1659237&r2=1659238&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_wc/token-map.h (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_wc/token-map.h Thu Feb 12 12:21:31 2015
@@ -33,6 +33,7 @@
 extern "C" {
 #endif
 
+/* The kind values used on NODES */
 static const svn_token_map_t kind_map[] = {
   { "file", svn_node_file }, /* MAP_FILE */
   { "dir", svn_node_dir }, /* MAP_DIR */
@@ -41,6 +42,16 @@ static const svn_token_map_t kind_map[]
   { NULL }
 };
 
+/* Like kind_map, but also supports 'none' */
+static const svn_token_map_t kind_map_none[] = {
+  { "none", svn_node_none },
+  { "file", svn_node_file },
+  { "dir", svn_node_dir },
+  { "symlink", svn_node_symlink },
+  { "unknown", svn_node_unknown },
+  { NULL }
+};
+
 /* Note: we only decode presence values from the database. These are a
    subset of all the status values. */
 static const svn_token_map_t presence_map[] = {

Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/update_editor.c?rev=1659238&r1=1659237&r2=1659238&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_wc/update_editor.c Thu Feb 12 12:21:31 2015
@@ -2288,15 +2288,7 @@ add_directory(const char *path,
 
   if (tree_conflict != NULL)
     {
-      if (eb->conflict_func)
-        SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, db->local_abspath,
-                                                 tree_conflict,
-                                                 NULL /* merge_options */,
-                                                 eb->conflict_func,
-                                                 eb->conflict_baton,
-                                                 eb->cancel_func,
-                                                 eb->cancel_baton,
-                                                 scratch_pool));
+      db->edit_conflict = tree_conflict;
 
       db->already_notified = TRUE;
       do_notification(eb, db->local_abspath, svn_node_dir,
@@ -2906,10 +2898,9 @@ close_directory(void *dir_baton,
                 (dav_prop_changes->nelts > 0)
                     ? svn_prop_array_to_hash(dav_prop_changes, pool)
                     : NULL,
-                conflict_skel,
                 (! db->shadowed) && new_base_props != NULL,
-                new_actual_props,
-                iprops, all_work_items,
+                new_actual_props, iprops,
+                conflict_skel, all_work_items,
                 scratch_pool));
     }
 
@@ -3295,7 +3286,7 @@ add_file(const char *path,
                                                       eb->db,
                                                       fb->local_abspath,
                                                       tree_conflict,
-                                                      fb->pool, fb->pool));
+                                                      fb->pool, scratch_pool));
 
           tree_conflict = svn_wc__conflict_skel_create(fb->pool);
 
@@ -3304,7 +3295,7 @@ add_file(const char *path,
                                         eb->db, fb->local_abspath,
                                         reason, svn_wc_conflict_action_replace,
                                         move_src_op_root_abspath,
-                                        fb->pool, fb->pool));
+                                        fb->pool, scratch_pool));
 
           /* And now stop checking for conflicts here and just perform
              a shadowed update */
@@ -3401,7 +3392,7 @@ add_file(const char *path,
                                       fb->local_abspath,
                                       status, FALSE, svn_node_none,
                                       svn_wc_conflict_action_add,
-                                      scratch_pool, scratch_pool));
+                                      fb->pool, scratch_pool));
         }
 
       if (tree_conflict == NULL)
@@ -3463,15 +3454,7 @@ add_file(const char *path,
                                           tree_conflict, NULL,
                                           scratch_pool));
 
-      if (eb->conflict_func)
-        SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, fb->local_abspath,
-                                                 tree_conflict,
-                                                 NULL /* merge_options */,
-                                                 eb->conflict_func,
-                                                 eb->conflict_baton,
-                                                 eb->cancel_func,
-                                                 eb->cancel_baton,
-                                                 scratch_pool));
+      fb->edit_conflict = tree_conflict;
 
       fb->already_notified = TRUE;
       do_notification(eb, fb->local_abspath, svn_node_file,

Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/wc-queries.sql?rev=1659238&r1=1659237&r2=1659238&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_wc/wc-queries.sql Thu Feb 12 12:21:31 2015
@@ -99,7 +99,7 @@ LIMIT 1
 -- STMT_SELECT_DEPTH_NODE
 SELECT repos_id, repos_path, presence, kind, revision, checksum,
   translated_size, changed_revision, changed_date, changed_author, depth,
-  symlink_target, last_mod_time, properties
+  symlink_target, properties, moved_to, moved_here
 FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3
 
@@ -332,6 +332,15 @@ WHERE wc_id = ?1
   AND op_depth = ?3
   AND presence != MAP_BASE_DELETED
   AND file_external is NULL
+ORDER BY local_relpath
+
+-- STMT_SELECT_OP_DEPTH_CHILDREN_EXISTS
+SELECT local_relpath, kind FROM nodes
+WHERE wc_id = ?1 
+  AND parent_relpath = ?2
+  AND op_depth = ?3
+  AND presence IN (MAP_NORMAL, MAP_INCOMPLETE)
+ORDER BY local_relpath
 
 /* Used by non-recursive revert to detect higher level children, and
    actual-only rows that would be left orphans, if the revert
@@ -479,7 +488,8 @@ SELECT op_depth, moved_to
 FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > ?3
   AND EXISTS(SELECT * from nodes
-             WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3)
+             WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3
+             AND presence IN (MAP_NORMAL, MAP_INCOMPLETE))
 ORDER BY op_depth ASC
 LIMIT 1
 
@@ -1378,8 +1388,9 @@ BEGIN
                             WHERE n.wc_id = OLD.wc_id
                               AND n.local_relpath = OLD.local_relpath)
             THEN 1
-            ELSE NULL
-          END;
+          END notify
+   WHERE OLD.conflict_data IS NOT NULL
+      OR notify IS NOT NULL;
 END;
 DROP TRIGGER IF EXISTS   trigger_revert_list_actual_update;
 CREATE TEMPORARY TRIGGER trigger_revert_list_actual_update
@@ -1395,8 +1406,9 @@ BEGIN
                             WHERE n.wc_id = OLD.wc_id
                               AND n.local_relpath = OLD.local_relpath)
             THEN 1
-            ELSE NULL
-          END;
+          END notify
+   WHERE OLD.conflict_data IS NOT NULL
+      OR notify IS NOT NULL;
 END
 
 -- STMT_DROP_REVERT_LIST_TRIGGERS
@@ -1422,12 +1434,15 @@ ORDER BY local_relpath
 DELETE FROM revert_list WHERE local_relpath = ?1
 
 -- STMT_SELECT_REVERT_LIST_RECURSIVE
-SELECT DISTINCT local_relpath
-FROM revert_list
-WHERE (local_relpath = ?1
-       OR IS_STRICT_DESCENDANT_OF(local_relpath, ?1))
-  AND (notify OR actual = 0)
-ORDER BY local_relpath
+SELECT p.local_relpath, n.kind, a.notify, a.kind
+FROM (SELECT DISTINCT local_relpath
+      FROM revert_list
+      WHERE (local_relpath = ?1
+        OR IS_STRICT_DESCENDANT_OF(local_relpath, ?1))) p
+
+LEFT JOIN revert_list n ON n.local_relpath=p.local_relpath AND n.actual=0
+LEFT JOIN revert_list a ON a.local_relpath=p.local_relpath AND a.actual=1
+ORDER BY p.local_relpath
 
 -- STMT_DELETE_REVERT_LIST_RECURSIVE
 DELETE FROM revert_list
@@ -1476,7 +1491,7 @@ CREATE TEMPORARY TABLE update_move_list
    ### working copies. queries, etc will need to be adjusted.  */
   local_relpath TEXT PRIMARY KEY NOT NULL UNIQUE,
   action INTEGER NOT NULL,
-  kind  INTEGER NOT NULL,
+  kind TEXT NOT NULL,
   content_state INTEGER NOT NULL,
   prop_state  INTEGER NOT NULL
   )
@@ -1494,6 +1509,11 @@ ORDER BY local_relpath
 -- STMT_FINALIZE_UPDATE_MOVE
 DROP TABLE IF EXISTS update_move_list
 
+-- STMT_MOVE_NOTIFY_TO_REVERT
+INSERT INTO revert_list (local_relpath, notify, kind, actual)
+       SELECT local_relpath, 2, kind, 1 FROM update_move_list;
+DROP TABLE update_move_list
+
 /* ------------------------------------------------------------------------- */
 
 /* Queries for revision status. */
@@ -1651,33 +1671,38 @@ WHERE wc_id = ?1
   AND moved_to IS NOT NULL
   AND NOT IS_STRICT_DESCENDANT_OF(moved_to, ?2)
 
--- STMT_SELECT_OP_DEPTH_MOVED_PAIR
-SELECT n.local_relpath, p.kind, n.moved_to, p.repos_path
-FROM nodes n
-JOIN nodes p ON p.wc_id = ?1 AND p.local_relpath = ?2
- AND p.op_depth=(SELECT MAX(d.op_depth)
+/* This statement is very similar to STMT_SELECT_MOVED_DESCENDANTS_SRC
+   but the passed op-depth is the depth of the shadowing node.
+
+   This version is slightly more efficient as the most inner query is
+   only executed once, but the Sqlite page cache makes the difference
+   not really measurable */
+-- STMT_SELECT_MOVED_DESCENDANTS_SHD
+SELECT n.op_depth, n.local_relpath, n.kind, n.repos_path, s.moved_to
+FROM nodes s
+JOIN nodes n ON n.wc_id = ?1 AND n.local_relpath = s.local_relpath
+ AND n.op_depth=(SELECT MAX(d.op_depth)
                  FROM nodes d
                  WHERE d.wc_id = ?1 AND d.local_relpath = ?2
                    AND d.op_depth < ?3)
-WHERE n.wc_id = ?1
-  AND IS_STRICT_DESCENDANT_OF(n.local_relpath, ?2)
-  AND n.op_depth = ?3
-  AND n.moved_to IS NOT NULL
+WHERE s.wc_id = ?1 AND s.op_depth = ?3
+  AND IS_STRICT_DESCENDANT_OF(s.local_relpath, ?2)
+  AND s.moved_to IS NOT NULL
 
--- STMT_SELECT_MOVED_DESCENDANTS
-SELECT n.local_relpath, h.moved_to
-FROM nodes n, nodes h
-WHERE n.wc_id = ?1
-  AND h.wc_id = ?1
+/* This statement is very similar to STMT_SELECT_MOVED_DESCENDANTS_SHD,
+   but the passed op-depth is the depth of the node as it originally existed */
+-- STMT_SELECT_MOVED_DESCENDANTS_SRC
+SELECT s.op_depth, n.local_relpath, n.kind, n.repos_path, s.moved_to
+FROM nodes n
+JOIN nodes s ON s.wc_id = n.wc_id AND s.local_relpath = n.local_relpath
+ AND s.op_depth = (SELECT MIN(d.op_depth)
+                    FROM nodes d
+                    WHERE d.wc_id = ?1
+                      AND d.local_relpath = s.local_relpath
+                      AND d.op_depth > ?3)
+WHERE n.wc_id = ?1 AND n.op_depth = ?3
   AND IS_STRICT_DESCENDANT_OF(n.local_relpath, ?2)
-  AND h.local_relpath = n.local_relpath
-  AND n.op_depth = ?3
-  AND h.op_depth = (SELECT MIN(o.op_depth)
-                    FROM nodes o
-                    WHERE o.wc_id = ?1
-                      AND o.local_relpath = n.local_relpath
-                      AND o.op_depth > ?3)
-  AND h.moved_to IS NOT NULL
+  AND s.moved_to IS NOT NULL
 
 -- STMT_COMMIT_UPDATE_ORIGIN
 UPDATE nodes SET repos_id = ?4,

Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db.c?rev=1659238&r1=1659237&r2=1659238&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db.c Thu Feb 12 12:21:31 2015
@@ -418,7 +418,7 @@ lock_from_columns(svn_sqlite__stmt_t *st
 svn_error_t *
 svn_wc__db_fetch_repos_info(const char **repos_root_url,
                             const char **repos_uuid,
-                            svn_sqlite__db_t *sdb,
+                            svn_wc__db_wcroot_t *wcroot,
                             apr_int64_t repos_id,
                             apr_pool_t *result_pool)
 {
@@ -437,7 +437,7 @@ svn_wc__db_fetch_repos_info(const char *
       return SVN_NO_ERROR;
     }
 
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_SELECT_REPOSITORY_BY_ID));
   SVN_ERR(svn_sqlite__bindf(stmt, "i", repos_id));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -1295,42 +1295,6 @@ gather_repo_children(const apr_array_hea
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_wc__db_get_children_op_depth(apr_hash_t **children,
-                                 svn_wc__db_wcroot_t *wcroot,
-                                 const char *local_relpath,
-                                 int op_depth,
-                                 apr_pool_t *result_pool,
-                                 apr_pool_t *scratch_pool)
-{
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-
-  *children = apr_hash_make(result_pool);
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_SELECT_OP_DEPTH_CHILDREN));
-  SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
-                            op_depth));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  while (have_row)
-    {
-      const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
-      svn_node_kind_t *child_kind = apr_palloc(result_pool, sizeof(svn_node_kind_t));
-
-      *child_kind = svn_sqlite__column_token(stmt, 1, kind_map);
-      svn_hash_sets(*children,
-                    svn_relpath_basename(child_relpath, result_pool),
-                    child_kind);
-
-      SVN_ERR(svn_sqlite__step(&have_row, stmt));
-    }
-  SVN_ERR(svn_sqlite__reset(stmt));
-
-  return SVN_NO_ERROR;
-}
-
-
 /* Return TRUE if CHILD_ABSPATH is an immediate child of PARENT_ABSPATH.
  * Else, return FALSE. */
 static svn_boolean_t
@@ -1771,10 +1735,10 @@ svn_wc__db_base_add_directory(svn_wc__db
                               const apr_array_header_t *children,
                               svn_depth_t depth,
                               apr_hash_t *dav_cache,
-                              const svn_skel_t *conflict,
                               svn_boolean_t update_actual_props,
                               apr_hash_t *new_actual_props,
                               apr_array_header_t *new_iprops,
+                              const svn_skel_t *conflict,
                               const svn_skel_t *work_items,
                               apr_pool_t *scratch_pool)
 {
@@ -2210,6 +2174,36 @@ clear_moved_here(svn_wc__db_wcroot_t *wc
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_wc__db_op_break_move_internal(svn_wc__db_wcroot_t *wcroot,
+                                  const char *src_relpath,
+                                  int src_op_depth,
+                                  const char *dst_relpath,
+                                  const svn_skel_t *work_items,
+                                  apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt;
+  int affected;
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_CLEAR_MOVED_TO_RELPATH));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, src_relpath,
+                            src_op_depth));
+  SVN_ERR(svn_sqlite__update(&affected, stmt));
+
+  if (affected != 1)
+    return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+                             _("Path '%s' is not moved"),
+                             path_for_error_message(wcroot, src_relpath,
+                                                    scratch_pool));
+
+  SVN_ERR(clear_moved_here(wcroot, dst_relpath, scratch_pool));
+
+  SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+
 /* The body of svn_wc__db_base_remove().
  */
 static svn_error_t *
@@ -2695,7 +2689,7 @@ svn_wc__db_base_get_info(svn_wc__db_stat
                                             wcroot, local_relpath,
                                             result_pool, scratch_pool),
           svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid,
-                                      wcroot->sdb, repos_id, result_pool),
+                                      wcroot, repos_id, result_pool),
           SVN_NO_ERROR,
           SVN_NO_ERROR,
           wcroot);
@@ -2756,7 +2750,7 @@ base_get_children_info(apr_hash_t **node
           svn_error_t *err;
 
           err = svn_wc__db_fetch_repos_info(&last_repos_root_url, NULL,
-                                            wcroot->sdb, repos_id,
+                                            wcroot, repos_id,
                                             result_pool);
 
           if (err)
@@ -3032,21 +3026,21 @@ svn_wc__db_depth_get_info(svn_wc__db_sta
         }
       if (had_props)
         {
-          *had_props = SQLITE_PROPERTIES_AVAILABLE(stmt, 13);
+          *had_props = SQLITE_PROPERTIES_AVAILABLE(stmt, 12);
         }
       if (props)
         {
           if (node_status == svn_wc__db_status_normal
               || node_status == svn_wc__db_status_incomplete)
             {
-              SVN_ERR(svn_sqlite__column_properties(props, stmt, 13,
+              SVN_ERR(svn_sqlite__column_properties(props, stmt, 12,
                                                     result_pool, scratch_pool));
               if (*props == NULL)
                 *props = apr_hash_make(result_pool);
             }
           else
             {
-              assert(svn_sqlite__column_is_null(stmt, 13));
+              assert(svn_sqlite__column_is_null(stmt, 12));
               *props = NULL;
             }
         }
@@ -3631,7 +3625,7 @@ svn_wc__db_external_read(svn_wc__db_stat
           err = svn_error_compose_create(
                         err,
                         svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid,
-                                                    wcroot->sdb, repos_id,
+                                                    wcroot, repos_id,
                                                     result_pool));
         }
 
@@ -4352,7 +4346,7 @@ get_info_for_copy(apr_int64_t *copyfrom_
          working copies in a single db)! */
 
       SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid,
-                                          src_wcroot->sdb, *copyfrom_id,
+                                          src_wcroot, *copyfrom_id,
                                           scratch_pool));
 
       SVN_ERR(create_repos_id(copyfrom_id, repos_root_url, repos_uuid,
@@ -5311,7 +5305,7 @@ db_op_copy_shadowed_layer(svn_wc__db_wcr
           const char *repos_uuid;
 
           SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid,
-                                              src_wcroot->sdb, node_repos_id,
+                                              src_wcroot, node_repos_id,
                                               scratch_pool));
 
           SVN_ERR(create_repos_id(&node_repos_id, repos_root_url, repos_uuid,
@@ -6744,6 +6738,8 @@ op_revert_txn(void *baton,
   svn_boolean_t moved_here;
   int affected_rows;
   const char *moved_to;
+  int op_depth_increased = 0;
+  svn_skel_t *conflict;
 
   /* ### Similar structure to op_revert_recursive_txn, should they be
          combined? */
@@ -6794,52 +6790,18 @@ op_revert_txn(void *baton,
 
   if (moved_to)
     {
-      SVN_ERR(svn_wc__db_resolve_break_moved_away_internal(wcroot,
-                                                           local_relpath,
-                                                           op_depth,
-                                                           scratch_pool));
+      SVN_ERR(svn_wc__db_op_break_move_internal(wcroot,
+                                                local_relpath, op_depth,
+                                                moved_to, NULL, scratch_pool));
     }
   else
     {
-      svn_skel_t *conflict;
-
       SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, wcroot,
                                                 local_relpath,
                                                 scratch_pool, scratch_pool));
-      if (conflict)
-        {
-          svn_wc_operation_t operation;
-          svn_boolean_t tree_conflicted;
-
-          SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, NULL,
-                                             &tree_conflicted,
-                                             db, wcroot->abspath,
-                                             conflict,
-                                             scratch_pool, scratch_pool));
-          if (tree_conflicted
-              && (operation == svn_wc_operation_update
-                  || operation == svn_wc_operation_switch))
-            {
-              svn_wc_conflict_reason_t reason;
-              svn_wc_conflict_action_t action;
-
-              SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action,
-                                                          NULL,
-                                                          db, wcroot->abspath,
-                                                          conflict,
-                                                          scratch_pool,
-                                                          scratch_pool));
-
-              if (reason == svn_wc_conflict_reason_deleted)
-                SVN_ERR(svn_wc__db_resolve_delete_raise_moved_away(
-                          db, svn_dirent_join(wcroot->abspath, local_relpath,
-                                              scratch_pool),
-                          NULL, NULL /* ### How do we notify this? */,
-                          scratch_pool));
-            }
-        }
     }
 
+
   if (op_depth > 0 && op_depth == relpath_depth(local_relpath))
     {
       /* Can't do non-recursive revert if children exist */
@@ -6864,7 +6826,7 @@ op_revert_txn(void *baton,
       SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
                                 local_relpath,
                                 op_depth));
-      SVN_ERR(svn_sqlite__step_done(stmt));
+      SVN_ERR(svn_sqlite__update(&op_depth_increased, stmt));
 
       SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                         STMT_DELETE_WORKING_NODE));
@@ -6882,6 +6844,54 @@ op_revert_txn(void *baton,
         SVN_ERR(clear_moved_to(wcroot, local_relpath, scratch_pool));
     }
 
+  if (op_depth_increased && conflict)
+    {
+      svn_wc_operation_t operation;
+      svn_boolean_t tree_conflicted;
+      const apr_array_header_t *locations;
+
+      SVN_ERR(svn_wc__conflict_read_info(&operation, &locations, NULL, NULL,
+                                          &tree_conflicted,
+                                          db, wcroot->abspath,
+                                          conflict,
+                                          scratch_pool, scratch_pool));
+      if (tree_conflicted
+          && (operation == svn_wc_operation_update
+              || operation == svn_wc_operation_switch))
+        {
+          svn_wc_conflict_reason_t reason;
+          svn_wc_conflict_action_t action;
+
+          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action,
+                                                      NULL,
+                                                      db, wcroot->abspath,
+                                                      conflict,
+                                                      scratch_pool,
+                                                      scratch_pool));
+
+          if (reason == svn_wc_conflict_reason_deleted
+              || reason == svn_wc_conflict_reason_replaced)
+            {
+              SVN_ERR(svn_wc__db_op_raise_moved_away_internal(
+                          wcroot, local_relpath, op_depth+1, db,
+                          operation, action,
+                          (locations && locations->nelts > 0)
+                            ? APR_ARRAY_IDX(locations, 0,
+                                            const svn_wc_conflict_version_t *)
+                            : NULL,
+                          (locations && locations->nelts > 1)
+                            ? APR_ARRAY_IDX(locations, 1,
+                                            const svn_wc_conflict_version_t *)
+                            : NULL,
+                          scratch_pool));
+
+              /* Transform the move information into revert information */
+              SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
+                                                  STMT_MOVE_NOTIFY_TO_REVERT));
+            }
+        }
+    }
+
   if (rvb->clear_changelists)
     {
       SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
@@ -6973,14 +6983,14 @@ op_revert_recursive_txn(void *baton,
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   while (have_row)
     {
-      const char *move_src_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      const char *src_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      const char *dst_relpath = svn_sqlite__column_text(stmt, 1, NULL);
       int move_op_depth = svn_sqlite__column_int(stmt, 2);
       svn_error_t *err;
 
-      err = svn_wc__db_resolve_break_moved_away_internal(wcroot,
-                                                         move_src_relpath,
-                                                         move_op_depth,
-                                                         scratch_pool);
+      err = svn_wc__db_op_break_move_internal(wcroot,
+                                              src_relpath, move_op_depth,
+                                              dst_relpath, NULL, scratch_pool);
       if (err)
         return svn_error_compose_create(err, svn_sqlite__reset(stmt));
 
@@ -7313,16 +7323,39 @@ svn_wc__db_revert_list_notify(svn_wc_not
   while (have_row)
     {
       const char *notify_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      svn_wc_notify_t *notify;
 
       svn_pool_clear(iterpool);
 
-      notify_func(notify_baton,
-                  svn_wc_create_notify(svn_dirent_join(wcroot->abspath,
-                                                       notify_relpath,
-                                                       iterpool),
-                                       svn_wc_notify_revert,
-                                       iterpool),
-                  iterpool);
+      notify = svn_wc_create_notify(svn_dirent_join(wcroot->abspath,
+                                                    notify_relpath,
+                                                    iterpool),
+                                    svn_wc_notify_revert,
+                                    iterpool);
+
+      if (!svn_sqlite__column_is_null(stmt, 1))
+        notify->kind = svn_sqlite__column_token(stmt, 1, kind_map);
+      else
+        {
+          if (!svn_sqlite__column_is_null(stmt, 3))
+            notify->kind = svn_sqlite__column_token(stmt, 3, kind_map_none);
+
+          switch (svn_sqlite__column_int(stmt, 2))
+            {
+              case 0:
+                continue;
+              case 1:
+                /* standard revert */
+                break;
+              case 2:
+                notify->action = svn_wc_notify_tree_conflict;
+                break;
+              default:
+                SVN_ERR_MALFUNCTION();
+            }
+        }
+
+      notify_func(notify_baton, notify, iterpool);
 
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
     }
@@ -9082,9 +9115,9 @@ svn_wc__db_read_info(svn_wc__db_status_t
                     have_base, have_more_work, have_work,
                     wcroot, local_relpath, result_pool, scratch_pool),
           svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid,
-                                      wcroot->sdb, repos_id, result_pool),
+                                      wcroot, repos_id, result_pool),
           svn_wc__db_fetch_repos_info(original_root_url, original_uuid,
-                                      wcroot->sdb, original_repos_id,
+                                      wcroot, original_repos_id,
                                       result_pool),
         SVN_NO_ERROR,
         wcroot);
@@ -9197,7 +9230,7 @@ read_children_info(svn_wc__db_wcroot_t *
                   last_repos_root_url = repos_root_url;
                   err = svn_wc__db_fetch_repos_info(&repos_root_url,
                                                     &repos_uuid,
-                                                    wcroot->sdb, repos_id,
+                                                    wcroot, repos_id,
                                                     result_pool);
                   if (err)
                     SVN_ERR(svn_error_compose_create(err,
@@ -9580,7 +9613,7 @@ read_single_info(const struct svn_wc__db
   mtb->copied = (original_repos_relpath != NULL);
 
   SVN_ERR(svn_wc__db_fetch_repos_info(&mtb->repos_root_url, &mtb->repos_uuid,
-                                      wcroot->sdb, repos_id, result_pool));
+                                      wcroot, repos_id, result_pool));
 
   if (!base_tree_only && mtb->kind == svn_node_dir)
     SVN_ERR(is_wclocked(&mtb->locked, wcroot, local_relpath, scratch_pool));
@@ -10023,7 +10056,7 @@ read_url_txn(const char **url,
         }
     }
 
-  SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, NULL, wcroot->sdb,
+  SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, NULL, wcroot,
                                       repos_id, scratch_pool));
 
   SVN_ERR_ASSERT(repos_root_url != NULL && repos_relpath != NULL);
@@ -11173,7 +11206,7 @@ relocate_txn(svn_wc__db_wcroot_t *wcroot
                                                   scratch_pool, scratch_pool));
     }
 
-  SVN_ERR(svn_wc__db_fetch_repos_info(NULL, &repos_uuid, wcroot->sdb,
+  SVN_ERR(svn_wc__db_fetch_repos_info(NULL, &repos_uuid, wcroot,
                                       old_repos_id, scratch_pool));
   SVN_ERR_ASSERT(repos_uuid);  /* This function affects all the children of the given local_relpath,
      but the way that it does this is through the repos inheritance mechanism.
@@ -11319,7 +11352,7 @@ moved_descendant_commit(svn_wc__db_wcroo
                  && *repos_relpath != '\0');
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_SELECT_MOVED_DESCENDANTS));
+                                    STMT_SELECT_MOVED_DESCENDANTS_SRC));
   SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
                                          local_relpath,
                                          op_depth));
@@ -11330,12 +11363,12 @@ moved_descendant_commit(svn_wc__db_wcroo
 
   children = apr_hash_make(scratch_pool);
 
-  /* First, obtain all moved children */
+  /* First, obtain all moved descendants */
   /* To keep error handling simple, first cache them in a hashtable */
   while (have_row)
     {
-      const char *src_relpath = svn_sqlite__column_text(stmt, 0, scratch_pool);
-      const char *to_relpath = svn_sqlite__column_text(stmt, 1, scratch_pool);
+      const char *src_relpath = svn_sqlite__column_text(stmt, 1, scratch_pool);
+      const char *to_relpath = svn_sqlite__column_text(stmt, 4, scratch_pool);
 
       svn_hash_sets(children, src_relpath, to_relpath);
 
@@ -12644,7 +12677,7 @@ svn_wc__db_scan_addition(svn_wc__db_stat
                               local_abspath, scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
-  SVN_WC__DB_WITH_TXN(
+  SVN_WC__DB_WITH_TXN4(
           scan_addition(status,
                         op_root_abspath
                                 ? &op_root_relpath
@@ -12654,6 +12687,12 @@ svn_wc__db_scan_addition(svn_wc__db_stat
                         original_revision,
                         NULL, NULL, NULL,
                         wcroot, local_relpath, result_pool, scratch_pool),
+          svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid, wcroot,
+                                      repos_id, result_pool),
+          svn_wc__db_fetch_repos_info(original_root_url, original_uuid,
+                                      wcroot, original_repos_id,
+                                      result_pool),
+          SVN_NO_ERROR,
           wcroot);
 
   if (op_root_abspath)
@@ -12662,12 +12701,6 @@ svn_wc__db_scan_addition(svn_wc__db_stat
   /* REPOS_ID must be valid if requested; ORIGINAL_REPOS_ID need not be. */
   SVN_ERR_ASSERT(repos_id_p == NULL || repos_id != INVALID_REPOS_ID);
 
-  SVN_ERR(svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid, wcroot->sdb,
-                                      repos_id, result_pool));
-  SVN_ERR(svn_wc__db_fetch_repos_info(original_root_url, original_uuid,
-                                      wcroot->sdb, original_repos_id,
-                                      result_pool));
-
   return SVN_NO_ERROR;
 }
 
@@ -12871,59 +12904,81 @@ svn_wc__db_follow_moved_to(apr_array_hea
 }
 
 svn_error_t *
-svn_wc__db_op_depth_moved_to(const char **move_dst_relpath,
-                             const char **move_dst_op_root_relpath,
-                             const char **move_src_root_relpath,
-                             const char **move_src_op_root_relpath,
-                             int op_depth,
-                             svn_wc__db_wcroot_t *wcroot,
-                             const char *local_relpath,
-                             apr_pool_t *result_pool,
-                             apr_pool_t *scratch_pool)
+svn_wc__db_scan_moved_to_internal(const char **move_src_relpath,
+                                  const char **move_dst_relpath,
+                                  const char **delete_relpath,
+                                  svn_wc__db_wcroot_t *wcroot,
+                                  const char *local_relpath,
+                                  int op_depth,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
   int delete_op_depth;
   const char *relpath = local_relpath;
+  const char *dst_relpath;
 
   SVN_ERR_ASSERT(local_relpath[0]); /* Not valid on the WC root */
 
-  *move_dst_relpath = *move_dst_op_root_relpath = NULL;
-  *move_src_root_relpath = *move_src_op_root_relpath = NULL;
+  if (move_src_relpath)
+    *move_src_relpath = NULL;
+  if (move_dst_relpath)
+    *move_dst_relpath = NULL;
+  if (delete_relpath)
+    *delete_relpath = NULL;
 
-  do
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_OP_DEPTH_MOVED_TO));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, relpath, op_depth));
+
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  if (!have_row)
     {
+      return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND,
+                               svn_sqlite__reset(stmt),
+                               _("Node '%s' is not shadowed"),
+                               path_for_error_message(wcroot, local_relpath,
+                                                      scratch_pool));
+    }
+
+  delete_op_depth = svn_sqlite__column_int(stmt, 0);
+  dst_relpath = svn_sqlite__column_text(stmt, 1, scratch_pool);
+
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  while (!dst_relpath && have_row)
+    {
+      relpath = svn_relpath_dirname(relpath, scratch_pool);
+
+      if (relpath_depth(relpath) < delete_op_depth)
+        break;
+
       SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                        STMT_SELECT_LOWEST_WORKING_NODE));
-      SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, relpath, op_depth));
+                                        STMT_SELECT_DEPTH_NODE));
+      SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, relpath,
+                                delete_op_depth));
+
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
       if (have_row)
-        {
-          delete_op_depth = svn_sqlite__column_int(stmt, 0);
-          *move_dst_op_root_relpath = svn_sqlite__column_text(stmt, 3,
-                                                              result_pool);
-          if (*move_dst_op_root_relpath)
-            {
-              *move_src_root_relpath = apr_pstrdup(result_pool, relpath);
-              SVN_ERR(svn_sqlite__reset(stmt));
+        dst_relpath = svn_sqlite__column_text(stmt, 13, scratch_pool);
 
-              break;
-            }
-        }
       SVN_ERR(svn_sqlite__reset(stmt));
-      relpath = svn_relpath_dirname(relpath, scratch_pool);
     }
-  while (have_row && delete_op_depth <= relpath_depth(relpath));
 
-  if (*move_dst_op_root_relpath)
+  if (dst_relpath)
     {
-      *move_dst_relpath
-        = svn_relpath_join(*move_dst_op_root_relpath,
-                           svn_relpath_skip_ancestor(relpath, local_relpath),
-                           result_pool);
+      if (move_src_relpath)
+        *move_src_relpath = apr_pstrdup(result_pool, relpath);
 
-      *move_src_op_root_relpath = svn_relpath_limit(relpath, delete_op_depth,
-                                                    result_pool);
+      if (move_dst_relpath)
+        *move_dst_relpath = apr_pstrdup(result_pool, dst_relpath);
+
+      if (delete_relpath)
+        *delete_relpath = svn_relpath_limit(local_relpath, delete_op_depth,
+                                            result_pool);
     }
 
   return SVN_NO_ERROR;
@@ -12936,7 +12991,7 @@ svn_error_t *
 svn_wc__db_base_moved_to(const char **move_dst_abspath,
                          const char **move_dst_op_root_abspath,
                          const char **move_src_root_abspath,
-                         const char **move_src_op_root_abspath,
+                         const char **delete_abspath,
                          svn_wc__db_t *db,
                          const char *local_abspath,
                          apr_pool_t *result_pool,
@@ -12944,47 +12999,54 @@ svn_wc__db_base_moved_to(const char **mo
 {
   svn_wc__db_wcroot_t *wcroot;
   const char *local_relpath;
-  const char *move_dst_relpath, *move_dst_op_root_relpath;
-  const char *move_src_root_relpath, *move_src_op_root_relpath;
+  const char *dst_root_relpath;
+  const char *src_root_relpath, *delete_relpath;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
+
   SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
                               local_abspath, scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
-  SVN_WC__DB_WITH_TXN(svn_wc__db_op_depth_moved_to(&move_dst_relpath,
-                                                   &move_dst_op_root_relpath,
-                                                   &move_src_root_relpath,
-                                                   &move_src_op_root_relpath,
-                                                   0 /* BASE op-depth */,
-                                                   wcroot, local_relpath,
-                                                   scratch_pool, scratch_pool),
+  SVN_WC__DB_WITH_TXN(svn_wc__db_scan_moved_to_internal(&src_root_relpath,
+                                                        &dst_root_relpath,
+                                                        &delete_relpath,
+                                                        wcroot, local_relpath,
+                                                        0 /* BASE */,
+                                                        scratch_pool,
+                                                        scratch_pool),
                       wcroot);
 
   if (move_dst_abspath)
-    *move_dst_abspath
-      = move_dst_relpath
-      ? svn_dirent_join(wcroot->abspath, move_dst_relpath, result_pool)
-      : NULL;
+    *move_dst_abspath =
+        dst_root_relpath
+          ? svn_dirent_join(wcroot->abspath,
+                            svn_dirent_join(
+                                    dst_root_relpath,
+                                    svn_relpath_skip_ancestor(src_root_relpath,
+                                                              local_relpath),
+                                    scratch_pool),
+                            result_pool)
+          : NULL;
 
   if (move_dst_op_root_abspath)
-    *move_dst_op_root_abspath
-      = move_dst_op_root_relpath
-      ? svn_dirent_join(wcroot->abspath, move_dst_op_root_relpath, result_pool)
-      : NULL;
+    *move_dst_op_root_abspath =
+          dst_root_relpath
+              ? svn_dirent_join(wcroot->abspath, dst_root_relpath, result_pool)
+              : NULL;
 
   if (move_src_root_abspath)
-    *move_src_root_abspath
-      = move_src_root_relpath
-      ? svn_dirent_join(wcroot->abspath, move_src_root_relpath, result_pool)
-      : NULL;
-
-  if (move_src_op_root_abspath)
-    *move_src_op_root_abspath
-      = move_src_op_root_relpath
-      ? svn_dirent_join(wcroot->abspath, move_src_op_root_relpath, result_pool)
-      : NULL;
+    *move_src_root_abspath =
+          src_root_relpath
+              ? svn_dirent_join(wcroot->abspath, src_root_relpath, result_pool)
+              : NULL;
+
+  if (delete_abspath)
+    *delete_abspath =
+          delete_relpath
+              ? svn_dirent_join(wcroot->abspath, delete_relpath, result_pool)
+              : NULL;
 
   return SVN_NO_ERROR;
 }
@@ -15231,7 +15293,7 @@ has_switched_subtrees(svn_boolean_t *is_
          does not match the given trailing URL then the whole working
          copy is switched. */
 
-      SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, NULL, wcroot->sdb,
+      SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, NULL, wcroot,
                                           repos_id, scratch_pool));
       url = svn_path_url_add_component2(repos_root_url, repos_relpath,
                                         scratch_pool);
@@ -15620,7 +15682,7 @@ svn_wc__db_base_get_lock_tokens_recursiv
       if (child_repos_id != last_repos_id)
         {
           svn_error_t *err = svn_wc__db_fetch_repos_info(&last_repos_root_url,
-                                                         NULL, wcroot->sdb,
+                                                         NULL, wcroot,
                                                          child_repos_id,
                                                          scratch_pool);
 



Mime
View raw message