You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2016/04/20 17:22:56 UTC

svn commit: r1740157 - in /subversion/trunk/subversion: include/svn_client.h libsvn_client/conflicts.c svn/conflict-callbacks.c tests/libsvn_client/conflicts-test.c

Author: stsp
Date: Wed Apr 20 15:22:56 2016
New Revision: 1740157

URL: http://svn.apache.org/viewvc?rev=1740157&view=rev
Log:
Add another resolution option for file/file "incoming add vs local
obstruction upon merge" tree conflicts.

This option ignores the incoming file and does not merge it.
It happens to have the same effect as the "accept current working copy state"
option but that might not be obvious to the user so it's best to offer this
functionality explicitly.

* subversion/include/svn_client.h
  (svn_client_conflict_option_merge_incoming_added_file_ignore): New option ID.

* subversion/libsvn_client/conflicts.c
  (resolve_merge_incoming_added_file_ignore,
   configure_option_merge_incoming_added_file_ignore): New resolution option.
  (svn_client_conflict_tree_get_resolution_options): Configure the new option.

* subversion/svn/conflict-callbacks.c
  (builtin_resolver_options): Map a menu key to the option and provide a
   short description.

* subversion/tests/libsvn_client/conflicts-test.c
  (test_option_merge_incoming_added_file_ignore, test_funcs): New test.

Modified:
    subversion/trunk/subversion/include/svn_client.h
    subversion/trunk/subversion/libsvn_client/conflicts.c
    subversion/trunk/subversion/svn/conflict-callbacks.c
    subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c

Modified: subversion/trunk/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=1740157&r1=1740156&r2=1740157&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Wed Apr 20 15:22:56 2016
@@ -4407,6 +4407,7 @@ typedef enum svn_client_conflict_option_
   svn_client_conflict_option_update_any_moved_away_children,
 
   /* Options for incoming file add vs local file 'obstruction' on merge. */
+  svn_client_conflict_option_merge_incoming_added_file_ignore,
   svn_client_conflict_option_merge_incoming_added_file_text_merge,
   svn_client_conflict_option_merge_incoming_added_file_replace,
   svn_client_conflict_option_merge_incoming_added_file_replace_and_merge,

Modified: subversion/trunk/subversion/libsvn_client/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/conflicts.c?rev=1740157&r1=1740156&r2=1740157&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/conflicts.c (original)
+++ subversion/trunk/subversion/libsvn_client/conflicts.c Wed Apr 20 15:22:56 2016
@@ -3595,6 +3595,46 @@ resolve_update_moved_away_node(svn_clien
 
 /* Implements conflict_option_resolve_func_t. */
 static svn_error_t *
+resolve_merge_incoming_added_file_ignore(svn_client_conflict_option_t *option,
+                                         svn_client_conflict_t *conflict,
+                                         apr_pool_t *scratch_pool)
+{
+  const char *local_abspath;
+  const char *lock_abspath;
+  svn_client_ctx_t *ctx = conflict->ctx;
+  svn_error_t *err;
+
+  local_abspath = svn_client_conflict_get_local_abspath(conflict);
+
+  SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx,
+                                                 local_abspath,
+                                                 scratch_pool, scratch_pool));
+
+  /* All other options for this conflict actively fetch the incoming
+   * new file. We can ignore the incoming new file by doing nothing. */
+
+  /* Resolve to current working copy state. */
+  err = svn_wc__del_tree_conflict(ctx->wc_ctx, local_abspath, scratch_pool);
+
+  /* svn_wc__del_tree_conflict doesn't handle notification for us */
+  if (ctx->notify_func2)
+    ctx->notify_func2(ctx->notify_baton2,
+                      svn_wc_create_notify(local_abspath,
+                                           svn_wc_notify_resolved_tree,
+                                           scratch_pool),
+                      scratch_pool);
+
+  err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
+                                                                 lock_abspath,
+                                                                 scratch_pool));
+  SVN_ERR(err);
+
+  conflict->resolution_tree = svn_client_conflict_option_get_id(option);
+
+  return SVN_NO_ERROR;
+}
+/* Implements conflict_option_resolve_func_t. */
+static svn_error_t *
 resolve_merge_incoming_added_file_text_merge(
   svn_client_conflict_option_t *option,
   svn_client_conflict_t *conflict,
@@ -4341,6 +4381,57 @@ configure_option_update_raise_moved_away
   return SVN_NO_ERROR;
 }
 
+/* Configure 'incoming added file ignore' resolution option for a tree
+ * conflict. */
+static svn_error_t *
+configure_option_merge_incoming_added_file_ignore(
+  svn_client_conflict_t *conflict,
+  apr_array_header_t *options,
+  apr_pool_t *scratch_pool)
+{
+  svn_wc_operation_t operation;
+  svn_wc_conflict_action_t incoming_change;
+  svn_wc_conflict_reason_t local_change;
+  svn_node_kind_t victim_node_kind;
+  const char *incoming_new_repos_relpath;
+  svn_revnum_t incoming_new_pegrev;
+  svn_node_kind_t incoming_new_kind;
+
+  operation = svn_client_conflict_get_operation(conflict);
+  incoming_change = svn_client_conflict_get_incoming_change(conflict);
+  local_change = svn_client_conflict_get_local_change(conflict);
+  victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict);
+  SVN_ERR(svn_client_conflict_get_incoming_new_repos_location(
+            &incoming_new_repos_relpath, &incoming_new_pegrev,
+            &incoming_new_kind, conflict, scratch_pool,
+            scratch_pool));
+
+  if (operation == svn_wc_operation_merge &&
+      victim_node_kind == svn_node_file &&
+      incoming_new_kind == svn_node_file &&
+      incoming_change == svn_wc_conflict_action_add &&
+      local_change == svn_wc_conflict_reason_obstructed)
+    {
+      svn_client_conflict_option_t *option;
+      const char *wcroot_abspath;
+
+      option = apr_pcalloc(options->pool, sizeof(*option));
+      option->id =
+        svn_client_conflict_option_merge_incoming_added_file_ignore;
+      SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, conflict->ctx->wc_ctx,
+                                 conflict->local_abspath, scratch_pool,
+                                 scratch_pool));
+      option->description =
+        apr_psprintf(options->pool, _("ignore and do not add '^/%s@%ld' here"),
+          incoming_new_repos_relpath, incoming_new_pegrev);
+      option->conflict = conflict;
+      option->do_resolve_func = resolve_merge_incoming_added_file_ignore;
+      APR_ARRAY_PUSH(options, const svn_client_conflict_option_t *) = option;
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* Configure 'incoming added file text merge' resolution option for a tree
  * conflict. */
 static svn_error_t *
@@ -4535,6 +4626,8 @@ svn_client_conflict_tree_get_resolution_
   SVN_ERR(configure_option_update_move_destination(conflict, *options));
   SVN_ERR(configure_option_update_raise_moved_away_children(conflict,
                                                             *options));
+  SVN_ERR(configure_option_merge_incoming_added_file_ignore(conflict, *options,
+                                                            scratch_pool));
   SVN_ERR(configure_option_merge_incoming_added_file_text_merge(conflict,
                                                                 *options,
                                                                 scratch_pool));

Modified: subversion/trunk/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/conflict-callbacks.c?rev=1740157&r1=1740156&r2=1740157&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/conflict-callbacks.c (original)
+++ subversion/trunk/subversion/svn/conflict-callbacks.c Wed Apr 20 15:22:56 2016
@@ -420,6 +420,8 @@ static const resolver_option_t builtin_r
     svn_client_conflict_option_update_any_moved_away_children },
 
   /* Options for incoming file add vs local file add upon merge. */
+  { "i", N_("ignore the incoming file"), NULL,
+    svn_client_conflict_option_merge_incoming_added_file_ignore },
   { "m", N_("merge the files"), NULL,
     svn_client_conflict_option_merge_incoming_added_file_text_merge },
   { "R", N_("replace my file with incoming file"), NULL,

Modified: subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c?rev=1740157&r1=1740156&r2=1740157&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c Wed Apr 20 15:22:56 2016
@@ -154,6 +154,79 @@ create_wc_with_add_vs_add_upon_merge_con
 }
 
 static svn_error_t *
+test_option_merge_incoming_added_file_ignore(const svn_test_opts_t *opts,
+                                              apr_pool_t *pool)
+{
+  svn_client_ctx_t *ctx;
+  svn_client_conflict_t *conflict;
+  const char *new_file_path;
+  svn_boolean_t text_conflicted;
+  apr_array_header_t *props_conflicted;
+  svn_boolean_t tree_conflicted;
+  struct status_baton sb;
+  struct svn_client_status_t *status;
+  svn_opt_revision_t opt_rev;
+  const svn_string_t *propval;
+
+  svn_test__sandbox_t *b = apr_palloc(pool, sizeof(*b));
+
+  SVN_ERR(svn_test__sandbox_create(b, "incoming_added_file_ignore",
+                                   opts, pool));
+
+  SVN_ERR(create_wc_with_add_vs_add_upon_merge_conflict(b));
+
+  /* Resolve the tree conflict. */
+  SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+  new_file_path = svn_relpath_join(branch_path, new_file_name, b->pool);
+  SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, new_file_path),
+                                  ctx, b->pool, b->pool));
+  SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+            conflict,
+            svn_client_conflict_option_merge_incoming_added_file_ignore,
+            b->pool));
+
+  /* Ensure that the file has the expected status. */
+  opt_rev.kind = svn_opt_revision_working;
+  sb.result_pool = b->pool;
+  SVN_ERR(svn_client_status6(NULL, ctx, sbox_wc_path(b, new_file_path),
+                             &opt_rev, svn_depth_unknown, TRUE, TRUE,
+                             TRUE, TRUE, FALSE, TRUE, NULL,
+                             status_func, &sb, b->pool));
+  status = sb.status;
+  SVN_TEST_ASSERT(status->kind == svn_node_file);
+  SVN_TEST_ASSERT(status->versioned);
+  SVN_TEST_ASSERT(!status->conflicted);
+  SVN_TEST_ASSERT(status->node_status == svn_wc_status_normal);
+  SVN_TEST_ASSERT(status->text_status == svn_wc_status_normal);
+  SVN_TEST_ASSERT(status->prop_status == svn_wc_status_normal);
+  SVN_TEST_ASSERT(!status->copied);
+  SVN_TEST_ASSERT(!status->switched);
+  SVN_TEST_ASSERT(!status->file_external);
+  SVN_TEST_ASSERT(status->moved_from_abspath == NULL);
+  SVN_TEST_ASSERT(status->moved_to_abspath == NULL);
+
+  SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, new_file_path),
+                                  ctx, b->pool, b->pool));
+
+  /* The file should not be in conflict. */
+  SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted,
+                                             &props_conflicted,
+                                             &tree_conflicted,
+                                             conflict, b->pool, b->pool));
+  SVN_TEST_ASSERT(!text_conflicted &&
+                  props_conflicted->nelts == 0 &&
+                  !tree_conflicted);
+
+  /* Verify the merged property value. */
+  SVN_ERR(svn_wc_prop_get2(&propval, ctx->wc_ctx,
+                           sbox_wc_path(b, new_file_path),
+                           "prop", b->pool, b->pool));
+  SVN_TEST_STRING_ASSERT(propval->data, propval_branch);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
 test_option_merge_incoming_added_file_text_merge(const svn_test_opts_t *opts,
                                                  apr_pool_t *pool)
 {
@@ -384,6 +457,8 @@ static int max_threads = 3;
 static struct svn_test_descriptor_t test_funcs[] =
   {
     SVN_TEST_NULL,
+    SVN_TEST_OPTS_PASS(test_option_merge_incoming_added_file_ignore,
+                       "test incoming add file ignore"),
     SVN_TEST_OPTS_PASS(test_option_merge_incoming_added_file_text_merge,
                        "test incoming add file text merge"),
     SVN_TEST_OPTS_PASS(test_option_merge_incoming_added_file_replace,