You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2011/05/15 14:06:16 UTC

svn commit: r1103333 - /subversion/trunk/subversion/libsvn_client/merge.c

Author: stsp
Date: Sun May 15 12:06:15 2011
New Revision: 1103333

URL: http://svn.apache.org/viewvc?rev=1103333&view=rev
Log:
Make multi-revision-range merges stop early if a range causes a conflict.

We already did this for text and prop conflicts, but not for tree conflicts.
Also, the merge was only aborted if a continuous revision ranges was split
due to merge tracking. Multiple ranges passed in from the command line were
all merged regardless of whether a conflict occurred while merging one of
these ranges.

The new behaviour makes it easier to resolve conflicts one-by-one.
The old behaviour could lead to nodes being both tree-conflicted
and text-conflicted, for instance. This is no longer possible.

Discussed briefly with gstein, jerenkrantz, and philip in Ireland.

Surprisingly, no tests are failing due to this change.

* subversion/libsvn_client/merge.c
  (tree_conflict, tree_conflict_on_add): Add victim paths to the merge
   baton's list of conflicted paths, which is checked later to see whether
   the multi-range merge should be aborted.
  (do_directory_merge): New parameter ABORT_ON_CONFLICTS which, if true,
   causes an SVN_ERR_WC_FOUND_CONFLICT error if a conflict occurred.
   This is necessary since do_directory_merge() is called for each revision
   range separately and does not know if it might be called again to merge
   additional ranges. It already handled the case where the range it is merging
   is split up due to merge-tracking, and this behaviour is not changed.
  (do_merge): While looping over revision ranges, set the ABORT_ON_CONFLICTS
   parameter of do_directory_merge() depending on whether there are ranges
   remaining to be merged.

Modified:
    subversion/trunk/subversion/libsvn_client/merge.c

Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1103333&r1=1103332&r2=1103333&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Sun May 15 12:06:15 2011
@@ -551,6 +551,12 @@ tree_conflict(merge_cmd_baton_t *merge_b
                                  node_kind, action, reason));
       SVN_ERR(svn_wc__add_tree_conflict(merge_b->ctx->wc_ctx, conflict,
                                         merge_b->pool));
+
+      if (merge_b->conflicted_paths == NULL)
+        merge_b->conflicted_paths = apr_hash_make(merge_b->pool);
+
+      apr_hash_set(merge_b->conflicted_paths, victim_abspath,
+                   APR_HASH_KEY_STRING, victim_abspath);
     }
 
   return SVN_NO_ERROR;
@@ -586,6 +592,12 @@ tree_conflict_on_add(merge_cmd_baton_t *
       /* There is no existing tree conflict so it is safe to add one. */
       SVN_ERR(svn_wc__add_tree_conflict(merge_b->ctx->wc_ctx, conflict,
                                         merge_b->pool));
+
+      if (merge_b->conflicted_paths == NULL)
+        merge_b->conflicted_paths = apr_hash_make(merge_b->pool);
+
+      apr_hash_set(merge_b->conflicted_paths, victim_abspath,
+                   APR_HASH_KEY_STRING, victim_abspath);
     }
   else if (existing_conflict->action == svn_wc_conflict_action_delete &&
            conflict->action == svn_wc_conflict_action_add)
@@ -610,6 +622,12 @@ tree_conflict_on_add(merge_cmd_baton_t *
 
       SVN_ERR(svn_wc__add_tree_conflict(merge_b->ctx->wc_ctx, conflict,
                                         merge_b->pool));
+
+      if (merge_b->conflicted_paths == NULL)
+        merge_b->conflicted_paths = apr_hash_make(merge_b->pool);
+
+      apr_hash_set(merge_b->conflicted_paths, victim_abspath,
+                   APR_HASH_KEY_STRING, victim_abspath);
     }
 
   /* In any other cases, we don't touch the existing conflict. */
@@ -8040,6 +8058,9 @@ remove_noop_subtree_ranges(const char *u
 
    Handle DEPTH as documented for svn_client_merge3().
 
+   If ABORT_ON_CONFLICTS is TRUE raise an SVN_ERR_WC_FOUND_CONFLICT error
+   if any merge conflicts occur.
+
    Perform any temporary allocations in SCRATCH_POOL.
 
    NOTE: This is a wrapper around drive_merge_report_editor() which
@@ -8056,6 +8077,7 @@ do_directory_merge(svn_mergeinfo_catalog
                    const char *target_abspath,
                    svn_depth_t depth,
                    svn_boolean_t squelch_mergeinfo_notifications,
+                   svn_boolean_t abort_on_conflicts,
                    notification_receiver_baton_t *notify_b,
                    merge_cmd_baton_t *merge_b,
                    apr_pool_t *scratch_pool)
@@ -8331,7 +8353,7 @@ do_directory_merge(svn_mergeinfo_catalog
               next_end_rev =
                 get_most_inclusive_end_rev(notify_b->children_with_mergeinfo,
                                            is_rollback);
-              if ((next_end_rev != SVN_INVALID_REVNUM)
+              if ((next_end_rev != SVN_INVALID_REVNUM || abort_on_conflicts)
                   && is_path_conflicted_by_merge(merge_b))
                 {
                   svn_merge_range_t conflicted_range;
@@ -8685,9 +8707,16 @@ do_merge(apr_hash_t **modified_subtrees,
         }
       else if (target_kind == svn_node_dir)
         {
+          /* If conflicts occur while merging any but the very last
+           * revision range we want an error to be raised that aborts
+           * the merge operation. The user will be asked to resolve conflicts
+           * before merging subsequent revision ranges. */
+          svn_boolean_t abort_on_conflicts = (i < merge_sources->nelts - 1);
+
           SVN_ERR(do_directory_merge(result_catalog,
                                      url1, rev1, url2, rev2, target_abspath,
                                      depth, squelch_mergeinfo_notifications,
+                                     abort_on_conflicts,
                                      &notify_baton, &merge_cmd_baton,
                                      iterpool));