summaryrefslogtreecommitdiff
path: root/subversion/tests/cmdline/merge_reintegrate_tests.py
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/tests/cmdline/merge_reintegrate_tests.py')
-rwxr-xr-xsubversion/tests/cmdline/merge_reintegrate_tests.py719
1 files changed, 446 insertions, 273 deletions
diff --git a/subversion/tests/cmdline/merge_reintegrate_tests.py b/subversion/tests/cmdline/merge_reintegrate_tests.py
index fc46c9c..8b3e91f 100755
--- a/subversion/tests/cmdline/merge_reintegrate_tests.py
+++ b/subversion/tests/cmdline/merge_reintegrate_tests.py
@@ -48,6 +48,62 @@ from merge_tests import set_up_branch
from merge_tests import expected_merge_output
#----------------------------------------------------------------------
+def run_reintegrate(src_url, tgt_path):
+ """Run 'svn merge --reintegrate SRC_URL TGT_PATH'. Raise an error if
+ there is nothing on stdout, anything on stderr, or a non-zero exit
+ code.
+ """
+ svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ 'merge', '--reintegrate',
+ src_url, tgt_path)
+
+def run_reintegrate_expect_error(src_url, tgt_path,
+ expected_stdout, expected_stderr):
+ """Run 'svn merge --reintegrate SRC_URL TGT_PATH'. Raise an error
+ unless stdout and stderr both match and the exit code is non-zero.
+ Every line of stderr must match the regex EXPECTED_STDERR.
+ """
+ expected_stderr += "|" + svntest.main.stack_trace_regexp
+
+ # The actions.run_and_verify_* methods are happy if one line of the error
+ # matches the regex, but we want to check that every line matches.
+ # So we will pass the stderr to svntest.verify.verify_outputs()
+ # ourselves, but as the 'actual_stdout' argument, that way each line of
+ # error must match the regex.
+ exit_code, out, err = svntest.actions.run_and_verify_svn(
+ None, expected_stdout, svntest.verify.AnyOutput,
+ 'merge', '--reintegrate',
+ src_url, tgt_path)
+ assert exit_code
+ svntest.verify.verify_outputs(
+ "Reintegrate failed but not in the way expected",
+ err, None,
+ expected_stderr, None,
+ True) # Match *all* lines
+
+def run_and_verify_reintegrate(tgt_dir, src_url,
+ output_tree,
+ mergeinfo_output_tree,
+ elision_output_tree,
+ disk_tree, status_tree, skip_tree,
+ error_re_string = None,
+ check_props = True,
+ dry_run = True):
+ """Run 'svn merge --reintegrate SRC_URL TGT_DIR'. Raise an error if
+ there is nothing on stdout, anything on stderr, or a non-zero exit
+ code, or if the expected ERROR_RE_STRING or any of the given expected
+ trees don't match.
+ """
+ svntest.actions.run_and_verify_merge(
+ tgt_dir, None, None, src_url, None,
+ output_tree, mergeinfo_output_tree, elision_output_tree,
+ disk_tree, status_tree, skip_tree,
+ error_re_string,
+ None, None, None, None, check_props, dry_run,
+ '--reintegrate', tgt_dir)
+
+
+#----------------------------------------------------------------------
@SkipUnless(server_has_mergeinfo)
@Issue(3640)
def basic_reintegrate(sbox):
@@ -61,7 +117,7 @@ def basic_reintegrate(sbox):
expected_disk, expected_status = set_up_branch(sbox)
# Make a change on the branch, to A/mu. Commit in r7.
- svntest.main.file_write(os.path.join(wc_dir, "A_COPY", "mu"),
+ svntest.main.file_write(sbox.ospath('A_COPY/mu'),
"Changed on the branch.")
expected_output = wc.State(wc_dir, {'A_COPY/mu' : Item(verb='Sending')})
expected_status.tweak('A_COPY/mu', wc_rev=7)
@@ -77,7 +133,7 @@ def basic_reintegrate(sbox):
None, None, None, None, None, True)
# Merge from trunk to branch (ie, r3-6), using normal cherry-harvest.
- A_COPY_path = os.path.join(wc_dir, "A_COPY")
+ A_COPY_path = sbox.ospath('A_COPY')
expected_output = wc.State(A_COPY_path, {
'D/H/psi' : Item(status='U '),
'D/G/rho' : Item(status='U '),
@@ -172,7 +228,7 @@ def basic_reintegrate(sbox):
# *finally*, actually run merge --reintegrate in trunk with the
# branch URL. This should bring in the mu change and the tauprime
# change.
- A_path = os.path.join(wc_dir, "A")
+ A_path = sbox.ospath('A')
expected_output = wc.State(A_path, {
'mu' : Item(status='U '),
})
@@ -204,17 +260,15 @@ def basic_reintegrate(sbox):
})
k_expected_disk.tweak('', props={SVN_PROP_MERGEINFO : '/A_COPY:2-8'})
expected_skip = wc.State(A_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
k_expected_disk,
k_expected_status,
expected_skip,
- None, None, None, None,
- None, True, True,
- '--reintegrate', A_path)
+ None, True, True)
# Test issue #3640:
#
@@ -230,7 +284,7 @@ def basic_reintegrate(sbox):
sbox.repo_url + '/A_MOVED',
'-m', 'Copy A to A_MOVED')
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
- A_MOVED_path = os.path.join(wc_dir, "A_MOVED")
+ A_MOVED_path = sbox.ospath('A_MOVED')
expected_output = wc.State(A_MOVED_path, {
'mu' : Item(status='U '),
})
@@ -263,17 +317,15 @@ def basic_reintegrate(sbox):
expected_status.tweak(wc_rev=9)
k_expected_disk.tweak('', props={SVN_PROP_MERGEINFO : '/A_COPY:2-9'})
expected_skip = wc.State(A_MOVED_path, {})
- svntest.actions.run_and_verify_merge(A_MOVED_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_MOVED_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
k_expected_disk,
expected_status,
expected_skip,
- None, None, None, None,
- None, True, True,
- '--reintegrate', A_MOVED_path)
+ None, True, True)
#----------------------------------------------------------------------
def reintegrate_with_rename(sbox):
@@ -285,7 +337,7 @@ def reintegrate_with_rename(sbox):
expected_disk, expected_status = set_up_branch(sbox)
# Make a change on the branch, to A/mu. Commit in r7.
- svntest.main.file_write(os.path.join(wc_dir, "A_COPY", "mu"),
+ svntest.main.file_write(sbox.ospath('A_COPY/mu'),
"Changed on the branch.")
expected_output = wc.State(wc_dir, {'A_COPY/mu' : Item(verb='Sending')})
expected_status.tweak('A_COPY/mu', wc_rev=7)
@@ -301,7 +353,7 @@ def reintegrate_with_rename(sbox):
None, None, None, None, None, True)
# Merge from trunk to branch (ie, r3-6), using normal cherry-harvest.
- A_COPY_path = os.path.join(wc_dir, "A_COPY")
+ A_COPY_path = sbox.ospath('A_COPY')
expected_output = wc.State(A_COPY_path, {
'D/H/psi' : Item(status='U '),
'D/G/rho' : Item(status='U '),
@@ -452,7 +504,7 @@ def reintegrate_with_rename(sbox):
# *finally*, actually run merge --reintegrate in trunk with the
# branch URL. This should bring in the mu change and the tauprime
# change.
- A_path = os.path.join(wc_dir, "A")
+ A_path = sbox.ospath('A')
expected_output = wc.State(A_path, {
'mu' : Item(status='U '),
'D/G/tauprime' : Item(status='A '),
@@ -492,17 +544,15 @@ def reintegrate_with_rename(sbox):
contents="This is the file 'tau'.\n")
})
expected_skip = wc.State(A_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
k_expected_disk,
k_expected_status,
expected_skip,
- None, None, None, None,
- None, True, True,
- '--reintegrate', A_path)
+ None, True, True)
# Finally, commit the result of the merge (r10).
expected_output = wc.State(wc_dir, {
@@ -527,7 +577,7 @@ def reintegrate_branch_never_merged_to(sbox):
expected_disk, expected_status = set_up_branch(sbox)
# Make a change on the branch, to A_COPY/mu. Commit in r7.
- svntest.main.file_write(os.path.join(wc_dir, "A_COPY", "mu"),
+ svntest.main.file_write(sbox.ospath('A_COPY/mu'),
"Changed on the branch.")
expected_output = wc.State(wc_dir, {'A_COPY/mu' : Item(verb='Sending')})
expected_status.tweak('A_COPY/mu', wc_rev=7)
@@ -570,7 +620,7 @@ def reintegrate_branch_never_merged_to(sbox):
# *finally*, actually run merge --reintegrate in trunk with the
# branch URL. This should bring in the mu change and the tauprime
# change.
- A_path = os.path.join(wc_dir, "A")
+ A_path = sbox.ospath('A')
expected_output = wc.State(A_path, {
'mu' : Item(status='U '),
'D/G/tauprime' : Item(status='A '),
@@ -625,17 +675,15 @@ def reintegrate_branch_never_merged_to(sbox):
'D/H/psi' : Item("New content"),
})
expected_skip = wc.State(A_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
k_expected_disk,
k_expected_status,
expected_skip,
- None, None, None, None,
- None, True, True,
- '--reintegrate', A_path)
+ None, True, True)
# Finally, commit the result of the merge (r9).
expected_output = wc.State(wc_dir, {
@@ -655,23 +703,30 @@ def reintegrate_fail_on_modified_wc(sbox):
"merge --reintegrate should fail in modified wc"
sbox.build()
wc_dir = sbox.wc_dir
- A_path = os.path.join(wc_dir, "A")
+ A_path = sbox.ospath('A')
+ A_COPY_path = sbox.ospath('A_COPY')
mu_path = os.path.join(A_path, "mu")
ignored_expected_disk, ignored_expected_status = set_up_branch(sbox)
+
+ # Do a 'sync' merge first so that the following merge really needs to be a
+ # reintegrate, so that an equivalent automatic merge would behave the same.
+ svntest.main.run_svn(None, 'merge', sbox.repo_url + '/A', A_COPY_path)
+ sbox.simple_commit()
+
svntest.main.file_write(mu_path, "Changed on 'trunk' (the merge target).")
sbox.simple_update() # avoid mixed-revision error
- svntest.actions.run_and_verify_merge(
- A_path, None, None, sbox.repo_url + '/A_COPY', None, None, None, None,
+ run_and_verify_reintegrate(
+ A_path, sbox.repo_url + '/A_COPY', None, None, None,
None, None, None,
".*Cannot merge into a working copy that has local modifications.*",
- None, None, None, None, True, False, '--reintegrate', A_path)
+ True, False)
#----------------------------------------------------------------------
def reintegrate_fail_on_mixed_rev_wc(sbox):
"merge --reintegrate should fail in mixed-rev wc"
sbox.build()
wc_dir = sbox.wc_dir
- A_path = os.path.join(wc_dir, "A")
+ A_path = sbox.ospath('A')
mu_path = os.path.join(A_path, "mu")
ignored_expected_disk, expected_status = set_up_branch(sbox)
# Make and commit a change, in order to get a mixed-rev wc.
@@ -683,22 +738,41 @@ def reintegrate_fail_on_mixed_rev_wc(sbox):
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
expected_status, None, wc_dir)
# Try merging into that same wc, expecting failure.
- svntest.actions.run_and_verify_merge(
- A_path, None, None, sbox.repo_url + '/A_COPY', None, None, None, None,
+ run_and_verify_reintegrate(
+ A_path, sbox.repo_url + '/A_COPY', None, None, None,
None, None, None,
".*Cannot merge into mixed-revision working copy.*",
- None, None, None, None, True, False, '--reintegrate', A_path)
+ True, False)
#----------------------------------------------------------------------
def reintegrate_fail_on_switched_wc(sbox):
"merge --reintegrate should fail in switched wc"
sbox.build()
wc_dir = sbox.wc_dir
- A_path = os.path.join(wc_dir, "A")
+ A_path = sbox.ospath('A')
+ A_COPY_path = sbox.ospath('A_COPY')
G_path = os.path.join(A_path, "D", "G")
switch_url = sbox.repo_url + "/A/D/H"
expected_disk, expected_status = set_up_branch(sbox)
+ # Do a 'sync' merge first so that the following merge really needs to be a
+ # reintegrate, so that an equivalent automatic merge would behave the same.
+ expected_disk.tweak(
+ 'A_COPY/D/H/psi',
+ 'A_COPY/D/G/rho',
+ 'A_COPY/B/E/beta',
+ 'A_COPY/D/H/omega',
+ contents="New content")
+ expected_status.tweak(
+ 'A_COPY/D/H/psi',
+ 'A_COPY/D/G/rho',
+ 'A_COPY/B/E/beta',
+ 'A_COPY/D/H/omega',
+ 'A_COPY',
+ wc_rev=7)
+ svntest.main.run_svn(None, 'merge', sbox.repo_url + '/A', A_COPY_path)
+ sbox.simple_commit()
+
# Switch a subdir of the target.
expected_output = svntest.wc.State(wc_dir, {
'A/D/G/pi' : Item(status='D '),
@@ -716,10 +790,10 @@ def reintegrate_fail_on_switched_wc(sbox):
})
expected_status.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
expected_status.add({
- 'A/D/G' : Item(status=' ', wc_rev=6, switched='S'),
- 'A/D/G/chi' : Item(status=' ', wc_rev=6),
- 'A/D/G/psi' : Item(status=' ', wc_rev=6),
- 'A/D/G/omega' : Item(status=' ', wc_rev=6),
+ 'A/D/G' : Item(status=' ', wc_rev=7, switched='S'),
+ 'A/D/G/chi' : Item(status=' ', wc_rev=7),
+ 'A/D/G/psi' : Item(status=' ', wc_rev=7),
+ 'A/D/G/omega' : Item(status=' ', wc_rev=7),
})
svntest.actions.run_and_verify_switch(wc_dir,
G_path,
@@ -730,11 +804,11 @@ def reintegrate_fail_on_switched_wc(sbox):
None, None, None, None, None,
False, '--ignore-ancestry')
sbox.simple_update() # avoid mixed-revision error
- svntest.actions.run_and_verify_merge(
- A_path, None, None, sbox.repo_url + '/A_COPY', None, None, None, None,
+ run_and_verify_reintegrate(
+ A_path, sbox.repo_url + '/A_COPY', None, None, None,
None, None, None,
".*Cannot merge into a working copy with a switched subtree.*",
- None, None, None, None, True, False, '--reintegrate', A_path)
+ True, False)
#----------------------------------------------------------------------
# Test for issue #3603 'allow reintegrate merges into WCs with
@@ -749,11 +823,11 @@ def reintegrate_on_shallow_wc(sbox):
expected_disk, expected_status = set_up_branch(sbox, branch_only = True)
# Some paths we'll care about
- A_path = os.path.join(wc_dir, "A")
- A_D_path = os.path.join(wc_dir, "A", "D")
- mu_COPY_path = os.path.join(wc_dir, "A_COPY", "mu")
- psi_COPY_path = os.path.join(wc_dir, "A_COPY", "D", "H", "psi")
- A_COPY_path = os.path.join(wc_dir, "A_COPY")
+ A_path = sbox.ospath('A')
+ A_D_path = sbox.ospath('A/D')
+ mu_COPY_path = sbox.ospath('A_COPY/mu')
+ psi_COPY_path = sbox.ospath('A_COPY/D/H/psi')
+ A_COPY_path = sbox.ospath('A_COPY')
# r3 - Make a change on the A_COPY branch that will be
# reintegrated back to A.
@@ -804,27 +878,26 @@ def reintegrate_on_shallow_wc(sbox):
'D' : Item(), # Don't expect anything under D, its depth is empty!
})
expected_A_skip = wc.State(A_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_A_disk,
expected_A_status,
expected_A_skip,
- None, None, None, None,
- None, 1, 1, "--reintegrate", A_path)
+ None, 1, 1)
# Now revert the reintegrate and make a second change on the
# branch in r4, but this time change a subtree that corresponds
# to the missing (shallow) portion of the source. The reintegrate
- # should still succeed, albeit skipping some paths.
+ # should still succeed.
svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R', wc_dir)
svntest.main.file_write(psi_COPY_path, "more branch work")
svntest.main.run_svn(None, 'commit', '-m',
'Some more work on the A_COPY branch', wc_dir)
- # Reuse the same expectations as the prior merge, except that
- # non-inheritable mergeinfo is set on the root of the missing subtree...
+ # Reuse the same expectations as the prior merge, except for the mergeinfo
+ # on the target root that now includes the latest rev on the branch.
expected_mergeinfo_output.add({
'D' : Item(status=' U')
})
@@ -832,20 +905,25 @@ def reintegrate_on_shallow_wc(sbox):
expected_A_disk.tweak('D', props={SVN_PROP_MERGEINFO : '/A_COPY/D:2-4*'})
# ... a depth-restricted item is skipped ...
expected_A_skip.add({
- 'D/H' : Item()
+ 'D/H' : Item(verb='Skipped missing target')
+ })
+ expected_output.add({
+ # Below the skip
+ 'D/H/psi' : Item(status=' ', treeconflict='U'),
})
- # ... and the mergeinfo on the target root includes the latest rev on the branch.
+ # Currently this fails due to r1424469. For a full explanation see
+ # http://svn.haxx.se/dev/archive-2012-12/0472.shtml
+ # and http://svn.haxx.se/dev/archive-2012-12/0475.shtml
expected_A_disk.tweak('', props={SVN_PROP_MERGEINFO : '/A_COPY:2-4'})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_A_disk,
expected_A_status,
expected_A_skip,
- None, None, None, None,
- None, 1, 1, "--reintegrate", A_path)
+ None, 1, 1)
#----------------------------------------------------------------------
@SkipUnless(server_has_mergeinfo)
@@ -854,13 +932,13 @@ def reintegrate_fail_on_stale_source(sbox):
sbox.build()
wc_dir = sbox.wc_dir
expected_disk, expected_status = set_up_branch(sbox)
- A_path = os.path.join(wc_dir, "A")
+ A_path = sbox.ospath('A')
mu_path = os.path.join(A_path, "mu")
svntest.main.file_append(mu_path, 'some text appended to mu\n')
svntest.actions.run_and_verify_svn(None, None, [], 'commit',
- '-m', 'a change to mu', mu_path);
+ '-m', 'a change to mu', mu_path)
# Unmix the revisions in the working copy.
- svntest.actions.run_and_verify_svn(None, None, [], 'update', wc_dir);
+ svntest.actions.run_and_verify_svn(None, None, [], 'update', wc_dir)
# The merge --reintegrate succeeds but since there were no changes
# on A_COPY after it was branched the only result is updated mergeinfo
# on the reintegrate target.
@@ -914,16 +992,15 @@ def reintegrate_fail_on_stale_source(sbox):
'D/H/omega' : Item("New content"),
})
expected_skip = wc.State(A_path, { })
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_disk,
expected_status,
expected_skip,
- [], None, None, None, None, True, True,
- '--reintegrate', A_path)
+ [], True, True)
#----------------------------------------------------------------------
def merge_file_with_space_in_its_path(sbox):
@@ -931,7 +1008,7 @@ def merge_file_with_space_in_its_path(sbox):
sbox.build()
wc_dir = sbox.wc_dir
- some_dir = os.path.join(wc_dir, "some dir")
+ some_dir = sbox.ospath('some dir')
file1 = os.path.join(some_dir, "file1")
file2 = os.path.join(some_dir, "file2")
@@ -953,9 +1030,7 @@ def merge_file_with_space_in_its_path(sbox):
"ci", "-m", "r4", wc_dir)
target_url = sbox.repo_url + '/some%20dir/file2'
- svntest.actions.run_and_verify_svn(None, None, [],
- "merge", "--reintegrate", target_url,
- file1)
+ run_reintegrate(target_url, file1)
#----------------------------------------------------------------------
@SkipUnless(server_has_mergeinfo)
@@ -963,43 +1038,65 @@ def reintegrate_with_subtree_mergeinfo(sbox):
"merge --reintegrate with subtree mergeinfo"
# Create a standard greek tree, branch A to A_COPY in r2, A to A_COPY_2 in
- # r3, A to A_COPY_3 in r3, and then make some changes under A in r5-8.
+ # r3, A to A_COPY_3 in r4, and then make some changes under A in r5-8.
+ #
+ # A_COPY_3 4---------
+ # /
+ # A -1--------5-6-7-8-
+ # \ \
+ # A_COPY 2-\-----------
+ # \
+ # A_COPY_2 3---------
+
sbox.build()
wc_dir = sbox.wc_dir
expected_disk, expected_status = set_up_branch(sbox, False, 3)
# Some paths we'll care about
- gamma_COPY_3_path = os.path.join(wc_dir, "A_COPY_3", "D", "gamma")
- D_path = os.path.join(wc_dir, "A", "D")
- gamma_path = os.path.join(wc_dir, "A", "D", "gamma")
- mu_COPY_2_path = os.path.join(wc_dir, "A_COPY_2", "mu")
- mu_path = os.path.join(wc_dir, "A", "mu")
- mu_COPY_path = os.path.join(wc_dir, "A_COPY", "mu")
- A_COPY_path = os.path.join(wc_dir, "A_COPY")
- D_COPY_path = os.path.join(wc_dir, "A_COPY")
- beta_COPY_path = os.path.join(wc_dir, "A_COPY", "B", "E", "beta")
- gamma_COPY_path = os.path.join(wc_dir, "A_COPY", "D", "gamma")
- gamma_moved_COPY_path = os.path.join(wc_dir, "A_COPY", "D", "gamma_moved")
- gamma_moved_path = os.path.join(wc_dir, "A", "D", "gamma_moved")
- rho_COPY_path = os.path.join(wc_dir, "A_COPY", "D", "G", "rho")
- omega_COPY_path = os.path.join(wc_dir, "A_COPY", "D", "H", "omega")
- psi_COPY_path = os.path.join(wc_dir, "A_COPY", "D", "H", "psi")
- D_COPY_path = os.path.join(wc_dir, "A_COPY", "D")
- alpha_COPY_path = os.path.join(wc_dir, "A_COPY", "B", "E", "alpha")
- A_path = os.path.join(wc_dir, "A")
+ gamma_COPY_3_path = sbox.ospath('A_COPY_3/D/gamma')
+ D_path = sbox.ospath('A/D')
+ gamma_path = sbox.ospath('A/D/gamma')
+ mu_COPY_2_path = sbox.ospath('A_COPY_2/mu')
+ mu_path = sbox.ospath('A/mu')
+ mu_COPY_path = sbox.ospath('A_COPY/mu')
+ A_COPY_path = sbox.ospath('A_COPY')
+ D_COPY_path = sbox.ospath('A_COPY')
+ beta_COPY_path = sbox.ospath('A_COPY/B/E/beta')
+ gamma_COPY_path = sbox.ospath('A_COPY/D/gamma')
+ gamma_moved_COPY_path = sbox.ospath('A_COPY/D/gamma_moved')
+ gamma_moved_path = sbox.ospath('A/D/gamma_moved')
+ rho_COPY_path = sbox.ospath('A_COPY/D/G/rho')
+ omega_COPY_path = sbox.ospath('A_COPY/D/H/omega')
+ psi_COPY_path = sbox.ospath('A_COPY/D/H/psi')
+ D_COPY_path = sbox.ospath('A_COPY/D')
+ alpha_COPY_path = sbox.ospath('A_COPY/B/E/alpha')
+ A_path = sbox.ospath('A')
# Now set up a situation where we try to reintegrate A_COPY back to A but
# both of these paths have subtree mergeinfo. Iff the mergeinfo on A_COPY
# reflects that the same revisions have been applied across all of A_COPY,
- # then the reintegrate merge should succeed.
+ # then the reintegrate merge should succeed. We'll try that case first.
+ #
+ # A_COPY_3 4-------[9]--
+ # / \
+ # / \
+ # A -1--------5-6-7-8---10-------------------WC--
+ # \ \ (D) \ /reint.
+ # \ \ (mu) \ /
+ # A_COPY 2-\--------------------12---13--14------
+ # \ /
+ # \ /
+ # A_COPY_2 3-------------[11]--
#
+ # Key: [#] = cherry-picked revision; (foo) = merge of subtree 'foo'
+ # Note: These diagrams show an overview and do not capture every detail.
+
# r9 - Make a text change to A_COPY_3/D/gamma
svntest.main.file_write(gamma_COPY_3_path, "New content")
expected_output = wc.State(wc_dir, {'A_COPY_3/D/gamma' : Item(verb='Sending')})
expected_status.tweak('A_COPY_3/D/gamma', wc_rev=9)
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
expected_status, None, wc_dir)
- expected_disk.tweak('A_COPY_3/D/gamma', contents="New content")
# r10 - Merge r9 from A_COPY_3/D to A/D, creating explicit subtree
# mergeinfo under A. For this and every subsequent merge we update the WC
@@ -1019,8 +1116,6 @@ def reintegrate_with_subtree_mergeinfo(sbox):
expected_status.tweak('A/D', 'A/D/gamma', wc_rev=10)
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
expected_status, None, wc_dir)
- expected_disk.tweak('A/D/gamma', contents="New content")
- expected_disk.tweak('A/D', props={SVN_PROP_MERGEINFO : '/A_COPY_3/D:9'})
# r11 - Make a text change to A_COPY_2/mu
svntest.main.file_write(mu_COPY_2_path, "New content")
@@ -1028,7 +1123,6 @@ def reintegrate_with_subtree_mergeinfo(sbox):
expected_status.tweak('A_COPY_2/mu', wc_rev=11)
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
expected_status, None, wc_dir)
- expected_disk.tweak('A_COPY_2/mu', contents="New content")
# r12 - Merge r11 from A_COPY_2/mu to A_COPY/mu
svntest.actions.run_and_verify_svn(None, exp_noop_up_out(11), [], 'up',
@@ -1045,7 +1139,6 @@ def reintegrate_with_subtree_mergeinfo(sbox):
expected_status.tweak('A_COPY/mu', wc_rev=12)
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
expected_status, None, wc_dir)
- expected_disk.tweak('A_COPY/mu', contents="New content")
# r13 - Do a 'synch' cherry harvest merge of all available revisions
# from A to A_COPY
@@ -1084,16 +1177,6 @@ def reintegrate_with_subtree_mergeinfo(sbox):
wc_rev=13)
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
expected_status, None, wc_dir)
- expected_disk.tweak('A_COPY/B/E/beta',
- 'A_COPY/D',
- 'A_COPY/D/G/rho',
- 'A_COPY/D/H/omega',
- 'A_COPY/D/H/psi',
- 'A_COPY/D/gamma',
- contents="New content")
- expected_disk.tweak('A_COPY', props={SVN_PROP_MERGEINFO : '/A:2-12'})
- expected_disk.tweak('A_COPY/D',
- props={SVN_PROP_MERGEINFO : '/A/D:2-12\n/A_COPY_3/D:9\n'})
# r14 - Make a text change on A_COPY/B/E/alpha
svntest.main.file_write(alpha_COPY_path, "New content")
@@ -1101,7 +1184,6 @@ def reintegrate_with_subtree_mergeinfo(sbox):
expected_status.tweak('A_COPY/B/E/alpha', wc_rev=14)
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
expected_status, None, wc_dir)
- expected_disk.tweak('A_COPY/B/E/alpha', contents="New content")
# Now, reintegrate A_COPY to A. This should succeed.
svntest.actions.run_and_verify_svn(None, exp_noop_up_out(14), [], 'up',
@@ -1166,22 +1248,32 @@ def reintegrate_with_subtree_mergeinfo(sbox):
'D/H/omega' : Item("New content"),
})
expected_A_skip = wc.State(A_COPY_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_A_disk,
expected_A_status,
expected_A_skip,
- None, None, None, None,
- None, 1, 1, "--reintegrate", A_path)
+ None, 1, 1)
# Make some more changes to A_COPY so that the same revisions have *not*
# been uniformly applied from A to A_COPY. In this case the reintegrate
# merge should fail, but should provide a helpful message as to where the
# problems are.
#
+ # A_COPY_3 4-------[9]--
+ # / \
+ # / \ [-8]___
+ # A -1---------5-6-7-8---10----------------\-------WC--
+ # \ \ (D) \ \ /reint.
+ # \ \ (mu) \ \ /
+ # A_COPY 2-\--------------------12---13--14--15--------
+ # \ / (D)
+ # \ /
+ # A_COPY_2 3-------------[11]--
+
# First revert the previous reintegrate merge
svntest.actions.run_and_verify_svn(None, None, [],
'revert', '-R', wc_dir)
@@ -1204,19 +1296,10 @@ def reintegrate_with_subtree_mergeinfo(sbox):
# to it from A, the merge should fail. Further we expect an error message
# that highlights the fact that A_COPY/D is the offending subtree.
#
- # The actions.run_and_verify_* methods are happy if one line of the error
- # matches the regex, but we want to know that the error actually provides
- # specific information about the paths that are stopping --reintegrate from
- # working. So we will pass the stderr to svntest.verify.verify_outputs()
- # ourselves, but as the 'actual_stdout' argument, that way each line of
- # error must match the regex.
- exit_code, out, err = svntest.actions.run_and_verify_svn(
- None, [], svntest.verify.AnyOutput,
- 'merge', '--reintegrate', sbox.repo_url + '/A_COPY', A_path)
-
- svntest.verify.verify_outputs("Reintegrate failed but not "
- "in the way expected",
- err, None,
+ # We want to know that the error provides specific information about the
+ # paths that are stopping --reintegrate from working.
+ run_reintegrate_expect_error(sbox.repo_url + '/A_COPY', A_path,
+ [],
"(svn: E195016: Reintegrate can only be used if "
"revisions 2 through 15 were previously "
"merged from .*/A to the reintegrate source, "
@@ -1225,10 +1308,7 @@ def reintegrate_with_subtree_mergeinfo(sbox):
"|( Missing ranges: /A/D:8\n)"
"|( A_COPY/mu\n)"
"|( Missing ranges: /A/mu:2-12\n)"
- "|(\n)"
- "|(.*apr_err.*)", # In case of debug build
- None,
- True) # Match *all* lines of stdout
+ "|(\n)")
# Test another common situation that can break reintegrate as a result
# of copies and moves:
@@ -1247,8 +1327,19 @@ def reintegrate_with_subtree_mergeinfo(sbox):
# rev N+3. The renamed subtree on 'branch' now has additional explicit
# mergeinfo decribing the synch merge from trunk@N+1 to trunk@N+2.
#
- # E) Reintegrate 'branch' to 'trunk'. This fails as it appears not all
- # of 'trunk' was previously merged to 'branch'
+ # E) Reintegrate 'branch' to 'trunk'.
+ #
+ # Step: A B C D E
+ # A_COPY_3 ---[9]--
+ # / \ (D/g.->
+ # / \ [-8]___ D/g.m.) (D/g.m.)
+ # A ------------10----------------\------16-------18--------WC
+ # \\ (D) \ \ \ \ /reint.
+ # \\ (mu) \ \ \ \ /
+ # A_COPY -\--------------12---13--14--15-------17-------19------
+ # \ / (D)
+ # \ /
+ # A_COPY_2 --------[11]--
# r16 - A) REPOS-to-REPOS rename of A/D/gamma to A/D/gamma_moved. Since
# r874258 WC-to-WC moves won't create mergeinfo on the dest if the source
@@ -1260,15 +1351,18 @@ def reintegrate_with_subtree_mergeinfo(sbox):
'-m', 'REPOS-to-REPOS move'
)
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
- expected_disk.remove('A/D/gamma')
- expected_disk.add({
- 'A/D/gamma_moved' : Item(props={SVN_PROP_MERGEINFO: '/A_COPY_3/D/gamma:9'},
- contents="New content")
- })
expected_status.tweak(wc_rev=16)
expected_status.remove('A/D/gamma')
expected_status.add({'A/D/gamma_moved' : Item(status=' ', wc_rev=16)})
+ # Why is gamma_moved notified as ' G' rather than ' U'? It was
+ # added by the merge and there is only a single editor drive, so
+ # how can any prop changes be merged to it? The answer is that
+ # the merge code does some quiet housekeeping, merging gamma_moved's
+ # inherited mergeinfo into its incoming mergeinfo, see
+ # http://subversion.tigris.org/issues/show_bug.cgi?id=4309
+ # This test is not covering issue #4309 so we let the current
+ # behavior pass.
# r17 - B) Synch merge from A to A_COPY
svntest.actions.run_and_verify_svn(
None,
@@ -1278,7 +1372,7 @@ def reintegrate_with_subtree_mergeinfo(sbox):
'D ' + gamma_COPY_path + '\n',
' U ' + A_COPY_path + '\n',
' U ' + D_COPY_path + '\n',
- ' U ' + gamma_moved_COPY_path + '\n']),
+ ' G ' + gamma_moved_COPY_path + '\n']),
[], 'merge', sbox.repo_url + '/A', A_COPY_path)
expected_output = wc.State(
wc_dir,
@@ -1298,11 +1392,6 @@ def reintegrate_with_subtree_mergeinfo(sbox):
expected_status.add({'A_COPY/D/gamma_moved' : Item(status=' ', wc_rev=17)})
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
expected_status, None, wc_dir)
- expected_disk.remove('A_COPY/D/gamma')
- expected_disk.add({
- 'A/D/gamma_moved' : Item(props={SVN_PROP_MERGEINFO: '/A_COPY_3/D/gamma:9'},
- contents="New content")
- })
# r18 - C) Text mod to A/D/gamma_moved
svntest.main.file_write(gamma_moved_path, "Even newer content")
@@ -1353,7 +1442,7 @@ def reintegrate_with_subtree_mergeinfo(sbox):
'' : Item(status=' U'),
'mu' : Item(status=' G'),
'D' : Item(status=' U'),
- 'D/gamma_moved' : Item(status=' U'),
+ 'D/gamma_moved' : Item(status=' G'), # More issue #4309 (see above)
})
expected_elision_output = wc.State(A_path, {
})
@@ -1397,38 +1486,49 @@ def reintegrate_with_subtree_mergeinfo(sbox):
'D/G/pi' : Item("This is the file 'pi'.\n"),
'D/G/rho' : Item("New content"),
'D/G/tau' : Item("This is the file 'tau'.\n"),
- # Why do we expect mergeinfo of '/A_COPY/D/G/tauprime:2-9' on
- # A/D/G/tauprime? Because this --reintegrate merge is effectively a
- # two URL merge of %URL%/A@9 %URL%/A_COPY@9 to 'A'. Since %URL%/A@9 and
- # %URL%/A_COPY@9 have a common ancestor in %URL%/A@1 we expect this 2-URL
- # merge to record mergeinfo and a component of that mergeinfo describes
- # the merge of %URL%/A_COPY@2 to %URL%/A_COPY@9. We see that above on
- # A. But we also get it on A's subtrees with explicit mergeinfo, namely
- # A/D/G/tauprime. Now I know what you are thinking, "'A_COPY/D/G/tauprime'
- # doesn't even exist until r9!", and you are quite right. But this
- # inheritance of bogus mergeinfo is a known problem, see
- # http://subversion.tigris.org/issues/show_bug.cgi?id=3157#desc8,
- # and is not what this test is about, so we won't fail because of it.
+ # What's with all this mergeinfo?
+ #
+ # '/A/D/gamma_moved:2-7,9-12' - Incoming from the merge source. Yes,
+ # this mergeinfo describes non-existent path-revs, this is the effect
+ # of issue #3669 'inheritance can result in mergeinfo describing
+ # nonexistent sources', but there is already a test for that issue so
+ # we tolerate it here.
+ #
+ # '/A_COPY/D/gamma_moved:17-19' - Describes the merge performed.
+ #
+ # '/A_COPY_3/D/gamma:9' - Explicit prior to the merge.
+ #
+ #'/A_COPY_3/D/gamma_moved:9' - Incoming from the merge source.
+ # For the curious, this was originally created in r17 when we merged
+ # ^/A to A_COPY. This merge added A_COPY/D/gamma_moved, which had
+ # explicit mergeinfo and due to issue #4309 'wrong notification and
+ # bogus mergeinfo during merge which adds subtree with mergeinfo'
+ # this file inherited this bogus mergeinfo from A_COPY/D. Yes, this
+ # is all quite ugly as the intersection or multiple known issues
+ # is likely to be. However, given that none of this mergeinfo is
+ # particularly harmful and that this test is *not* about issues #3669
+ # or #4309, we are tolerting it.
'D/gamma_moved' : Item(
"Even newer content", props={SVN_PROP_MERGEINFO :
+ '/A/D/gamma_moved:2-7,9-12\n'
'/A_COPY/D/gamma_moved:17-19\n'
- '/A_COPY_3/D/gamma:9'}),
+ '/A_COPY_3/D/gamma:9\n'
+ '/A_COPY_3/D/gamma_moved:9'}),
'D/H' : Item(),
'D/H/chi' : Item("This is the file 'chi'.\n"),
'D/H/psi' : Item("New content"),
'D/H/omega' : Item("New content"),
})
expected_A_skip = wc.State(A_COPY_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_A_disk,
expected_A_status,
expected_A_skip,
- None, None, None, None,
- None, 1, 1, "--reintegrate", A_path)
+ None, 1, 1)
#----------------------------------------------------------------------
@SkipUnless(server_has_mergeinfo)
@@ -1441,11 +1541,11 @@ def multiple_reintegrates_from_the_same_branch(sbox):
expected_disk, expected_status = set_up_branch(sbox)
# Some paths we'll care about
- A_path = os.path.join(wc_dir, "A")
- mu_path = os.path.join(wc_dir, "A", "mu")
- A_COPY_path = os.path.join(wc_dir, "A_COPY")
- psi_COPY_path = os.path.join(wc_dir, "A_COPY", "D", "H", "psi")
- Feature_branch_path = os.path.join(wc_dir, "A_FEATURE_BRANCH")
+ A_path = sbox.ospath('A')
+ mu_path = sbox.ospath('A/mu')
+ A_COPY_path = sbox.ospath('A_COPY')
+ psi_COPY_path = sbox.ospath('A_COPY/D/H/psi')
+ Feature_branch_path = sbox.ospath('A_FEATURE_BRANCH')
Feature_beta_path = os.path.join(wc_dir, "A_FEATURE_BRANCH", "B", "E",
"beta")
@@ -1485,9 +1585,7 @@ def multiple_reintegrates_from_the_same_branch(sbox):
# r11 - Reintegrate the feature branch back to 'A'.
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
- svntest.actions.run_and_verify_svn(None, None, [], 'merge', '--reintegrate',
- sbox.repo_url + '/A_FEATURE_BRANCH',
- A_path)
+ run_reintegrate(sbox.repo_url + '/A_FEATURE_BRANCH', A_path)
svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
"Reintegrate feature branch back to 'A'",
wc_dir)
@@ -1495,7 +1593,7 @@ def multiple_reintegrates_from_the_same_branch(sbox):
# r12 - Do a --record-only merge from 'A' to the feature branch so we
# don't try to merge r11 from trunk during the next sync merge.
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
- svntest.actions.run_and_verify_svn(None, None, [], 'merge',
+ svntest.actions.run_and_verify_svn(None, None, [], 'merge', '-c11',
'--record-only',
sbox.repo_url + '/A',
Feature_branch_path)
@@ -1579,17 +1677,15 @@ def multiple_reintegrates_from_the_same_branch(sbox):
'D/H/omega' : Item("New content"),
})
expected_skip = wc.State(A_path, { })
- svntest.actions.run_and_verify_merge(A_path, None, None,
+ run_and_verify_reintegrate(A_path,
sbox.repo_url + '/A_FEATURE_BRANCH',
- None,
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_disk,
expected_status,
expected_skip,
- None, None, None, None,
- None, 1, 1, '--reintegrate', A_path)
+ None, 1, 1)
svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
"2nd Reintegrate feature branch back to 'A'",
wc_dir)
@@ -1631,11 +1727,11 @@ def reintegrate_with_self_referential_mergeinfo(sbox):
wc_disk, wc_status = set_up_branch(sbox, nbr_of_branches=0)
# Some paths we'll care about
- A_path = os.path.join(wc_dir, "A")
- A2_path = os.path.join(wc_dir, "A2")
- A2_B_path = os.path.join(wc_dir, "A2", "B")
- A2_1_path = os.path.join(wc_dir, "A2.1")
- A2_1_mu_path = os.path.join(wc_dir, "A2.1", "mu")
+ A_path = sbox.ospath('A')
+ A2_path = sbox.ospath('A2')
+ A2_B_path = sbox.ospath('A2/B')
+ A2_1_path = sbox.ospath('A2.1')
+ A2_1_mu_path = sbox.ospath('A2.1/mu')
# r6 Copy A to A2 and then manually set some self-referential mergeinfo on
# A2/B and A2.
@@ -1737,20 +1833,22 @@ def reintegrate_with_self_referential_mergeinfo(sbox):
# ..\..\..\subversion\libsvn_fs_fs\tree.c:2886: (apr_err=160013)
# ..\..\..\subversion\libsvn_fs_fs\tree.c:669: (apr_err=160013)
# svn: File not found: revision 4, path '/A2'
- svntest.actions.run_and_verify_merge(A2_path, None, None,
- sbox.repo_url + '/A2.1', None,
+ run_and_verify_reintegrate(A2_path,
+ sbox.repo_url + '/A2.1',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_disk,
expected_status,
expected_skip,
- None, None, None, None,
- None, 1, 0, '--reintegrate', A2_path)
+ None, 1, 0)
#----------------------------------------------------------------------
-# Test for issue #3577 '1.7 subtree mergeinfo recording breaks reintegrate'.
-@Issue(3577)
+# Test for issue #3577 '1.7 subtree mergeinfo recording breaks reintegrate'
+# and issue #4329 'automatic merge uses reintegrate type merge if source is
+# fully synced'.
+@Issue(3577,4329)
+@SkipUnless(server_has_mergeinfo)
def reintegrate_with_subtree_merges(sbox):
"reintegrate with prior subtree merges to source"
@@ -1761,12 +1859,13 @@ def reintegrate_with_subtree_merges(sbox):
expected_disk, expected_status = set_up_branch(sbox)
# Some paths we'll care about
- A_path = os.path.join(wc_dir, "A")
- mu_COPY_path = os.path.join(wc_dir, "A_COPY", "mu")
- A_COPY_path = os.path.join(wc_dir, "A_COPY")
- B_COPY_path = os.path.join(wc_dir, "A_COPY", "B")
- rho_COPY_path = os.path.join(wc_dir, "A_COPY", "D", "G", "rho")
- H_COPY_path = os.path.join(wc_dir, "A_COPY", "D", "H")
+ A_path = sbox.ospath('A')
+ psi_path = sbox.ospath('A/D/H/psi')
+ mu_COPY_path = sbox.ospath('A_COPY/mu')
+ A_COPY_path = sbox.ospath('A_COPY')
+ B_COPY_path = sbox.ospath('A_COPY/B')
+ rho_COPY_path = sbox.ospath('A_COPY/D/G/rho')
+ H_COPY_path = sbox.ospath('A_COPY/D/H')
# r7 - Make a change on the A_COPY branch that will be
# reintegrated back to A.
@@ -1821,7 +1920,7 @@ def reintegrate_with_subtree_merges(sbox):
'mu' : Item(status='U '),
})
expected_mergeinfo_output = wc.State(A_path, {
- '' : Item(status=' G'),
+ '' : Item(status=' U'),
})
expected_elision_output = wc.State(A_path, {
})
@@ -1869,16 +1968,37 @@ def reintegrate_with_subtree_merges(sbox):
'D/H/omega' : Item("New content"),
})
expected_A_skip = wc.State(A_COPY_path, {})
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
+ expected_output,
+ expected_mergeinfo_output,
+ expected_elision_output,
+ expected_A_disk,
+ expected_A_status,
+ expected_A_skip,
+ None, 1, 1)
+
+ # Test issue #4329. Revert previous merge and commit a new edit to
+ # A/D/H/psi. Attempt the same merge without the --reintegrate option.
+ # It should succeed because the automatic merge code should detect that
+ # a reintegrate-style merge is required, that merge should succeed and
+ # there should be not conflict on A/D/H/psi.
+ svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R', wc_dir)
+ svntest.main.file_write(psi_path, "Non-conflicting trunk edit.\n")
+ svntest.main.run_svn(None, 'commit', '-m',
+ 'An edit on trunk prior to reintegrate.', wc_dir)
+ sbox.simple_update()
+ expected_A_status.tweak(wc_rev=9)
+ expected_A_disk.tweak('', props={SVN_PROP_MERGEINFO: '/A_COPY:2-9'})
+ expected_A_disk.tweak('D/H/psi', contents='Non-conflicting trunk edit.\n')
svntest.actions.run_and_verify_merge(A_path, None, None,
sbox.repo_url + '/A_COPY', None,
expected_output,
expected_mergeinfo_output,
expected_elision_output,
- expected_A_disk,
- expected_A_status,
- expected_A_skip,
- None, None, None, None,
- None, 1, 1, "--reintegrate", A_path)
+ expected_A_disk, expected_A_status,
+ expected_A_skip, None, None, None,
+ None, None, True, False, A_path)
#----------------------------------------------------------------------
# Test for issue #3654 'added subtrees with mergeinfo break reintegrate'.
@@ -1890,13 +2010,13 @@ def added_subtrees_with_mergeinfo_break_reintegrate(sbox):
wc_dir = sbox.wc_dir
# Some paths we'll care about
- A_path = os.path.join(wc_dir, "A")
- nu_path = os.path.join(wc_dir, "A", "C", "nu")
- mu_path = os.path.join(wc_dir, "A", "mu")
- A_COPY_path = os.path.join(wc_dir, "A_COPY")
- lambda_COPY_path = os.path.join(wc_dir, "A_COPY", "B", "lambda")
- A_COPY_2_path = os.path.join(wc_dir, "A_COPY_2")
- nu_COPY_2_path = os.path.join(wc_dir, "A_COPY_2", "C", "nu")
+ A_path = sbox.ospath('A')
+ nu_path = sbox.ospath('A/C/nu')
+ mu_path = sbox.ospath('A/mu')
+ A_COPY_path = sbox.ospath('A_COPY')
+ lambda_COPY_path = sbox.ospath('A_COPY/B/lambda')
+ A_COPY_2_path = sbox.ospath('A_COPY_2')
+ nu_COPY_2_path = sbox.ospath('A_COPY_2/C/nu')
# Branch A@1 to A_COPY and A_COPY_2 in r2 and r3 respectively.
# Make some changes under 'A' in r4-7.
@@ -1952,9 +2072,7 @@ def added_subtrees_with_mergeinfo_break_reintegrate(sbox):
# r14 - Reintegrate A_COPY to A.
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
- svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
- 'merge', '--reintegrate',
- sbox.repo_url + '/A_COPY', A_path)
+ run_reintegrate(sbox.repo_url + '/A_COPY', A_path)
svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
'Reintegrate A_COPY to A.',
wc_dir)
@@ -2064,16 +2182,15 @@ def added_subtrees_with_mergeinfo_break_reintegrate(sbox):
'D/H/omega' : Item("New content"),
})
expected_skip = wc.State(A_COPY_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_disk,
expected_status,
expected_skip,
- None, None, None, None,
- None, 1, 1, "--reintegrate", A_path)
+ None, 1, 1)
#----------------------------------------------------------------------
# Test for issue #3648 '2-URL merges incorrectly reverse-merge mergeinfo
@@ -2086,10 +2203,10 @@ def two_URL_merge_removes_valid_mergeinfo_from_target(sbox):
wc_dir = sbox.wc_dir
# Some paths we'll care about
- lambda_COPY_path = os.path.join(wc_dir, "A_COPY", "B", "lambda")
- mu_path = os.path.join(wc_dir, "A", "mu")
- A_COPY_path = os.path.join(wc_dir, "A_COPY")
- A_COPY_2_path = os.path.join(wc_dir, "A_COPY_2")
+ lambda_COPY_path = sbox.ospath('A_COPY/B/lambda')
+ mu_path = sbox.ospath('A/mu')
+ A_COPY_path = sbox.ospath('A_COPY')
+ A_COPY_2_path = sbox.ospath('A_COPY_2')
# Branch A@1 to A_COPY r2
# Branch A@1 to A_COPY_2 in r3.
@@ -2245,14 +2362,14 @@ def reintegrate_creates_bogus_mergeinfo(sbox):
sbox.build()
wc_dir=sbox.wc_dir
- mu_path = os.path.join(sbox.wc_dir, "A", "mu")
- lambda_path = os.path.join(sbox.wc_dir, "A", "B", "lambda")
- alpha_path = os.path.join(sbox.wc_dir, "A", "B", "E", "alpha")
- beta_path = os.path.join(sbox.wc_dir, "A", "B", "E", "beta")
- A_path = os.path.join(sbox.wc_dir, "A")
- A_path_1 = os.path.join(sbox.wc_dir, "A@1")
- A_COPY_path = os.path.join(sbox.wc_dir, "A_COPY")
- A_COPY_psi_path = os.path.join(sbox.wc_dir, "A_COPY", "D", "H", "psi")
+ mu_path = sbox.ospath('A/mu')
+ lambda_path = sbox.ospath('A/B/lambda')
+ alpha_path = sbox.ospath('A/B/E/alpha')
+ beta_path = sbox.ospath('A/B/E/beta')
+ A_path = sbox.ospath('A')
+ A_path_1 = sbox.ospath('A@1')
+ A_COPY_path = sbox.ospath('A_COPY')
+ A_COPY_psi_path = sbox.ospath('A_COPY/D/H/psi')
A_COPY_url = sbox.repo_url + "/A_COPY"
# Make 2 commits under /A pushing the repo to rev3
@@ -2280,7 +2397,7 @@ def reintegrate_creates_bogus_mergeinfo(sbox):
svntest.main.run_svn(None, "up", wc_dir)
# Reintegrate A_COPY to A. The resulting merginfo on A should be
- # /A_COPY:4-10
+ # /A_COPY:4-6
expected_output = wc.State(A_path, {
'D/H/psi' : Item(status='U '),
})
@@ -2313,14 +2430,14 @@ def reintegrate_creates_bogus_mergeinfo(sbox):
})
expected_skip = wc.State(A_COPY_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- A_COPY_url, None,
+ run_and_verify_reintegrate(A_path,
+ A_COPY_url,
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_disk, None, expected_skip,
- None, None, None, None, None,
- 1, 1, "--reintegrate", A_path)
+ None,
+ 1, 1)
#----------------------------------------------------------------------
@@ -2335,7 +2452,7 @@ def no_source_subtree_mergeinfo(sbox):
sbox.build()
wc_dir=sbox.wc_dir
- svntest.main.file_write(os.path.join(wc_dir, 'A', 'B', 'E', 'alpha'),
+ svntest.main.file_write(sbox.ospath('A/B/E/alpha'),
'AAA\n' +
'BBB\n' +
'CCC\n')
@@ -2344,32 +2461,32 @@ def no_source_subtree_mergeinfo(sbox):
# Create branch-1
svntest.main.run_svn(None, 'copy',
- os.path.join(wc_dir, 'A', 'B'),
- os.path.join(wc_dir, 'A', 'B1'))
+ sbox.ospath('A/B'),
+ sbox.ospath('A/B1'))
svntest.main.run_svn(None, 'commit', '-m', 'log message', wc_dir)
# Create branch-1
svntest.main.run_svn(None, 'copy',
- os.path.join(wc_dir, 'A', 'B'),
- os.path.join(wc_dir, 'A', 'B2'))
+ sbox.ospath('A/B'),
+ sbox.ospath('A/B2'))
svntest.main.run_svn(None, 'commit', '-m', 'log message', wc_dir)
# Change on trunk
- svntest.main.file_write(os.path.join(wc_dir, 'A', 'B', 'E', 'alpha'),
+ svntest.main.file_write(sbox.ospath('A/B/E/alpha'),
'AAAxx\n' +
'BBB\n' +
'CCC\n')
svntest.main.run_svn(None, 'commit', '-m', 'log message', wc_dir)
# Change on branch-1
- svntest.main.file_write(os.path.join(wc_dir, 'A', 'B1', 'E', 'alpha'),
+ svntest.main.file_write(sbox.ospath('A/B1/E/alpha'),
'AAA\n' +
'BBBxx\n' +
'CCC\n')
svntest.main.run_svn(None, 'commit', '-m', 'log message', wc_dir)
# Change on branch-2
- svntest.main.file_write(os.path.join(wc_dir, 'A', 'B2', 'E', 'alpha'),
+ svntest.main.file_write(sbox.ospath('A/B2/E/alpha'),
'AAA\n' +
'BBB\n' +
'CCCxx\n')
@@ -2377,45 +2494,52 @@ def no_source_subtree_mergeinfo(sbox):
svntest.main.run_svn(None, 'update', wc_dir)
# Merge trunk to branch-1
- svntest.main.run_svn(None, 'merge', '^/A/B', os.path.join(wc_dir, 'A', 'B1'))
+ svntest.main.run_svn(None, 'merge', '^/A/B', sbox.ospath('A/B1'))
svntest.main.run_svn(None, 'commit', '-m', 'log message', wc_dir)
svntest.main.run_svn(None, 'update', wc_dir)
# Reintegrate branch-1 subtree to trunk subtree
- svntest.main.run_svn(None, 'merge', '--reintegrate',
- '^/A/B1/E', os.path.join(wc_dir, 'A', 'B', 'E'))
+ run_reintegrate('^/A/B1/E', sbox.ospath('A/B/E'))
svntest.main.run_svn(None, 'commit', '-m', 'log message', wc_dir)
svntest.main.run_svn(None, 'update', wc_dir)
# Merge trunk to branch-2
- svntest.main.run_svn(None, 'merge', '^/A/B', os.path.join(wc_dir, 'A', 'B2'))
+ svntest.main.run_svn(None, 'merge', '^/A/B', sbox.ospath('A/B2'))
svntest.main.run_svn(None, 'commit', '-m', 'log message', wc_dir)
svntest.main.run_svn(None, 'update', wc_dir)
# Reverse merge branch-1 subtree to branch-2 subtree, this removes
# the subtree mergeinfo from branch 2
svntest.main.run_svn(None, 'merge', '-r8:2',
- '^/A/B1/E', os.path.join(wc_dir, 'A', 'B2', 'E'))
+ '^/A/B1/E', sbox.ospath('A/B2/E'))
svntest.main.run_svn(None, 'commit', '-m', 'log message', wc_dir)
svntest.main.run_svn(None, 'update', wc_dir)
+ # Verify that merge results in no subtree mergeinfo
+ svntest.actions.run_and_verify_svn(None, [], [], 'propget', 'svn:mergeinfo',
+ sbox.repo_url + '/A/B2/E')
+
# Merge trunk to branch-2
- svntest.main.run_svn(None, 'merge', '^/A/B', os.path.join(wc_dir, 'A', 'B2'))
+ svntest.main.run_svn(None, 'merge', '^/A/B', sbox.ospath('A/B2'))
svntest.main.run_svn(None, 'commit', '-m', 'log message', wc_dir)
svntest.main.run_svn(None, 'update', wc_dir)
+ # Verify that there is still no subtree mergeinfo
+ svntest.actions.run_and_verify_svn(None, [], [], 'propget', 'svn:mergeinfo',
+ sbox.repo_url + '/A/B2/E')
+
# Reintegrate branch-2 to trunk, this fails in 1.6.x from 1.6.13.
# The error message states revisions /A/B/E:3-11 are missing from
# /A/B2/E and yet the mergeinfo on /A/B2 is /A/B:3-11 and /A/B2/E
# has no mergeinfo.
- expected_output = wc.State(os.path.join(wc_dir, 'A', 'B'), {
+ expected_output = wc.State(sbox.ospath('A/B'), {
'E' : Item(status=' U'),
'E/alpha' : Item(status='U '),
})
- expected_mergeinfo = wc.State(os.path.join(wc_dir, 'A', 'B'), {
+ expected_mergeinfo = wc.State(sbox.ospath('A/B'), {
'' : Item(status=' U'),
})
- expected_elision = wc.State(os.path.join(wc_dir, 'A', 'B'), {
+ expected_elision = wc.State(sbox.ospath('A/B'), {
})
expected_disk = wc.State('', {
'' : Item(props={SVN_PROP_MERGEINFO : '/A/B2:4-12'}),
@@ -2427,24 +2551,15 @@ def no_source_subtree_mergeinfo(sbox):
'F' : Item(),
'lambda' : Item("This is the file 'lambda'.\n"),
})
- expected_skip = wc.State(os.path.join(wc_dir, 'A', 'B'), {
+ expected_skip = wc.State(sbox.ospath('A/B'), {
})
- svntest.actions.run_and_verify_merge(os.path.join(wc_dir, 'A', 'B'),
- None, None, '^/A/B2', None,
+ run_and_verify_reintegrate(sbox.ospath('A/B'),
+ '^/A/B2',
expected_output, expected_mergeinfo,
expected_elision, expected_disk,
None, expected_skip,
- None, None, None, None, None,
- 1, 1, '--reintegrate',
- os.path.join(wc_dir, 'A', 'B'))
- # For 1.6 testsuite use:
- # svntest.actions.run_and_verify_merge(os.path.join(wc_dir, 'A', 'B'),
- # None, None, '^/A/B2',
- # expected_output,
- # expected_disk,
- # None, expected_skip,
- # None, None, None, None, None,
- # 1, 1, '--reintegrate')
+ None,
+ 1, 1)
#----------------------------------------------------------------------
@SkipUnless(server_has_mergeinfo)
@@ -2457,15 +2572,15 @@ def reintegrate_replaced_source(sbox):
wc_dir = sbox.wc_dir
expected_disk, expected_status = set_up_branch(sbox)
- A_path = os.path.join(sbox.wc_dir, "A")
- A_COPY_path = os.path.join(sbox.wc_dir, "A_COPY")
- beta_COPY_path = os.path.join(sbox.wc_dir, "A_COPY", "B", "E", "beta")
- mu_COPY_path = os.path.join(sbox.wc_dir, "A_COPY", "mu")
+ A_path = sbox.ospath('A')
+ A_COPY_path = sbox.ospath('A_COPY')
+ beta_COPY_path = sbox.ospath('A_COPY/B/E/beta')
+ mu_COPY_path = sbox.ospath('A_COPY/mu')
# Using cherrypick merges, simulate a series of sync merges from A to
# A_COPY with a replace of A_COPY along the way.
#
- # r6 - Merge r3 from A to A_COPY
+ # r7 - Merge r3 from A to A_COPY
svntest.main.run_svn(None, 'up', wc_dir)
svntest.main.run_svn(None, 'merge', sbox.repo_url + '/A', A_COPY_path,
'-c3')
@@ -2500,7 +2615,7 @@ def reintegrate_replaced_source(sbox):
wc_dir)
# r12 - Do a final sync merge of A to A_COPY in preparation for
- # reintegration.
+ # reintegration.
svntest.main.run_svn(None, 'up', wc_dir)
svntest.main.run_svn(None, 'merge', sbox.repo_url + '/A', A_COPY_path)
svntest.main.run_svn(None, 'ci', '-m', 'Sycn A_COPY with A', wc_dir)
@@ -2561,17 +2676,16 @@ def reintegrate_replaced_source(sbox):
'D/H/omega' : Item("New content"),
})
expected_skip = wc.State(A_path, { })
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_disk,
expected_status,
expected_skip,
- [], None, None, None, None, True, True,
- '--reintegrate', A_path)
-
+ [], True, True)
+
#----------------------------------------------------------------------
@SkipUnless(svntest.main.is_posix_os)
@Issue(4052)
@@ -2607,10 +2721,66 @@ def reintegrate_symlink_deletion(sbox):
## reintegrate
# ### TODO: verify something here
- svntest.main.run_svn(None, 'merge', '--reintegrate',
- A_COPY_url, A_path)
+ run_reintegrate(A_COPY_url, A_path)
+
+#----------------------------------------------------------------------
+def no_op_reintegrate(sbox):
+ """no-op reintegrate"""
+
+ # Make A_COPY branch in r2, and do a few more commits to A in r3-6.
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ A_path = sbox.ospath('A')
+ A_COPY_path = sbox.ospath('A_COPY')
+ expected_disk, expected_status = set_up_branch(sbox)
+
+ # Sync merge from trunk to branch
+ svntest.main.run_svn(None, 'merge', sbox.repo_url + '/A', A_COPY_path)
+ sbox.simple_commit()
+ sbox.simple_update()
+ # Reintegrate; there are no relevant changes on the branch.
+ # ### TODO: Check the result more carefully than merely that it completed.
+ run_reintegrate(sbox.repo_url + '/A_COPY', A_path)
+
+#----------------------------------------------------------------------
+def renamed_branch_reintegrate(sbox):
+ """reintegrate a branch that has been renamed"""
+
+ # The idea of this test is to ensure that the reintegrate merge is able to
+ # cope when one or both of the branches have been renamed.
+ #
+ # A -1-----3-4-5-6----------------------9--------
+ # \ \ / reintegrate
+ # A_COPY 2--------------7-------- /
+ # sync \ /
+ # RENAMED rename 8----------------
+
+ # TODO: Make some changes between the sync/rename/reintegrate steps so
+ # the reintegrate merge actually has to do something.
+ # TODO: Rename the other branch as well.
+
+ # Make A_COPY branch in r2, and do a few more commits to A in r3-6.
+ sbox.build()
+
+ wc_dir = sbox.wc_dir
+ A_path = sbox.ospath('A')
+ A_COPY_path = sbox.ospath('A_COPY')
+ expected_disk, expected_status = set_up_branch(sbox)
+
+ # Sync merge from trunk to branch
+ svntest.main.run_svn(None, 'merge', sbox.repo_url + '/A', A_COPY_path)
+ sbox.simple_commit()
+ sbox.simple_update()
+
+ # Rename the branch
+ sbox.simple_move('A_COPY', 'RENAMED')
+ sbox.simple_commit()
+ sbox.simple_update()
+ # Reintegrate; there are no relevant changes on the branch.
+ # ### TODO: Check the result more carefully than merely that it completed.
+ run_reintegrate(sbox.repo_url + '/RENAMED@8', A_path)
########################################################################
# Run the tests
@@ -2630,12 +2800,15 @@ test_list = [ None,
reintegrate_with_subtree_mergeinfo,
multiple_reintegrates_from_the_same_branch,
reintegrate_with_self_referential_mergeinfo,
+ reintegrate_with_subtree_merges,
added_subtrees_with_mergeinfo_break_reintegrate,
two_URL_merge_removes_valid_mergeinfo_from_target,
reintegrate_creates_bogus_mergeinfo,
no_source_subtree_mergeinfo,
reintegrate_replaced_source,
reintegrate_symlink_deletion,
+ no_op_reintegrate,
+ renamed_branch_reintegrate,
]
if __name__ == '__main__':