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/06/15 14:04:02 UTC

svn commit: r1748584 - /subversion/trunk/subversion/svn/conflict-callbacks.c

Author: stsp
Date: Wed Jun 15 14:04:02 2016
New Revision: 1748584

URL: http://svn.apache.org/viewvc?rev=1748584&view=rev
Log:
Add a 'choose move destination' menu item to the conflict prompt.

* subversion/svn/conflict-callbacks.c
  (extra_resolver_options_tree): Add "c" option.
  (build_tree_conflict_options): Add 'possible_moved_to_abspaths' output param.
   If an option is found which allows a choice of move destination, return
   that list to the caller and add the new "c" option to the conlifct prompt.
  (prompt_move_target_abspath): New prompt helper for selecting a move target.
  (handle_tree_conflict): Handle the new "c" option.

Modified:
    subversion/trunk/subversion/svn/conflict-callbacks.c

Modified: subversion/trunk/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/conflict-callbacks.c?rev=1748584&r1=1748583&r2=1748584&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/conflict-callbacks.c (original)
+++ subversion/trunk/subversion/svn/conflict-callbacks.c Wed Jun 15 14:04:02 2016
@@ -511,8 +511,13 @@ static const resolver_option_t extra_res
 {
   /* Translators: keep long_desc below 70 characters (wrap with a left
      margin of 9 spaces if needed) */
+  { "c",  N_("choose move destination"),
+          N_("choose a move target path from a list of possible targets"),
+                                  svn_client_conflict_option_undefined },
+
   { "h",  N_("help"),             N_("show this help (also '?')"),
-                                   svn_client_conflict_option_undefined },
+                                  svn_client_conflict_option_undefined },
+
   { NULL }
 };
 
@@ -1418,6 +1423,7 @@ handle_prop_conflicts(svn_boolean_t *res
 /* Set *OPTIONS to an array of resolution options for CONFLICT. */
 static svn_error_t *
 build_tree_conflict_options(resolver_option_t **options,
+                            apr_array_header_t **possible_moved_to_abspaths,
                             svn_client_conflict_t *conflict,
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool)
@@ -1433,9 +1439,10 @@ build_tree_conflict_options(resolver_opt
                                                           conflict,
                                                           scratch_pool,
                                                           scratch_pool));
-  nopt = builtin_options->nelts + ARRAY_LEN(extra_resolver_options) +
-           ARRAY_LEN(extra_resolver_options_tree);
+  nopt = builtin_options->nelts + ARRAY_LEN(extra_resolver_options_tree) +
+           ARRAY_LEN(extra_resolver_options);
   *options = apr_pcalloc(result_pool, sizeof(*opt) * (nopt + 1));
+  *possible_moved_to_abspaths = NULL;
 
   opt = *options;
   iterpool = svn_pool_create(scratch_pool);
@@ -1463,19 +1470,109 @@ build_tree_conflict_options(resolver_opt
       opt->accept_arg = known_option->accept_arg;
 
       opt++; 
-    }
 
+      if (id == svn_client_conflict_option_incoming_move_file_text_merge)
+        SVN_ERR(svn_client_conflict_option_get_moved_to_abspath_candidates(
+                  possible_moved_to_abspaths, builtin_option,
+                  result_pool, iterpool));
+    }
 
   svn_pool_destroy(iterpool);
 
-  for (o = extra_resolver_options; o->code; o++)
-    *opt++ = *o;
   for (o = extra_resolver_options_tree; o->code; o++)
+    {
+      /* Add the move target choice option only if there are multiple
+       * move targets to choose from. */
+      if (strcmp(o->code, "c") == 0 &&
+          (*possible_moved_to_abspaths == NULL || 
+           (*possible_moved_to_abspaths)->nelts <= 1))
+        continue;
+
+      *opt++ = *o;
+    }
+  for (o = extra_resolver_options; o->code; o++)
     *opt++ = *o;
 
   return SVN_NO_ERROR;
 }
 
+/* Make the user select a move target path for the moved-away VICTIM_ABSPATH. */
+static svn_error_t *
+prompt_move_target_abspath(int *preferred_move_target_idx,
+                           apr_array_header_t *possible_moved_to_abspaths,
+                           svn_cmdline_prompt_baton_t *pb,
+                           const char *victim_abspath,
+                           svn_client_ctx_t *ctx,
+                           apr_pool_t *scratch_pool)
+{
+  const char *move_targets_prompt = "";
+  const char *move_targets_list = "";
+  const char *wcroot_abspath;
+  const char *victim_relpath;
+  int i;
+  apr_int64_t idx;
+  apr_pool_t *iterpool;
+
+  SVN_ERR(svn_client_get_wc_root(&wcroot_abspath, victim_abspath,
+                                 ctx, scratch_pool, scratch_pool));
+  victim_relpath = svn_cl__local_style_skip_ancestor(wcroot_abspath,
+                                                     victim_abspath,
+                                                     scratch_pool),
+  iterpool = svn_pool_create(scratch_pool);
+
+  /* Build the prompt. */
+  for (i = 0; i < possible_moved_to_abspaths->nelts; i++)
+    {
+      const char *moved_to_abspath;
+      const char *moved_to_relpath;
+
+      svn_pool_clear(iterpool);
+
+      moved_to_abspath = APR_ARRAY_IDX(possible_moved_to_abspaths, i,
+                                       const char *);
+      moved_to_relpath = svn_cl__local_style_skip_ancestor(
+                           wcroot_abspath, moved_to_abspath, iterpool),
+      move_targets_list = apr_psprintf(scratch_pool, "%s (%d): %s\n",
+                                       move_targets_list, i + 1,
+                                       moved_to_relpath);
+    }
+  move_targets_prompt =
+    apr_psprintf(scratch_pool,
+                 _("Possible destinations for moved-away '%s' are:\n%s"
+                   "Select a move target path by number: "),
+                 victim_relpath, move_targets_list);
+
+  /* Keep asking the user until we got a valid choice. */
+  while (1)
+    {
+      const char *answer;
+      svn_error_t *err;
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_cmdline_prompt_user2(&answer, move_targets_prompt,
+                                       pb, iterpool));
+      err = svn_cstring_strtoi64(&idx, answer, 1,
+                                 possible_moved_to_abspaths->nelts, 10);
+      if (err)
+        {
+          char buf[1024];
+
+          svn_cmdline_fprintf(stderr, iterpool, "%s\n",
+                              svn_err_best_message(err, buf, sizeof(buf)));
+          svn_error_clear(err);
+          continue;
+        }
+
+      break;
+    }
+
+  svn_pool_destroy(iterpool);
+
+  *preferred_move_target_idx = (idx - 1);
+  return SVN_NO_ERROR;
+}
+
 /* Ask the user what to do about the tree conflict described by CONFLICT
  * and either resolve the conflict accordingly or postpone resolution.
  * SCRATCH_POOL is used for temporary allocations. */
@@ -1494,11 +1591,14 @@ handle_tree_conflict(svn_boolean_t *reso
   apr_pool_t *iterpool;
   resolver_option_t *tree_conflict_options;
   svn_client_conflict_option_id_t option_id;
+  const char *local_abspath;
   const char *conflict_description;
   const char *local_change_description;
   const char *incoming_change_description;
+  apr_array_header_t *possible_moved_to_abspaths;
 
   option_id = svn_client_conflict_option_unspecified;
+  local_abspath = svn_client_conflict_get_local_abspath(conflict);
 
   /* Always show the best possible conflict description and options. */
   SVN_ERR(svn_client_conflict_tree_get_details(conflict, scratch_pool));
@@ -1513,13 +1613,12 @@ handle_tree_conflict(svn_boolean_t *reso
     SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
                                 _("Tree conflict on '%s':\n%s\n"),
                                 svn_cl__local_style_skip_ancestor(
-                                  path_prefix,
-                                  svn_client_conflict_get_local_abspath(conflict),
-                                  scratch_pool),
+                                  path_prefix, local_abspath, scratch_pool),
                                 conflict_description));
 
-  SVN_ERR(build_tree_conflict_options(&tree_conflict_options, conflict,
-                                      scratch_pool, scratch_pool));
+  SVN_ERR(build_tree_conflict_options(&tree_conflict_options,
+                                      &possible_moved_to_abspaths,
+                                      conflict, scratch_pool, scratch_pool));
   iterpool = svn_pool_create(scratch_pool);
   while (1)
     {
@@ -1528,8 +1627,7 @@ handle_tree_conflict(svn_boolean_t *reso
       svn_pool_clear(iterpool);
 
       SVN_ERR(prompt_user(&opt, tree_conflict_options, NULL,
-                          *printed_description ? NULL : conflict_description,
-                          pb, iterpool));
+                          conflict_description, pb, iterpool));
       *printed_description = TRUE;
       if (! opt)
         continue;
@@ -1540,6 +1638,38 @@ handle_tree_conflict(svn_boolean_t *reso
           *quit = TRUE;
           break;
         }
+      else if (strcmp(opt->code, "c") == 0)
+        {
+          int preferred_move_target_idx;
+          apr_array_header_t *options;
+          svn_client_conflict_option_t *conflict_option;
+
+          SVN_ERR(prompt_move_target_abspath(&preferred_move_target_idx,
+                                             possible_moved_to_abspaths, pb,
+                                             local_abspath, ctx, iterpool));
+
+          /* Update preferred move target path. */
+          SVN_ERR(svn_client_conflict_tree_get_resolution_options(&options,
+                                                                  conflict,
+                                                                  iterpool,
+                                                                  iterpool));
+          conflict_option =
+            svn_client_conflict_option_find_by_id( 
+              options,
+              svn_client_conflict_option_incoming_move_file_text_merge);
+          if (conflict_option)
+            {
+              SVN_ERR(svn_client_conflict_option_set_moved_to_abspath(
+                        conflict_option, preferred_move_target_idx, iterpool));
+
+              /* Update option description. */
+              SVN_ERR(build_tree_conflict_options(&tree_conflict_options,
+                                                  &possible_moved_to_abspaths,
+                                                  conflict,
+                                                  scratch_pool, scratch_pool));
+            }
+          continue;
+        }
       else if (opt->choice != svn_client_conflict_option_undefined)
         {
           option_id = opt->choice;