You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by sv...@apache.org on 2013/08/17 06:00:46 UTC
svn commit: r1514942 - in /subversion/branches/1.7.x: ./ STATUS
subversion/libsvn_client/merge.c subversion/tests/cmdline/merge_tests.py
Author: svn-role
Date: Sat Aug 17 04:00:46 2013
New Revision: 1514942
URL: http://svn.apache.org/r1514942
Log:
Merge the 1.7.x-issue4306 branch:
* r1438602, r1438683, r1441810
Fix issue #4306, "multiple editor drive file merges record wrong mergeinfo
during conflicts"
Justification:
Bogus mergeinfo is created during conflicting merges with file targets.
Notes: r1438602 is the initial test and r1438683 the initial fix. r1441810
is a follow-up that addressed a bug in the initial fix (see
http://svn.haxx.se/dev/archive-2013-02/0001.shtml) and also reworked the
test to use prop edits rather than text edits as the changes to be
merged. Unfortunately, 1.7.x has unrelated problems with property
conflicts: It doesn't abort the merge if it encounters them! It merrily
plugs along sans any "One or more conflicts were produced while
merging...resolve all conflicts and rerun the merge to apply the
remaining unmerged revisions" error (this is fixed on trunk). So while
r1441810 is a valid fix (IMO) its test fails for unrelated reasons. So
I reworked the earlier version of test to demonstrate the problem
r1441810 fixes, but using file conflicts.
Branch:
^/subversion/branches/1.7.x-issue4306
Votes:
+1: stsp, pburba, rhuijben
Modified:
subversion/branches/1.7.x/ (props changed)
subversion/branches/1.7.x/STATUS
subversion/branches/1.7.x/subversion/libsvn_client/merge.c
subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py
Propchange: subversion/branches/1.7.x/
------------------------------------------------------------------------------
Merged /subversion/branches/1.7.x-issue4306:r1438872-1514941
Merged /subversion/trunk:r1438602,1438683,1441810
Modified: subversion/branches/1.7.x/STATUS
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/STATUS?rev=1514942&r1=1514941&r2=1514942&view=diff
==============================================================================
--- subversion/branches/1.7.x/STATUS (original)
+++ subversion/branches/1.7.x/STATUS Sat Aug 17 04:00:46 2013
@@ -157,28 +157,6 @@ Veto-blocked changes:
Approved changes:
=================
- * r1438602, r1438683, r1441810
- Fix issue #4306, "multiple editor drive file merges record wrong mergeinfo
- during conflicts"
- Justification:
- Bogus mergeinfo is created during conflicting merges with file targets.
- Notes: r1438602 is the initial test and r1438683 the initial fix. r1441810
- is a follow-up that addressed a bug in the initial fix (see
- http://svn.haxx.se/dev/archive-2013-02/0001.shtml) and also reworked the
- test to use prop edits rather than text edits as the changes to be
- merged. Unfortunately, 1.7.x has unrelated problems with property
- conflicts: It doesn't abort the merge if it encounters them! It merrily
- plugs along sans any "One or more conflicts were produced while
- merging...resolve all conflicts and rerun the merge to apply the
- remaining unmerged revisions" error (this is fixed on trunk). So while
- r1441810 is a valid fix (IMO) its test fails for unrelated reasons. So
- I reworked the earlier version of test to demonstrate the problem
- r1441810 fixes, but using file conflicts.
- Branch:
- ^/subversion/branches/1.7.x-issue4306
- Votes:
- +1: stsp, pburba, rhuijben
-
* ^/subversion/branches/1.7.x-issue4408
Fix invalid output from diff --summarize.
Branch:
Modified: subversion/branches/1.7.x/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/libsvn_client/merge.c?rev=1514942&r1=1514941&r2=1514942&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/1.7.x/subversion/libsvn_client/merge.c Sat Aug 17 04:00:46 2013
@@ -6598,6 +6598,7 @@ do_file_merge(svn_mergeinfo_catalog_t re
svn_boolean_t sources_related,
svn_boolean_t squelch_mergeinfo_notifications,
notification_receiver_baton_t *notify_b,
+ svn_boolean_t abort_on_conflicts,
merge_cmd_baton_t *merge_b,
apr_pool_t *scratch_pool)
{
@@ -6862,10 +6863,13 @@ do_file_merge(svn_mergeinfo_catalog_t re
SVN_ERR(svn_io_remove_file2(tmpfile1, TRUE, iterpool));
SVN_ERR(svn_io_remove_file2(tmpfile2, TRUE, iterpool));
- if ((i < (ranges_to_merge->nelts - 1))
+ if ((i < (ranges_to_merge->nelts - 1) || abort_on_conflicts)
&& is_path_conflicted_by_merge(merge_b))
{
conflicted_range = svn_merge_range_dup(r, scratch_pool);
+ /* Only record partial mergeinfo if only a partial merge was
+ performed before a conflict was encountered. */
+ range.end = r->end;
break;
}
}
@@ -6887,7 +6891,8 @@ do_file_merge(svn_mergeinfo_catalog_t re
&filtered_rangelist,
mergeinfo_path,
merge_target->implicit_mergeinfo,
- &range, iterpool));
+ &range,
+ iterpool));
/* Only record mergeinfo if there is something other than
self-referential mergeinfo, but don't record mergeinfo if
@@ -8801,6 +8806,11 @@ do_merge(apr_hash_t **modified_subtrees,
APR_ARRAY_IDX(merge_sources, i, merge_source_t *);
const char *url1, *url2;
svn_revnum_t rev1, rev2;
+ /* If conflicts occur while merging any but the very last
+ * revision range we want an error to be raised that aborts
+ * the merge operation. The user will be asked to resolve conflicts
+ * before merging subsequent revision ranges. */
+ svn_boolean_t abort_on_conflicts = (i < merge_sources->nelts - 1);
svn_pool_clear(iterpool);
@@ -8854,16 +8864,11 @@ do_merge(apr_hash_t **modified_subtrees,
sources_related,
squelch_mergeinfo_notifications,
¬ify_baton,
+ abort_on_conflicts,
&merge_cmd_baton, iterpool));
}
else if (target_kind == svn_node_dir)
{
- /* If conflicts occur while merging any but the very last
- * revision range we want an error to be raised that aborts
- * the merge operation. The user will be asked to resolve conflicts
- * before merging subsequent revision ranges. */
- svn_boolean_t abort_on_conflicts = (i < merge_sources->nelts - 1);
-
SVN_ERR(do_directory_merge(result_catalog,
url1, rev1, url2, rev2, target_abspath,
depth, squelch_mergeinfo_notifications,
Modified: subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py?rev=1514942&r1=1514941&r2=1514942&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py Sat Aug 17 04:00:46 2013
@@ -17492,6 +17492,122 @@ def merge_with_externals_with_mergeinfo(
[], 'merge', '--reintegrate', sbox.repo_url + '/A_COPY',
A_path)
+@SkipUnless(server_has_mergeinfo)
+@Issue(4306)
+# Test for issue #4306 'multiple editor drive file merges record wrong
+# mergeinfo during conflicts'
+def conflict_aborted_mergeinfo_described_partial_merge(sbox):
+ "conflicted split merge can be repeated"
+
+ sbox.build()
+
+ trunk = 'A'
+ branch = 'A2'
+ file = 'mu'
+ trunk_file = 'A/mu'
+
+ # r2: initial state
+ file_text = 'line 1\n'
+ for i in range(2, 22):
+ file_text += 'line ' + str(i) + '.\n'
+ svntest.main.file_write(sbox.ospath('A/mu'), file_text)
+ sbox.simple_commit()
+
+ # r3: branch
+ svntest.actions.run_and_verify_svn(None, None, [], 'up', sbox.wc_dir)
+ sbox.simple_copy(trunk, branch)
+ sbox.simple_commit()
+
+ # r4 through r13: simple edits
+ for r in range (1, 11):
+ file_text = file_text.replace('line ' + str(r*2) + '.', 'line ' +
+ str(r*2) + ' Edited in r' + str(r+3) + '.')
+ svntest.main.file_write(sbox.ospath('A/mu'), file_text)
+ sbox.simple_commit()
+
+ # r14: merge some changes to the branch so that later merges will be split
+ svntest.actions.run_and_verify_svn(None, None, [], 'merge', '-c5,9',
+ '^/' + trunk, sbox.ospath(branch),
+ '--accept', 'theirs-conflict')
+ sbox.simple_commit()
+ svntest.actions.run_and_verify_svn(None, None, [], 'up', sbox.wc_dir)
+
+ def try_merge(target, conflict_rev, rev_ranges, mergeinfo, expect_error=True):
+ """Revert TARGET_PATH in the branch; merge TARGET_PATH in the trunk
+ to TARGET_PATH in the branch; expect to find MERGEINFO.
+ """
+ src_url = '^/' + trunk + '/' + target
+ src_path = trunk + '/' + target
+ tgt_path = branch + '/' + target
+ svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R',
+ sbox.ospath(tgt_path))
+ file_text = open(sbox.ospath(tgt_path), 'r').read()
+ r = conflict_rev - 3
+ file_text = file_text.replace('line ' + str(r*2) + '.', 'line ' +
+ str(r*2) + ' Conflicted.')
+ svntest.main.file_write(sbox.ospath('A2/mu'), file_text)
+
+ if expect_error:
+ expected_error = ('^svn: E155015: .* conflicts were produced .* into$'
+ "|^'.*" + sbox.ospath(tgt_path) + "' --$"
+ '|^resolve all conflicts .* remaining$'
+ '|^unmerged revisions$')
+ else:
+ expected_error = []
+ svntest.actions.run_and_verify_svn(None, None, expected_error,
+ 'merge',
+ src_url, sbox.ospath(tgt_path),
+ '--accept', 'postpone',
+ *rev_ranges)
+ expected_out = ['/' + src_path + ':' + mergeinfo + '\n']
+ svntest.actions.run_and_verify_svn(
+ "Incorrect mergeinfo set during conflict aborted merge",
+ expected_out, [], 'pg', SVN_PROP_MERGEINFO, sbox.ospath(tgt_path))
+
+ # In a mergeinfo-aware merge, each specified revision range is split
+ # internally into sub-ranges, to avoid any already-merged revisions.
+ #
+ # From white-box inspection, we see there are code paths that treat
+ # the last specified range and the last sub-range specially. The
+ # first specified range or sub-range is not treated specially in terms
+ # of the code paths, although it might be in terms of data flow.
+ #
+ # We test merges that raise a conflict in the first and last sub-range
+ # of the first and last specified range.
+
+ # First test: Merge "everything" to the branch.
+ #
+ # This merge is split into three sub-ranges: r3-4, r6-8, r10-head.
+ # We have arranged that the merge will raise a conflict in the first
+ # sub-range. Since we are postponing conflict resolution, the merge
+ # should stop after the first sub-range, allowing us to resolve and
+ # repeat the merge at which point the next sub-range(s) can be merged.
+ # The mergeinfo on the target then should only reflect that the first
+ # sub-range (r3-4) has been merged.
+ #
+ # Previously the merge failed after merging only r3-4 (as it should)
+ # but mergeinfo for the whole range was recorded, preventing subsequent
+ # repeat merges from applying the rest of the source changes.
+ try_merge(file, 4, [], '3-5,9')
+
+ # Try a multiple-range merge that raises a conflict in the
+ # first sub-range in the first specified range.
+ try_merge(file, 4, ['-r1:6', '-r7:10'], '3-5,9')
+
+ # Try a multiple-range merge that raises a conflict in the
+ # last sub-range in the first specified range.
+ try_merge(file, 6, ['-r1:6', '-r7:10'], '3-6,9')
+
+ # Try a multiple-range merge that raises a conflict in the
+ # first sub-range in the last specified range.
+ try_merge(file, 8, ['-r1:6', '-r7:10'], '3-6,8-9')
+
+ # Try a multiple-range merge that raises a conflict in the
+ # last sub-range in the last specified range.
+ # (Expect no error, because 'svn merge' does not throw an error if
+ # there is no more merging to do when a conflict occurs.)
+ try_merge(file, 10, ['-r1:6', '-r7:10'], '3-6,8-10', expect_error=False)
+
########################################################################
# Run the tests
@@ -17624,6 +17740,7 @@ test_list = [ None,
merge_adds_then_deletes_subtree,
merge_with_added_subtrees_with_mergeinfo,
merge_with_externals_with_mergeinfo,
+ conflict_aborted_mergeinfo_described_partial_merge,
]
if __name__ == '__main__':