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/11/29 11:04:51 UTC
svn commit: r1771881 - in /subversion/trunk/subversion:
libsvn_wc/wc_db_update_move.c tests/libsvn_client/conflicts-test.c
Author: stsp
Date: Tue Nov 29 11:04:51 2016
New Revision: 1771881
URL: http://svn.apache.org/viewvc?rev=1771881&view=rev
Log:
Fix handling of nested file moves in the while updating incoming moves.
Also fix some bugs in the associated regression test.
* subversion/svn/conflict-callbacks.c
(tc_editor_merge_local_file_change): Fix tree conflict recording in case
a file is missing or obstructed. The existing code was inherited from the
local-move update code and not yet adjusted. Only merge props and text if
no tree conflict was raised.
* subversion/tests/libsvn_client/conflicts-test.c
(modified_file_content): New global constant.
(test_update_incoming_dir_move_with_nested_file_move): Fix a typo in a path
which caused a new unversioned file to be created, instead of a local
modification to a versioned file. And this test did not check the
resolution result at all! Expect a tree conflict on the nested moved file.
Modified:
subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c
subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c
Modified: subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c?rev=1771881&r1=1771880&r2=1771881&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c Tue Nov 29 11:04:51 2016
@@ -1437,24 +1437,79 @@ tc_editor_merge_local_file_change(node_m
dst_relpath,
scratch_pool);
svn_skel_t *conflict_skel = NULL;
- apr_hash_t *actual_props;
- apr_array_header_t *propchanges;
enum svn_wc_merge_outcome_t merge_outcome;
- svn_wc_notify_state_t prop_state, content_state;
+ svn_wc_notify_state_t prop_state = svn_wc_notify_state_unchanged;
+ svn_wc_notify_state_t content_state = svn_wc_notify_state_unchanged;
svn_skel_t *work_item, *work_items = NULL;
svn_node_kind_t dst_kind_on_disk;
+ const char *dst_repos_relpath;
svn_boolean_t obstructed = FALSE;
+ svn_node_kind_t dst_db_kind;
+ svn_error_t *err;
SVN_ERR(mark_node_edited(nmb, scratch_pool));
if (nmb->skip)
return SVN_NO_ERROR;
+ err = svn_wc__db_base_get_info_internal(NULL, &dst_db_kind, NULL,
+ &dst_repos_relpath,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ b->wcroot, dst_relpath,
+ scratch_pool, scratch_pool);
+ if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ {
+ const char *dst_parent_relpath;
+ const char *dst_parent_repos_relpath;
+
+ svn_error_clear(err);
+
+ dst_db_kind = svn_node_none;
+ SVN_ERR(create_node_tree_conflict(&conflict_skel, nmb, dst_relpath,
+ svn_node_file, dst_db_kind,
+ svn_wc_conflict_reason_missing,
+ svn_wc_conflict_action_edit,
+ NULL, scratch_pool, scratch_pool));
+ dst_parent_relpath = svn_relpath_dirname(dst_relpath, scratch_pool);
+ SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, NULL,
+ &dst_parent_repos_relpath,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, b->wcroot,
+ dst_parent_relpath,
+ scratch_pool, scratch_pool));
+ dst_repos_relpath = svn_relpath_join(dst_parent_repos_relpath,
+ svn_relpath_basename(dst_relpath,
+ scratch_pool),
+ scratch_pool);
+ obstructed = TRUE;
+ }
+ else
+ SVN_ERR(err);
+
+ if ((dst_db_kind == svn_node_none || dst_db_kind != svn_node_file) &&
+ conflict_skel == NULL)
+ {
+ SVN_ERR(create_node_tree_conflict(&conflict_skel, nmb, dst_relpath,
+ svn_node_file, dst_kind_on_disk,
+ dst_db_kind == svn_node_none
+ ? svn_wc_conflict_reason_missing
+ : svn_wc_conflict_reason_obstructed,
+ svn_wc_conflict_action_edit,
+ NULL,
+ scratch_pool, scratch_pool));
+ obstructed = TRUE;
+ }
+
SVN_ERR(svn_io_check_path(dst_abspath, &dst_kind_on_disk, scratch_pool));
- if (dst_kind_on_disk != svn_node_none && dst_kind_on_disk != svn_node_file)
+ if ((dst_kind_on_disk == svn_node_none || dst_kind_on_disk != svn_node_file)
+ && conflict_skel == NULL)
{
SVN_ERR(create_node_tree_conflict(&conflict_skel, nmb, dst_relpath,
- svn_node_file, svn_node_file,
- svn_wc_conflict_reason_obstructed,
+ svn_node_file, dst_kind_on_disk,
+ dst_kind_on_disk == svn_node_none
+ ? svn_wc_conflict_reason_missing
+ : svn_wc_conflict_reason_obstructed,
svn_wc_conflict_action_edit,
NULL,
scratch_pool, scratch_pool));
@@ -1469,74 +1524,70 @@ tc_editor_merge_local_file_change(node_m
new_version.checksum = dst_checksum;
new_version.props = dst_props;
- SVN_ERR(update_working_props(&prop_state, &conflict_skel, &propchanges,
- &actual_props, b, dst_relpath,
- &old_version, &new_version,
- scratch_pool, scratch_pool));
-
- if (!obstructed && do_text_merge)
+ /* Merge properties and text content if there is no tree conflict. */
+ if (conflict_skel == NULL)
{
- const char *old_pristine_abspath;
- const char *src_abspath;
- const char *label_left;
- const char *label_target;
-
- /*
- * Run a 3-way merge to update the file at its post-move location, using
- * the pre-move file's pristine text as the merge base, the post-move
- * content as the merge-right version, and the current content of the
- * working file at the pre-move location as the merge-left version.
- */
- SVN_ERR(svn_wc__db_pristine_get_path(&old_pristine_abspath,
- b->db, b->wcroot->abspath,
- src_checksum,
- scratch_pool, scratch_pool));
- src_abspath = svn_dirent_join(b->wcroot->abspath, src_relpath,
- scratch_pool);
- label_left = apr_psprintf(scratch_pool, ".r%ld", b->old_version->peg_rev);
- label_target = apr_psprintf(scratch_pool, ".r%ld",
- b->new_version->peg_rev);
- SVN_ERR(svn_wc__internal_merge(&work_item, &conflict_skel,
- &merge_outcome, b->db,
- old_pristine_abspath,
- src_abspath,
- dst_abspath,
- dst_abspath,
- label_left,
- _(".working"),
- label_target,
- actual_props,
- FALSE, /* dry-run */
- NULL, /* diff3-cmd */
- NULL, /* merge options */
- propchanges,
- b->cancel_func, b->cancel_baton,
- scratch_pool, scratch_pool));
-
- work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
-
- if (merge_outcome == svn_wc_merge_conflict)
- content_state = svn_wc_notify_state_conflicted;
- else
- content_state = svn_wc_notify_state_merged;
+ apr_hash_t *actual_props;
+ apr_array_header_t *propchanges;
+
+ SVN_ERR(update_working_props(&prop_state, &conflict_skel, &propchanges,
+ &actual_props, b, dst_relpath,
+ &old_version, &new_version,
+ scratch_pool, scratch_pool));
+ if (do_text_merge)
+ {
+ const char *old_pristine_abspath;
+ const char *src_abspath;
+ const char *label_left;
+ const char *label_target;
+
+ /*
+ * Run a 3-way merge to update the file at its post-move location,
+ * using the pre-move file's pristine text as the merge base, the
+ * post-move content as the merge-right version, and the current
+ * content of the working file at the pre-move location as the
+ * merge-left version.
+ */
+ SVN_ERR(svn_wc__db_pristine_get_path(&old_pristine_abspath,
+ b->db, b->wcroot->abspath,
+ src_checksum,
+ scratch_pool, scratch_pool));
+ src_abspath = svn_dirent_join(b->wcroot->abspath, src_relpath,
+ scratch_pool);
+ label_left = apr_psprintf(scratch_pool, ".r%ld",
+ b->old_version->peg_rev);
+ label_target = apr_psprintf(scratch_pool, ".r%ld",
+ b->new_version->peg_rev);
+ SVN_ERR(svn_wc__internal_merge(&work_item, &conflict_skel,
+ &merge_outcome, b->db,
+ old_pristine_abspath,
+ src_abspath,
+ dst_abspath,
+ dst_abspath,
+ label_left,
+ _(".working"),
+ label_target,
+ actual_props,
+ FALSE, /* dry-run */
+ NULL, /* diff3-cmd */
+ NULL, /* merge options */
+ propchanges,
+ b->cancel_func, b->cancel_baton,
+ scratch_pool, scratch_pool));
+
+ work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+
+ if (merge_outcome == svn_wc_merge_conflict)
+ content_state = svn_wc_notify_state_conflicted;
+ else
+ content_state = svn_wc_notify_state_merged;
+ }
}
- else
- content_state = svn_wc_notify_state_unchanged;
/* If there are any conflicts to be stored, convert them into work items
* too. */
if (conflict_skel)
{
- const char *dst_repos_relpath;
-
- SVN_ERR(svn_wc__db_depth_get_info(NULL, NULL, NULL,
- &dst_repos_relpath, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL,
- b->wcroot, dst_relpath,
- b->dst_op_depth,
- scratch_pool, scratch_pool));
-
SVN_ERR(create_conflict_markers(&work_item, dst_abspath, b->db,
dst_repos_relpath, conflict_skel,
b->operation, &old_version, &new_version,
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=1771881&r1=1771880&r2=1771881&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c Tue Nov 29 11:04:51 2016
@@ -175,6 +175,8 @@ static const char *propval_branch = "Thi
static const char *propval_different = "This is a different property value.";
/* File content. */
+static const char *modified_file_content =
+ "This is a modified file\n";
static const char *modified_file_on_branch_content =
"This is a modified file on the branch\n";
static const char *added_file_on_branch_content =
@@ -3218,7 +3220,7 @@ test_update_incoming_dir_move_with_neste
/* Rename a file inside the moved directory. */
deleted_file = svn_relpath_join(moved_dir, "lambda" , b->pool);
- moved_file = svn_relpath_join(moved_dir, "lamdba-moved", b->pool);
+ moved_file = svn_relpath_join(moved_dir, "lambda-moved", b->pool);
SVN_ERR(sbox_wc_move(b, deleted_file, moved_file));
SVN_ERR(sbox_wc_commit(b, ""));
@@ -3227,8 +3229,8 @@ test_update_incoming_dir_move_with_neste
SVN_ERR(sbox_wc_update(b, "", 1));
/* Modify a file in the working copy. */
- deleted_file = svn_relpath_join(trunk_path, "B/lamdba", b->pool);
- SVN_ERR(sbox_file_write(b, deleted_file, "This is a modified file\n"));
+ deleted_file = svn_relpath_join(trunk_path, "B/lambda", b->pool);
+ SVN_ERR(sbox_file_write(b, deleted_file, modified_file_content));
/* Update to HEAD.
* This should raise an "incoming move vs local edit" tree conflict. */
@@ -3275,6 +3277,23 @@ test_update_incoming_dir_move_with_neste
conflict, svn_client_conflict_option_incoming_move_dir_merge,
ctx, pool));
+ /* There should now be a tree conflict inside the moved directory,
+ * signaling a missing file. */
+ deleted_file = svn_relpath_join(moved_dir, "lambda" , b->pool);
+ SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, deleted_file),
+ ctx, pool, pool));
+ SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted,
+ &props_conflicted,
+ &tree_conflicted,
+ conflict, pool, pool));
+ SVN_TEST_ASSERT(!text_conflicted);
+ SVN_TEST_INT_ASSERT(props_conflicted->nelts, 0);
+ SVN_TEST_ASSERT(tree_conflicted);
+ SVN_TEST_ASSERT(svn_client_conflict_get_local_change(conflict) ==
+ svn_wc_conflict_reason_missing);
+ SVN_TEST_ASSERT(svn_client_conflict_get_incoming_change(conflict) ==
+ svn_wc_conflict_action_edit);
+
return SVN_NO_ERROR;
}