subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From julianf...@apache.org
Subject svn commit: r1658462 [9/31] - in /subversion/branches/move-tracking-2: ./ build/ build/generator/ build/generator/templates/ notes/ subversion/ subversion/bindings/cxxhl/include/svncxxhl/ subversion/bindings/javahl/native/ subversion/bindings/javahl/na...
Date Mon, 09 Feb 2015 16:46:21 GMT
Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/conflicts.c?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/conflicts.c Mon Feb  9 16:46:16 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,18 @@ 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,
+                              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 +1977,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 +1989,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 +2027,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 +2038,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,
+                                              result->choice,
+                                              apr_hash_make(scratch_pool),
+                                              NULL, NULL, /* ### notify */
+                                              cancel_func, cancel_baton,
+                                              scratch_pool));
     }
 
   return SVN_NO_ERROR;
@@ -2240,7 +2257,7 @@ svn_wc__read_conflicts(const apr_array_h
     {
       /* Some callers expect not NULL */
       *conflicts = apr_array_make(result_pool, 0,
-                                  sizeof(svn_wc_conflict_description2_t *));;
+                                  sizeof(svn_wc_conflict_description2_t *));
       return SVN_NO_ERROR;
     }
 
@@ -2300,190 +2317,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.
@@ -2745,7 +2578,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);
@@ -2769,7 +2604,7 @@ resolve_tree_conflict_on_node(svn_boolea
                                                             scratch_pool));
         }
       else if (reason == svn_wc_conflict_reason_moved_away
-              && action == svn_wc_conflict_action_edit)
+               && action == svn_wc_conflict_action_edit)
         {
           /* After updates, we can resolve local moved-away
            * vs. any incoming change, either by updating the
@@ -2786,7 +2621,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);
@@ -2825,6 +2662,34 @@ resolve_tree_conflict_on_node(svn_boolea
                                      svn_dirent_local_style(local_abspath,
                                                             scratch_pool));
         }
+      else if (reason == svn_wc_conflict_reason_moved_away
+               && action != svn_wc_conflict_action_edit)
+        {
+          /* action added is impossible, because that would imply that
+             something was added, but before that already moved...
+             (which would imply a replace) */
+          SVN_ERR_ASSERT(action == svn_wc_conflict_action_delete
+                         || action == svn_wc_conflict_action_replace);
+
+          if (conflict_choice == svn_wc_conflict_choose_merged)
+            {
+              /* Whatever was moved is removed at its original location by the
+                 update. That must also remove the recording of the move, so
+                 we don't have to do anything here. */
+
+              *did_resolve = TRUE;
+            }
+          else if (conflict_choice == svn_wc_conflict_choose_mine_conflict)
+            {
+              return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
+                                       NULL,
+                                       _("Tree conflict can only be "
+                                         "resolved to 'working' state; "
+                                         "'%s' is no longer moved"),
+                                       svn_dirent_local_style(local_abspath,
+                                                              scratch_pool));
+            }
+        }
     }
 
   if (! *did_resolve)
@@ -2862,14 +2727,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 *
@@ -2905,6 +2784,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 *
@@ -2920,12 +2828,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));
 
@@ -2934,16 +2846,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 "
@@ -2953,8 +2871,6 @@ conflict_status_walker(void *baton,
                                       iterpool, iterpool));
 
           my_choice = result->choice;
-          merged_file = result->merged_file;
-          /* ### Bug: ignores result->save_merged */
         }
 
 
@@ -2971,8 +2887,8 @@ conflict_status_walker(void *baton,
                                                   local_abspath,
                                                   my_choice,
                                                   cswb->resolve_later,
-                                                  cswb->notify_func,
-                                                  cswb->notify_baton,
+                                                  tree_conflict_collector,
+                                                  cswb,
                                                   cswb->cancel_func,
                                                   cswb->cancel_baton,
                                                   iterpool));
@@ -2985,17 +2901,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:
@@ -3013,7 +2938,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));
@@ -3101,7 +3028,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,
@@ -3121,7 +3050,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;
@@ -3132,17 +3061,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/move-tracking-2/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/copy.c?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/copy.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/copy.c Mon Feb  9 16:46:16 2015
@@ -42,6 +42,7 @@
 #include "svn_private_config.h"
 #include "private/svn_wc_private.h"
 
+/* #define RECORD_MIXED_MOVE */
 
 /*** Code. ***/
 
@@ -567,10 +568,10 @@ copy_versioned_dir(svn_wc__db_t *db,
  * The additional parameter IS_MOVE indicates whether this is a copy or
  * a move operation.
  *
- * If MOVE_DEGRADED_TO_COPY is not NULL and a move had to be degraded
- * to a copy, then set *MOVE_DEGRADED_TO_COPY. */
+ * If RECORD_MOVE_ON_DELETE is not NULL and a move had to be degraded
+ * to a copy, then set *RECORD_MOVE_ON_DELETE to FALSE. */
 static svn_error_t *
-copy_or_move(svn_boolean_t *move_degraded_to_copy,
+copy_or_move(svn_boolean_t *record_move_on_delete,
              svn_wc_context_t *wc_ctx,
              const char *src_abspath,
              const char *dst_abspath,
@@ -820,8 +821,8 @@ copy_or_move(svn_boolean_t *move_degrade
   if (is_move
       && !within_one_wc)
     {
-      if (move_degraded_to_copy)
-        *move_degraded_to_copy = TRUE;
+      if (record_move_on_delete)
+        *record_move_on_delete = FALSE;
 
       is_move = FALSE;
     }
@@ -865,9 +866,11 @@ copy_or_move(svn_boolean_t *move_degrade
                                                                 scratch_pool),
                                          min_rev, max_rev);
 
+#ifndef RECORD_MIXED_MOVE
               is_move = FALSE;
-              if (move_degraded_to_copy)
-                *move_degraded_to_copy = TRUE;
+              if (record_move_on_delete)
+                *record_move_on_delete = FALSE;
+#endif
             }
         }
 
@@ -1054,7 +1057,7 @@ svn_wc__move2(svn_wc_context_t *wc_ctx,
               apr_pool_t *scratch_pool)
 {
   svn_wc__db_t *db = wc_ctx->db;
-  svn_boolean_t move_degraded_to_copy = FALSE;
+  svn_boolean_t record_on_delete = TRUE;
   svn_node_kind_t kind;
   svn_boolean_t conflicted;
 
@@ -1066,7 +1069,7 @@ svn_wc__move2(svn_wc_context_t *wc_ctx,
                               svn_dirent_dirname(dst_abspath, scratch_pool),
                               scratch_pool));
 
-  SVN_ERR(copy_or_move(&move_degraded_to_copy,
+  SVN_ERR(copy_or_move(&record_on_delete,
                        wc_ctx, src_abspath, dst_abspath,
                        TRUE /* metadata_only */,
                        TRUE /* is_move */,
@@ -1109,7 +1112,7 @@ svn_wc__move2(svn_wc_context_t *wc_ctx,
                                          scratch_pool));
 
   SVN_ERR(svn_wc__db_op_delete(db, src_abspath,
-                               move_degraded_to_copy ? NULL : dst_abspath,
+                               record_on_delete ? dst_abspath : NULL,
                                TRUE /* delete_dir_externals */,
                                NULL /* conflict */, NULL /* work_items */,
                                cancel_func, cancel_baton,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/deprecated.c?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/deprecated.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/deprecated.c Mon Feb  9 16:46:16 2015
@@ -1076,7 +1076,8 @@ svn_wc_revert4(svn_wc_context_t *wc_ctx,
                                         depth,
                                         use_commit_times,
                                         changelist_filter,
-                                        FALSE /* clear_changelists*/,
+                                        FALSE /* clear_changelists */,
+                                        FALSE /* metadata_only */,
                                         cancel_func, cancel_baton,
                                         notify_func, notify_baton,
                                         scratch_pool));

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c Mon Feb  9 16:46:16 2015
@@ -2192,7 +2192,7 @@ change_file_prop(void *file_baton,
 
   propchange = apr_array_push(fb->propchanges);
   propchange->name = apr_pstrdup(fb->pool, name);
-  propchange->value = value ? svn_string_dup(value, fb->pool) : NULL;
+  propchange->value = svn_string_dup(value, fb->pool);
 
   return SVN_NO_ERROR;
 }
@@ -2217,7 +2217,7 @@ change_dir_prop(void *dir_baton,
 
   propchange = apr_array_push(db->propchanges);
   propchange->name = apr_pstrdup(db->pool, name);
-  propchange->value = value ? svn_string_dup(value, db->pool) : NULL;
+  propchange->value = svn_string_dup(value, db->pool);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/externals.c?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/externals.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/externals.c Mon Feb  9 16:46:16 2015
@@ -602,7 +602,7 @@ change_file_prop(void *file_baton,
 
   propchange = apr_array_push(eb->propchanges);
   propchange->name = apr_pstrdup(eb->pool, name);
-  propchange->value = value ? svn_string_dup(value, eb->pool) : NULL;
+  propchange->value = svn_string_dup(value, eb->pool);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/merge.c?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/merge.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/merge.c Mon Feb  9 16:46:16 2015
@@ -180,7 +180,7 @@ detranslate_wc_file(const char **detrans
       = prop ? (prop->value ? prop->value->data : NULL) : old_mime_value;
 
     old_is_binary = old_mime_value && svn_mime_type_is_binary(old_mime_value);
-    new_is_binary = new_mime_value && svn_mime_type_is_binary(new_mime_value);;
+    new_is_binary = new_mime_value && svn_mime_type_is_binary(new_mime_value);
   }
 
   /* See what translations we want to do */

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/props.c?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/props.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/props.c Mon Feb  9 16:46:16 2015
@@ -1272,7 +1272,7 @@ svn_wc__merge_props(svn_skel_t **conflic
 
       svn_pool_clear(iterpool);
 
-      to_val = to_val ? svn_string_dup(to_val, result_pool) : NULL;
+      to_val = svn_string_dup(to_val, result_pool);
 
       svn_hash_sets(their_props, propname, to_val);
 

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/revert.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/revert.c?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/revert.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/revert.c Mon Feb  9 16:46:16 2015
@@ -246,6 +246,22 @@ revert_restore_handle_copied_dirs(svn_bo
   return SVN_NO_ERROR;
 }
 
+/* Forward definition */
+static svn_error_t *
+revert_wc_data(svn_boolean_t *run_wq,
+               svn_boolean_t *notify_required,
+               svn_wc__db_t *db,
+               const char *local_abspath,
+               svn_wc__db_status_t status,
+               svn_node_kind_t kind,
+               svn_node_kind_t reverted_kind,
+               svn_filesize_t recorded_size,
+               apr_time_t recorded_time,
+               svn_boolean_t copied_here,
+               svn_boolean_t use_commit_times,
+               svn_cancel_func_t cancel_func,
+               void *cancel_baton,
+               apr_pool_t *scratch_pool);
 
 /* Make the working tree under LOCAL_ABSPATH to depth DEPTH match the
    versioned tree.  This function is called after svn_wc__db_op_revert
@@ -254,56 +270,63 @@ revert_restore_handle_copied_dirs(svn_bo
 
    REVERT_ROOT is true for explicit revert targets and FALSE for targets
    reached via recursion.
+
+   Sets *RUN_WQ to TRUE when the caller should (eventually) run the workqueue.
+   (The function sets it to FALSE when it has run the WQ itself)
+
+   If INFO is NULL, LOCAL_ABSPATH doesn't exist in DB. Otherwise INFO
+   specifies the state of LOCAL_ABSPATH in DB.
  */
 static svn_error_t *
-revert_restore(svn_wc__db_t *db,
+revert_restore(svn_boolean_t *run_wq,
+               svn_wc__db_t *db,
                const char *local_abspath,
                svn_depth_t depth,
+               svn_boolean_t metadata_only,
                svn_boolean_t use_commit_times,
                svn_boolean_t revert_root,
+               const struct svn_wc__db_info_t *info,
                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_error_t *err;
   svn_wc__db_status_t status;
   svn_node_kind_t kind;
-  svn_node_kind_t on_disk;
   svn_boolean_t notify_required;
   const apr_array_header_t *conflict_files;
   svn_filesize_t recorded_size;
   apr_time_t recorded_time;
-  apr_finfo_t finfo;
-#ifdef HAVE_SYMLINK
-  svn_boolean_t special;
-#endif
   svn_boolean_t copied_here;
   svn_node_kind_t reverted_kind;
-  svn_boolean_t is_wcroot;
-
   if (cancel_func)
     SVN_ERR(cancel_func(cancel_baton));
 
-  SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath, scratch_pool));
-  if (is_wcroot && !revert_root)
+  if (!revert_root)
     {
-      /* Issue #4162: Obstructing working copy. We can't access the working
-         copy data from the parent working copy for this node by just using
-         local_abspath */
+      svn_boolean_t is_wcroot;
 
-      if (notify_func)
+      SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath, scratch_pool));
+      if (is_wcroot)
         {
-          svn_wc_notify_t *notify = svn_wc_create_notify(
+          /* Issue #4162: Obstructing working copy. We can't access the working
+             copy data from the parent working copy for this node by just using
+             local_abspath */
+
+          if (notify_func)
+            {
+              svn_wc_notify_t *notify =
+                        svn_wc_create_notify(
                                         local_abspath,
                                         svn_wc_notify_update_skip_obstruction,
                                         scratch_pool);
 
-          notify_func(notify_baton, notify, scratch_pool);
-        }
+              notify_func(notify_baton, notify, scratch_pool);
+            }
 
-      return SVN_NO_ERROR; /* We don't revert obstructing working copies */
+          return SVN_NO_ERROR; /* We don't revert obstructing working copies */
+        }
     }
 
   SVN_ERR(svn_wc__db_revert_list_read(&notify_required,
@@ -312,17 +335,15 @@ revert_restore(svn_wc__db_t *db,
                                       db, local_abspath,
                                       scratch_pool, scratch_pool));
 
-  err = svn_wc__db_read_info(&status, &kind,
-                             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             &recorded_size, &recorded_time, NULL,
-                             NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             db, local_abspath, scratch_pool, scratch_pool);
-
-  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+  if (info)
+    {
+      status = info->status;
+      kind = info->kind;
+      recorded_size = info->recorded_size;
+      recorded_time = info->recorded_time;
+    }
+  else
     {
-      svn_error_clear(err);
-
       if (!copied_here)
         {
           if (notify_func && notify_required)
@@ -349,9 +370,116 @@ revert_restore(svn_wc__db_t *db,
           recorded_time = 0;
         }
     }
-  else if (err)
-    return svn_error_trace(err);
 
+  if (!metadata_only)
+    {
+      SVN_ERR(revert_wc_data(run_wq,
+                             &notify_required,
+                             db, local_abspath, status, kind,
+                             reverted_kind, recorded_size, recorded_time,
+                             copied_here, use_commit_times,
+                             cancel_func, cancel_baton, scratch_pool));
+    }
+
+  /* We delete these marker files even though they are not strictly metadata.
+     But for users that use revert as an API with metadata_only, these are. */
+  if (conflict_files)
+    {
+      int i;
+      for (i = 0; i < conflict_files->nelts; i++)
+        {
+          SVN_ERR(remove_conflict_file(&notify_required,
+                                       APR_ARRAY_IDX(conflict_files, i,
+                                                     const char *),
+                                       local_abspath, scratch_pool));
+        }
+    }
+
+  if (notify_func && notify_required)
+    notify_func(notify_baton,
+                svn_wc_create_notify(local_abspath, svn_wc_notify_revert,
+                                     scratch_pool),
+                scratch_pool);
+
+  if (depth == svn_depth_infinity && kind == svn_node_dir)
+    {
+      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+      apr_hash_t *children, *conflicts;
+      apr_hash_index_t *hi;
+
+      SVN_ERR(revert_restore_handle_copied_dirs(NULL, db, local_abspath, FALSE,
+                                                cancel_func, cancel_baton,
+                                                iterpool));
+
+      SVN_ERR(svn_wc__db_read_children_info(&children, &conflicts,
+                                            db, local_abspath, FALSE,
+                                            scratch_pool, iterpool));
+
+      for (hi = apr_hash_first(scratch_pool, children);
+           hi;
+           hi = apr_hash_next(hi))
+        {
+          const char *child_name = apr_hash_this_key(hi);
+          const char *child_abspath;
+
+          svn_pool_clear(iterpool);
+
+          child_abspath = svn_dirent_join(local_abspath, child_name, iterpool);
+
+          SVN_ERR(revert_restore(run_wq,
+                                 db, child_abspath, depth, metadata_only,
+                                 use_commit_times, FALSE /* revert root */,
+                                 apr_hash_this_val(hi),
+                                 cancel_func, cancel_baton,
+                                 notify_func, notify_baton,
+                                 iterpool));
+        }
+
+      /* Run the queue per directory */
+      if (*run_wq)
+        {
+          SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+                                 iterpool));
+          *run_wq = FALSE;
+        }
+
+      svn_pool_destroy(iterpool);
+    }
+
+  if (notify_func && (revert_root || kind == svn_node_dir))
+    SVN_ERR(svn_wc__db_revert_list_notify(notify_func, notify_baton,
+                                          db, local_abspath, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* Perform the in-working copy revert of LOCAL_ABSPATH, to what is stored in DB */
+static svn_error_t *
+revert_wc_data(svn_boolean_t *run_wq,
+               svn_boolean_t *notify_required,
+               svn_wc__db_t *db,
+               const char *local_abspath,
+               svn_wc__db_status_t status,
+               svn_node_kind_t kind,
+               svn_node_kind_t reverted_kind,
+               svn_filesize_t recorded_size,
+               apr_time_t recorded_time,
+               svn_boolean_t copied_here,
+               svn_boolean_t use_commit_times,
+               svn_cancel_func_t cancel_func,
+               void *cancel_baton,
+               apr_pool_t *scratch_pool)
+{
+  svn_error_t *err;
+  apr_finfo_t finfo;
+  svn_node_kind_t on_disk;
+#ifdef HAVE_SYMLINK
+  svn_boolean_t special;
+#endif
+
+  /* Would be nice to use svn_io_dirent2_t here, but the performance
+     improvement that provides doesn't work, because we need the read
+     only and executable bits later on, in the most likely code path */
   err = svn_io_stat(&finfo, local_abspath,
                     APR_FINFO_TYPE | APR_FINFO_LINK
                     | APR_FINFO_SIZE | APR_FINFO_MTIME
@@ -477,14 +605,14 @@ revert_restore(svn_wc__db_t *db,
                   modified = FALSE;
                 }
               else
+                /* Side effect: fixes recorded timestamps */
                 SVN_ERR(svn_wc__internal_file_modified_p(&modified,
                                                          db, local_abspath,
                                                          TRUE, scratch_pool));
 
               if (modified)
                 {
-                  SVN_ERR(svn_io_remove_file2(local_abspath, FALSE,
-                                              scratch_pool));
+                  /* Install will replace the file */
                   on_disk = svn_node_none;
                 }
               else
@@ -504,14 +632,14 @@ revert_restore(svn_wc__db_t *db,
                           SVN_ERR(svn_io_set_file_read_only(local_abspath,
                                                             FALSE,
                                                             scratch_pool));
-                          notify_required = TRUE;
+                          *notify_required = TRUE;
                         }
                       else if (!needs_lock_prop && read_only)
                         {
                           SVN_ERR(svn_io_set_file_read_write(local_abspath,
                                                              FALSE,
                                                              scratch_pool));
-                          notify_required = TRUE;
+                          *notify_required = TRUE;
                         }
                     }
 
@@ -532,14 +660,14 @@ revert_restore(svn_wc__db_t *db,
                           SVN_ERR(svn_io_set_file_executable(local_abspath,
                                                              TRUE, FALSE,
                                                              scratch_pool));
-                          notify_required = TRUE;
+                          *notify_required = TRUE;
                         }
                       else if (!executable_prop && executable)
                         {
                           SVN_ERR(svn_io_set_file_executable(local_abspath,
                                                              FALSE, FALSE,
                                                              scratch_pool));
-                          notify_required = TRUE;
+                          *notify_required = TRUE;
                         }
                     }
 #endif
@@ -563,74 +691,16 @@ revert_restore(svn_wc__db_t *db,
         {
           svn_skel_t *work_item;
 
-          /* ### Get the checksum from read_info above and pass in here? */
           SVN_ERR(svn_wc__wq_build_file_install(&work_item, db, local_abspath,
                                                 NULL, use_commit_times, TRUE,
                                                 scratch_pool, scratch_pool));
           SVN_ERR(svn_wc__db_wq_add(db, local_abspath, work_item,
                                     scratch_pool));
-          SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
-                                 scratch_pool));
-        }
-      notify_required = TRUE;
-    }
-
-  if (conflict_files)
-    {
-      int i;
-      for (i = 0; i < conflict_files->nelts; i++)
-        {
-          SVN_ERR(remove_conflict_file(&notify_required,
-                                       APR_ARRAY_IDX(conflict_files, i,
-                                                     const char *),
-                                       local_abspath, scratch_pool));
+          *run_wq = TRUE;
         }
+      *notify_required = TRUE;
     }
 
-  if (notify_func && notify_required)
-    notify_func(notify_baton,
-                svn_wc_create_notify(local_abspath, svn_wc_notify_revert,
-                                     scratch_pool),
-                scratch_pool);
-
-  if (depth == svn_depth_infinity && kind == svn_node_dir)
-    {
-      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-      const apr_array_header_t *children;
-      int i;
-
-      SVN_ERR(revert_restore_handle_copied_dirs(NULL, db, local_abspath, FALSE,
-                                                cancel_func, cancel_baton,
-                                                iterpool));
-
-      SVN_ERR(svn_wc__db_read_children_of_working_node(&children, db,
-                                                       local_abspath,
-                                                       scratch_pool,
-                                                       iterpool));
-      for (i = 0; i < children->nelts; ++i)
-        {
-          const char *child_abspath;
-
-          svn_pool_clear(iterpool);
-
-          child_abspath = svn_dirent_join(local_abspath,
-                                          APR_ARRAY_IDX(children, i,
-                                                        const char *),
-                                          iterpool);
-
-          SVN_ERR(revert_restore(db, child_abspath, depth,
-                                 use_commit_times, FALSE /* revert root */,
-                                 cancel_func, cancel_baton,
-                                 notify_func, notify_baton,
-                                 iterpool));
-        }
-
-      svn_pool_destroy(iterpool);
-    }
-
-  if (notify_func)
-    SVN_ERR(svn_wc__db_revert_list_notify(notify_func, notify_baton,
-                                          db, local_abspath, scratch_pool));
   return SVN_NO_ERROR;
 }
 
@@ -641,6 +711,7 @@ revert(svn_wc__db_t *db,
        svn_depth_t depth,
        svn_boolean_t use_commit_times,
        svn_boolean_t clear_changelists,
+       svn_boolean_t metadata_only,
        svn_cancel_func_t cancel_func,
        void *cancel_baton,
        svn_wc_notify_func2_t notify_func,
@@ -648,6 +719,8 @@ revert(svn_wc__db_t *db,
        apr_pool_t *scratch_pool)
 {
   svn_error_t *err;
+  const struct svn_wc__db_info_t *info = NULL;
+  svn_boolean_t run_queue = FALSE;
 
   SVN_ERR_ASSERT(depth == svn_depth_empty || depth == svn_depth_infinity);
 
@@ -667,15 +740,37 @@ revert(svn_wc__db_t *db,
     SVN_ERR(svn_wc__write_check(db, dir_abspath, scratch_pool));
   }
 
-  err = svn_wc__db_op_revert(db, local_abspath, depth, clear_changelists,
-                             scratch_pool, scratch_pool);
+  err = svn_error_trace(
+        svn_wc__db_op_revert(db, local_abspath, depth, clear_changelists,
+                             scratch_pool, scratch_pool));
 
   if (!err)
-    err = revert_restore(db, local_abspath, depth,
-                         use_commit_times, TRUE /* revert root */,
-                         cancel_func, cancel_baton,
-                         notify_func, notify_baton,
-                         scratch_pool);
+    {
+      err = svn_error_trace(
+              svn_wc__db_read_single_info(&info, db, local_abspath, FALSE,
+                                          scratch_pool, scratch_pool));
+
+      if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+        {
+          svn_error_clear(err);
+          err = NULL;
+          info = NULL;
+        }
+    }
+
+  if (!err)
+    err = svn_error_trace(
+              revert_restore(&run_queue, db, local_abspath, depth, metadata_only,
+                             use_commit_times, TRUE /* revert root */,
+                             info, cancel_func, cancel_baton,
+                             notify_func, notify_baton,
+                             scratch_pool));
+
+  if (run_queue)
+    err = svn_error_compose_create(err,
+                                   svn_wc__wq_run(db, local_abspath,
+                                                  cancel_func, cancel_baton,
+                                                  scratch_pool));
 
   err = svn_error_compose_create(err,
                                  svn_wc__db_revert_list_done(db,
@@ -695,6 +790,7 @@ revert_changelist(svn_wc__db_t *db,
                   svn_boolean_t use_commit_times,
                   apr_hash_t *changelist_hash,
                   svn_boolean_t clear_changelists,
+                  svn_boolean_t metadata_only,
                   svn_cancel_func_t cancel_func,
                   void *cancel_baton,
                   svn_wc_notify_func2_t notify_func,
@@ -713,6 +809,7 @@ revert_changelist(svn_wc__db_t *db,
                                         scratch_pool))
     SVN_ERR(revert(db, local_abspath,
                    svn_depth_empty, use_commit_times, clear_changelists,
+                   metadata_only,
                    cancel_func, cancel_baton,
                    notify_func, notify_baton,
                    scratch_pool));
@@ -747,7 +844,7 @@ revert_changelist(svn_wc__db_t *db,
 
       SVN_ERR(revert_changelist(db, child_abspath, depth,
                                 use_commit_times, changelist_hash,
-                                clear_changelists,
+                                clear_changelists, metadata_only,
                                 cancel_func, cancel_baton,
                                 notify_func, notify_baton,
                                 iterpool));
@@ -773,6 +870,7 @@ revert_partial(svn_wc__db_t *db,
                svn_depth_t depth,
                svn_boolean_t use_commit_times,
                svn_boolean_t clear_changelists,
+               svn_boolean_t metadata_only,
                svn_cancel_func_t cancel_func,
                void *cancel_baton,
                svn_wc_notify_func2_t notify_func,
@@ -793,7 +891,7 @@ revert_partial(svn_wc__db_t *db,
   /* Revert the root node itself (depth=empty), then move on to the
      children.  */
   SVN_ERR(revert(db, local_abspath, svn_depth_empty,
-                 use_commit_times, clear_changelists,
+                 use_commit_times, clear_changelists, metadata_only,
                  cancel_func, cancel_baton,
                  notify_func, notify_baton, iterpool));
 
@@ -828,6 +926,7 @@ revert_partial(svn_wc__db_t *db,
       /* Revert just this node (depth=empty).  */
       SVN_ERR(revert(db, child_abspath,
                      svn_depth_empty, use_commit_times, clear_changelists,
+                     metadata_only,
                      cancel_func, cancel_baton,
                      notify_func, notify_baton,
                      iterpool));
@@ -846,6 +945,7 @@ svn_wc_revert5(svn_wc_context_t *wc_ctx,
                svn_boolean_t use_commit_times,
                const apr_array_header_t *changelist_filter,
                svn_boolean_t clear_changelists,
+               svn_boolean_t metadata_only,
                svn_cancel_func_t cancel_func,
                void *cancel_baton,
                svn_wc_notify_func2_t notify_func,
@@ -862,6 +962,7 @@ svn_wc_revert5(svn_wc_context_t *wc_ctx,
                                                depth, use_commit_times,
                                                changelist_hash,
                                                clear_changelists,
+                                               metadata_only,
                                                cancel_func, cancel_baton,
                                                notify_func, notify_baton,
                                                scratch_pool));
@@ -870,6 +971,7 @@ svn_wc_revert5(svn_wc_context_t *wc_ctx,
   if (depth == svn_depth_empty || depth == svn_depth_infinity)
     return svn_error_trace(revert(wc_ctx->db, local_abspath,
                                   depth, use_commit_times, clear_changelists,
+                                  metadata_only,
                                   cancel_func, cancel_baton,
                                   notify_func, notify_baton,
                                   scratch_pool));
@@ -883,7 +985,7 @@ svn_wc_revert5(svn_wc_context_t *wc_ctx,
   if (depth == svn_depth_files || depth == svn_depth_immediates)
     return svn_error_trace(revert_partial(wc_ctx->db, local_abspath,
                                           depth, use_commit_times,
-                                          clear_changelists,
+                                          clear_changelists, metadata_only,
                                           cancel_func, cancel_baton,
                                           notify_func, notify_baton,
                                           scratch_pool));

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/update_editor.c?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/update_editor.c Mon Feb  9 16:46:16 2015
@@ -2112,13 +2112,12 @@ add_directory(const char *path,
       if (tree_conflict)
         {
           svn_wc_conflict_reason_t reason;
+          const char *move_src_op_root_abspath;
           /* So this deletion wasn't just a deletion, it is actually a
              replacement. Let's install a better tree conflict. */
 
-          /* ### Should store the conflict in DB to allow reinstalling
-             ### with theoretically more data in close_directory() */
-
-          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL, NULL,
+          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+                                                     &move_src_op_root_abspath,
                                                       eb->db,
                                                       db->local_abspath,
                                                       tree_conflict,
@@ -2130,7 +2129,7 @@ add_directory(const char *path,
                                         tree_conflict,
                                         eb->db, db->local_abspath,
                                         reason, svn_wc_conflict_action_replace,
-                                        NULL,
+                                        move_src_op_root_abspath,
                                         db->pool, scratch_pool));
 
           /* And now stop checking for conflicts here and just perform
@@ -2289,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,
@@ -2489,7 +2480,7 @@ change_dir_prop(void *dir_baton,
 
   propchange = apr_array_push(db->propchanges);
   propchange->name = apr_pstrdup(db->pool, name);
-  propchange->value = value ? svn_string_dup(value, db->pool) : NULL;
+  propchange->value = svn_string_dup(value, db->pool);
 
   if (!db->edited && svn_property_kind2(name) == svn_prop_regular_kind)
     SVN_ERR(mark_directory_edited(db, pool));
@@ -3287,17 +3278,16 @@ add_file(const char *path,
       if (tree_conflict)
         {
           svn_wc_conflict_reason_t reason;
+          const char *move_src_op_root_abspath;
           /* So this deletion wasn't just a deletion, it is actually a
              replacement. Let's install a better tree conflict. */
 
-          /* ### Should store the conflict in DB to allow reinstalling
-             ### with theoretically more data in close_directory() */
-
-          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL, NULL,
+          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+                                                     &move_src_op_root_abspath,
                                                       eb->db,
                                                       fb->local_abspath,
                                                       tree_conflict,
-                                                      fb->pool, fb->pool));
+                                                      fb->pool, scratch_pool));
 
           tree_conflict = svn_wc__conflict_skel_create(fb->pool);
 
@@ -3305,8 +3295,8 @@ add_file(const char *path,
                                         tree_conflict,
                                         eb->db, fb->local_abspath,
                                         reason, svn_wc_conflict_action_replace,
-                                        NULL,
-                                        fb->pool, fb->pool));
+                                        move_src_op_root_abspath,
+                                        fb->pool, scratch_pool));
 
           /* And now stop checking for conflicts here and just perform
              a shadowed update */
@@ -3403,7 +3393,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)
@@ -3465,15 +3455,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,
@@ -3805,7 +3787,7 @@ change_file_prop(void *file_baton,
   /* Push a new propchange to the file baton's array of propchanges */
   propchange = apr_array_push(fb->propchanges);
   propchange->name = apr_pstrdup(fb->pool, name);
-  propchange->value = value ? svn_string_dup(value, fb->pool) : NULL;
+  propchange->value = svn_string_dup(value, fb->pool);
 
   if (!fb->edited && svn_property_kind2(name) == svn_prop_regular_kind)
     SVN_ERR(mark_file_edited(fb, scratch_pool));



Mime
View raw message