Author: breser
Date: Mon May 13 22:42:22 2013
New Revision: 1482138
URL: http://svn.apache.org/r1482138
Log:
Merge the r1477294 group from trunk:
* r1477294, r1480616, r1480641, r1480642, r1480664, r1480669
Further improvements for interactive resolution of property conflicts.
Allow conflicted properties to be edited and resolved to the edited value.
Justification:
This is a usability enhancement we could make in 1.8.0.
It also fixes a bug in libsvn_wc where it doesn't use results provided
by the conflict callback (see r1480641), which might help API consumers.
Notes:
This group depends on r1470246.
r1477294 and r1480616 are merged to avoid text conflicts from refactoring.
r1480641 and r1480642 are the main changes.
The other revisions are small follow-up fixes.
Votes:
+1: stsp (for 1.8.0, but not any 1.8.x since it changes the UI)
+1: steveking
+1: julianfoad
-0: rhuijben (requires backport branch. I get a merge conflict using 1.7
<stsp> This is because this group requires r1470246 to
be merged first, as noted under Notes:)
Modified:
subversion/branches/1.8.x/ (props changed)
subversion/branches/1.8.x/STATUS
subversion/branches/1.8.x/subversion/libsvn_wc/conflicts.c
subversion/branches/1.8.x/subversion/svn/conflict-callbacks.c
Propchange: subversion/branches/1.8.x/
------------------------------------------------------------------------------
Merged /subversion/trunk:r1477294,1480616,1480641-1480642,1480664,1480669
Modified: subversion/branches/1.8.x/STATUS
URL:
http://svn.apache.org/viewvc/subversion/branches/1.8.x/STATUS?rev=1482138&r1=1482137&r2=1482138&view=diff
==============================================================================
--- subversion/branches/1.8.x/STATUS (original)
+++ subversion/branches/1.8.x/STATUS Mon May 13 22:42:22 2013
@@ -125,26 +125,6 @@ Approved changes:
# blocking issues. If in doubt see this link for details:
#
http://subversion.apache.org/docs/community-guide/releasing.html#release-stabilization
- * r1477294, r1480616, r1480641, r1480642, r1480664, r1480669
- Further improvements for interactive resolution of property conflicts.
- Allow conflicted properties to be edited and resolved to the edited value.
- Justification:
- This is a usability enhancement we could make in 1.8.0.
- It also fixes a bug in libsvn_wc where it doesn't use results provided
- by the conflict callback (see r1480641), which might help API consumers.
- Notes:
- This group depends on r1470246.
- r1477294 and r1480616 are merged to avoid text conflicts from refactoring.
- r1480641 and r1480642 are the main changes.
- The other revisions are small follow-up fixes.
- Votes:
- +1: stsp (for 1.8.0, but not any 1.8.x since it changes the UI)
- +1: steveking
- +1: julianfoad
- -0: rhuijben (requires backport branch. I get a merge conflict using 1.7
- <stsp> This is because this group requires r1470246 to
- be merged first, as noted under Notes:)
-
* r1469363, r1469645, r1469674, r1470037, r1470537, r1478220, r1478221,
r1478465, r1478998, r1480723
Fix issue #4355 'svn_client_log5 broken with multiple revisions which
Modified: subversion/branches/1.8.x/subversion/libsvn_wc/conflicts.c
URL:
http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_wc/conflicts.c?rev=1482138&r1=1482137&r2=1482138&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/branches/1.8.x/subversion/libsvn_wc/conflicts.c Mon May 13
22:42:22 2013
@@ -2302,15 +2302,52 @@ svn_wc__read_conflicts(const apr_array_h
/*** Resolving a conflict automatically ***/
-/*
- * Resolve the text conflict found in DB/LOCAL_ABSPATH/CONFLICTS
- * according to CONFLICT_CHOICE. (Don't mark it as resolved.)
+/* Prepare to delete an artifact file at ARTIFACT_FILE_ABSPATH in the
+ * working copy at DB/WRI_ABSPATH.
+ *
+ * Set *WORK_ITEMS to a new work item that, when run, will delete the
+ * artifact file; or to NULL if there is no file to delete.
*
- * If there were any marker files recorded and present on disk, append to
- * *WORK_ITEMS work items to remove them, and set *REMOVED_REJECT_FILES
- * to TRUE. Otherwise, don't change *REMOVED_REJECT_FILES.
+ * Set *FILE_FOUND to TRUE if the artifact file is found on disk and its
+ * node kind is 'file'; otherwise do not change *FILE_FOUND. FILE_FOUND
+ * may be NULL if not required.
+ */
+static svn_error_t *
+remove_artifact_file_if_exists(svn_skel_t **work_items,
+ svn_boolean_t *file_found,
+ svn_wc__db_t *db,
+ const char *wri_abspath,
+ const char *artifact_file_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ *work_items = NULL;
+ if (artifact_file_abspath)
+ {
+ svn_node_kind_t node_kind;
+
+ SVN_ERR(svn_io_check_path(artifact_file_abspath, &node_kind,
+ scratch_pool));
+ if (node_kind == svn_node_file)
+ {
+ SVN_ERR(svn_wc__wq_build_file_remove(work_items,
+ db, wri_abspath,
+ artifact_file_abspath,
+ result_pool, scratch_pool));
+ if (file_found)
+ *file_found = TRUE;
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/*
+ * Resolve the text conflict found in DB/LOCAL_ABSPATH according
+ * to CONFLICT_CHOICE.
*
- * It is an error if there is no text conflict.
+ * It is not an error if there is no text conflict. If a text conflict
+ * existed and was resolved, set *DID_RESOLVE to TRUE, else set it to FALSE.
*
* Note: When there are no conflict markers to remove there is no existing
* text conflict; just a database containing old information, which we should
@@ -2319,21 +2356,37 @@ svn_wc__read_conflicts(const apr_array_h
* Subversion 1.0.
*/
static svn_error_t *
-resolve_text_conflict_on_node(svn_boolean_t *removed_reject_files,
- svn_skel_t **work_items,
+resolve_text_conflict_on_node(svn_boolean_t *did_resolve,
svn_wc__db_t *db,
const char *local_abspath,
- svn_wc_operation_t operation,
- svn_skel_t *conflicts,
svn_wc_conflict_choice_t conflict_choice,
+ const char *merged_file,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *scratch_pool)
{
const char *conflict_old = NULL;
const char *conflict_new = NULL;
const char *conflict_working = NULL;
const char *auto_resolve_src;
- svn_node_kind_t node_kind;
svn_skel_t *work_item;
+ svn_skel_t *work_items = NULL;
+ svn_skel_t *conflicts;
+ svn_wc_operation_t operation;
+ svn_boolean_t text_conflicted;
+
+ *did_resolve = FALSE;
+
+ SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath,
+ scratch_pool, scratch_pool));
+ if (!conflicts)
+ return SVN_NO_ERROR;
+
+ SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, &text_conflicted,
+ NULL, NULL, db, local_abspath, conflicts,
+ scratch_pool, scratch_pool));
+ if (!text_conflicted)
+ return SVN_NO_ERROR;
SVN_ERR(svn_wc__conflict_read_text_conflict(&conflict_working,
&conflict_old,
@@ -2355,7 +2408,7 @@ resolve_text_conflict_on_node(svn_boolea
auto_resolve_src = conflict_new;
break;
case svn_wc_conflict_choose_merged:
- auto_resolve_src = NULL;
+ auto_resolve_src = merged_file;
break;
case svn_wc_conflict_choose_theirs_conflict:
case svn_wc_conflict_choose_mine_conflict:
@@ -2411,12 +2464,12 @@ resolve_text_conflict_on_node(svn_boolea
SVN_ERR(svn_wc__wq_build_file_copy_translated(
&work_item, db, local_abspath,
auto_resolve_src, local_abspath, scratch_pool, scratch_pool));
- *work_items = svn_wc__wq_merge(*work_items, work_item, scratch_pool);
+ work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
SVN_ERR(svn_wc__wq_build_sync_file_flags(&work_item, db,
local_abspath,
scratch_pool, scratch_pool));
- *work_items = svn_wc__wq_merge(*work_items, work_item, scratch_pool);
+ work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
}
/* Legacy behavior: Only report text conflicts as resolved when at least
@@ -2425,60 +2478,36 @@ resolve_text_conflict_on_node(svn_boolea
If not the UI shows the conflict as already resolved
(and in this case we just remove the in-db conflict) */
- if (conflict_old)
- {
- SVN_ERR(svn_io_check_path(conflict_old, &node_kind, scratch_pool));
- if (node_kind == svn_node_file)
- {
- SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
- local_abspath,
- conflict_old,
- scratch_pool, scratch_pool));
- *work_items = svn_wc__wq_merge(*work_items, work_item, scratch_pool);
- *removed_reject_files = TRUE;
- }
- }
-
- if (conflict_new)
- {
- SVN_ERR(svn_io_check_path(conflict_new, &node_kind, scratch_pool));
- if (node_kind == svn_node_file)
- {
- SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
- local_abspath,
- conflict_new,
- scratch_pool, scratch_pool));
- *work_items = svn_wc__wq_merge(*work_items, work_item, scratch_pool);
- *removed_reject_files = TRUE;
- }
- }
-
- if (conflict_working)
- {
- SVN_ERR(svn_io_check_path(conflict_working, &node_kind, scratch_pool));
- if (node_kind == svn_node_file)
- {
- SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
- local_abspath,
- conflict_working,
- scratch_pool, scratch_pool));
- *work_items = svn_wc__wq_merge(*work_items, work_item, scratch_pool);
- *removed_reject_files = TRUE;
- }
- }
+ SVN_ERR(remove_artifact_file_if_exists(&work_item, did_resolve,
+ db, local_abspath, conflict_old,
+ scratch_pool, scratch_pool));
+ work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+
+ SVN_ERR(remove_artifact_file_if_exists(&work_item, did_resolve,
+ db, local_abspath, conflict_new,
+ scratch_pool, scratch_pool));
+ work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+
+ SVN_ERR(remove_artifact_file_if_exists(&work_item, did_resolve,
+ db, local_abspath, conflict_working,
+ scratch_pool, scratch_pool));
+ work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+
+ SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath,
+ TRUE, FALSE, FALSE,
+ work_items, scratch_pool));
+ SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+ scratch_pool));
return SVN_NO_ERROR;
}
/*
- * Resolve the property conflicts found in DB/LOCAL_ABSPATH/CONFLICTS
- * according to CONFLICT_CHOICE. (Don't mark it as resolved.)
+ * Resolve the property conflicts found in DB/LOCAL_ABSPATH according
+ * to CONFLICT_CHOICE.
*
- * If there was a reject file recorded and present on disk, append to
- * *WORK_ITEMS a work item to remove it, and set *REMOVED_REJECT_FILE
- * to TRUE. Otherwise, don't change *REMOVED_REJECT_FILE.
- *
- * It is an error if there is no prop conflict.
+ * It is not an error if there is no prop conflict. If a prop conflict
+ * existed and was resolved, set *DID_RESOLVE to TRUE, else set it to FALSE.
*
* Note: When there are no conflict markers on-disk to remove there is
* no existing text conflict (unless we are still in the process of
@@ -2509,16 +2538,16 @@ resolve_text_conflict_on_node(svn_boolea
*
*/
static svn_error_t *
-resolve_prop_conflict_on_node(svn_boolean_t *removed_reject_file,
- svn_skel_t **work_items,
+resolve_prop_conflict_on_node(svn_boolean_t *did_resolve,
svn_wc__db_t *db,
const char *local_abspath,
- svn_wc_operation_t operation,
- svn_skel_t *conflicts,
+ const char *conflicted_propname,
svn_wc_conflict_choice_t conflict_choice,
+ const char *merged_file,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *scratch_pool)
{
- svn_node_kind_t node_kind;
const char *prop_reject_file;
apr_hash_t *mine_props;
apr_hash_t *their_old_props;
@@ -2526,6 +2555,24 @@ resolve_prop_conflict_on_node(svn_boolea
apr_hash_t *conflicted_props;
apr_hash_t *old_props;
apr_hash_t *resolve_from = NULL;
+ svn_skel_t *work_items = NULL;
+ svn_skel_t *conflicts;
+ svn_wc_operation_t operation;
+ svn_boolean_t prop_conflicted;
+
+ *did_resolve = FALSE;
+
+ SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ if (!conflicts)
+ return SVN_NO_ERROR;
+
+ SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, &prop_conflicted,
+ NULL, db, local_abspath, conflicts,
+ scratch_pool, scratch_pool));
+ if (!prop_conflicted)
+ return SVN_NO_ERROR;
SVN_ERR(svn_wc__conflict_read_prop_conflict(&prop_reject_file,
&mine_props, &their_old_props,
@@ -2564,7 +2611,24 @@ resolve_prop_conflict_on_node(svn_boolea
resolve_from = their_props;
break;
case svn_wc_conflict_choose_merged:
- resolve_from = NULL;
+ if (merged_file && conflicted_propname[0] != '\0')
+ {
+ apr_hash_t *actual_props;
+ svn_stream_t *stream;
+ svn_string_t *merged_propval;
+
+ SVN_ERR(svn_wc__db_read_props(&actual_props, db, local_abspath,
+ scratch_pool, scratch_pool));
+ resolve_from = actual_props;
+
+ SVN_ERR(svn_stream_open_readonly(&stream, merged_file,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_string_from_stream(&merged_propval, stream,
+ scratch_pool, scratch_pool));
+ svn_hash_sets(resolve_from, conflicted_propname, merged_propval);
+ }
+ else
+ resolve_from = NULL;
break;
default:
return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
@@ -2601,39 +2665,36 @@ resolve_prop_conflict_on_node(svn_boolea
If not the UI shows the conflict as already resolved
(and in this case we just remove the in-db conflict) */
- if (prop_reject_file)
- {
- SVN_ERR(svn_io_check_path(prop_reject_file, &node_kind, scratch_pool));
- if (node_kind == svn_node_file)
- {
- svn_skel_t *work_item;
+ {
+ svn_skel_t *work_item;
- SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
- local_abspath,
- prop_reject_file,
- scratch_pool, scratch_pool));
- *work_items = svn_wc__wq_merge(*work_items, work_item, scratch_pool);
- *removed_reject_file = TRUE;
- }
- }
+ SVN_ERR(remove_artifact_file_if_exists(&work_item, did_resolve,
+ db, local_abspath, prop_reject_file,
+ scratch_pool, scratch_pool));
+ work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+ }
+
+ SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath, FALSE, TRUE, FALSE,
+ work_items, scratch_pool));
+ SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+ scratch_pool));
return SVN_NO_ERROR;
}
/*
- * Resolve the tree conflict found in DB/LOCAL_ABSPATH/CONFLICTS
- * according to CONFLICT_CHOICE. (Don't mark it as resolved.)
+ * Resolve the tree conflict found in DB/LOCAL_ABSPATH according to
+ * CONFLICT_CHOICE.
*
- * ### ... append to *WORK_ITEMS work items to ...?
+ * It is not an error if there is no tree conflict. If a tree conflict
+ * existed and was resolved, set *DID_RESOLVE to TRUE, else set it to FALSE.
*
- * It is an error if there is no tree conflict.
+ * It is not an error if there is no tree conflict.
*/
static svn_error_t *
-resolve_tree_conflict_on_node(svn_skel_t **work_items,
+resolve_tree_conflict_on_node(svn_boolean_t *did_resolve,
svn_wc__db_t *db,
const char *local_abspath,
- svn_wc_operation_t operation,
- svn_skel_t *conflicts,
svn_wc_conflict_choice_t conflict_choice,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
@@ -2643,7 +2704,22 @@ resolve_tree_conflict_on_node(svn_skel_t
{
svn_wc_conflict_reason_t reason;
svn_wc_conflict_action_t action;
- svn_boolean_t did_resolve = FALSE;
+ svn_skel_t *conflicts;
+ svn_wc_operation_t operation;
+ svn_boolean_t tree_conflicted;
+
+ *did_resolve = FALSE;
+
+ SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath,
+ scratch_pool, scratch_pool));
+ if (!conflicts)
+ return SVN_NO_ERROR;
+
+ SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, NULL,
+ &tree_conflicted, db, local_abspath,
+ conflicts, scratch_pool, scratch_pool));
+ if (!tree_conflicted)
+ return SVN_NO_ERROR;
SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action, NULL,
db, local_abspath,
@@ -2663,7 +2739,7 @@ resolve_tree_conflict_on_node(svn_skel_t
SVN_ERR(svn_wc__db_resolve_break_moved_away_children(
db, local_abspath, notify_func, notify_baton,
scratch_pool));
- did_resolve = TRUE;
+ *did_resolve = TRUE;
}
else if (conflict_choice == svn_wc_conflict_choose_mine_conflict)
{
@@ -2674,7 +2750,7 @@ resolve_tree_conflict_on_node(svn_skel_t
SVN_ERR(svn_wc__db_resolve_delete_raise_moved_away(
db, local_abspath, notify_func, notify_baton,
scratch_pool));
- did_resolve = TRUE;
+ *did_resolve = TRUE;
}
else
return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
@@ -2699,7 +2775,7 @@ resolve_tree_conflict_on_node(svn_skel_t
notify_func, notify_baton,
cancel_func, cancel_baton,
scratch_pool));
- did_resolve = TRUE;
+ *did_resolve = TRUE;
}
else if (conflict_choice == svn_wc_conflict_choose_merged)
{
@@ -2714,7 +2790,7 @@ resolve_tree_conflict_on_node(svn_skel_t
notify_func,
notify_baton,
scratch_pool));
- did_resolve = TRUE;
+ *did_resolve = TRUE;
}
else
return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
@@ -2727,7 +2803,7 @@ resolve_tree_conflict_on_node(svn_skel_t
}
}
- if (! did_resolve && conflict_choice != svn_wc_conflict_choose_merged)
+ if (! *did_resolve && conflict_choice != svn_wc_conflict_choose_merged)
{
/* For other tree conflicts, there is no way to pick
* theirs-full or mine-full, etc. Throw an error if the
@@ -2741,110 +2817,13 @@ resolve_tree_conflict_on_node(svn_skel_t
scratch_pool));
}
+ SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath, FALSE, FALSE, TRUE,
+ NULL, scratch_pool));
+ SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+ scratch_pool));
return SVN_NO_ERROR;
}
-/* Conflict resolution involves removing the conflict files, if they exist,
- and clearing the conflict filenames from the entry. The latter needs to
- be done whether or not the conflict files exist.
-
- ### This func combines *resolving* and *marking as resolved* -- seems poor.
-
- LOCAL_ABSPATH in DB is the path to the item to be resolved.
- RESOLVE_TEXT, RESOLVE_PROPS and RESOLVE_TREE are TRUE iff text, property
- and tree conflicts respectively are to be resolved.
-
- If this call marks any conflict as resolved, set *DID_RESOLVE to true,
- else to false.
- If asked to resolve a text or prop conflict, only set *DID_RESOLVE
- to true if a conflict marker file was present, because if no marker
- file was present then the conflict is considered to be marked as
- resolved already.
- ### If asked to resolve a tree conflict, always set *DID_RESOLVE to true.
- This would make sense if 'resolve_tree' is only requested when
- there is in fact a tree conflict to be resolved, but, for
- consistency with text & prop conflicts, the code should probably
- say "if (resolve_tree && tree_conflicted) *did_resolve = TRUE".
-
- See svn_wc_resolved_conflict5() for how CONFLICT_CHOICE behaves.
-*/
-static svn_error_t *
-resolve_conflict_on_node(svn_boolean_t *did_resolve,
- svn_wc__db_t *db,
- const char *local_abspath,
- svn_boolean_t resolve_text,
- svn_boolean_t resolve_props,
- svn_boolean_t resolve_tree,
- svn_wc_conflict_choice_t conflict_choice,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
-{
- svn_skel_t *conflicts;
- svn_wc_operation_t operation;
- svn_boolean_t text_conflicted;
- svn_boolean_t prop_conflicted;
- svn_boolean_t tree_conflicted;
- svn_skel_t *work_items = NULL;
-
- *did_resolve = FALSE;
-
- SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath,
- scratch_pool, scratch_pool));
-
- if (!conflicts)
- return SVN_NO_ERROR;
-
- SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, &text_conflicted,
- &prop_conflicted, &tree_conflicted,
- db, local_abspath, conflicts,
- scratch_pool, scratch_pool));
-
- if (resolve_text && text_conflicted)
- SVN_ERR(resolve_text_conflict_on_node(did_resolve, &work_items,
- db, local_abspath,
- operation, conflicts,
- conflict_choice,
- scratch_pool));
-
- if (resolve_props && prop_conflicted)
- SVN_ERR(resolve_prop_conflict_on_node(did_resolve, &work_items,
- db, local_abspath,
- operation, conflicts,
- conflict_choice,
- scratch_pool));
-
- if (resolve_tree)
- {
- SVN_ERR(resolve_tree_conflict_on_node(&work_items,
- db, local_abspath,
- operation, conflicts,
- conflict_choice,
- notify_func, notify_baton,
- cancel_func, cancel_baton,
- scratch_pool));
- *did_resolve = TRUE;
- }
-
- if (resolve_text || resolve_props || resolve_tree)
- {
- SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath,
- resolve_text, resolve_props,
- resolve_tree, work_items,
- scratch_pool));
-
- /* Run the work queue to remove conflict marker files. */
- SVN_ERR(svn_wc__wq_run(db, local_abspath,
- cancel_func, cancel_baton,
- scratch_pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-
svn_error_t *
svn_wc__mark_resolved_text_conflict(svn_wc__db_t *db,
const char *local_abspath,
@@ -2852,15 +2831,11 @@ svn_wc__mark_resolved_text_conflict(svn_
{
svn_boolean_t ignored_result;
- return svn_error_trace(resolve_conflict_on_node(
+ return svn_error_trace(resolve_text_conflict_on_node(
&ignored_result,
db, local_abspath,
- TRUE /* resolve_text */,
- FALSE /* resolve_props */,
- FALSE /* resolve_tree */,
- svn_wc_conflict_choose_merged,
- NULL, NULL, /* notify_func */
- NULL, NULL, /* cancel_func */
+ svn_wc_conflict_choose_merged, NULL,
+ NULL, NULL,
scratch_pool));
}
@@ -2871,15 +2846,11 @@ svn_wc__mark_resolved_prop_conflicts(svn
{
svn_boolean_t ignored_result;
- return svn_error_trace(resolve_conflict_on_node(
+ return svn_error_trace(resolve_prop_conflict_on_node(
&ignored_result,
- db, local_abspath,
- FALSE /* resolve_text */,
- TRUE /* resolve_props */,
- FALSE /* resolve_tree */,
- svn_wc_conflict_choose_merged,
- NULL, NULL, /* notify_func */
- NULL, NULL, /* cancel_func */
+ db, local_abspath, "",
+ svn_wc_conflict_choose_merged, NULL,
+ NULL, NULL,
scratch_pool));
}
@@ -2901,8 +2872,6 @@ struct conflict_status_walker_baton
};
/* Implements svn_wc_status4_t to walk all conflicts to resolve.
- *
- * ### Bug: ignores the resolver callback's 'result->merged_file' output.
*/
static svn_error_t *
conflict_status_walker(void *baton,
@@ -2931,6 +2900,7 @@ conflict_status_walker(void *baton,
const svn_wc_conflict_description2_t *cd;
svn_boolean_t did_resolve;
svn_wc_conflict_choice_t my_choice = cswb->conflict_choice;
+ const char *merged_file = NULL;
cd = APR_ARRAY_IDX(conflicts, i, const svn_wc_conflict_description2_t *);
@@ -2949,7 +2919,8 @@ conflict_status_walker(void *baton,
iterpool, iterpool));
my_choice = result->choice;
- /* ### Bug: ignores result->merged_file (and ->save_merged) */
+ merged_file = result->merged_file;
+ /* ### Bug: ignores result->save_merged */
}
@@ -2961,18 +2932,15 @@ conflict_status_walker(void *baton,
case svn_wc_conflict_kind_tree:
if (!cswb->resolve_tree)
break;
- SVN_ERR(resolve_conflict_on_node(&did_resolve,
- db,
- local_abspath,
- FALSE /* resolve_text */,
- FALSE /* resolve_props */,
- TRUE /* resolve_tree */,
- my_choice,
- cswb->notify_func,
- cswb->notify_baton,
- cswb->cancel_func,
- cswb->cancel_baton,
- iterpool));
+ SVN_ERR(resolve_tree_conflict_on_node(&did_resolve,
+ db,
+ local_abspath,
+ my_choice,
+ cswb->notify_func,
+ cswb->notify_baton,
+ cswb->cancel_func,
+ cswb->cancel_baton,
+ iterpool));
resolved = TRUE;
break;
@@ -2981,18 +2949,14 @@ conflict_status_walker(void *baton,
if (!cswb->resolve_text)
break;
- SVN_ERR(resolve_conflict_on_node(&did_resolve,
- db,
- local_abspath,
- TRUE /* resolve_text */,
- FALSE /* resolve_props */,
- FALSE /* resolve_tree */,
- my_choice,
- cswb->notify_func,
- cswb->notify_baton,
- cswb->cancel_func,
- cswb->cancel_baton,
- iterpool));
+ SVN_ERR(resolve_text_conflict_on_node(&did_resolve,
+ db,
+ local_abspath,
+ my_choice,
+ merged_file,
+ cswb->cancel_func,
+ cswb->cancel_baton,
+ iterpool));
if (did_resolve)
resolved = TRUE;
@@ -3002,28 +2966,21 @@ conflict_status_walker(void *baton,
if (!cswb->resolve_prop)
break;
- /* ### this is bogus. resolve_conflict_on_node() does not handle
- ### individual property resolution. */
if (*cswb->resolve_prop != '\0' &&
strcmp(cswb->resolve_prop, cd->property_name) != 0)
{
- break; /* Skip this property conflict */
+ break; /* This is not the property we want to resolve. */
}
-
- /* We don't have property name handling here yet :( */
- SVN_ERR(resolve_conflict_on_node(&did_resolve,
- db,
- local_abspath,
- FALSE /* resolve_text */,
- TRUE /* resolve_props */,
- FALSE /* resolve_tree */,
- my_choice,
- cswb->notify_func,
- cswb->notify_baton,
- cswb->cancel_func,
- cswb->cancel_baton,
- iterpool));
+ SVN_ERR(resolve_prop_conflict_on_node(&did_resolve,
+ db,
+ local_abspath,
+ cd->property_name,
+ my_choice,
+ merged_file,
+ cswb->cancel_func,
+ cswb->cancel_baton,
+ iterpool));
if (did_resolve)
resolved = TRUE;
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=1482138&r1=1482137&r2=1482138&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:42:22 2013
@@ -225,20 +225,25 @@ show_conflicts(const svn_wc_conflict_des
pool);
}
-/* Display the conflicting values of a property as a 3-way diff.
+/* Perform a 3-way merge of the conflicting values of a property,
+ * and write the result to the OUTPUT stream.
+ *
+ * If MERGED_ABSPATH is non-NULL, use it as 'my' version instead of
+ * DESC->MY_ABSPATH.
*
* 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)
+merge_prop_conflict(svn_stream_t *output,
+ const svn_wc_conflict_description2_t *desc,
+ const char *merged_abspath,
+ 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. */
@@ -258,13 +263,15 @@ show_prop_conflict(const svn_wc_conflict
}
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,
+ base_abspath,
+ merged_abspath ? merged_abspath : my_abspath,
+ their_abspath,
options, pool));
SVN_ERR(svn_diff_file_output_merge2(output, diff,
base_abspath,
- my_abspath,
+ merged_abspath ? merged_abspath
+ : my_abspath,
their_abspath,
_("||||||| ORIGINAL"),
_("<<<<<<< MINE"),
@@ -276,8 +283,27 @@ show_prop_conflict(const svn_wc_conflict
return SVN_NO_ERROR;
}
+/* Display the conflicting values of a property as a 3-way diff.
+ *
+ * If MERGED_ABSPATH is non-NULL, show it as 'my' version instead of
+ * DESC->MY_ABSPATH.
+ *
+ * Assume the values are printable UTF-8 text.
+ */
+static svn_error_t *
+show_prop_conflict(const svn_wc_conflict_description2_t *desc,
+ const char *merged_abspath,
+ apr_pool_t *pool)
+{
+ svn_stream_t *output;
+
+ SVN_ERR(svn_stream_for_stdout(&output, pool));
+ SVN_ERR(merge_prop_conflict(output, desc, merged_abspath, pool));
-/* Run an external editor, passing it the 'merged' file in DESC, or, if the
+ return SVN_NO_ERROR;
+}
+
+/* Run an external editor, passing it the MERGED_FILE, or, if the
* 'merged' file is null, return an error. The tool to use is determined by
* B->editor_cmd, B->config and environment variables; see
* svn_cl__edit_file_externally() for details.
@@ -288,15 +314,15 @@ show_prop_conflict(const svn_wc_conflict
* return that error. */
static svn_error_t *
open_editor(svn_boolean_t *performed_edit,
- const svn_wc_conflict_description2_t *desc,
+ const char *merged_file,
svn_cl__interactive_conflict_baton_t *b,
apr_pool_t *pool)
{
svn_error_t *err;
- if (desc->merged_file)
+ if (merged_file)
{
- err = svn_cmdline__edit_file_externally(desc->merged_file, b->editor_cmd,
+ err = svn_cmdline__edit_file_externally(merged_file, b->editor_cmd,
b->config, pool);
if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_EDITOR))
{
@@ -329,6 +355,34 @@ open_editor(svn_boolean_t *performed_edi
return SVN_NO_ERROR;
}
+/* Run an external editor, passing it the 'merged' property in DESC.
+ * The tool to use is determined by B->editor_cmd, B->config and
+ * environment variables; see svn_cl__edit_file_externally() for details. */
+static svn_error_t *
+edit_prop_conflict(const char **merged_file_path,
+ const svn_wc_conflict_description2_t *desc,
+ svn_cl__interactive_conflict_baton_t *b,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_file_t *file;
+ const char *file_path;
+ svn_boolean_t performed_edit = FALSE;
+ svn_stream_t *merged_prop;
+
+ SVN_ERR(svn_io_open_unique_file3(&file, &file_path, NULL,
+ svn_io_file_del_on_pool_cleanup,
+ result_pool, scratch_pool));
+ merged_prop = svn_stream_from_aprfile2(file, TRUE /* disown */,
+ scratch_pool);
+ SVN_ERR(merge_prop_conflict(merged_prop, desc, NULL, scratch_pool));
+ SVN_ERR(svn_stream_close(merged_prop));
+ SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool));
+ SVN_ERR(open_editor(&performed_edit, file_path, b, scratch_pool));
+ *merged_file_path = (performed_edit ? file_path : NULL);
+
+ return SVN_NO_ERROR;
+}
/* Run an external merge tool, passing it the 'base', 'their', 'my' and
* 'merged' files in DESC. The tool to use is determined by B->config and
@@ -445,6 +499,10 @@ static const resolver_option_t prop_conf
"(same) [theirs-full]"),
svn_wc_conflict_choose_theirs_full },
{ "dc", N_("display conflict"), N_("show conflicts in this property"), -1 },
+ { "e", N_("edit property"), N_("change merged property value in an
editor"
+ " [edit]"), -1 },
+ { "r", N_("resolved"), N_("accept edited version of property"),
+ svn_wc_conflict_choose_merged },
{ "q", N_("quit resolution"), N_("postpone all remaining conflicts"),
svn_wc_conflict_choose_postpone },
{ "h", N_("help"), N_("show this help (also '?')"), -1 },
@@ -790,7 +848,7 @@ handle_text_conflict(svn_wc_conflict_res
}
else if (strcmp(opt->code, "e") == 0 || strcmp(opt->code, ":-E") == 0)
{
- SVN_ERR(open_editor(&performed_edit, desc, b, iterpool));
+ SVN_ERR(open_editor(&performed_edit, desc->merged_file, b,
iterpool));
if (performed_edit)
knows_something = TRUE;
}
@@ -890,10 +948,13 @@ static svn_error_t *
handle_prop_conflict(svn_wc_conflict_result_t *result,
const svn_wc_conflict_description2_t *desc,
svn_cl__interactive_conflict_baton_t *b,
+ apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
apr_pool_t *iterpool;
const char *message;
+ const char *merged_file_path = NULL;
+ svn_boolean_t resolved_allowed = FALSE;
/* ### Work around a historical bug in the provider: the path to the
* conflict description file was put in the 'theirs' field, and
@@ -919,10 +980,23 @@ handle_prop_conflict(svn_wc_conflict_res
while (TRUE)
{
const resolver_option_t *opt;
+ const char *options[ARRAY_LEN(prop_conflict_options)];
+ const char **next_option = options;
+
+ *next_option++ = "p";
+ *next_option++ = "mf";
+ *next_option++ = "tf";
+ *next_option++ = "dc";
+ *next_option++ = "e";
+ if (resolved_allowed)
+ *next_option++ = "r";
+ *next_option++ = "q";
+ *next_option++ = "h";
+ *next_option++ = NULL;
svn_pool_clear(iterpool);
- SVN_ERR(prompt_user(&opt, prop_conflict_options, NULL, b->pb,
+ SVN_ERR(prompt_user(&opt, prop_conflict_options, options, b->pb,
iterpool));
if (! opt)
continue;
@@ -936,7 +1010,27 @@ handle_prop_conflict(svn_wc_conflict_res
}
else if (strcmp(opt->code, "dc") == 0)
{
- SVN_ERR(show_prop_conflict(desc, scratch_pool));
+ SVN_ERR(show_prop_conflict(desc, merged_file_path, scratch_pool));
+ }
+ else if (strcmp(opt->code, "e") == 0)
+ {
+ SVN_ERR(edit_prop_conflict(&merged_file_path, desc, b,
+ result_pool, scratch_pool));
+ resolved_allowed = (merged_file_path != NULL);
+ }
+ else if (strcmp(opt->code, "r") == 0)
+ {
+ if (! resolved_allowed)
+ {
+ SVN_ERR(svn_cmdline_fprintf(stderr, iterpool,
+ _("Invalid option; please edit the property "
+ "first.\n\n")));
+ continue;
+ }
+
+ result->merged_file = merged_file_path;
+ result->choice = svn_wc_conflict_choose_merged;
+ break;
}
else if (opt->choice != -1)
{
@@ -1214,7 +1308,7 @@ conflict_func_interactive(svn_wc_conflic
&& (desc->reason == svn_wc_conflict_reason_edited)))
SVN_ERR(handle_text_conflict(*result, desc, b, scratch_pool));
else if (desc->kind == svn_wc_conflict_kind_property)
- SVN_ERR(handle_prop_conflict(*result, desc, b, scratch_pool));
+ SVN_ERR(handle_prop_conflict(*result, desc, b, result_pool, scratch_pool));
/*
Dealing with obstruction of additions can be tricky. The