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/03/22 15:32:26 UTC

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

Author: stsp
Date: Tue Mar 22 14:32:26 2016
New Revision: 1736197

URL: http://svn.apache.org/viewvc?rev=1736197&view=rev
Log:
At the API level, provide tree conflict descriptions in two parts: one part
describing the local change, and one part describing the incomcng change.

This will make it easier for client implementors to display conflict
descriptions in a useful way.

* subversion/include/svn_client.h
  (svn_client_conflict_tree_get_description): Split the single 'description'
   output parameter into two output parameters: 'local_change_description'
   and 'incoming_change_description'. Document some syntactical properties
   of descriptions which client implementors may rely on.

* subversion/libsvn_client/conflicts.c
  (tree_conflict_get_description_func_t): Use two output params here as well.
  (conflict_tree_get_description_generic
   conflict_tree_get_description_incoming_delete,
   conflict_tree_get_description_incoming_add,
   conflict_tree_get_description_incoming_edit,
   svn_client_conflict_tree_get_description): Update accordingly.

* subversion/svn/conflict-callbacks.c
  (handle_tree_conflict): Update to use the changed API.

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

Modified: subversion/trunk/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=1736197&r1=1736196&r2=1736197&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Tue Mar 22 14:32:26 2016
@@ -4495,18 +4495,40 @@ svn_client_conflict_prop_get_description
  * Additionally, the description may be localized to the language used
  * by the current locale.
  *
+ * While client implementors are free to enhance descriptions by adding
+ * additional information to the text, or break up very long lines for
+ * formatting purposes, there is no syntax defined for descriptions, and
+ * implementors should not rely on any particular parts of descriptions
+ * to remain stable over time, apart from what is stated below.
+ * Descriptions may or may not form complete sentences. They may contain
+ * paths relative to the repository root; such paths always start with "^/",
+ * and end with either a peg revision (e.g. "@100") or a colon followed by
+ * a range of revisions (as in svn:mergeinfo, e.g. ":100-200").
+ * Paths may appear on a line of their own to avoid overlong lines.
+ * Any revision numbers mentioned elsewhere in the description are
+ * prefixed with the letter 'r' (e.g. "r99").
+ *
+ * The description has two parts: One describing the "local change" which
+ * occured in the working copy or perhaps a branch (the merge target).
+ * The other part describes the "incoming change" which conflicts with
+ * the local change. Both parts are provided independently to allow for
+ * some flexibility when displaying the description.
+ *
  * By default, the description is based only on information available in
  * the working copy. If svn_client_conflict_tree_get_details() was already
  * called for @a conflict, the description might also contain useful
- * information obtained from the repository.
+ * information obtained from the repository and provide for a much better
+ * user experience.
  *
  * @since New in 1.10.
  */
 svn_error_t *
-svn_client_conflict_tree_get_description(const char **description,
-                                         svn_client_conflict_t *conflict,
-                                         apr_pool_t *result_pool,
-                                         apr_pool_t *scratch_pool);
+svn_client_conflict_tree_get_description(
+  const char **local_change_description,
+  const char **incoming_change_description,
+  svn_client_conflict_t *conflict,
+  apr_pool_t *result_pool,
+  apr_pool_t *scratch_pool);
 
 /**
  * Set @a *options to an array of pointers to svn_client_conflict_option_t

Modified: subversion/trunk/subversion/libsvn_client/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/conflicts.c?rev=1736197&r1=1736196&r2=1736197&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/conflicts.c (original)
+++ subversion/trunk/subversion/libsvn_client/conflicts.c Tue Mar 22 14:32:26 2016
@@ -51,7 +51,8 @@
 
 /* Describe a tree conflict. */
 typedef svn_error_t *(*tree_conflict_get_description_func_t)(
-  const char **description,
+  const char **local_change_description,
+  const char **incoming_change_description,
   svn_client_conflict_t *conflict,
   apr_pool_t *result_pool,
   apr_pool_t *scratch_pool);
@@ -730,7 +731,8 @@ svn_client_conflict_prop_get_description
 
 /* Implements tree_conflict_get_description_func_t. */
 static svn_error_t *
-conflict_tree_get_description_generic(const char **description,
+conflict_tree_get_description_generic(const char **local_change_description,
+                                      const char **incoming_change_description,
                                       svn_client_conflict_t *conflict,
                                       apr_pool_t *result_pool,
                                       apr_pool_t *scratch_pool)
@@ -776,23 +778,24 @@ conflict_tree_get_description_generic(co
 
   if (action && reason)
     {
-      *description = apr_psprintf(result_pool, _("%s, %s %s"),
-                                  reason, action, operation);
+      *local_change_description = apr_pstrdup(result_pool, reason);
+      *incoming_change_description = apr_pstrdup(result_pool, action);
     }
   else
     {
       /* A catch-all message for very rare or nominally impossible cases.
          It will not be pretty, but is closer to an internal error than
          an ordinary user-facing string. */
-      *description = apr_psprintf(result_pool,
-                                  _("local: %s %s incoming: %s %s %s"),
-                                  svn_node_kind_to_word(conflict_node_kind),
-                                  svn_token__to_word(map_conflict_reason,
-                                                     conflict_reason),
-                                  svn_node_kind_to_word(incoming_kind),
-                                  svn_token__to_word(map_conflict_action,
-                                                     conflict_action),
-                                  operation);
+      *local_change_description = apr_psprintf(result_pool,
+                                    _("local: %s %s"),
+                                    svn_node_kind_to_word(conflict_node_kind),
+                                    svn_token__to_word(map_conflict_reason,
+                                                       conflict_reason));
+      *incoming_change_description = apr_psprintf(result_pool,
+                                       _("incoming: %s %s"),
+                                       svn_node_kind_to_word(incoming_kind),
+                                       svn_token__to_word(map_conflict_action,
+                                                          conflict_action));
     }
   return SVN_NO_ERROR;
 }
@@ -1344,10 +1347,12 @@ describe_incoming_reverse_addition_upon_
 
 /* Implements tree_conflict_get_description_func_t. */
 static svn_error_t *
-conflict_tree_get_description_incoming_delete(const char **description,
-                                              svn_client_conflict_t *conflict,
-                                              apr_pool_t *result_pool,
-                                              apr_pool_t *scratch_pool)
+conflict_tree_get_description_incoming_delete(
+  const char **local_change_description,
+  const char **incoming_change_description,
+  svn_client_conflict_t *conflict,
+  apr_pool_t *result_pool,
+  apr_pool_t *scratch_pool)
 {
   const char *action, *reason;
   svn_node_kind_t victim_node_kind;
@@ -1360,20 +1365,20 @@ conflict_tree_get_description_incoming_d
   struct conflict_tree_incoming_delete_details *details;
 
   if (conflict->tree_conflict_details == NULL)
-    return svn_error_trace(conflict_tree_get_description_generic(description,
-                                                                 conflict,
-                                                                 result_pool,
-                                                                 scratch_pool));
+    return svn_error_trace(conflict_tree_get_description_generic(
+                             local_change_description,
+                             incoming_change_description,
+                             conflict, result_pool, scratch_pool));
 
   local_change = svn_client_conflict_get_local_change(conflict);
   conflict_operation = svn_client_conflict_get_operation(conflict);
   victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict);
   SVN_ERR(describe_local_change(&reason, conflict, scratch_pool, scratch_pool));
   if (reason == NULL)
-    return svn_error_trace(conflict_tree_get_description_generic(description,
-                                                                 conflict,
-                                                                 result_pool,
-                                                                 scratch_pool));
+    return svn_error_trace(conflict_tree_get_description_generic(
+                             local_change_description,
+                             incoming_change_description,
+                             conflict, result_pool, scratch_pool));
   SVN_ERR(svn_client_conflict_get_incoming_old_repos_location(
             &old_repos_relpath, &old_rev, NULL, conflict, scratch_pool,
             scratch_pool));
@@ -1442,7 +1447,9 @@ conflict_tree_get_description_incoming_d
         }
       }
 
-  *description = apr_psprintf(result_pool, _("%s, %s"), reason, action);
+  *local_change_description = apr_pstrdup(result_pool, reason);
+  *incoming_change_description = apr_pstrdup(result_pool, action);
+
   return SVN_NO_ERROR;
 }
 
@@ -2293,10 +2300,12 @@ describe_incoming_reverse_deletion_upon_
 
 /* Implements tree_conflict_get_description_func_t. */
 static svn_error_t *
-conflict_tree_get_description_incoming_add(const char **description,
-                                           svn_client_conflict_t *conflict,
-                                           apr_pool_t *result_pool,
-                                           apr_pool_t *scratch_pool)
+conflict_tree_get_description_incoming_add(
+  const char **local_change_description,
+  const char **incoming_change_description,
+  svn_client_conflict_t *conflict,
+  apr_pool_t *result_pool,
+  apr_pool_t *scratch_pool)
 {
   const char *action, *reason;
   svn_node_kind_t victim_node_kind;
@@ -2311,20 +2320,21 @@ conflict_tree_get_description_incoming_a
   struct conflict_tree_incoming_add_details *details;
 
   if (conflict->tree_conflict_details == NULL)
-    return svn_error_trace(conflict_tree_get_description_generic(description,
-                                                                 conflict,
-                                                                 result_pool,
-                                                                 scratch_pool));
+    return svn_error_trace(conflict_tree_get_description_generic(
+                             local_change_description,
+                             incoming_change_description,
+                             conflict, result_pool, scratch_pool));
 
   local_change = svn_client_conflict_get_local_change(conflict);
   conflict_operation = svn_client_conflict_get_operation(conflict);
   victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict);
   SVN_ERR(describe_local_change(&reason, conflict, scratch_pool, scratch_pool));
   if (reason == NULL)
-    return svn_error_trace(conflict_tree_get_description_generic(description,
-                                                                 conflict,
-                                                                 result_pool,
-                                                                 scratch_pool));
+    return svn_error_trace(conflict_tree_get_description_generic(
+                             local_change_description,
+                             incoming_change_description,
+                             conflict, result_pool, scratch_pool));
+
   SVN_ERR(svn_client_conflict_get_incoming_old_repos_location(
             &old_repos_relpath, &old_rev, &old_node_kind, conflict,
             scratch_pool, scratch_pool));
@@ -2364,7 +2374,9 @@ conflict_tree_get_description_incoming_a
                    old_rev, new_rev, result_pool);
     }
 
-  *description = apr_psprintf(result_pool, _("%s, %s"), reason, action);
+  *local_change_description = apr_pstrdup(result_pool, reason);
+  *incoming_change_description = apr_pstrdup(result_pool, action);
+
   return SVN_NO_ERROR;
 }
 
@@ -2708,10 +2720,12 @@ describe_incoming_edit_list_modified_rev
 
 /* Implements tree_conflict_get_description_func_t. */
 static svn_error_t *
-conflict_tree_get_description_incoming_edit(const char **description,
-                                            svn_client_conflict_t *conflict,
-                                            apr_pool_t *result_pool,
-                                            apr_pool_t *scratch_pool)
+conflict_tree_get_description_incoming_edit(
+  const char **local_change_description,
+  const char **incoming_change_description,
+  svn_client_conflict_t *conflict,
+  apr_pool_t *result_pool,
+  apr_pool_t *scratch_pool)
 {
   const char *action, *reason;
   svn_node_kind_t victim_node_kind;
@@ -2726,10 +2740,10 @@ conflict_tree_get_description_incoming_e
   apr_array_header_t *edits;
 
   if (conflict->tree_conflict_details == NULL)
-    return svn_error_trace(conflict_tree_get_description_generic(description,
-                                                                 conflict,
-                                                                 result_pool,
-                                                                 scratch_pool));
+    return svn_error_trace(conflict_tree_get_description_generic(
+                             local_change_description,
+                             incoming_change_description,
+                             conflict, result_pool, scratch_pool));
 
   SVN_ERR(svn_client_conflict_get_incoming_old_repos_location(
             &old_repos_relpath, &old_rev, &old_node_kind, conflict,
@@ -2743,10 +2757,10 @@ conflict_tree_get_description_incoming_e
   victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict);
   SVN_ERR(describe_local_change(&reason, conflict, scratch_pool, scratch_pool));
   if (reason == NULL)
-    return svn_error_trace(conflict_tree_get_description_generic(description,
-                                                                 conflict,
-                                                                 result_pool,
-                                                                 scratch_pool));
+    return svn_error_trace(conflict_tree_get_description_generic(
+                             local_change_description,
+                             incoming_change_description,
+                             conflict, result_pool, scratch_pool));
 
   edits = conflict->tree_conflict_details;
 
@@ -2783,8 +2797,9 @@ conflict_tree_get_description_incoming_e
                                         "^/%s:%ld"),
                                       new_repos_relpath, new_rev);
 
-              *description = apr_psprintf(result_pool, _("%s, %s"),
-                                           reason, action);
+              *local_change_description = apr_pstrdup(result_pool, reason);
+              *incoming_change_description = apr_pstrdup(result_pool, action);
+
               return SVN_NO_ERROR;
             }
           else
@@ -2833,8 +2848,9 @@ conflict_tree_get_description_incoming_e
                                         "of ^/%s:%ld"),
                                       new_repos_relpath, old_rev);
 
-              *description = apr_psprintf(result_pool, _("%s, %s"),
-                                           reason, action);
+              *local_change_description = apr_pstrdup(result_pool, reason);
+              *incoming_change_description = apr_pstrdup(result_pool, action);
+
               return SVN_NO_ERROR;
             }
           else
@@ -2868,18 +2884,24 @@ conflict_tree_get_description_incoming_e
   action = apr_psprintf(scratch_pool, "%s:%s", action,
                         describe_incoming_edit_list_modified_revs(
                           edits, scratch_pool));
-  *description = apr_psprintf(result_pool, _("%s, %s"), reason, action);
+  *local_change_description = apr_pstrdup(result_pool, reason);
+  *incoming_change_description = apr_pstrdup(result_pool, action);
+
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
-svn_client_conflict_tree_get_description(const char **description,
-                                         svn_client_conflict_t *conflict,
-                                         apr_pool_t *result_pool,
-                                         apr_pool_t *scratch_pool)
+svn_client_conflict_tree_get_description(
+  const char **local_change_description,
+  const char **incoming_change_description,
+  svn_client_conflict_t *conflict,
+  apr_pool_t *result_pool,
+  apr_pool_t *scratch_pool)
 {
   return svn_error_trace(conflict->tree_conflict_get_description_func(
-                           description, conflict, result_pool, scratch_pool));
+                           local_change_description,
+                           incoming_change_description,
+                           conflict, result_pool, scratch_pool));
 }
 
 void

Modified: subversion/trunk/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/conflict-callbacks.c?rev=1736197&r1=1736196&r2=1736197&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/conflict-callbacks.c (original)
+++ subversion/trunk/subversion/svn/conflict-callbacks.c Tue Mar 22 14:32:26 2016
@@ -1419,7 +1419,8 @@ handle_tree_conflict(svn_boolean_t *reso
                      svn_client_ctx_t *ctx,
                      apr_pool_t *scratch_pool)
 {
-  const char *description;
+  const char *local_change_description;
+  const char *incoming_change_description;
   const char *src_left_version;
   const char *src_right_version;
   const char *repos_root_url;
@@ -1436,13 +1437,14 @@ handle_tree_conflict(svn_boolean_t *reso
   SVN_ERR(svn_client_conflict_tree_get_details(conflict, scratch_pool));
 
   SVN_ERR(svn_client_conflict_tree_get_description(
-           &description, conflict, scratch_pool, scratch_pool));
+           &local_change_description, &incoming_change_description,
+           conflict, scratch_pool, scratch_pool));
   SVN_ERR(svn_cmdline_fprintf(
                stderr, scratch_pool,
-               _("Tree conflict on '%s'\n   > %s\n"),
+               _("Tree conflict on '%s'\n   > %s, %s\n"),
                svn_cl__local_style_skip_ancestor(path_prefix,
                  svn_client_conflict_get_local_abspath(conflict), scratch_pool),
-               description));
+               local_change_description, incoming_change_description));
 
   SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, conflict,
                                              scratch_pool, scratch_pool));