Author: breser
Date: Mon May 13 22:28:32 2013
New Revision: 1482124
URL: http://svn.apache.org/r1482124
Log:
Merge r1470246 from trunk:
* r1470246
Improve the interactive resolution of property conflicts. Instead of
showing the contents of the '.prej' file once for each prop conflict, show
initially a single line such as
"local delete, incoming edit upon merge"
(similar to resolving a text conflict) and allow the user to display a 3-way
diff by adding a 'dc - display conflict' option.
Justification:
Showing the whole .prej file each time was confusing and ugly when more
than one property was in conflict.
Votes:
+1: julianfoad, rhuijben
+1: stsp (for 1.8.0, but not any 1.8.x since it changes the UI)
Modified:
subversion/branches/1.8.x/ (props changed)
subversion/branches/1.8.x/subversion/svn/cl-conflicts.c
subversion/branches/1.8.x/subversion/svn/cl-conflicts.h
subversion/branches/1.8.x/subversion/svn/conflict-callbacks.c
Propchange: subversion/branches/1.8.x/
------------------------------------------------------------------------------
Merged /subversion/trunk:r1470246
Modified: subversion/branches/1.8.x/subversion/svn/cl-conflicts.c
URL:
http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/svn/cl-conflicts.c?rev=1482124&r1=1482123&r2=1482124&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/svn/cl-conflicts.c (original)
+++ subversion/branches/1.8.x/subversion/svn/cl-conflicts.c Mon May 13 22:28:32
2013
@@ -185,6 +185,60 @@ operation_str(svn_wc_operation_t operati
}
svn_error_t *
+svn_cl__get_human_readable_prop_conflict_description(
+ const char **desc,
+ const svn_wc_conflict_description2_t *conflict,
+ apr_pool_t *pool)
+{
+ const char *reason_str, *action_str;
+
+ /* We provide separately translatable strings for the values that we
+ * know about, and a fall-back in case any other values occur. */
+ switch (conflict->reason)
+ {
+ case svn_wc_conflict_reason_edited:
+ reason_str = _("local edit");
+ break;
+ case svn_wc_conflict_reason_added:
+ reason_str = _("local add");
+ break;
+ case svn_wc_conflict_reason_deleted:
+ reason_str = _("local delete");
+ break;
+ case svn_wc_conflict_reason_obstructed:
+ reason_str = _("local obstruction");
+ break;
+ default:
+ reason_str = apr_psprintf(pool, _("local %s"),
+ svn_token__to_word(map_conflict_reason_xml,
+ conflict->reason));
+ break;
+ }
+ switch (conflict->action)
+ {
+ case svn_wc_conflict_action_edit:
+ action_str = _("incoming edit");
+ break;
+ case svn_wc_conflict_action_add:
+ action_str = _("incoming add");
+ break;
+ case svn_wc_conflict_action_delete:
+ action_str = _("incoming delete");
+ break;
+ default:
+ action_str = apr_psprintf(pool, _("incoming %s"),
+ svn_token__to_word(map_conflict_action_xml,
+ conflict->action));
+ break;
+ }
+ SVN_ERR_ASSERT(reason_str && action_str);
+ *desc = apr_psprintf(pool, _("%s, %s %s"),
+ reason_str, action_str,
+ operation_str(conflict->operation));
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_cl__get_human_readable_tree_conflict_description(
const char **desc,
const svn_wc_conflict_description2_t *conflict,
Modified: subversion/branches/1.8.x/subversion/svn/cl-conflicts.h
URL:
http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/svn/cl-conflicts.h?rev=1482124&r1=1482123&r2=1482124&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/svn/cl-conflicts.h (original)
+++ subversion/branches/1.8.x/subversion/svn/cl-conflicts.h Mon May 13 22:28:32
2013
@@ -41,6 +41,18 @@ extern "C" {
/**
* Return in @a desc a possibly localized human readable
+ * description of a property conflict described by @a conflict.
+ *
+ * Allocate the result in @a pool.
+ */
+svn_error_t *
+svn_cl__get_human_readable_prop_conflict_description(
+ const char **desc,
+ const svn_wc_conflict_description2_t *conflict,
+ apr_pool_t *pool);
+
+/**
+ * Return in @a desc a possibly localized human readable
* description of a tree conflict described by @a conflict.
*
* Allocate the result in @a pool.
Modified: subversion/branches/1.8.x/subversion/svn/conflict-callbacks.c
URL:
http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/svn/conflict-callbacks.c?rev=1482124&r1=1482123&r2=1482124&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/svn/conflict-callbacks.c (original)
+++ subversion/branches/1.8.x/subversion/svn/conflict-callbacks.c Mon May 13
22:28:32 2013
@@ -225,6 +225,57 @@ show_conflicts(const svn_wc_conflict_des
pool);
}
+/* Display the conflicting values of a property as a 3-way diff.
+ *
+ * Assume the values are printable UTF-8 text.
+ */
+static svn_error_t *
+show_prop_conflict(const svn_wc_conflict_description2_t *desc,
+ apr_pool_t *pool)
+{
+ const char *base_abspath = desc->base_abspath;
+ const char *my_abspath = desc->my_abspath;
+ const char *their_abspath = desc->their_abspath;
+ svn_diff_file_options_t *options = svn_diff_file_options_create(pool);
+ svn_diff_t *diff;
+ svn_stream_t *output;
+
+ /* If any of the property values is missing, use an empty file instead
+ * for the purpose of showing a diff. */
+ if (! base_abspath || ! my_abspath || ! their_abspath)
+ {
+ const char *empty_file;
+
+ SVN_ERR(svn_io_open_unique_file3(NULL, &empty_file,
+ NULL, svn_io_file_del_on_pool_cleanup,
+ pool, pool));
+ if (! base_abspath)
+ base_abspath = empty_file;
+ if (! my_abspath)
+ my_abspath = empty_file;
+ if (! their_abspath)
+ their_abspath = empty_file;
+ }
+
+ options->ignore_eol_style = TRUE;
+ SVN_ERR(svn_stream_for_stdout(&output, pool));
+ SVN_ERR(svn_diff_file_diff3_2(&diff,
+ base_abspath, my_abspath, their_abspath,
+ options, pool));
+ SVN_ERR(svn_diff_file_output_merge2(output, diff,
+ base_abspath,
+ my_abspath,
+ their_abspath,
+ _("||||||| ORIGINAL"),
+ _("<<<<<<< MINE"),
+ _(">>>>>>> THEIRS"),
+ "=======",
+
svn_diff_conflict_display_modified_original_latest,
+ pool));
+
+ return SVN_NO_ERROR;
+}
+
/* Run an external editor, passing it the 'merged' file in DESC, or, if the
* 'merged' file is null, return an error. The tool to use is determined by
@@ -393,6 +444,7 @@ static const resolver_option_t prop_conf
{ "tf", N_("their version"), N_("accept their version of entire file "
"(same) [theirs-full]"),
svn_wc_conflict_choose_theirs_full },
+ { "dc", N_("display conflict"), N_("show conflicts in this property"), -1 },
{ "q", N_("quit resolution"), N_("postpone all remaining conflicts"),
svn_wc_conflict_choose_postpone },
{ "h", N_("help"), N_("show this help (also '?')"), -1 },
@@ -841,6 +893,13 @@ handle_prop_conflict(svn_wc_conflict_res
apr_pool_t *scratch_pool)
{
apr_pool_t *iterpool;
+ const char *message;
+
+ /* ### Work around a historical bug in the provider: the path to the
+ * conflict description file was put in the 'theirs' field, and
+ * 'theirs' was put in the 'merged' field. */
+ ((svn_wc_conflict_description2_t *)desc)->their_abspath = desc->merged_file;
+ ((svn_wc_conflict_description2_t *)desc)->merged_file = NULL;
SVN_ERR_ASSERT(desc->kind == svn_wc_conflict_kind_property);
@@ -852,32 +911,9 @@ handle_prop_conflict(svn_wc_conflict_res
b->path_prefix, desc->local_abspath,
scratch_pool)));
- /* ### Currently, the only useful information in a prop conflict
- * ### description is the .prej file path, which, possibly due to
- * ### deceitful interference from outer space, is stored in the
- * ### 'their_abspath' field of the description.
- * ### This needs to be fixed so we can present better options here. */
- if (desc->their_abspath)
- {
- svn_stringbuf_t *prop_reject;
-
- /* ### The library dumps an svn_string_t into a temp file, and
- * ### we read it back from the file into an svn_stringbuf_t here.
- * ### That's rather silly. We should be passed svn_string_t's
- * ### containing the old/mine/theirs values instead. */
- SVN_ERR(svn_stringbuf_from_file2(&prop_reject,
- desc->their_abspath,
- scratch_pool));
- /* Print reject file contents. */
- SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
- "%s\n", prop_reject->data));
- }
- else
- {
- /* Nothing much we can do without a prej file... */
- result->choice = svn_wc_conflict_choose_postpone;
- return SVN_NO_ERROR;
- }
+ SVN_ERR(svn_cl__get_human_readable_prop_conflict_description(&message, desc,
+ scratch_pool));
+ SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n", message));
iterpool = svn_pool_create(scratch_pool);
while (TRUE)
@@ -898,6 +934,10 @@ handle_prop_conflict(svn_wc_conflict_res
b->quit = TRUE;
break;
}
+ else if (strcmp(opt->code, "dc") == 0)
+ {
+ SVN_ERR(show_prop_conflict(desc, scratch_pool));
+ }
else if (opt->choice != -1)
{
result->choice = opt->choice;