You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2013/02/23 02:25:44 UTC
svn commit: r1449262 [20/25] - in /subversion/branches/ev2-export: ./ build/
build/ac-macros/ build/generator/ build/generator/swig/
build/generator/templates/ build/win32/
contrib/server-side/fsfsfixer/fixer/ contrib/server-side/svncutter/ notes/
note...
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/merge_tests.py?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/merge_tests.py Sat Feb 23 01:25:38 2013
@@ -32,6 +32,8 @@ import time
import svntest
from svntest import main, wc, verify, actions
+from prop_tests import binary_mime_type_on_text_file_warning
+
# (abbreviation)
Item = wc.StateItem
Skip = svntest.testcase.Skip_deco
@@ -47,11 +49,12 @@ from svntest.main import server_has_merg
from svntest.actions import fill_file_with_lines
from svntest.actions import make_conflict_marker_text
from svntest.actions import inject_conflict_into_expected_state
+from svntest.verify import RegexListOutput
-def expected_merge_output(rev_ranges, additional_lines=None, foreign=False,
+def expected_merge_output(rev_ranges, additional_lines=[], foreign=False,
elides=False, two_url=False, target=None,
text_conflicts=0, prop_conflicts=0, tree_conflicts=0,
- resolved=[]):
+ skipped_paths=0):
"""Generate an (inefficient) regex representing the expected merge
output and mergeinfo notifications from REV_RANGES and ADDITIONAL_LINES.
@@ -63,7 +66,8 @@ def expected_merge_output(rev_ranges, ad
ADDITIONAL_LINES is a list of strings to match the other lines of output;
these are basically regular expressions except that backslashes will be
- escaped herein.
+ escaped herein. If ADDITIONAL_LINES is a single string, it is interpreted
+ the same as a list containing that string.
If ELIDES is true, add to the regex an expression representing elision
notification. If TWO_URL is true, tweak the regex to expect the
@@ -72,11 +76,9 @@ def expected_merge_output(rev_ranges, ad
TARGET is the local path to the target, as it should appear in
notifications; if None, it is not checked.
- TEXT_CONFLICTS, PROP_CONFLICTS and TREE_CONFLICTS specify the number of
- each kind of conflict to expect.
-
- RESOLVED contains a list of target paths of which conflicts are resolved
- during merging"""
+ TEXT_CONFLICTS, PROP_CONFLICTS, TREE_CONFLICTS and SKIPPED_PATHS specify
+ the number of each kind of conflict to expect.
+ """
if rev_ranges is None:
lines = [svntest.main.merge_notify_line(None, None, False, foreign)]
@@ -98,34 +100,21 @@ def expected_merge_output(rev_ranges, ad
if (two_url):
lines += ["--- Recording mergeinfo for merge between repository URLs .*\n"]
- if isinstance(additional_lines, list):
- # Address "The Backslash Plague"
- #
- # If ADDITIONAL_LINES are present there are possibly paths in it with
- # multiple components and on Windows these components are separated with
- # '\'. These need to be escaped properly in the regexp for the match to
- # work correctly. See http://aspn.activestate.com/ASPN/docs/ActivePython
- # /2.2/howto/regex/regex.html#SECTION000420000000000000000.
- if sys.platform == 'win32':
- for i in range(0, len(additional_lines)):
- additional_lines[i] = additional_lines[i].replace("\\", "\\\\")
- lines.extend(additional_lines)
- else:
- if sys.platform == 'win32' and additional_lines != None:
- additional_lines = additional_lines.replace("\\", "\\\\")
- lines.append(str(additional_lines))
-
- for rslv in resolved:
- lines.append("Resolved conflicted state of '%s'" % re.escape(rslv))
-
- if text_conflicts or prop_conflicts or tree_conflicts:
- lines.append("Summary of conflicts:\n")
- if text_conflicts:
- lines.append(" Text conflicts: %d\n" % text_conflicts)
- if prop_conflicts:
- lines.append(" Property conflicts: %d\n" % prop_conflicts)
- if tree_conflicts:
- lines.append(" Tree conflicts: %d\n" % tree_conflicts)
+ # Address "The Backslash Plague"
+ #
+ # If ADDITIONAL_LINES are present there are possibly paths in it with
+ # multiple components and on Windows these components are separated with
+ # '\'. These need to be escaped properly in the regexp for the match to
+ # work correctly. See http://aspn.activestate.com/ASPN/docs/ActivePython
+ # /2.2/howto/regex/regex.html#SECTION000420000000000000000.
+ if isinstance(additional_lines, str):
+ additional_lines = [additional_lines]
+ if sys.platform == 'win32':
+ additional_lines = [line.replace("\\", "\\\\") for line in additional_lines]
+ lines += additional_lines
+
+ lines += svntest.main.summary_of_conflicts(text_conflicts, prop_conflicts,
+ tree_conflicts, skipped_paths)
return "|".join(lines)
@@ -1401,6 +1390,13 @@ def merge_in_new_file_and_diff(sbox):
# Finally, run diff.
expected_output = [
+ "Index: " + url_branch_path + "/newfile\n",
+ "===================================================================\n",
+ "--- "+ url_branch_path + "/newfile (revision 0)\n",
+ "+++ "+ url_branch_path + "/newfile (working copy)\n",
+ "@@ -0,0 +1 @@\n",
+ "+newfile\n",
+
"Index: " + url_branch_path + "\n",
"===================================================================\n",
"--- "+ url_branch_path + "\t(revision 2)\n",
@@ -1410,12 +1406,7 @@ def merge_in_new_file_and_diff(sbox):
"___________________________________________________________________\n",
"Added: " + SVN_PROP_MERGEINFO + "\n",
" Merged /A/B/E:r2-3\n",
- "Index: " + url_branch_path + "/newfile\n",
- "===================================================================\n",
- "--- "+ url_branch_path + "/newfile (revision 0)\n",
- "+++ "+ url_branch_path + "/newfile (working copy)\n",
- "@@ -0,0 +1 @@\n",
- "+newfile\n"]
+ ]
svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
'--show-copies-as-adds', branch_path)
@@ -1518,6 +1509,7 @@ def merge_skips_obstructions(sbox):
expected_output = wc.State(C_path, {
'foo' : Item(status='A '),
+ 'Q/bar' : Item(status=' ', treeconflict='A'), # Skipped
})
expected_mergeinfo_output = wc.State(C_path, {
'' : Item(status=' U'),
@@ -1535,7 +1527,6 @@ def merge_skips_obstructions(sbox):
})
expected_skip = wc.State(C_path, {
'Q' : Item(verb='Skipped'),
- 'Q/bar' : Item(verb='Skipped'),
})
svntest.actions.run_and_verify_merge(C_path, '1', '2', F_url, None,
@@ -7023,8 +7014,7 @@ def single_file_replace_style_merge_capa
# Merge the file mu alone to rev1
svntest.actions.run_and_verify_svn(None,
expected_merge_output(None,
- ['D ' + mu_path + '\n',
- 'A ' + mu_path + '\n']),
+ ['R ' + mu_path + '\n']),
[],
'merge',
mu_path + '@2',
@@ -7803,6 +7793,9 @@ def merge_to_sparse_directories(sbox):
'D' : Item(status=' U'),
'mu' : Item(status='U '),
'' : Item(status=' U'),
+ # Shadowed below skips
+ 'D/H/omega' : Item(status=' ', treeconflict='U'),
+ 'B/E/beta' : Item(status=' ', treeconflict='U'),
})
expected_mergeinfo_output = wc.State(immediates_dir, {
'' : Item(status=' U'),
@@ -7828,8 +7821,8 @@ def merge_to_sparse_directories(sbox):
"prop:name" : "propval"}),
})
expected_skip = svntest.wc.State(immediates_dir, {
- 'D/H/omega' : Item(verb="Skipped"),
- 'B/E/beta' : Item(verb="Skipped"),
+ 'D/H' : Item(verb='Skipped missing target'),
+ 'B/E' : Item(verb='Skipped missing target'),
})
svntest.actions.run_and_verify_merge(immediates_dir, '4', '9',
sbox.repo_url + '/A', None,
@@ -7864,6 +7857,9 @@ def merge_to_sparse_directories(sbox):
expected_output = wc.State(files_dir, {
'mu' : Item(status='U '),
'' : Item(status=' U'),
+ # Below the skips
+ 'D/H/omega' : Item(status=' ', treeconflict='U'),
+ 'B/E/beta' : Item(status=' ', treeconflict='U'),
})
expected_mergeinfo_output = wc.State(files_dir, {
'' : Item(status=' U'),
@@ -7882,9 +7878,8 @@ def merge_to_sparse_directories(sbox):
props={SVN_PROP_MERGEINFO : '/A/mu:5-9'}),
})
expected_skip = svntest.wc.State(files_dir, {
- 'D' : Item(verb="Skipped"),
- 'D/H/omega' : Item(verb="Skipped"),
- 'B/E/beta' : Item(verb="Skipped"),
+ 'D' : Item(verb='Skipped missing target'),
+ 'B' : Item(verb='Skipped missing target'),
})
svntest.actions.run_and_verify_merge(files_dir, '4', '9',
sbox.repo_url + '/A', None,
@@ -7912,6 +7907,9 @@ def merge_to_sparse_directories(sbox):
# the one change that affects it directly (the prop add from r9).
expected_output = wc.State(empty_dir, {
'' : Item(status=' U'),
+ # Below the skips
+ 'B/E/beta' : Item(status=' ', treeconflict='U'),
+ 'D/H/omega' : Item(status=' ', treeconflict='U'),
})
expected_mergeinfo_output = wc.State(empty_dir, {
'' : Item(status=' U'),
@@ -7926,10 +7924,9 @@ def merge_to_sparse_directories(sbox):
"prop:name" : "propval"}),
})
expected_skip = svntest.wc.State(empty_dir, {
- 'mu' : Item(verb="Skipped missing target"),
- 'D' : Item(verb="Skipped"),
- 'D/H/omega' : Item(verb="Skipped"),
- 'B/E/beta' : Item(verb="Skipped"),
+ 'mu' : Item(verb='Skipped missing target'),
+ 'D' : Item(verb='Skipped missing target'),
+ 'B' : Item(verb='Skipped missing target'),
})
svntest.actions.run_and_verify_merge(empty_dir, '4', '9',
sbox.repo_url + '/A', None,
@@ -12545,8 +12542,7 @@ def svn_copy(s_rev, path1, path2):
'-r', s_rev, path1, path2)
def svn_merge(rev_range, source, target, lines=None, elides=[],
- text_conflicts=0, prop_conflicts=0, tree_conflicts=0, args=[],
- resolved=[]):
+ text_conflicts=0, prop_conflicts=0, tree_conflicts=0, args=[]):
"""Merge a single change from path SOURCE to path TARGET and verify the
output and that there is no error. (The changes made are not verified.)
@@ -12562,9 +12558,7 @@ def svn_merge(rev_range, source, target,
each kind of conflict to expect.
ARGS are additional arguments passed to svn merge.
-
- RESOLVED contains a list of targets of which conflicts are resolved
- during merging"""
+ """
source = local_path(source)
target = local_path(target)
@@ -12585,8 +12579,7 @@ def svn_merge(rev_range, source, target,
elides=elides,
text_conflicts=text_conflicts,
prop_conflicts=prop_conflicts,
- tree_conflicts=tree_conflicts,
- resolved=resolved)
+ tree_conflicts=tree_conflicts)
svntest.actions.run_and_verify_svn(None, exp_out, [],
'merge', rev_arg, source, target, *args)
@@ -13057,6 +13050,8 @@ def merge_target_and_subtrees_need_nonin
None, 1)
#----------------------------------------------------------------------
+# Part of this test is a regression test for issue #3250 "Repeated merging
+# of conflicting properties fails".
@Issue(3250)
def merge_two_edits_to_same_prop(sbox):
"merge two successive edits to the same property"
@@ -13103,12 +13098,21 @@ def merge_two_edits_to_same_prop(sbox):
# some other target within the same merge requiring only a part of the
# revision range.
- # We test issue #3250 here
- # Revert changes to target branch wc
+ # ====================================================================
+
+ # We test issue #3250 here: that is, test that we can make two successive
+ # conflicting changes to the same property on the same node (here a file;
+ # in #3250 it was on a dir).
+ #
+ # ### But we no longer support merging into a node that's already in
+ # conflict, and the 'rev3' merge here has been tweaked to resolve
+ # the conflict, so it no longer tests the original #3250 scenario.
+ #
+ # Revert changes to branch wc
svntest.actions.run_and_verify_svn(None, None, [],
'revert', '--recursive', A_COPY_path)
- # In the target branch, make two successive changes to the same property
+ # In the branch, make two successive changes to the same property
sbox.simple_propset('p', 'new-val-3', 'A_COPY/mu')
sbox.simple_commit('A_COPY/mu')
rev3 = initial_rev + 3
@@ -13116,22 +13120,21 @@ def merge_two_edits_to_same_prop(sbox):
sbox.simple_commit('A_COPY/mu')
rev4 = initial_rev + 4
- # Merge the two changes together to source.
+ # Merge the two changes together to trunk.
svn_merge([rev3, rev4], A_COPY_path, A_path, [
" C %s\n" % mu_path,
], prop_conflicts=1, args=['--allow-mixed-revisions'])
- # Revert changes to source wc, to test next scenario of #3250
+ # Revert changes to trunk wc, to test next scenario of #3250
svntest.actions.run_and_verify_svn(None, None, [],
'revert', '--recursive', A_path)
- # Merge the first change, then the second, to source.
+ # Merge the first change, then the second, to trunk.
svn_merge(rev3, A_COPY_path, A_path, [
- " C %s\n" % mu_path,
- ], prop_conflicts=1,
+ " G %s\n" % mu_path,
+ ],
args=['--allow-mixed-revisions',
- '--accept=working'],
- resolved=[mu_path])
+ '--accept=working'])
svn_merge(rev4, A_COPY_path, A_path, [
" C %s\n" % mu_path,
], prop_conflicts=1, args=['--allow-mixed-revisions'])
@@ -13955,9 +13958,17 @@ def no_self_referential_filtering_on_add
'C' : Item(status='D '),
'C_MOVED' : Item(status='A '),
})
+ # Why is C_MOVED notified as ' G' rather than ' U'? C_MOVED 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 C_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.
expected_mergeinfo_output = wc.State(A_COPY_2_path, {
'' : Item(status=' G'),
- 'C_MOVED' : Item(status=' G', prev_status=' G'),
+ 'C_MOVED' : Item(status=' G'),
})
expected_elision_output = wc.State(A_COPY_2_path, {
})
@@ -13992,6 +14003,7 @@ def no_self_referential_filtering_on_add
'B/E/beta' : Item("New content"),
'B/lambda' : Item("This is the file 'lambda'.\n"),
'B/F' : Item(),
+ # What's up with the mergeinfo
'C_MOVED' : Item(props={SVN_PROP_MERGEINFO : '/A/C_MOVED:10\n' +
'/A_COPY/C:8\n' +
'/A_COPY/C_MOVED:8',
@@ -15134,8 +15146,6 @@ def record_only_merge(sbox):
#----------------------------------------------------------------------
# Test for issue #3514 'svn merge --accept [ base | theirs-full ]
# doesn't work'
-#
-# This test is marked as XFail until issue #3514 is fixed.
@Issue(3514)
def merge_automatic_conflict_resolution(sbox):
"automatic conflict resolutions work with merge"
@@ -15233,7 +15243,7 @@ def merge_automatic_conflict_resolution(
'revert', '--recursive', wc_dir)
# Test --accept mine-conflict and mine-full
- expected_output = wc.State(A_COPY_path, {'D/H/psi' : Item(status='C ')})
+ expected_output = wc.State(A_COPY_path, {'D/H/psi' : Item(status='U ')})
expected_disk.tweak('D/H/psi', contents="BASE.\n")
expected_status.tweak('D/H/psi', status=' ')
svntest.actions.run_and_verify_merge(A_COPY_path, '2', '3',
@@ -15268,7 +15278,7 @@ def merge_automatic_conflict_resolution(
'revert', '--recursive', wc_dir)
# Test --accept theirs-conflict and theirs-full
- expected_output = wc.State(A_COPY_path, {'D/H/psi' : Item(status='C ')})
+ expected_output = wc.State(A_COPY_path, {'D/H/psi' : Item(status='U ')})
expected_disk.tweak('D/H/psi', contents="New content")
expected_status.tweak('D/H/psi', status='M ')
svntest.actions.run_and_verify_merge(A_COPY_path, '2', '3',
@@ -15302,7 +15312,7 @@ def merge_automatic_conflict_resolution(
svntest.actions.run_and_verify_svn(None, None, [],
'revert', '--recursive', wc_dir)
# Test --accept base
- expected_output = wc.State(A_COPY_path, {'D/H/psi' : Item(status='C ')})
+ expected_output = wc.State(A_COPY_path, {'D/H/psi' : Item(status='U ')})
expected_elision_output = wc.State(A_COPY_path, {
})
expected_disk.tweak('D/H/psi', contents="This is the file 'psi'.\n")
@@ -16511,7 +16521,8 @@ def merge_change_to_file_with_executable
beta_path = sbox.ospath('A/B/E/beta')
# Force one of the files to be a binary type
- svntest.actions.run_and_verify_svn(None, None, [],
+ svntest.actions.run_and_verify_svn2(None, None,
+ binary_mime_type_on_text_file_warning, 0,
'propset', 'svn:mime-type',
'application/octet-stream',
alpha_path)
@@ -17487,6 +17498,13 @@ def merge_source_with_replacement(sbox):
'merge', sbox.repo_url + '/A',
A_COPY_path)
+ # Misleading notifications are one thing, incorrect mergeinfo is quite
+ # another.
+ svntest.actions.run_and_verify_svn(None,
+ [A_COPY_path + ' - /A:2-5,7-8\n'],
+ [], 'pg', SVN_PROP_MERGEINFO,
+ '-R', A_COPY_path)
+
#----------------------------------------------------------------------
# Test for issue #4144 'Reverse merge with replace in source applies
# diffs in forward order'.
@@ -17747,8 +17765,8 @@ def merge_with_added_subtrees_with_merge
})
expected_mergeinfo_output = wc.State(A_COPY2_path, {
'' : Item(status=' U'),
- 'C/X/Y' : Item(status=' G'), # Added with explicit mergeinfo so mergeinfo
- }) # describing the merge shows as mer'G'ed.
+ 'C/X/Y' : Item(status=' U'), # Added with explicit mergeinfo
+ })
expected_elision_output = wc.State(A_COPY2_path, {
})
expected_status = wc.State(A_COPY2_path, {
@@ -17902,7 +17920,9 @@ def merge_binary_file_with_keywords(sbox
# make some 'binary' files with keyword expansion enabled
for f in files:
svntest.main.file_append(sbox.ospath(f), "With $Revision: $ keyword.\n")
- sbox.simple_propset('svn:mime-type', 'application/octet-stream', f)
+ svntest.main.run_svn(binary_mime_type_on_text_file_warning,
+ 'propset', 'svn:mime-type',
+ 'application/octet-stream', sbox.ospath(f))
sbox.simple_propset('svn:keywords', 'Revision', f)
sbox.simple_commit()
@@ -18069,10 +18089,11 @@ def merge_target_selection(sbox):
# Merge the file (wrong target)
expected_output = [
- 'Skipped missing target: \'.\'\n',
- 'Summary of conflicts:\n',
- ' Skipped paths: 1\n',
- ]
+ '--- Merging r4 into \'.\':\n',
+ ' C .\n',
+ '--- Recording mergeinfo for merge of r4 into \'.\':\n',
+ ' U .\n',
+ ] + svntest.main.summary_of_conflicts(tree_conflicts=1)
svntest.actions.run_and_verify_svn(None, expected_output, [],
'merge', '^/dir/binary-file', '-c', '4', '.')
@@ -18080,15 +18101,613 @@ def merge_target_selection(sbox):
# Merge the dir (wrong target)
expected_output = [
- 'Skipped \'%s\'\n' % os.path.join('binary-file', 'binary-file'),
+ '--- Merging r4 into \'binary-file\':\n',
+ ' C %s\n' % os.path.join('binary-file'),
'--- Recording mergeinfo for merge of r4 into \'binary-file\':\n',
' U binary-file\n',
- 'Summary of conflicts:\n',
- ' Skipped paths: 1\n',
- ]
+ ] + svntest.main.summary_of_conflicts(tree_conflicts=1)
svntest.actions.run_and_verify_svn(None, expected_output, [],
'merge', '^/dir', '-c', '4', 'binary-file')
+@Issue(3405)
+def merge_properties_on_adds(sbox):
+ "merged directory properties are added"
+
+ sbox.build()
+
+ sbox.simple_copy('A/D/G', 'G')
+
+ sbox.simple_mkdir('A/D/G/M')
+ sbox.simple_mkdir('A/D/G/M/N')
+ sbox.simple_add_text('QQ', 'A/D/G/file', 'A/D/G/M/file')
+ sbox.simple_propset('key', 'value',
+ 'A/D/G/M', 'A/D/G/file', 'A/D/G/M/N', 'A/D/G/M/file')
+ sbox.simple_commit()
+ sbox.simple_update()
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'merge', '^/A/D/G', sbox.ospath('G'))
+
+ expected_output = svntest.verify.UnorderedOutput([
+ 'Properties on \'%s\':\n' % sbox.ospath('G'),
+ ' svn:mergeinfo\n',
+ 'Properties on \'%s\':\n' % sbox.ospath('G/M'),
+ ' key\n',
+ 'Properties on \'%s\':\n' % sbox.ospath('G/file'),
+ ' key\n',
+ 'Properties on \'%s\':\n' % sbox.ospath('G/M/N'),
+ ' key\n',
+ 'Properties on \'%s\':\n' % sbox.ospath('G/M/file'),
+ ' key\n',
+ ])
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'proplist', '-R', sbox.ospath('G'))
+
+ expected_output = svntest.verify.UnorderedOutput([
+ 'Properties on \'%s\':\n' % sbox.ospath('G/M'),
+ ' key\n',
+ 'Properties on \'%s\':\n' % sbox.ospath('G/file'),
+ ' key\n',
+ 'Properties on \'%s\':\n' % sbox.ospath('G/M/N'),
+ ' key\n',
+ 'Properties on \'%s\':\n' % sbox.ospath('G/M/file'),
+ ' key\n',
+ ])
+
+ # I merged the tree, which should include history but only the files have
+ # the properties stored in PRISTINE. All directories have the properties
+ # as local changes in ACTUAL.
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'proplist', '-R', sbox.ospath('G'),
+ '-r', 'BASE')
+
+ # Note that this is not a regression. This has been the case since 1.0.
+ # ### We just made status, update and merge handle this without users
+ # ### knowing about this limitation.
+
+ # ### My guess is that the base merge support on svn_wc_merge_props()
+ # ### was originally designed to resolve this problem, but I can't
+ # ### find a released version where this was actually implemented.
+
+ # For fun, also check the status: 'svn status' suppresses the M from AM.
+
+ # G = sbox.ospath('G')
+ #
+ # expected_status = wc.State('G', {
+ # '' : Item(status=' M', wc_rev='2'),
+ # 'pi' : Item(status=' ', wc_rev='2'),
+ # 'tau' : Item(status=' ', wc_rev='2'),
+ # 'file' : Item(status='A ', copied='+', wc_rev='-'), # Copied, no changes
+ # 'M' : Item(status='A ', copied='+', wc_rev='-'), # Copied, changes
+ # 'M/file' : Item(status=' ', copied='+', wc_rev='-'), # Copied, no changes
+ # 'M/N' : Item(status=' M', copied='+', wc_rev='-'), # Local changes
+ # 'rho' : Item(status=' ', wc_rev='2'),
+ # })
+ # svntest.actions.run_and_verify_status(G, expected_status)
+
+
+# ======================================================================
+# Functions for parsing mergeinfo
+
+def parse_changes_list(changes_string):
+ """Parse a string containing a list of revision numbers in the form
+ of the '--change' command-line argument (e.g. '1,3,-5,7-10').
+ Return a list of elements of the form [[1], [3], [-5], [7,10]].
+ """
+ rev_ranges = []
+ for rr in changes_string.split(','):
+ if '-' in rr[1:]:
+ revs = rr.split('-')
+ rev_ranges.append([int(revs[0]), int(revs[1])])
+ else:
+ rev_ranges.append([int(rr)])
+ return rev_ranges
+
+def parse_rev_args(arg_list):
+ """Return a list of [rX:rY] or [rZ] elements representing ARG_LIST
+ whose elements are strings in the form '-rX:Y' or '-cZ,X-Y,...'.
+ """
+ rev_ranges = []
+ for arg in arg_list:
+ kind = arg[:2]
+ val = arg[2:]
+ if kind == '-r':
+ if ':' in val:
+ revs = map(int, val.split(':'))
+ if revs[0] < revs[1]:
+ rev_ranges.append([revs[0] + 1, revs[1]])
+ else:
+ rev_ranges.append([revs[0], revs[1] + 1])
+ else:
+ rev_ranges.append([int(val)])
+ elif kind == '-c':
+ rev_ranges.extend(parse_changes_list(val))
+ else:
+ raise ValueError("revision arg '" + arg + "' in '" + arg_list +
+ "' does not start with -r or -c")
+ return rev_ranges
+
+class RangeList(list):
+ """Represents of a list of revision ranges, as a list of one- or
+ two-element lists, each of the form [X] meaning "--revision (X-1):X"
+ or [X,Y] meaning "--revision (X-1):Y".
+ """
+ def __init__(self, arg):
+ """
+ """
+ self.as_given = arg
+ if isinstance(arg, str):
+ list.__init__(self, parse_changes_list(arg))
+ elif isinstance(arg, list):
+ list.__init__(self, parse_rev_args(arg))
+ else:
+ raise ValueError("RangeList needs a string or a list, not '" + str(arg) + "'")
+
+def expected_merge_output2(tgt_ospath,
+ recorded_ranges,
+ merged_ranges=None,
+ prop_conflicts=0):
+ """Return an ExpectedOutput instance corresponding to the expected
+ output of a merge into TGT_OSPATH, with one 'recording
+ mergeinfo...' notification per specified revision range in
+ RECORDED_RANGES and one 'merging...' notification per revision
+ range in MERGED_RANGES.
+
+ RECORDED_RANGES is a mergeinfo-string or a RangeList.
+
+ MERGED_RANGES is a list of mergeinfo-strings or a list of
+ RangeLists. If None, it means [[r] for r in RECORDED_RANGES].
+ """
+ # Convert RECORDED_RANGES to a RangeList.
+ if isinstance(recorded_ranges, str):
+ recorded_ranges = RangeList(recorded_ranges)
+ # Convert MERGED_RANGES to a list of RangeLists.
+ if merged_ranges is None:
+ merged_ranges = [[r] for r in recorded_ranges]
+ elif len(merged_ranges) > 0 and isinstance(merged_ranges[0], str):
+ # List of mergeinfo-strings => list of rangelists
+ merged_ranges = [RangeList(r) for r in merged_ranges]
+
+ status_letters_re = prop_conflicts and ' [UC]' or ' U'
+ status_letters_mi = ' [UG]'
+ lines = []
+ for i, rr in enumerate(recorded_ranges):
+ # Merging ...
+ for sr in merged_ranges[i]:
+ revstart = sr[0]
+ revend = len(sr) > 1 and sr[1] or None
+ lines += [svntest.main.merge_notify_line(revstart, revend,
+ target=tgt_ospath)]
+ lines += [status_letters_re + ' ' + re.escape(tgt_ospath) + '\n']
+ # Recording mergeinfo ...
+ revstart = rr[0]
+ revend = len(rr) > 1 and rr[1] or None
+ lines += [svntest.main.mergeinfo_notify_line(revstart, revend,
+ target=tgt_ospath)]
+ lines += [status_letters_mi + ' ' + re.escape(tgt_ospath) + '\n']
+
+ # Summary of conflicts
+ lines += svntest.main.summary_of_conflicts(prop_conflicts=prop_conflicts)
+
+ return RegexListOutput(lines)
+
+def expected_out_and_err(tgt_ospath,
+ recorded_ranges,
+ merged_ranges=None,
+ prop_conflicts=0,
+ expect_error=True):
+ """Return a tuple (expected_out, expected_err) giving the expected
+ output and expected error output for a merge into TGT_OSPATH. See
+ expected_merge_output2() for details of RECORDED_RANGES and
+ MERGED_RANGES and PROP_CONFLICTS. EXPECT_ERROR should be true iff
+ we expect the merge to abort with an error about conflicts being
+ raised.
+ """
+ expected_out = expected_merge_output2(tgt_ospath, recorded_ranges,
+ merged_ranges, prop_conflicts)
+ if expect_error:
+ expected_err = RegexListOutput([
+ '^svn: E155015: .* conflicts were produced .* into$',
+ "^'.*" + re.escape(tgt_ospath) + "' --$",
+ '^resolve all conflicts .* remaining$',
+ '^unmerged revisions$'],
+ match_all=False)
+ else:
+ expected_err = []
+
+ return expected_out, expected_err
+
+def check_mergeinfo(expected_mergeinfo, tgt_ospath):
+ """Read the mergeinfo on TGT_OSPATH; verify that it matches
+ EXPECTED_MERGEINFO (list of lines).
+ """
+ svntest.actions.run_and_verify_svn(
+ None, expected_mergeinfo, [], 'pg', SVN_PROP_MERGEINFO, tgt_ospath)
+
+def simple_merge(src_path, tgt_ospath, rev_args):
+ """Merge from ^/SRC_PATH to TGT_OSPATH using revision arguments REV_ARGS
+ (list of '-r...' or '-c...' strings); expect a single-target merge
+ with no conflicts or errors.
+ """
+ rev_ranges = RangeList(rev_args)
+
+ expected_out = expected_merge_output(rev_ranges,
+ [' U ' + tgt_ospath + '\n',
+ ' [UG] ' + tgt_ospath + '\n'],
+ target=tgt_ospath)
+ src_url = '^/' + src_path
+ svntest.actions.run_and_verify_svn(
+ None, expected_out, [],
+ 'merge', src_url, tgt_ospath, '--accept', 'postpone', *rev_args)
+
+@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'
+ dir = 'B'
+ trunk_file = 'A/mu'
+ trunk_dir = 'A/B'
+
+ # r2: initial state
+ for rev in range(4, 11):
+ sbox.simple_propset('prop-' + str(rev), 'Old pval ' + str(rev),
+ trunk_file, trunk_dir)
+ sbox.simple_commit()
+
+ # r3: branch
+ sbox.simple_copy(trunk, branch)
+ sbox.simple_commit()
+
+ zero_rev = 3
+
+ def edit_file_or_dir(path, rev, val):
+ """Make a local edit to the file at PATH."""
+ sbox.simple_propset('prop-' + str(rev), val + ' pval ' + str(rev), path)
+
+ # r4 through r10: simple edits
+ for rev in range(4, 11):
+ edit_file_or_dir(trunk_file, rev, 'Edited')
+ edit_file_or_dir(trunk_dir, rev, 'Edited')
+ 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()
+ sbox.simple_update()
+
+ def revert_branch():
+ svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R',
+ sbox.ospath(branch))
+
+ def try_merge(relpath, conflict_rev, rev_args,
+ expected_out_err, expected_mi):
+ """Revert RELPATH in the branch; make a change that will conflict
+ with CONFLICT_REV if not None; merge RELPATH in the trunk
+ to RELPATH in the branch using revision arguments REV_ARGS (list of
+ '-r...' or '-c...' strings).
+
+ EXPECTED_OUT_ERR_MI is a tuple: (expected_out, expected_err,
+ expected_mi). EXPECTED_OUT and EXPECTED_ERR are instances of
+ ExpectedOutput.
+
+ Expect to find mergeinfo EXPECTED_MI if not None. EXPECTED_MI is
+ a single mergeinfo-string.
+ """
+ src_path = trunk + '/' + relpath
+ tgt_path = branch + '/' + relpath
+ tgt_ospath = sbox.ospath(tgt_path)
+
+ expected_out, expected_err = expected_out_err
+
+ revert_branch()
+
+ # Arrange for the merge to conflict at CONFLICT_REV.
+ if conflict_rev:
+ edit_file_or_dir(tgt_path, conflict_rev, 'Conflict')
+
+ src_url = '^/' + src_path
+ svntest.actions.run_and_verify_svn(
+ None, expected_out, expected_err,
+ 'merge', src_url, tgt_ospath, '--accept', 'postpone',
+ *rev_args)
+
+ if expected_mi is not None:
+ expected_mergeinfo = ['/' + src_path + ':' + expected_mi + '\n']
+ check_mergeinfo(expected_mergeinfo, tgt_ospath)
+
+ # 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.
+
+ for target in [file, dir]:
+
+ tgt_ospath = sbox.ospath(branch + '/' + target)
+
+ # 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.
+ expect = expected_out_and_err(tgt_ospath,
+ '3-4', ['3-4'],
+ prop_conflicts=1)
+ try_merge(target, 4, [], expect, '3-5,9')
+
+ # Try a multiple-range merge that raises a conflict in the
+ # first sub-range in the first specified range;
+ expect = expected_out_and_err(tgt_ospath,
+ '4', ['4'],
+ prop_conflicts=1)
+ try_merge(target, 4, ['-c4-6,8-10'], expect, '4-5,9')
+ # last sub-range in the first specified range;
+ expect = expected_out_and_err(tgt_ospath,
+ '4-6', ['4,6'],
+ prop_conflicts=1)
+ try_merge(target, 6, ['-c4-6,8-10'], expect, '4-6,9')
+ # first sub-range in the last specified range;
+ expect = expected_out_and_err(tgt_ospath,
+ '4-6,8', ['4,6', '8'],
+ prop_conflicts=1)
+ try_merge(target, 8, ['-c4-6,8-10'], expect, '4-6,8-9')
+ # 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.)
+ expect = expected_out_and_err(tgt_ospath,
+ '4-6,8-10', ['4,6', '8,10'],
+ prop_conflicts=1, expect_error=False)
+ try_merge(target, 10, ['-c4-6,8-10'], expect, '4-6,8-10')
+
+ # Try similar merges but involving ranges in reverse order.
+ expect = expected_out_and_err(tgt_ospath,
+ '8', ['8'],
+ prop_conflicts=1)
+ try_merge(target, 8, ['-c8-10,4-6'], expect, '5,8-9')
+ expect = expected_out_and_err(tgt_ospath,
+ '8-10', ['8,10'],
+ prop_conflicts=1)
+ try_merge(target, 10, ['-c8-10,4-6'], expect, '5,8-10')
+ expect = expected_out_and_err(tgt_ospath,
+ '8-10,4', ['8,10', '4'],
+ prop_conflicts=1)
+ try_merge(target, 4, ['-c8-10,4-6'], expect, '4-5,8-10')
+ expect = expected_out_and_err(tgt_ospath,
+ '8-10,4-6', ['8,10', '4,6'],
+ prop_conflicts=1, expect_error=False)
+ try_merge(target, 6, ['-c8-10,4-6'], expect, '4-6,8-10')
+
+ # Try some reverse merges, with ranges in forward and reverse order.
+ #
+ # Reverse merges start with all source changes merged except 5 and 9.
+ revert_branch()
+ simple_merge(trunk + '/' + target, sbox.ospath(branch + '/' + target),
+ ['-c-5,-9,4,6-8,10'])
+ sbox.simple_commit()
+ sbox.simple_update()
+
+ expect = expected_out_and_err(tgt_ospath,
+ '6-4,10-8', ['-6,-4', '-10,-8'],
+ expect_error=False)
+ try_merge(target, None, ['-r6:3', '-r10:7'], expect, '7')
+ expect = expected_out_and_err(tgt_ospath,
+ '-6', ['-6'],
+ prop_conflicts=1)
+ try_merge(target, 6, ['-r6:3', '-r10:7'], expect, '4,7-8,10')
+ expect = expected_out_and_err(tgt_ospath,
+ '6-4', ['-6,-4'],
+ prop_conflicts=1)
+ try_merge(target, 4, ['-r6:3', '-r10:7'], expect, '7-8,10')
+ expect = expected_out_and_err(tgt_ospath,
+ '6-4,-10', ['-6,-4', '-10'],
+ prop_conflicts=1)
+ try_merge(target, 10, ['-r6:3', '-r10:7'], expect, '7-8')
+ expect = expected_out_and_err(tgt_ospath,
+ '6-4,10-8', ['-6,-4', '-10,-8'],
+ prop_conflicts=1, expect_error=False)
+ try_merge(target, 8, ['-r6:3', '-r10:7'], expect, '7')
+
+@SkipUnless(server_has_mergeinfo)
+@Issue(4310)
+# Test for issue #4310 "each editor drive gets its own notification
+# during 'svn merge'"
+def multiple_editor_drive_merge_notifications(sbox):
+ "each editor drive gets its own notification"
+
+ sbox.build()
+
+ iota_branch_path = sbox.ospath('iota-copy')
+ C_branch_path = sbox.ospath('branch')
+
+ # Branch a file and a directory:
+
+ # r2
+ sbox.simple_copy('iota', 'iota-copy')
+ sbox.simple_commit()
+
+ # r3
+ sbox.simple_copy('A/C', 'branch')
+ sbox.simple_commit()
+
+ # r4-8 - Set five non-conflicting properties on the branch parents.
+ for i in range(0,5):
+ sbox.simple_propset('foo' + str(i) , 'bar', 'iota')
+ sbox.simple_propset('foo' + str(i) , 'bar', 'A/C')
+ sbox.simple_commit()
+
+ # Cherry pick merge r5 and r6 to each branch and commit.
+ svntest.actions.run_and_verify_svn(None, None, [], 'merge', '^/iota',
+ '-c', '5,7', iota_branch_path)
+ svntest.actions.run_and_verify_svn(None, None, [], 'merge', '^/A/C',
+ '-c', '5,7', C_branch_path)
+ sbox.simple_commit()
+
+ # Now auto merge all eligible revisions to each branch.
+ # First the directory target:
+ #
+ # TODO: We don't use run_and_verify_merge here because it has limitations
+ # re checking the merge notification headers -- which need to be improved
+ # at some point.
+ svntest.actions.run_and_verify_svn(
+ None,
+ ["--- Merging r2 through r4 into '" + C_branch_path + "':\n",
+ " U " + C_branch_path + "\n",
+ "--- Merging r6 into '" + C_branch_path + "':\n",
+ " U " + C_branch_path + "\n",
+ "--- Merging r8 through r9 into '" + C_branch_path + "':\n",
+ " U " + C_branch_path + "\n",
+ "--- Recording mergeinfo for merge of r2 through r9 into '" +
+ C_branch_path + "':\n",
+ " U " + C_branch_path + "\n"],
+ [], 'merge', sbox.repo_url + '/A/C', C_branch_path)
+
+ # Then the file target:
+ # Previously this failed because only the first range notification was
+ # printed:
+ #
+ # >svn merge ^/iota iota-copy
+ # --- Merging r2 through r4 into 'iota-copy':
+ # U iota-copy
+ # U iota-copy
+ # U iota-copy
+ # --- Recording mergeinfo for merge of r2 through r9 into 'iota-copy':
+ # U iota-copy
+ #
+ # This is what we expect:
+ #
+ # --- Merging r2 through r4 into 'iota-copy':
+ # U iota-copy
+ # --- Merging r6 into 'iota-copy': <-- 2nd editor drive
+ # U iota-copy
+ # --- Merging r8 through r9 into 'iota-copy': <-- 3rd editor drive
+ # U iota-copy
+ # --- Recording mergeinfo for merge of r2 through r9 into 'iota-copy':
+ # U iota-copy
+ svntest.actions.run_and_verify_svn(
+ None,
+ ["--- Merging r2 through r4 into '" + iota_branch_path + "':\n",
+ " U " + iota_branch_path + "\n",
+ "--- Merging r6 into '" + iota_branch_path + "':\n",
+ " U " + iota_branch_path + "\n",
+ "--- Merging r8 through r9 into '" + iota_branch_path + "':\n",
+ " U " + iota_branch_path + "\n",
+ "--- Recording mergeinfo for merge of r2 through r9 into '" +
+ iota_branch_path + "':\n",
+ " U " + iota_branch_path + "\n"],
+ [], 'merge', sbox.repo_url + '/iota', iota_branch_path)
+
+#----------------------------------------------------------------------
+@SkipUnless(server_has_mergeinfo)
+@Issue(4317)
+# Test for issue #4317 "redundant notifications in single editor drive merge".
+def single_editor_drive_merge_notifications(sbox):
+ "single editor drive merge notifications"
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ A_copy_path = sbox.ospath('A_COPY')
+ D_copy_path = sbox.ospath('A_COPY/D')
+ psi_copy_path = sbox.ospath('A_COPY/D/H/psi')
+ omega_copy_path = sbox.ospath('A_COPY/D/H/omega')
+ beta_copy_path = sbox.ospath('A_COPY/B/E/beta')
+
+ # r2 - r6: Copy A to A_COPY and then make some text changes under A.
+ set_up_branch(sbox)
+
+ # r7 - Subtree merge
+ svntest.actions.run_and_verify_svn(None, None, [], 'merge', '^/A/D',
+ '-c4', D_copy_path)
+ sbox.simple_commit()
+ sbox.simple_update()
+
+ # Previously this failed because of redundant merge notifications
+ # for r4-7:
+ #
+ # >svn merge ^/A A_COPY
+ # --- Merging r2 through r3 into 'A_COPY\D':
+ # U A_COPY\D\H\psi
+ # --- Merging r5 through r7 into 'A_COPY\D':
+ # U A_COPY\D\H\omega
+ # --- Merging r4 through r7 into 'A_COPY':
+ # U A_COPY\B\E\beta
+ # --- Recording mergeinfo for merge of r2 through r7 into 'A_COPY':
+ # U A_COPY
+ # --- Recording mergeinfo for merge of r2 through r7 into 'A_COPY\D':
+ # U A_COPY\D
+ # --- Eliding mergeinfo from 'A_COPY\D':
+ # U A_COPY\D
+ #
+ # The order of 'beta' and 'omega' can vary, so use UnorderedOutput. This
+ # raises the possibility that the test could spuriously pass if the 'U'pdate
+ # notifications aren't grouped with the correct headers, but that's not what
+ # is being tested here.
+ expected_output = svntest.verify.UnorderedOutput(
+ ["--- Merging r2 through r3 into '" + A_copy_path + "':\n",
+ "U " + psi_copy_path + "\n",
+ "--- Merging r4 through r7 into '" + A_copy_path + "':\n",
+ "U " + omega_copy_path + "\n",
+ "U " + beta_copy_path + "\n",
+ "--- Recording mergeinfo for merge of r2 through r7 into '" +
+ A_copy_path + "':\n",
+ " U " + A_copy_path + "\n",
+ "--- Recording mergeinfo for merge of r2 through r7 into '" +
+ D_copy_path + "':\n",
+ " U " + D_copy_path + "\n",
+ "--- Eliding mergeinfo from '" + D_copy_path + "':\n",
+ " U " + D_copy_path + "\n"])
+ svntest.actions.run_and_verify_svn(None, expected_output, [], 'merge',
+ sbox.repo_url + '/A', A_copy_path)
+
+ # r8 and r9 - Commit and do reverse subtree merge.
+ sbox.simple_commit()
+ sbox.simple_update()
+ svntest.actions.run_and_verify_svn(None, None, [], 'merge', '^/A/D',
+ '-c-4', D_copy_path)
+ sbox.simple_commit()
+
+ # Now try a reverse merge. There should only be one notification for
+ # r7-5:
+ sbox.simple_update()
+ expected_output = svntest.verify.UnorderedOutput(
+ ["--- Reverse-merging r7 through r5 into '" + A_copy_path + "':\n",
+ "U " + beta_copy_path + "\n",
+ "U " + omega_copy_path + "\n",
+ "--- Reverse-merging r4 through r3 into '" + A_copy_path + "':\n",
+ "U " + psi_copy_path + "\n",
+ "--- Recording mergeinfo for reverse merge of r7 through r3 into '" +
+ A_copy_path + "':\n",
+ " U " + A_copy_path + "\n",
+ "--- Recording mergeinfo for reverse merge of r7 through r3 into '" +
+ D_copy_path + "':\n",
+ " U " + D_copy_path + "\n",
+ "--- Eliding mergeinfo from '" + D_copy_path + "':\n",
+ " U " + D_copy_path + "\n"])
+ svntest.actions.run_and_verify_svn(None, expected_output, [], 'merge',
+ '-r9:2', sbox.repo_url + '/A',
+ A_copy_path)
########################################################################
# Run the tests
@@ -18229,6 +18848,10 @@ test_list = [ None,
merge_binary_file_with_keywords,
merge_conflict_when_keywords_removed,
merge_target_selection,
+ merge_properties_on_adds,
+ conflict_aborted_mergeinfo_described_partial_merge,
+ multiple_editor_drive_merge_notifications,
+ single_editor_drive_merge_notifications,
]
if __name__ == '__main__':
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/merge_tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/merge_tree_conflict_tests.py?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/merge_tree_conflict_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/merge_tree_conflict_tests.py Sat Feb 23 01:25:38 2013
@@ -30,7 +30,7 @@ import time
# Our testing module
import svntest
-from svntest import main, wc, verify, actions
+from svntest import main, wc, verify, actions, deeptrees
# (abbreviation)
Item = wc.StateItem
@@ -789,21 +789,21 @@ def tree_conflicts_and_obstructions(sbox
# parent directory.
# convenience definitions
-leaf_edit = svntest.actions.deep_trees_leaf_edit
-tree_del = svntest.actions.deep_trees_tree_del
-leaf_del = svntest.actions.deep_trees_leaf_del
-
-disk_after_leaf_edit = svntest.actions.deep_trees_after_leaf_edit
-disk_after_leaf_del = svntest.actions.deep_trees_after_leaf_del
-disk_after_tree_del = svntest.actions.deep_trees_after_tree_del
-disk_after_leaf_del_no_ci = svntest.actions.deep_trees_after_leaf_del_no_ci
-disk_after_tree_del_no_ci = svntest.actions.deep_trees_after_tree_del_no_ci
+leaf_edit = svntest.deeptrees.deep_trees_leaf_edit
+tree_del = svntest.deeptrees.deep_trees_tree_del
+leaf_del = svntest.deeptrees.deep_trees_leaf_del
+
+disk_after_leaf_edit = svntest.deeptrees.deep_trees_after_leaf_edit
+disk_after_leaf_del = svntest.deeptrees.deep_trees_after_leaf_del
+disk_after_tree_del = svntest.deeptrees.deep_trees_after_tree_del
+disk_after_leaf_del_no_ci = svntest.deeptrees.deep_trees_after_leaf_del_no_ci
+disk_after_tree_del_no_ci = svntest.deeptrees.deep_trees_after_tree_del_no_ci
-deep_trees_conflict_output = svntest.actions.deep_trees_conflict_output
+deep_trees_conflict_output = svntest.deeptrees.deep_trees_conflict_output
j = os.path.join
-DeepTreesTestCase = svntest.actions.DeepTreesTestCase
+DeepTreesTestCase = svntest.deeptrees.DeepTreesTestCase
alpha_beta_gamma = svntest.wc.State('', {
'F/alpha' : Item(),
@@ -840,7 +840,7 @@ def tree_conflicts_on_merge_local_ci_4_1
expected_skip = svntest.wc.State('', { })
- svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox,
+ svntest.deeptrees.deep_trees_run_tests_scheme_for_merge(sbox,
[ DeepTreesTestCase("local_tree_del_incoming_leaf_edit",
tree_del,
leaf_edit,
@@ -878,7 +878,7 @@ def tree_conflicts_on_merge_local_ci_4_2
expected_skip = svntest.wc.State('', {
})
- svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox,
+ svntest.deeptrees.deep_trees_run_tests_scheme_for_merge(sbox,
[ DeepTreesTestCase("local_tree_del_incoming_leaf_del",
tree_del,
leaf_del,
@@ -888,7 +888,6 @@ def tree_conflicts_on_merge_local_ci_4_2
expected_skip) ], True)
#----------------------------------------------------------------------
-@XFail()
@Issue(2282)
def tree_conflicts_on_merge_local_ci_5_1(sbox):
"tree conflicts 5.1: leaf edit, tree del"
@@ -906,23 +905,23 @@ def tree_conflicts_on_merge_local_ci_5_1
'' : Item(status=' M', wc_rev='3'),
'D' : Item(status=' ', wc_rev='3'),
'D/D1' : Item(status=' ', treeconflict='C', wc_rev='4'),
- 'D/D1/delta' : Item(status='D ', wc_rev='4'),
+ 'D/D1/delta' : Item(status=' ', wc_rev='4'),
'DD' : Item(status=' ', wc_rev='3'),
- 'DD/D1' : Item(status=' ', treeconflict='C', wc_rev='4'),
- 'DD/D1/D2' : Item(status='D ', wc_rev='3'),
- 'DD/D1/D2/epsilon' : Item(status='D ', wc_rev='4'),
+ 'DD/D1' : Item(status=' ', treeconflict='C', wc_rev='3'),
+ 'DD/D1/D2' : Item(status=' ', wc_rev='4'),
+ 'DD/D1/D2/epsilon' : Item(status=' ', wc_rev='4'),
'DDD' : Item(status=' ', wc_rev='3'),
- 'DDD/D1' : Item(status=' ', treeconflict='C', wc_rev='4'),
- 'DDD/D1/D2' : Item(status='D ', wc_rev='3'),
- 'DDD/D1/D2/D3' : Item(status='D ', wc_rev='3'),
- 'DDD/D1/D2/D3/zeta' : Item(status='D ', wc_rev='4'),
+ 'DDD/D1' : Item(status=' ', treeconflict='C', wc_rev='3'),
+ 'DDD/D1/D2' : Item(status=' ', wc_rev='3'),
+ 'DDD/D1/D2/D3' : Item(status=' ', wc_rev='4'),
+ 'DDD/D1/D2/D3/zeta' : Item(status=' ', wc_rev='4'),
'DDF' : Item(status=' ', wc_rev='3'),
- 'DDF/D1' : Item(status=' ', treeconflict='C', wc_rev='4'),
- 'DDF/D1/D2' : Item(status='D ', wc_rev='3'),
- 'DDF/D1/D2/gamma' : Item(status='D ', wc_rev='4'),
+ 'DDF/D1' : Item(status=' ', treeconflict='C', wc_rev='3'),
+ 'DDF/D1/D2' : Item(status=' ', wc_rev='3'),
+ 'DDF/D1/D2/gamma' : Item(status=' ', wc_rev='4'),
'DF' : Item(status=' ', wc_rev='3'),
- 'DF/D1' : Item(status=' ', treeconflict='C', wc_rev='4'),
- 'DF/D1/beta' : Item(status='D ', wc_rev='4'),
+ 'DF/D1' : Item(status=' ', treeconflict='C', wc_rev='3'),
+ 'DF/D1/beta' : Item(status=' ', wc_rev='4'),
'F' : Item(status=' ', wc_rev='3'),
'F/alpha' : Item(status=' ', treeconflict='C', wc_rev='4'),
@@ -931,7 +930,7 @@ def tree_conflicts_on_merge_local_ci_5_1
expected_skip = svntest.wc.State('', {
})
- svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox,
+ svntest.deeptrees.deep_trees_run_tests_scheme_for_merge(sbox,
[ DeepTreesTestCase("local_leaf_edit_incoming_tree_del",
leaf_edit,
tree_del,
@@ -941,7 +940,6 @@ def tree_conflicts_on_merge_local_ci_5_1
expected_skip) ], True)
#----------------------------------------------------------------------
-@XFail()
@Issue(2282)
def tree_conflicts_on_merge_local_ci_5_2(sbox):
"tree conflicts 5.2: leaf del, tree del"
@@ -957,15 +955,15 @@ def tree_conflicts_on_merge_local_ci_5_2
'D' : Item(status=' ', wc_rev='3'),
'F' : Item(status=' ', wc_rev='3'),
'DD' : Item(status=' ', wc_rev='3'),
- 'DD/D1' : Item(status='! ', treeconflict='C'),
+ 'DD/D1' : Item(status=' ', wc_rev='3', treeconflict='C'),
'DF' : Item(status=' ', wc_rev='3'),
- 'DF/D1' : Item(status='! ', treeconflict='C'),
+ 'DF/D1' : Item(status=' ', wc_rev='3', treeconflict='C'),
'DDD' : Item(status=' ', wc_rev='3'),
- 'DDD/D1' : Item(status='! ', treeconflict='C'),
- 'DDD/D1/D2' : Item(status='D ', wc_rev='3'),
+ 'DDD/D1' : Item(status=' ', wc_rev='3', treeconflict='C'),
+ 'DDD/D1/D2' : Item(status=' ', wc_rev='3'),
'DDF' : Item(status=' ', wc_rev='3'),
- 'DDF/D1' : Item(status='! ', treeconflict='C'),
- 'DDF/D1/D2' : Item(status='D ', wc_rev='3'),
+ 'DDF/D1' : Item(status=' ', wc_rev='3', treeconflict='C'),
+ 'DDF/D1/D2' : Item(status=' ', wc_rev='3'),
'D/D1' : Item(status='! ', treeconflict='C'),
'F/alpha' : Item(status='! ', treeconflict='C'),
})
@@ -973,7 +971,7 @@ def tree_conflicts_on_merge_local_ci_5_2
expected_skip = svntest.wc.State('', {
})
- svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox,
+ svntest.deeptrees.deep_trees_run_tests_scheme_for_merge(sbox,
[ DeepTreesTestCase("local_leaf_del_incoming_tree_del",
leaf_del,
tree_del,
@@ -1012,7 +1010,7 @@ def tree_conflicts_on_merge_local_ci_6(s
expected_skip = svntest.wc.State('', {
})
- svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox,
+ svntest.deeptrees.deep_trees_run_tests_scheme_for_merge(sbox,
[ DeepTreesTestCase("local_tree_del_incoming_tree_del",
tree_del,
tree_del,
@@ -1059,7 +1057,7 @@ def tree_conflicts_on_merge_no_local_ci_
expected_skip = svntest.wc.State('', {
})
- svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox,
+ svntest.deeptrees.deep_trees_run_tests_scheme_for_merge(sbox,
[ DeepTreesTestCase(
"local_tree_del_incoming_leaf_edit",
tree_del,
@@ -1107,7 +1105,7 @@ def tree_conflicts_on_merge_no_local_ci_
expected_skip = svntest.wc.State('', {
})
- svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox,
+ svntest.deeptrees.deep_trees_run_tests_scheme_for_merge(sbox,
[ DeepTreesTestCase(
"local_tree_del_incoming_leaf_del",
tree_del,
@@ -1158,7 +1156,7 @@ def tree_conflicts_on_merge_no_local_ci_
expected_skip = svntest.wc.State('', {
})
- svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox,
+ svntest.deeptrees.deep_trees_run_tests_scheme_for_merge(sbox,
[ DeepTreesTestCase(
"local_leaf_edit_incoming_tree_del",
leaf_edit,
@@ -1170,7 +1168,6 @@ def tree_conflicts_on_merge_no_local_ci_
) ], False)
#----------------------------------------------------------------------
-@XFail()
@Issue(2282)
def tree_conflicts_on_merge_no_local_ci_5_2(sbox):
"tree conflicts 5.2: leaf del (no ci), tree del"
@@ -1188,25 +1185,25 @@ def tree_conflicts_on_merge_no_local_ci_
'F' : Item(status=' ', wc_rev='3'),
'F/alpha' : Item(status='D ', wc_rev='3', treeconflict='C'),
'DD' : Item(status=' ', wc_rev='3'),
- 'DD/D1' : Item(status='D ', wc_rev='3', treeconflict='C'),
+ 'DD/D1' : Item(status=' ', wc_rev='3', treeconflict='C'),
'DD/D1/D2' : Item(status='D ', wc_rev='3'),
'DF' : Item(status=' ', wc_rev='3'),
- 'DF/D1' : Item(status='D ', wc_rev='3', treeconflict='C'),
+ 'DF/D1' : Item(status=' ', wc_rev='3', treeconflict='C'),
'DF/D1/beta' : Item(status='D ', wc_rev='3'),
'DDD' : Item(status=' ', wc_rev='3'),
- 'DDD/D1' : Item(status='D ', wc_rev='3', treeconflict='C'),
- 'DDD/D1/D2' : Item(status='D ', wc_rev='3'),
+ 'DDD/D1' : Item(status=' ', wc_rev='3', treeconflict='C'),
+ 'DDD/D1/D2' : Item(status=' ', wc_rev='3'),
'DDD/D1/D2/D3' : Item(status='D ', wc_rev='3'),
'DDF' : Item(status=' ', wc_rev='3'),
- 'DDF/D1' : Item(status='D ', wc_rev='3', treeconflict='C'),
- 'DDF/D1/D2' : Item(status='D ', wc_rev='3'),
+ 'DDF/D1' : Item(status=' ', wc_rev='3', treeconflict='C'),
+ 'DDF/D1/D2' : Item(status=' ', wc_rev='3'),
'DDF/D1/D2/gamma' : Item(status='D ', wc_rev='3'),
})
expected_skip = svntest.wc.State('', {
})
- svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox,
+ svntest.deeptrees.deep_trees_run_tests_scheme_for_merge(sbox,
[ DeepTreesTestCase(
"local_leaf_del_incoming_tree_del",
leaf_del,
@@ -1255,7 +1252,7 @@ def tree_conflicts_on_merge_no_local_ci_
expected_skip = svntest.wc.State('', {
})
- svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox,
+ svntest.deeptrees.deep_trees_run_tests_scheme_for_merge(sbox,
[ DeepTreesTestCase(
"local_tree_del_incoming_tree_del",
tree_del,
@@ -1284,6 +1281,14 @@ def tree_conflicts_merge_edit_onto_missi
sbox.build()
expected_output = wc.State('', {
+ # Below the skips
+ 'DD/D1/D2' : Item(status=' ', treeconflict='U'),
+ 'DD/D1/D2/epsilon' : Item(status=' ', treeconflict='A'),
+ 'DDD/D1/D2/D3' : Item(status=' ', treeconflict='U'),
+ 'DDD/D1/D2/D3/zeta' : Item(status=' ', treeconflict='A'),
+ 'DDF/D1/D2/gamma' : Item(status=' ', treeconflict='U'),
+ 'D/D1/delta' : Item(status=' ', treeconflict='A'),
+ 'DF/D1/beta' : Item(status=' ', treeconflict='U'),
})
expected_disk = disk_after_tree_del
@@ -1315,22 +1320,20 @@ def tree_conflicts_merge_edit_onto_missi
expected_skip = svntest.wc.State('', {
'F/alpha' : Item(verb='Skipped missing target'),
# Obstruction handling improvements in 1.7 and 1.8 added
- 'DF/D1/beta' : Item(verb='Skipped missing target'),
- 'DDD/D1/D2/D3/zeta' : Item(verb='Skipped'),
- 'DDD/D1/D2/D3' : Item(verb='Skipped missing target'),
- 'DDF/D1/D2/gamma' : Item(verb='Skipped missing target'),
- 'D/D1/delta' : Item(verb='Skipped'),
+ 'DDD/D1' : Item(verb='Skipped missing target'),
+ 'DF/D1' : Item(verb='Skipped missing target'),
+ 'DDF/D1' : Item(verb='Skipped missing target'),
'D/D1' : Item(verb='Skipped missing target'),
- 'DD/D1/D2/epsilon' : Item(verb='Skipped'),
- 'DD/D1/D2' : Item(verb='Skipped missing target'),
- })
+ 'DD/D1' : Item(verb='Skipped missing target'),
+ 'F/alpha' : Item(verb='Skipped missing target'),
+ })
# Currently this test fails because some parts of the merge
# start succeeding.
- svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox,
+ svntest.deeptrees.deep_trees_run_tests_scheme_for_merge(sbox,
[ DeepTreesTestCase(
"local_tree_missing_incoming_leaf_edit",
- svntest.actions.deep_trees_rmtree,
+ svntest.deeptrees.deep_trees_rmtree,
leaf_edit,
expected_output,
expected_disk,
@@ -1356,6 +1359,11 @@ def tree_conflicts_merge_del_onto_missin
sbox.build()
expected_output = wc.State('', {
+ # Below the skips
+ 'DF/D1/beta' : Item(status=' ', treeconflict='D'),
+ 'DDD/D1/D2/D3' : Item(status=' ', treeconflict='D'),
+ 'DD/D1/D2' : Item(status=' ', treeconflict='D'),
+ 'DDF/D1/D2/gamma' : Item(status=' ', treeconflict='D'),
})
expected_disk = disk_after_tree_del
@@ -1388,17 +1396,16 @@ def tree_conflicts_merge_del_onto_missin
'F/alpha' : Item(verb='Skipped missing target'),
'D/D1' : Item(verb='Skipped missing target'),
# Obstruction handling improvements in 1.7 and 1.8 added
- 'D/D1' : Item(verb='Skipped missing target'),
- 'DD/D1/D2' : Item(verb='Skipped missing target'),
- 'DF/D1/beta' : Item(verb='Skipped missing target'),
- 'DDD/D1/D2/D3' : Item(verb='Skipped missing target'),
- 'DDF/D1/D2/gamma' : Item(verb='Skipped missing target'),
- })
+ 'DDD/D1' : Item(verb='Skipped missing target'),
+ 'DD/D1' : Item(verb='Skipped missing target'),
+ 'DDF/D1' : Item(verb='Skipped missing target'),
+ 'DF/D1' : Item(verb='Skipped missing target'),
+ })
- svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox,
+ svntest.deeptrees.deep_trees_run_tests_scheme_for_merge(sbox,
[ DeepTreesTestCase(
"local_tree_missing_incoming_leaf_del",
- svntest.actions.deep_trees_rmtree,
+ svntest.deeptrees.deep_trees_rmtree,
leaf_del,
expected_output,
expected_disk,
@@ -1714,7 +1721,6 @@ def merge_replace_causes_tree_conflict(s
actions.run_and_verify_status(wc_dir, expected_status)
#----------------------------------------------------------------------
-@XFail()
@Issue(3806)
def merge_replace_causes_tree_conflict2(sbox):
"replace vs. delete tree-conflicts"
@@ -1775,13 +1781,18 @@ def merge_replace_causes_tree_conflict2(
'A/D/H', 'A/D/H/chi', 'A/D/H/omega', 'A/D/H/psi',
status='D ')
+ # H is now a file. This hides the status of the descendants.
+ expected_status.remove('A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega')
+
# Merge them one by one to see all the errors.
### A file-with-file replacement onto a deleted file.
# svn merge $URL/A/mu $URL/branch/mu A/mu
expected_stdout = expected_merge_output(None, [
' C ' + A_mu + '\n', # merge
+ 'A ' + A_mu + '\n', # merge
" U " + A + "\n", # mergeinfo
+ " U " + A_mu + "\n", # mergeinfo -> 'RM' status
], target=A, two_url=True, tree_conflicts=1)
actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'merge',
@@ -1793,13 +1804,14 @@ def merge_replace_causes_tree_conflict2(
#
# D C merge_tree_conflict_tests-23\A\mu
# > local delete, incoming replace upon merge
- expected_status.tweak('A/mu', status='R ', wc_rev='-', copied='+',
+ expected_status.tweak('A/mu', status='RM', wc_rev='-', copied='+',
treeconflict='C')
### A dir-with-dir replacement onto a deleted directory.
# svn merge $URL/A/B $URL/branch/B A/B
expected_stdout = expected_merge_output(None, [
' C ' + A_B_E + '\n', # merge
+ 'A ' + A_B_E + '\n', # merge
" U " + A_B + "\n", # mergeinfo
], target=A_B, two_url=True, tree_conflicts=1)
@@ -1819,8 +1831,8 @@ def merge_replace_causes_tree_conflict2(
# svn merge --depth=immediates $URL/A/D $URL/branch/D A/D
expected_stdout = expected_merge_output(None, [
' C ' + A_D_H + '\n', # merge
+ 'A ' + A_D_H + '\n', # merge
" U " + A_D + "\n", # mergeinfo
- " U " + A_D_G + "\n",
], target=A_D, two_url=True, tree_conflicts=1)
actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'merge',
@@ -1839,7 +1851,9 @@ def merge_replace_causes_tree_conflict2(
# svn merge $URL/A/D/G $URL/branch/D/G A/D/G
expected_stdout = expected_merge_output(None, [
' C ' + A_D_G_pi + '\n', # merge
- ], target=A_D_G, elides=[A_D_G_pi, A_D_G], two_url=True, tree_conflicts=1)
+ 'A ' + A_D_G_pi + '\n', # merge
+ " U " + A_D_G + "\n", # mergeinfo
+ ], target=A_D_G, two_url=True, tree_conflicts=1)
actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'merge',
url_A_D_G, url_branch_D_G, A_D_G)
@@ -1858,7 +1872,8 @@ def merge_replace_causes_tree_conflict2(
# Check the tree conflict types:
expected_stdout = '(R.*)|(Summary of conflicts.*)|( Tree conflicts.*)' \
- '|(.*local delete, incoming replace upon merge.*)'
+ '|(.*local delete, incoming replace upon merge.*)' \
+ '|( \>.*)'
tree_conflicted_path = [A_B_E, A_mu, A_D_G_pi, A_D_H]
for path in tree_conflicted_path:
actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'st',
@@ -1868,7 +1883,6 @@ def merge_replace_causes_tree_conflict2(
# Test for issue #4011 'merge of replacement on local delete fails'
@SkipUnless(server_has_mergeinfo)
@Issue(4011)
-@XFail()
def merge_replace_on_del_fails(sbox):
"merge replace on local delete fails"
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/patch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/patch_tests.py?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/patch_tests.py Sat Feb 23 01:25:38 2013
@@ -34,6 +34,7 @@ import tempfile
import textwrap
import zlib
import posixpath
+import filecmp
# Our testing module
import svntest
@@ -265,9 +266,7 @@ def patch_absolute_paths(sbox):
expected_output = [
'U %s\n' % os.path.join('A', 'B', 'E', 'alpha'),
'Skipped missing target: \'%s\'\n' % lambda_path,
- 'Summary of conflicts:\n',
- ' Skipped paths: 1\n'
- ]
+ ] + svntest.main.summary_of_conflicts(skipped_paths=1)
alpha_contents = "This is the file 'alpha'.\nWhoooo whooooo whoooooooo!\n"
@@ -971,10 +970,9 @@ def patch_add_new_dir(sbox):
C_path = sbox.ospath('A/C')
E_path = sbox.ospath('A/B/E')
- svntest.actions.run_and_verify_svn("Deleting C failed", None, [],
- 'rm', C_path)
- svntest.actions.run_and_verify_svn("Deleting E failed", None, [],
- 'rm', E_path)
+
+ svntest.main.safe_rmtree(C_path)
+ svntest.main.safe_rmtree(E_path)
svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
A_B_E_Y_new_path = sbox.ospath('A/B/E/Y/new')
@@ -987,9 +985,7 @@ def patch_add_new_dir(sbox):
'Skipped missing target: \'%s\'\n' % A_B_E_Y_new_path,
'Skipped missing target: \'%s\'\n' % A_C_new_path,
'Skipped missing target: \'%s\'\n' % A_Z_new_path,
- 'Summary of conflicts:\n',
- ' Skipped paths: 3\n',
- ]
+ ] + svntest.main.summary_of_conflicts(skipped_paths=3)
# Create the unversioned obstructing directory
os.mkdir(os.path.dirname(A_Z_new_path))
@@ -1003,13 +999,13 @@ def patch_add_new_dir(sbox):
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
expected_status.add({
- 'X' : Item(status='A ', wc_rev=0),
- 'X/Y' : Item(status='A ', wc_rev=0),
- 'X/Y/new' : Item(status='A ', wc_rev=0),
- 'A/B/E' : Item(status='D ', wc_rev=1),
- 'A/B/E/alpha': Item(status='D ', wc_rev=1),
- 'A/B/E/beta': Item(status='D ', wc_rev=1),
- 'A/C' : Item(status='D ', wc_rev=1),
+ 'X' : Item(status='A ', wc_rev=0),
+ 'X/Y' : Item(status='A ', wc_rev=0),
+ 'X/Y/new' : Item(status='A ', wc_rev=0),
+ 'A/B/E' : Item(status='! ', wc_rev=1),
+ 'A/B/E/alpha': Item(status='! ', wc_rev=1),
+ 'A/B/E/beta' : Item(status='! ', wc_rev=1),
+ 'A/C' : Item(status='! ', wc_rev=1),
})
expected_skip = wc.State(
@@ -1173,9 +1169,7 @@ def patch_reject(sbox):
expected_output = [
'C %s\n' % sbox.ospath('A/D/gamma'),
'> rejected hunk @@ -1,1 +1,1 @@\n',
- 'Summary of conflicts:\n',
- ' Text conflicts: 1\n',
- ]
+ ] + svntest.main.summary_of_conflicts(text_conflicts=1)
expected_disk = svntest.main.greek_state.copy()
expected_disk.tweak('A/D/gamma', contents=gamma_contents)
@@ -2455,9 +2449,7 @@ def patch_same_twice(sbox):
'> hunk @@ -6,6 +6,9 @@ already applied\n',
'> hunk @@ -14,11 +17,8 @@ already applied\n',
'Skipped \'%s\'\n' % beta_path,
- 'Summary of conflicts:\n',
- ' Skipped paths: 1\n',
- ]
+ ] + svntest.main.summary_of_conflicts(skipped_paths=1)
expected_skip = wc.State('', {beta_path : Item(verb='Skipped')})
@@ -2542,9 +2534,7 @@ def patch_dir_properties(sbox):
expected_output = [
' U %s\n' % wc_dir,
' C %s\n' % sbox.ospath('A/B'),
- 'Summary of conflicts:\n',
- ' Property conflicts: 1\n',
- ]
+ ] + svntest.main.summary_of_conflicts(prop_conflicts=1)
expected_disk = svntest.main.greek_state.copy()
expected_disk.add({
@@ -3968,9 +3958,7 @@ def patch_delete_and_skip(sbox):
'D %s\n' % os.path.join('A', 'B', 'E', 'beta'),
'D %s\n' % os.path.join('A', 'B', 'E'),
'Skipped missing target: \'%s\'\n' % skipped_path,
- 'Summary of conflicts:\n',
- ' Skipped paths: 1\n'
- ]
+ ] + svntest.main.summary_of_conflicts(skipped_paths=1)
expected_disk = svntest.main.greek_state.copy()
expected_disk.remove('A/B/E/alpha')
@@ -4401,9 +4389,7 @@ def single_line_mismatch(sbox):
expected_output = [
'C %s\n' % sbox.ospath('test'),
'> rejected hunk @@ -1,1 +1,1 @@\n',
- 'Summary of conflicts:\n',
- ' Text conflicts: 1\n',
- ]
+ ] + svntest.main.summary_of_conflicts(text_conflicts=1)
svntest.actions.run_and_verify_svn(None, expected_output, [],
'patch', patch_file_path, wc_dir)
@@ -4468,6 +4454,168 @@ def patch_empty_file(sbox):
svntest.actions.verify_disk(wc_dir, expected_disk)
+@Issue(3362)
+def patch_apply_no_fuz(sbox):
+ "svn diff created patch should apply without fuz"
+
+ sbox.build(read_only=True)
+ wc_dir = sbox.wc_dir
+
+ svntest.main.file_write(sbox.ospath('test.txt'), '\n'.join([
+ "line_1",
+ "line_2",
+ "line_3",
+ "line_4",
+ "line_5",
+ "line_6",
+ "line_7",
+ "line_8",
+ "line_9",
+ "line_10",
+ "line_11",
+ "line_12",
+ "line_13",
+ "line_14",
+ "line_15",
+ "line_16",
+ "line_17",
+ "line_18",
+ "line_19",
+ "line_20",
+ "line_21",
+ "line_22",
+ "line_23",
+ "line_24",
+ "line_25",
+ "line_26",
+ "line_27",
+ "line_28",
+ "line_29",
+ "line_30",
+ ""
+ ]))
+ svntest.main.file_write(sbox.ospath('test_v2.txt'), '\n'.join([
+ "line_1a",
+ "line_1b",
+ "line_1c",
+ "line_1",
+ "line_2",
+ "line_3",
+ "line_4",
+ "line_5a",
+ "line_5b",
+ "line_5c",
+ "line_6",
+ "line_7",
+ "line_8",
+ "line_9",
+ "line_10",
+ "line_11a",
+ "line_11b",
+ "line_11c",
+ "line_12",
+ "line_13",
+ "line_14",
+ "line_15",
+ "line_16",
+ "line_17",
+ "line_18",
+ "line_19a",
+ "line_19b",
+ "line_19c",
+ "line_20",
+ "line_21",
+ "line_22",
+ "line_23",
+ "line_24",
+ "line_25",
+ "line_26",
+ "line_27a",
+ "line_27b",
+ "line_27c",
+ "line_28",
+ "line_29",
+ "line_30",
+ ""
+ ]))
+
+ sbox.simple_add('test.txt', 'test_v2.txt')
+
+ result, out_text, err_text = svntest.main.run_svn(None,
+ 'diff',
+ '--old',
+ sbox.ospath('test.txt'),
+ '--new',
+ sbox.ospath('test_v2.txt'))
+
+ patch_path = sbox.ospath('patch.diff')
+ svntest.main.file_write(patch_path, ''.join(out_text))
+
+ expected_output = [
+ 'G %s\n' % sbox.ospath('test.txt'),
+ ]
+
+ # Current result: lf.txt patched ok, new created, empty succeeds with offset.
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'patch', patch_path, wc_dir)
+
+ if not filecmp.cmp(sbox.ospath('test.txt'), sbox.ospath('test_v2.txt')):
+ raise svntest.Failure("Patch result not identical")
+
+@XFail()
+def patch_lacking_trailing_eol_on_context(sbox):
+ "patch file lacking trailing eol on context"
+
+ # Apply a patch where a hunk (the only hunk, in this case) ends with a
+ # context line that has no EOL, where this context line is going to
+ # match an existing line that *does* have an EOL.
+ #
+ # Around trunk@1443700, 'svn patch' wrongly removed an EOL from the
+ # target file at that position.
+
+ sbox.build(read_only = True)
+ wc_dir = sbox.wc_dir
+
+ patch_file_path = make_patch_path(sbox)
+
+ # Prepare
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_disk = svntest.main.greek_state.copy()
+
+ # Prepare the patch
+ unidiff_patch = [
+ "Index: iota\n",
+ "===================================================================\n",
+ "--- iota\t(revision 1)\n",
+ "+++ iota\t(working copy)\n",
+ # TODO: -1 +1
+ "@@ -1 +1,2 @@\n",
+ "+Some more bytes\n",
+ " This is the file 'iota'.", # No trailing \n on this context line!
+ ]
+ svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+ iota_contents = "This is the file 'iota'.\n"
+
+ expected_output = [ 'U %s\n' % sbox.ospath('iota') ]
+
+ # Test where the no-EOL context line is the last line in the target.
+ expected_disk.tweak('iota', contents="Some more bytes\n" + iota_contents)
+ expected_status.tweak('iota', status='M ')
+ expected_skip = wc.State('', { })
+ svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+ expected_output, expected_disk,
+ expected_status, expected_skip)
+
+ # Test where the no-EOL context line is a non-last line in the target.
+ sbox.simple_revert('iota')
+ sbox.simple_append('iota', "Another line.\n")
+ expected_disk.tweak('iota', contents="Some more bytes\n" + iota_contents +
+ "Another line.\n")
+ expected_output = [ 'G %s\n' % sbox.ospath('iota') ]
+ svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+ expected_output, expected_disk,
+ expected_status, expected_skip)
########################################################################
@@ -4519,6 +4667,8 @@ test_list = [ None,
patch_replace_dir_with_file_and_vv,
single_line_mismatch,
patch_empty_file,
+ patch_apply_no_fuz,
+ patch_lacking_trailing_eol_on_context,
]
if __name__ == '__main__':
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/prop_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/prop_tests.py?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/prop_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/prop_tests.py Sat Feb 23 01:25:38 2013
@@ -49,6 +49,10 @@ def is_non_posix_and_non_windows_os():
"""lambda function to skip revprop_change test"""
return (not svntest.main.is_posix_os()) and sys.platform != 'win32'
+# this is global so other test files can use it
+binary_mime_type_on_text_file_warning = \
+ "svn: warning:.*is a binary mime-type but file.*looks like text.*"
+
######################################################################
# Tests
@@ -612,7 +616,9 @@ def inappropriate_props(sbox):
svntest.main.file_append(path, "binary")
sbox.simple_add('binary')
- sbox.simple_propset('svn:mime-type', 'application/octet-stream', 'binary')
+ svntest.main.run_svn(binary_mime_type_on_text_file_warning,
+ 'propset', 'svn:mime-type', 'application/octet-stream',
+ sbox.ospath('binary'))
svntest.actions.run_and_verify_svn('Illegal target', None,
svntest.verify.AnyOutput,
@@ -1790,7 +1796,7 @@ def rm_of_replaced_file(sbox):
exit_code, output, errput = svntest.main.run_svn(None,
'proplist', '-v',
mu_path + '@base')
- expected_output = svntest.verify.UnorderedRegexOutput([
+ expected_output = svntest.verify.UnorderedRegexListOutput([
'Properties on',
' yellow',
' submarine',
@@ -2124,6 +2130,8 @@ def propget_redirection(sbox):
# it refers to non-existent path-revs, but that is not relevant to
# this test. What matters is that it is a realistic 'big' mergeinfo
# value (it is from Subversion's own 1.6.x branch in fact).
+ # Also, the syntax is wrong: every path should start with '/';
+ # Subversion currently silently corrects this.
big_prop_val = "subversion/branches/1.5.x:872364-874936\n" + \
"subversion/branches/1.5.x-34184:874657-874741\n" + \
"subversion/branches/1.5.x-34432:874744-874798\n" + \
@@ -2263,131 +2271,26 @@ def propget_redirection(sbox):
# Check if the redirected output of svn pg -vR on the root of the WC
# is what we expect.
+ expected_mergeinfo_displayed = [
+ ' /' + line for line in big_prop_val.splitlines(True) ]
expected_output = [
"Properties on '" + B_path + "':\n", # Should ocur only once!
+ " svn:mergeinfo\n",
+ ] + expected_mergeinfo_displayed + [
"Properties on '" + C_path + "':\n", # Should ocur only once!
+ " svn:mergeinfo\n",
+ ] + expected_mergeinfo_displayed + [
"Properties on '" + D_path + "':\n", # Should ocur only once!
- # Everything below should appear three times since this same
- # mergeinfo value is set on three paths in the WC.
" svn:mergeinfo\n",
- " /subversion/branches/1.5.x:872364-874936\n",
- " /subversion/branches/1.5.x-34184:874657-874741\n",
- " /subversion/branches/1.5.x-34432:874744-874798\n",
- " /subversion/branches/1.5.x-issue3067:872184-872314\n",
- " /subversion/branches/1.5.x-issue3157:872165-872175\n",
- " /subversion/branches/1.5.x-issue3174:872178-872348\n",
- " /subversion/branches/1.5.x-r30215:870310,870312,870319,870362\n",
- " /subversion/branches/1.5.x-r30756:874853-874870\n",
- " /subversion/branches/1.5.x-r30868:870951-870970\n",
- " /subversion/branches/1.5.x-r31314:874476-874605\n",
- " /subversion/branches/1.5.x-r31516:871592-871649\n",
- " /subversion/branches/1.5.x-r32470:872546-872676\n",
- " /subversion/branches/1.5.x-r32968:873773-873872\n",
- " /subversion/branches/1.5.x-r33447:873527-873547\n",
- " /subversion/branches/1.5.x-r33465:873541-873549\n",
- " /subversion/branches/1.5.x-r33641:873880-873883\n",
- " /subversion/branches/1.5.x-r34050-followups:874639-874686\n",
- " /subversion/branches/1.5.x-r34487:874562-874581\n",
- " /subversion/branches/1.5.x-ra_serf-backports:872354-872626\n",
- " /subversion/branches/1.5.x-rb-test-fix:874916-874919\n",
- " /subversion/branches/1.5.x-reintegrate-improvements:874586-874922\n",
- " /subversion/branches/1.5.x-tests-pass:870925-870973\n",
- " /subversion/branches/dont-save-plaintext-passwords-by-default:"
- "870728-871118\n",
- " /subversion/branches/gnome-keyring:870558-871410\n",
- " /subversion/branches/issue-3220-dev:872210-872226\n",
- " /subversion/branches/kwallet:870785-871314\n",
- " /subversion/branches/log-g-performance:870941-871032\n",
- " /subversion/branches/r30963-1.5.x:871056-871076\n",
- " /subversion/branches/reintegrate-improvements:873853-874164\n",
- " /subversion/branches/svn-mergeinfo-enhancements:870196\n",
- " /subversion/branches/svnpatch-diff:871905\n",
- " /subversion/trunk:869159-869165,869168-869181,869185,869188,869191,"
- "869200-869201,869203-869207,869209-869224,869227-869238,869240-869244,"
- "869248,869250-869260,869262-869263,869265,869267-869268,869272-869280,"
- "869282-869325,869328-869330,869335,869341-869347,869351,869354-869355,"
- "869358,869361-869377,869379-869381,869383-869417,869419-869422,869432-"
- "869453,869455-869466,869471-869473,869475,869483,869486,869488-869489,"
- "869491-869497,869499-869500,869503,869506-869508,869510-869521,869523-"
- "869540,869542-869552,869556,869558,869560-869561,869563,869565,869567,"
- "869570,869572,869582,869601-869602,869605,869607,869613-869614,869616,"
- "869618,869620,869625,869627,869630,869633,869639,869641-869643,869645-"
- "869652,869655,869657,869665,869668,869674,869677,869681,869685,869687-"
- "869688,869693,869697,869699-869700,869704-869708,869716,869719,869722,"
- "869724,869730,869733-869734,869737-869740,869745-869746,869751-869754,"
- "869766,869812-869813,869815-869818,869820,869825,869837,869841,869843-"
- "869844,869858,869860-869861,869871,869875,869889,869895,869898,869902,"
- "869907,869909,869926,869928-869929,869931-869933,869942-869943,869950,"
- "869952,869957-869958,869969,869972,869974,869988,869994,869996,869999,"
- "870004,870013-870014,870016,870024,870032,870036,870039,870041-870043,"
- "870054,870060,870068-870071,870078,870083,870094,870104,870124,870127-"
- "870128,870133,870135-870136,870141,870144,870148,870160,870172,870175,"
- "870191,870198,870203-870204,870211,870219,870225,870233,870235-870236,"
- "870254-870255,870259,870307,870311,870313,870320,870323,870330-870331,"
- "870352-870353,870355,870359-870360,870371,870373,870378,870393-870395,"
- "870402,870409-870410,870414,870416,870421,870436,870442,870447,870449,"
- "870452,870454,870466,870476,870481-870483,870486,870500,870502,870505,"
- "870513-870518,870522-870523,870527,870529,870534,870536-870538,870540-"
- "870541,870543-870548,870554,870556,870561,870563,870584,870590-870592,"
- "870594-870595,870597,870618,870620,870622,870625-870626,870641,870647,"
- "870657,870665,870671,870681,870702-870703,870706-870708,870717-870718,"
- "870727,870730,870737,870740,870742,870752,870758,870800,870809,870815,"
- "870817,870820-870825,870830,870834-870836,870850-870851,870853,870859,"
- "870861,870886,870894,870916-870918,870942,870945,870957,870962,870970,"
- "870979,870981,870989,870996,871003,871005,871009,871011,871023,871033,"
- "871035-871038,871041,871060,871078,871080,871092,871097,871099,871105,"
- "871107,871120,871123-871127,871130,871133-871135,871140,871149,871155-"
- "871156,871160,871162,871164,871181,871191,871199-871200,871205,871211-"
- "871212,871215,871219,871225,871227,871229,871231,871236,871270,871273,"
- "871277,871283,871297,871302,871306,871308,871315-871320,871323-871325,"
- "871333-871335,871345,871347-871350,871354,871357,871361,871363-871366,"
- "871374-871375,871377,871382,871385-871388,871391,871408,871411,871422,"
- "871435,871441,871443-871444,871465,871470,871472-871476,871481,871489,"
- "871499,871501-871502,871505,871508,871520,871523,871525-871527,871538,"
- "871542,871544,871547-871549,871556,871559,871562-871563,871578,871581,"
- "871587,871589-871597,871608,871613,871616-871617,871620,871624,871649,"
- "871668,871675,871677,871693-871694,871696,871704,871732-871733,871744,"
- "871747,871759,871762,871766,871769,871793,871796,871799,871801,871811,"
- "871813,871821-871826,871831,871843,871860,871880,871891,871894,871899,"
- "871907,871911,871926,871928,871933,871935,871941-871942,871947-871949,"
- "871958,871974,872000-872001,872003,872005,872018,872022,872038,872065,"
- "872068,872086,872091,872093,872097,872103,872112,872130,872154,872157,"
- "872206,872216,872218-872219,872227,872234,872238,872243,872253,872255,"
- "872259,872261,872278-872279,872281,872310-872311,872362,872404,872416-"
- "872417,872429,872431,872434,872439,872450-872453,872468,872470,872477-"
- "872478,872483,872490-872491,872495,872515-872516,872518-872519,872537,"
- "872541,872544,872565,872568,872571-872573,872584,872596-872597,872612,"
- "872619,872624,872632,872656,872670,872706,872710,872713,872717,872746-"
- "872748,872777,872780-872782,872791,872804,872813,872845,872864,872870,"
- "872872,872947-872948,872961,872974,872981,872985-872987,873004,873042,"
- "873049,873051,873076,873087,873090,873096,873098,873100,873183,873186,"
- "873192,873195,873210-873211,873247,873252,873256,873259,873275,873286,"
- "873288,873343,873379-873381,873443,873521,873538-873539,873714-873715,"
- "873718,873733,873745,873751,873767,873778,873781,873849,873856,873862,"
- "873914,873940,873947-873948,873975-873976,873987,873998,874026-874027,"
- "874075,874077-874078,874124-874125,874127,874156,874159,874161,874165,"
- "874168,874170,874184,874189,874204,874223-874224,874245,874258,874262,"
- "874270,874292-874297,874300-874301,874303,874305,874316-874318,874330,"
- "874363,874380,874405,874421,874441,874459,874467,874473,874497,874506,"
- "874545-874546,874561,874566,874568,874580,874619,874621,874634,874636,"
- "874659,874673,874681,874727,874730,874743,874765-874767,874806,874816,"
- "874848,874868,874888,874896,874909,874912,874996,875051,875069,875129,"
- "875132,875134,875137,875151-875153,875186-875188,875190,875235-875237,"
- "875242-875243,875249,875388,875393,875406,875411\n"]
+ ] + expected_mergeinfo_displayed
svntest.verify.verify_outputs(
"Redirected pg -vR doesn't match pg -vR stdout",
pg_stdout_redir, None,
svntest.verify.UnorderedOutput(expected_output), None)
- # Because we are using UnorderedOutput above, this test would spuriously
- # pass if the redirected pg output contained duplicates. This hasn't been
- # observed as part of issue #3721, but we might as well be thorough...
- #
- # ...Since we've set the same mergeinfo prop on A/B, A/C, and A/D, this
- # means the number of lines in the redirected output of svn pg -vR should
- # be three times the number of lines in EXPECTED_OUTPUT, adjusted for the
- # fact the "Properties on '[A/B | A/C | A/D]'" headers appear only once.
- if ((len(expected_output) * 3) - 6) != len(pg_stdout_redir):
- raise svntest.Failure("Redirected pg -vR has unexpected duplicates")
+ # (We want this check to fail if the redirected pg output contains
+ # unexpected duplicate lines, although this hasn't been observed as
+ # part of issue #3721. We used to check separately here because the old
+ # UnorderedOutput class ignored duplicates but now it detects them.)
@Issue(3852)
def file_matching_dir_prop_reject(sbox):
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/resolve_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/resolve_tests.py?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/resolve_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/resolve_tests.py Sat Feb 23 01:25:38 2013
@@ -584,7 +584,6 @@ def theirs_conflict_in_subdir(sbox):
# Regression test for issue #4238 "merge -cA,B with --accept option aborts
# if rA conflicts".
@Issue(4238)
-@XFail()
def multi_range_merge_with_accept(sbox):
"multi range merge with --accept keeps going"
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/revert_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/revert_tests.py?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/revert_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/revert_tests.py Sat Feb 23 01:25:38 2013
@@ -1444,7 +1444,7 @@ def revert_tree_conflicts_with_replaceme
# Revert everything (i.e., accept "theirs-full").
svntest.actions.run_and_verify_revert([
wc('A/B/E'),
- wc('A/B/E/alpha'), # incoming
+ wc('A/B/E/alpha'), # incoming & local
wc('A/B/E/beta'),
wc('A/B/E/loc_beta'),
wc('A/B/lambda'),
@@ -1459,7 +1459,6 @@ def revert_tree_conflicts_with_replaceme
wc('A/D/H/loc_psi'),
wc('A/D/gamma'),
wc('A/mu'),
- wc('A/B/E/alpha'),
], '-R', wc_dir)
# Remove a few unversioned files that revert left behind.