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/01/22 00:37:04 UTC
svn commit: r1436688 [10/12] - in /subversion/branches/ev2-export: ./
contrib/client-side/emacs/ notes/commit-access-templates/
subversion/bindings/javahl/native/ subversion/bindings/swig/perl/native/t/
subversion/bindings/swig/ruby/test/ subversion/in...
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=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/merge_tests.py Mon Jan 21 23:37:01 2013
@@ -1831,7 +1831,7 @@ def merge_into_missing(sbox):
expected_status = wc.State(F_path, {
'' : Item(status=' ', wc_rev=1),
'foo' : Item(status='! ', wc_rev=2),
- 'Q' : Item(status='! ', entry_rev='?', wc_rev='2'),
+ 'Q' : Item(status='! ', wc_rev='2'),
# Revision is known and we can record mergeinfo
'Q/R' : Item(status='! ', wc_rev='3'),
'Q/R/bar' : Item(status='! ', wc_rev='3'),
@@ -7420,16 +7420,16 @@ def merge_away_subtrees_noninheritable_r
# Now merge -c10 from A to A_COPY.
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
- expected_output = wc.State('.', {
+ expected_output = wc.State('', {
'nu': Item(status='A '),
})
- expected_mergeinfo_output = wc.State('.', {
+ expected_mergeinfo_output = wc.State('', {
'' : Item(status=' U'),
'nu' : Item(status=' U'),
})
- expected_elision_output = wc.State('.', {
+ expected_elision_output = wc.State('', {
})
- expected_status = wc.State('.', {
+ expected_status = wc.State('', {
'' : Item(status=' M'),
'nu' : Item(status='A ', copied='+'),
'B' : Item(status=' '),
@@ -7479,7 +7479,7 @@ def merge_away_subtrees_noninheritable_r
expected_skip = wc.State('.', { })
saved_cwd = os.getcwd()
os.chdir(A_COPY_path)
- svntest.actions.run_and_verify_merge('.', '9', '10',
+ svntest.actions.run_and_verify_merge('', '9', '10',
sbox.repo_url + '/A', None,
expected_output,
expected_mergeinfo_output,
@@ -7527,7 +7527,7 @@ def merge_away_subtrees_noninheritable_r
})
expected_elision_output = wc.State('.', {
})
- expected_status = wc.State('.', {
+ expected_status = wc.State('', {
'' : Item(status=' M'),
'B' : Item(status=' '),
'mu' : Item(status='MM'),
@@ -8100,10 +8100,10 @@ def merge_old_and_new_revs_from_renamed_
# because /A_MOVED has renames in its history between the boundaries
# of the requested merge range.
expected_output = wc.State(A_COPY_path, {
- 'mu' : Item(status='G '), # mu gets touched twice
+ 'mu' : Item(status='G ', prev_status='U '), # mu gets touched twice
})
expected_mergeinfo_output = wc.State(A_COPY_path, {
- '' : Item(status=' G'),
+ '' : Item(status=' G', prev_status=' U'),
})
expected_elision_output = wc.State(A_COPY_path, {
})
@@ -8266,7 +8266,7 @@ def merge_with_child_having_different_re
expected_skip = wc.State(A_COPY_path, {})
expected_output = wc.State(A_COPY_path, {
'' : Item(status=' U'),
- 'mu' : Item(status='G '),
+ 'mu' : Item(status='G ', prev_status='G '), # Updated twice
})
expected_mergeinfo_output = wc.State(A_COPY_path, {
'' : Item(status=' U'),
@@ -8399,7 +8399,7 @@ def merge_with_child_having_different_re
svntest.main.file_write(A_COPY_mu_path, tweaked_17th_line_1)
expected_output = wc.State(A_COPY_path, {
'' : Item(status=' G'),
- 'mu' : Item(status='G '),
+ 'mu' : Item(status='G ', prev_status='G '),
})
expected_mergeinfo_output = wc.State(A_COPY_path, {
'' : Item(status=' G'),
@@ -10907,9 +10907,7 @@ def merge_added_subtree(sbox):
svntest.actions.run_and_verify_svn("", None, [],
"cp", A_COPY_url + '/D2',
os.path.join(A_path, "D2"))
- actual_tree = svntest.tree.build_tree_from_wc(A_path, 0)
- svntest.tree.compare_trees("expected disk",
- actual_tree, expected_disk.old_tree())
+ svntest.actions.verify_disk(A_path, expected_disk)
svntest.actions.run_and_verify_status(A_path, expected_status)
# Remove the copy artifacts
@@ -12143,7 +12141,7 @@ def subtree_source_missing_in_requested_
expected_output = wc.State(A_COPY_path, {
'D/H/omega' : Item(status='U '),
'D/H/psi' : Item(status='U '),
- 'D/H/omega' : Item(status='G '),
+ 'D/H/omega' : Item(status='G ', prev_status='G '),
})
expected_mergeinfo_output = wc.State(A_COPY_path, {
'' : Item(status=' U'),
@@ -13797,11 +13795,10 @@ def subtree_gets_changes_even_if_ultimat
# r9: Merge r3,7 from A/D/H to A_COPY/D/H, then reverse merge r7 from
# A/D/H/psi to A_COPY/D/H/psi.
expected_output = wc.State(H_COPY_path, {
- 'psi' : Item(status='U '),
- 'psi' : Item(status='G '),
+ 'psi' : Item(status='G ', prev_status='U '), # Touched twice
})
expected_mergeinfo_output = wc.State(H_COPY_path, {
- '' : Item(status=' G'),
+ '' : Item(status=' G', prev_status=' U'),
})
expected_elision_output = wc.State(H_COPY_path, {
})
@@ -13849,7 +13846,7 @@ def subtree_gets_changes_even_if_ultimat
svntest.main.run_svn(None, 'up', wc_dir)
expected_output = wc.State(H_COPY_path, {
'omega' : Item(status='U '),
- 'psi' : Item(status='D '),
+ 'psi' : Item(status='D ', prev_status='U '),
})
expected_mergeinfo_output = wc.State(H_COPY_path, {
'' : Item(status=' U'),
@@ -13960,7 +13957,7 @@ def no_self_referential_filtering_on_add
})
expected_mergeinfo_output = wc.State(A_COPY_2_path, {
'' : Item(status=' G'),
- 'C_MOVED' : Item(status=' G'),
+ 'C_MOVED' : Item(status=' G', prev_status=' G'),
})
expected_elision_output = wc.State(A_COPY_2_path, {
})
@@ -17873,11 +17870,11 @@ def merge_with_externals_with_mergeinfo(
A_path)
#----------------------------------------------------------------------
-# Test for issue #4221 'Trivial merge of a binary file with svn:keywords
-# raises a conflict'.
+# Test merging 'binary' files with keyword expansion enabled.
+# Tests issue #4221 'Trivial merge of a binary file with svn:keywords
+# raises a conflict', among other cases.
@SkipUnless(server_has_mergeinfo)
@Issue(4221)
-@XFail()
def merge_binary_file_with_keywords(sbox):
"merge binary file with keywords"
@@ -17885,32 +17882,66 @@ def merge_binary_file_with_keywords(sbox
os.chdir(sbox.wc_dir)
sbox.wc_dir = ''
- # make a 'binary' file with keyword expansion enabled
- svntest.main.file_write('foo', "Line 1 with $Revision: $ keyword.\n")
- sbox.simple_add('foo')
- sbox.simple_propset('svn:mime-type', 'application/octet-stream', 'foo')
- sbox.simple_propset('svn:keywords', 'Revision', 'foo')
+ # Some binary files, and some binary files that will become text files.
+ # 'mod_src' means a content change on the branch (the merge source);
+ # 'mod_tgt' means a content change on the original (the merge target);
+ # 'to_txt' means svn:mime-type removed on the branch (the merge source).
+ file_mod_both = 'A/B/E/alpha'
+ file_mod_src = 'A/D/G/pi'
+ file_mod_tgt = 'A/D/G/rho'
+ file_mod_none = 'A/D/G/tau'
+ file_mod_both_to_txt = 'A/B/E/beta'
+ file_mod_src_to_txt = 'A/D/H/chi'
+ file_mod_tgt_to_txt = 'A/D/H/psi'
+ file_mod_none_to_txt = 'A/D/H/omega'
+ files_bin = [ file_mod_both, file_mod_src, file_mod_tgt, file_mod_none ]
+ files_txt = [ file_mod_both_to_txt, file_mod_src_to_txt,
+ file_mod_tgt_to_txt, file_mod_none_to_txt ]
+ files = files_bin + files_txt
+
+ # 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)
+ sbox.simple_propset('svn:keywords', 'Revision', f)
sbox.simple_commit()
- # branch the file
- sbox.simple_copy('foo', 'bar')
- sbox.simple_commit()
+ # branch the files
+ sbox.simple_repo_copy('A', 'A2')
+ sbox.simple_update()
- # modify the branched version (although the bug shows even if we modify
- # just the original version -- or neither, which is a completely
- # degenerate 'merge' case)
- # ### Perhaps a dir merge would behave differently from a single-file merge?
- svntest.main.file_append('bar', "Line 2.\n")
+ # Modify the branched (source) and/or original (target) versions. Remove
+ # the svn:mime-type from the 'to_txt' files on the branch.
+ # The original bug in issue #4221 gave a conflict if we modified either
+ # version or neither (using a single-file merge test case).
+ for f in [ file_mod_both, file_mod_both_to_txt,
+ file_mod_src, file_mod_src_to_txt ]:
+ f_branch = 'A2' + f[1:]
+ svntest.main.file_append(sbox.ospath(f_branch), "Incoming mod.\n")
+ for f in [ file_mod_both, file_mod_both_to_txt,
+ file_mod_tgt, file_mod_tgt_to_txt ]:
+ svntest.main.file_append(sbox.ospath(f), "Mod on merge target.\n")
+ for f in files_txt:
+ f_branch = 'A2' + f[1:]
+ sbox.simple_propdel('svn:mime-type', f_branch)
sbox.simple_commit()
+ sbox.simple_update()
# merge back
svntest.actions.run_and_verify_svn(
None,
expected_merge_output([[3,4]],
- ['U foo\n',
- ' U foo\n'],
- target='foo'),
- [], 'merge', '^/bar', 'foo')
+ ['C ' + sbox.ospath(file_mod_both) + '\n',
+ 'U ' + sbox.ospath(file_mod_src) + '\n',
+ #' ' + sbox.ospath(file_mod_tgt) + '\n',
+ #' ' + sbox.ospath(file_mod_none) + '\n',
+ 'CU ' + sbox.ospath(file_mod_both_to_txt) + '\n',
+ 'UU ' + sbox.ospath(file_mod_src_to_txt) + '\n',
+ ' U ' + sbox.ospath(file_mod_tgt_to_txt) + '\n',
+ ' U ' + sbox.ospath(file_mod_none_to_txt) + '\n',
+ ' U A\n'],
+ text_conflicts=2),
+ [], 'merge', '^/A2', 'A')
#----------------------------------------------------------------------
# Test for issue #4155 'Merge conflict text of expanded keyword incorrect
@@ -17962,6 +17993,102 @@ def merge_conflict_when_keywords_removed
' U A2\n']),
[], 'merge', '--accept=postpone', '^/A', 'A2')
+@SkipUnless(server_has_mergeinfo)
+@Issue(4139, 3274, 3503)
+def merge_target_selection(sbox):
+ "merge target selection handling"
+
+ sbox.build()
+
+ # r2
+ sbox.simple_mkdir('dir')
+ sbox.simple_add_text('\1\2\3\4\5', 'dir/binary-file')
+ sbox.simple_add_text('abcde', 'dir/text-file')
+ sbox.simple_commit()
+
+ # r3
+ sbox.simple_copy('dir', 'branch')
+ sbox.simple_commit()
+
+ # r4
+ svntest.main.file_write(sbox.ospath('dir/binary-file'), '\5\4\3\2\1')
+ sbox.simple_commit()
+
+ sbox.simple_update()
+
+ os.chdir(sbox.ospath('branch'))
+
+ # Merge the directory (no target)
+ expected_output = [
+ '--- Merging r4 into \'.\':\n',
+ 'U binary-file\n',
+ '--- Recording mergeinfo for merge of r4 into \'.\':\n',
+ ' U .\n',
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'merge', '^/dir', '-c', '4')
+
+ svntest.main.run_svn(None, 'revert', '-R', '.')
+
+ # Merge the file (no target)
+ expected_output = [
+ '--- Merging r4 into \'binary-file\':\n',
+ 'U binary-file\n',
+ '--- Recording mergeinfo for merge of r4 into \'binary-file\':\n',
+ ' U binary-file\n',
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'merge', '^/dir/binary-file', '-c', '4')
+
+ svntest.main.run_svn(None, 'revert', '-R', '.')
+
+ # Merge the directory (explicit target)
+ expected_output = [
+ '--- Merging r4 into \'.\':\n',
+ 'U binary-file\n',
+ '--- Recording mergeinfo for merge of r4 into \'.\':\n',
+ ' U .\n',
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'merge', '^/dir', '-c', '4', '.')
+
+ svntest.main.run_svn(None, 'revert', '-R', '.')
+
+ # Merge the file (explicit target)
+ expected_output = [
+ '--- Merging r4 into \'binary-file\':\n',
+ 'U binary-file\n',
+ '--- Recording mergeinfo for merge of r4 into \'binary-file\':\n',
+ ' U binary-file\n',
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'merge', '^/dir/binary-file', '-c', '4', 'binary-file')
+
+ svntest.main.run_svn(None, 'revert', '-R', '.')
+
+ # Merge the file (wrong target)
+ expected_output = [
+ 'Skipped missing target: \'.\'\n',
+ 'Summary of conflicts:\n',
+ ' Skipped paths: 1\n',
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'merge', '^/dir/binary-file', '-c', '4', '.')
+
+ svntest.main.run_svn(None, 'revert', '-R', '.')
+
+ # Merge the dir (wrong target)
+ expected_output = [
+ 'Skipped \'%s\'\n' % os.path.join('binary-file', '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.actions.run_and_verify_svn(None, expected_output, [],
+ 'merge', '^/dir', '-c', '4', 'binary-file')
+
+
########################################################################
# Run the tests
@@ -18100,6 +18227,7 @@ test_list = [ None,
merge_with_externals_with_mergeinfo,
merge_binary_file_with_keywords,
merge_conflict_when_keywords_removed,
+ merge_target_selection,
]
if __name__ == '__main__':
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=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/patch_tests.py Mon Jan 21 23:37:01 2013
@@ -274,14 +274,14 @@ def patch_absolute_paths(sbox):
expected_disk = svntest.main.greek_state.copy()
expected_disk.tweak('A/B/E/alpha', contents=alpha_contents)
- expected_status = svntest.actions.get_virginal_state('.', 1)
+ expected_status = svntest.actions.get_virginal_state('', 1)
expected_status.tweak('A/B/E/alpha', status='M ')
expected_skip = wc.State('', {
lambda_path: Item(verb='Skipped missing target'),
})
- svntest.actions.run_and_verify_patch('.', os.path.abspath(patch_file_path),
+ svntest.actions.run_and_verify_patch('', os.path.abspath(patch_file_path),
expected_output,
expected_disk,
expected_status,
@@ -488,13 +488,13 @@ def patch_offset(sbox):
expected_disk.tweak('A/mu', contents=''.join(mu_contents))
expected_disk.tweak('iota', contents=''.join(iota_contents))
- expected_status = svntest.actions.get_virginal_state('.', 1)
+ expected_status = svntest.actions.get_virginal_state('', 1)
expected_status.tweak('A/mu', status='M ', wc_rev=2)
expected_status.tweak('iota', status='M ', wc_rev=2)
expected_skip = wc.State('', { })
- svntest.actions.run_and_verify_patch('.', os.path.abspath(patch_file_path),
+ svntest.actions.run_and_verify_patch('', os.path.abspath(patch_file_path),
expected_output,
expected_disk,
expected_status,
@@ -1097,6 +1097,7 @@ def patch_remove_empty_dirs(sbox):
'D %s\n' % sbox.ospath('A/B/lambda'),
'D %s\n' % sbox.ospath('A/B/E/alpha'),
'D %s\n' % sbox.ospath('A/B/E/beta'),
+ 'D %s\n' % sbox.ospath('A/B/E'),
'D %s\n' % sbox.ospath('A/B'),
]
@@ -2835,12 +2836,12 @@ def patch_prop_offset(sbox):
expected_disk.tweak('iota', props = {'prop1' : prop1_content,
'prop2' : prop2_content})
- expected_status = svntest.actions.get_virginal_state('.', 1)
+ expected_status = svntest.actions.get_virginal_state('', 1)
expected_status.tweak('iota', status=' M', wc_rev=2)
expected_skip = wc.State('', { })
- svntest.actions.run_and_verify_patch('.', os.path.abspath(patch_file_path),
+ svntest.actions.run_and_verify_patch('', os.path.abspath(patch_file_path),
expected_output,
expected_disk,
expected_status,
@@ -3965,8 +3966,8 @@ def patch_delete_and_skip(sbox):
expected_output = [
'D %s\n' % os.path.join('A', 'B', 'E', 'alpha'),
'D %s\n' % os.path.join('A', 'B', 'E', 'beta'),
- 'Skipped missing target: \'%s\'\n' % skipped_path,
'D %s\n' % os.path.join('A', 'B', 'E'),
+ 'Skipped missing target: \'%s\'\n' % skipped_path,
'Summary of conflicts:\n',
' Skipped paths: 1\n'
]
@@ -3976,7 +3977,7 @@ def patch_delete_and_skip(sbox):
expected_disk.remove('A/B/E/beta')
expected_disk.remove('A/B/E')
- expected_status = svntest.actions.get_virginal_state('.', 1)
+ expected_status = svntest.actions.get_virginal_state('', 1)
expected_status.tweak('A/B/E', status='D ')
expected_status.tweak('A/B/E/alpha', status='D ')
expected_status.tweak('A/B/E/beta', status='D ')
@@ -3985,7 +3986,7 @@ def patch_delete_and_skip(sbox):
'',
{skipped_path: Item(verb='Skipped missing target')})
- svntest.actions.run_and_verify_patch('.', os.path.abspath(patch_file_path),
+ svntest.actions.run_and_verify_patch('', os.path.abspath(patch_file_path),
expected_output,
expected_disk,
expected_status,
@@ -4181,9 +4182,9 @@ def patch_git_with_index_line(sbox):
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
expected_status.add({
- 'src/' : Item(status='A ', wc_rev=0),
+ 'src' : Item(status='A ', wc_rev=0),
'src/tools' : Item(status='A ', wc_rev=0),
- 'src/tools/ConsoleRunner/' : Item(status='A ', wc_rev=0),
+ 'src/tools/ConsoleRunner' : Item(status='A ', wc_rev=0),
'src/tools/ConsoleRunner/hi.txt' : Item(status='A ', wc_rev=0),
})
@@ -4206,7 +4207,6 @@ def patch_git_with_index_line(sbox):
1, # check-props
1) # dry-run
-@XFail()
@Issue(4273)
def patch_change_symlink_target(sbox):
"patch changes symlink target"
@@ -4217,30 +4217,259 @@ def patch_change_symlink_target(sbox):
svntest.main.file_write(patch_file_path, '\n'.join([
"Index: link",
"===================================================================",
- "--- iota (revision 1)",
- "+++ iota (working copy)",
+ "--- link\t(revision 1)",
+ "+++ link\t(working copy)",
"@@ -1 +1 @@",
"-link foo",
"\\ No newline at end of file",
- "+link bar",
+ "+link bardame",
"\\ No newline at end of file",
"",
]))
-
- # r2
- sbox.simple_add_symlink('target', 'link')
- sbox.simple_commit()
- expected_output = [
- 'M %s\n' % sbox.ospath('link'),
+ # r2 - Try as plain text with how we encode the symlink
+ svntest.main.file_write(sbox.ospath('link'), 'link foo')
+ sbox.simple_add('link')
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'link' : Item(verb='Adding'),
+ })
+ svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+ None, None, wc_dir)
+
+ patch_output = [
+ 'U %s\n' % sbox.ospath('link'),
]
- # This currently fails.
+ svntest.actions.run_and_verify_svn(None, patch_output, [],
+ 'patch', patch_file_path, wc_dir)
+
+ # r3 - Store result
+ expected_output = svntest.wc.State(wc_dir, {
+ 'link' : Item(verb='Sending'),
+ })
+ svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+ None, None, wc_dir)
+
+ # r4 - Now as symlink
+ sbox.simple_rm('link')
+ sbox.simple_add_symlink('foo', 'link')
+ expected_output = svntest.wc.State(wc_dir, {
+ 'link' : Item(verb='Replacing'),
+ })
+ svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+ None, None, wc_dir)
+
+ svntest.actions.run_and_verify_svn(None, patch_output, [],
+ 'patch', patch_file_path, wc_dir)
+
# TODO: when it passes, verify that the on-disk 'link' is correct ---
# symlink to 'bar' (or "link bar" on non-HAVE_SYMLINK platforms)
- svntest.actions.run_and_verify_svn(None, "U *link", [],
+
+ # BH: easy check for node type: a non symlink would show as obstructed
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.add({
+ 'link' : Item(status='M ', wc_rev='4'),
+ })
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+def patch_replace_dir_with_file_and_vv(sbox):
+ "replace dir with file and file with dir"
+ sbox.build(read_only=True)
+
+ patch_file_path = make_patch_path(sbox)
+ svntest.main.file_write(patch_file_path, ''.join([
+ # Delete all files in D and descendants to delete D itself
+ "Index: A/D/G/pi\n",
+ "===================================================================\n",
+ "--- A/D/G/pi\t(revision 1)\n",
+ "+++ A/D/G/pi\t(working copy)\n",
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'pi'.\n",
+ "Index: A/D/G/rho\n",
+ "===================================================================\n",
+ "--- A/D/G/rho\t(revision 1)\n",
+ "+++ A/D/G/rho\t(working copy)\n",
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'rho'.\n",
+ "Index: A/D/G/tau\n",
+ "===================================================================\n",
+ "--- A/D/G/tau\t(revision 1)\n",
+ "+++ A/D/G/tau\t(working copy)\n",
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'tau'.\n",
+ "Index: A/D/H/chi\n",
+ "===================================================================\n",
+ "--- A/D/H/chi\t(revision 1)\n",
+ "+++ A/D/H/chi\t(working copy)\n",
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'chi'.\n",
+ "Index: A/D/H/omega\n",
+ "===================================================================\n",
+ "--- A/D/H/omega\t(revision 1)\n",
+ "+++ A/D/H/omega\t(working copy)\n",
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'omega'.\n",
+ "Index: A/D/H/psi\n",
+ "===================================================================\n",
+ "--- A/D/H/psi\t(revision 1)\n",
+ "+++ A/D/H/psi\t(working copy)\n",
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'psi'.\n",
+ "Index: A/D/gamma\n",
+ "===================================================================\n",
+ "--- A/D/gamma\t(revision 1)\n",
+ "+++ A/D/gamma\t(working copy)\n",
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'gamma'.\n",
+ # Delete iota
+ "Index: iota\n",
+ "===================================================================\n",
+ "--- iota\t(revision 1)\n",
+ "+++ iota\t(working copy)\n",
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'iota'.\n",
+
+ # Add A/D as file
+ "Index: A/D\n",
+ "===================================================================\n",
+ "--- A/D\t(revision 0)\n",
+ "+++ A/D\t(working copy)\n",
+ "@@ -0,0 +1 @@\n",
+ "+New file\n",
+ "\ No newline at end of file\n",
+
+ # Add iota as directory
+ "Index: iota\n",
+ "===================================================================\n",
+ "--- iota\t(revision 1)\n",
+ "+++ iota\t(working copy)\n",
+ "\n",
+ "Property changes on: iota\n",
+ "___________________________________________________________________\n",
+ "Added: k\n",
+ "## -0,0 +1 ##\n",
+ "+v\n",
+ "\ No newline at end of property\n",
+ ]))
+
+ expected_output = [
+ 'D %s\n' % sbox.ospath('A/D/G/pi'),
+ 'D %s\n' % sbox.ospath('A/D/G/rho'),
+ 'D %s\n' % sbox.ospath('A/D/G/tau'),
+ 'D %s\n' % sbox.ospath('A/D/G'),
+ 'D %s\n' % sbox.ospath('A/D/H/chi'),
+ 'D %s\n' % sbox.ospath('A/D/H/omega'),
+ 'D %s\n' % sbox.ospath('A/D/H/psi'),
+ 'D %s\n' % sbox.ospath('A/D/H'),
+ 'D %s\n' % sbox.ospath('A/D/gamma'),
+ 'D %s\n' % sbox.ospath('A/D'),
+ 'D %s\n' % sbox.ospath('iota'),
+ 'A %s\n' % sbox.ospath('A/D'),
+ 'A %s\n' % sbox.ospath('iota'),
+ ]
+
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'patch', patch_file_path, sbox.wc_dir)
+
+@Issue(4297)
+def single_line_mismatch(sbox):
+ "single line replacement mismatch"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ patch_file_path = make_patch_path(sbox)
+ svntest.main.file_write(patch_file_path, ''.join([
+ "Index: test\n",
+ "===================================================================\n",
+ "--- test\t(revision 1)\n",
+ "+++ test\t(working copy)\n",
+ "@@ -1 +1 @@\n",
+ "-foo\n",
+ "\\ No newline at end of file\n",
+ "+bar\n",
+ "\\ No newline at end of file\n"
+ ]))
+
+ # r2 - Try as plain text with how we encode the symlink
+ svntest.main.file_write(sbox.ospath('test'), 'line')
+ sbox.simple_add('test')
+ sbox.simple_commit()
+
+ # And now this patch should fail, as 'line' doesn't equal 'foo'
+ # But yet it shows up as deleted instead of conflicted
+ expected_output = [
+ 'C %s\n' % sbox.ospath('test'),
+ '> rejected hunk @@ -1,1 +1,1 @@\n',
+ 'Summary of conflicts:\n',
+ ' Text conflicts: 1\n',
+ ]
+
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'patch', patch_file_path, wc_dir)
+
+@Issue(3644)
+def patch_empty_file(sbox):
+ "apply a patch to an empty file"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ patch_file_path = make_patch_path(sbox)
+ svntest.main.file_write(patch_file_path, ''.join([
+ # patch a file containing just '\n' to 'replacement\n'
+ "Index: lf.txt\n",
+ "===================================================================\n",
+ "--- lf.txt\t(revision 2)\n",
+ "+++ lf.txt\t(working copy)\n",
+ "@@ -1 +1 @@\n",
+ "\n"
+ "+replacement\n",
+
+ # patch a new file 'new.txt\n'
+ "Index: new.txt\n",
+ "===================================================================\n",
+ "--- new.txt\t(revision 0)\n",
+ "+++ new.txt\t(working copy)\n",
+ "@@ -0,0 +1 @@\n",
+ "+new file\n",
+
+ # patch a file containing 0 bytes to 'replacement\n'
+ "Index: empty.txt\n",
+ "===================================================================\n",
+ "--- empty.txt\t(revision 2)\n",
+ "+++ empty.txt\t(working copy)\n",
+ "@@ -0,0 +1 @@\n",
+ "+replacement\n",
+ ]))
+
+ sbox.simple_add_text('', 'empty.txt')
+ sbox.simple_add_text('\n', 'lf.txt')
+ sbox.simple_commit()
+
+ expected_output = [
+ 'U %s\n' % sbox.ospath('lf.txt'),
+ 'A %s\n' % sbox.ospath('new.txt'),
+ 'U %s\n' % sbox.ospath('empty.txt'),
+ # Not sure if this line is necessary, but it doesn't hurt
+ '> applied hunk @@ -0,0 +1,1 @@ with offset 0\n',
+ ]
+
+ # Current result: lf.txt patched ok, new created, empty succeeds with offset.
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
'patch', patch_file_path, wc_dir)
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.add({
+ 'lf.txt' : Item(contents="\n"),
+ 'new.txt' : Item(contents="new file\n"),
+ 'empty.txt' : Item(contents="replacement\n"),
+ })
+
+ svntest.actions.verify_disk(wc_dir, expected_disk)
+
+
+
########################################################################
#Run the tests
@@ -4287,6 +4516,9 @@ test_list = [ None,
patch_add_and_delete,
patch_git_with_index_line,
patch_change_symlink_target,
+ patch_replace_dir_with_file_and_vv,
+ single_line_mismatch,
+ patch_empty_file,
]
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=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/prop_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/prop_tests.py Mon Jan 21 23:37:01 2013
@@ -92,11 +92,7 @@ def make_local_props(sbox):
# Read the real disk tree. Notice we are passing the (normally
# disabled) "load props" flag to this routine. This will run 'svn
# proplist' on every item in the working copy!
- actual_disk_tree = svntest.tree.build_tree_from_wc(wc_dir, 1)
-
- # Compare actual vs. expected disk trees.
- svntest.tree.compare_trees("disk", actual_disk_tree,
- expected_disk.old_tree())
+ svntest.actions.verify_disk(wc_dir, expected_disk, True)
# Edit without actually changing the property
svntest.main.use_editor('identity')
@@ -1319,9 +1315,7 @@ def props_on_replaced_file(sbox):
# check that the replaced file has no properties
expected_disk = svntest.main.greek_state.copy()
expected_disk.tweak('iota', contents="some mod")
- actual_disk_tree = svntest.tree.build_tree_from_wc(wc_dir, 1)
- svntest.tree.compare_trees("disk", actual_disk_tree,
- expected_disk.old_tree())
+ svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True)
# now add a new property to iota
sbox.simple_propset('red', 'mojo', 'iota')
@@ -1329,9 +1323,7 @@ def props_on_replaced_file(sbox):
# What we expect the disk tree to look like:
expected_disk.tweak('iota', props={'red' : 'mojo', 'groovy' : 'baby'})
- actual_disk_tree = svntest.tree.build_tree_from_wc(wc_dir, 1)
- svntest.tree.compare_trees("disk", actual_disk_tree,
- expected_disk.old_tree())
+ svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True)
#----------------------------------------------------------------------
@@ -1781,9 +1773,7 @@ def rm_of_replaced_file(sbox):
expected_disk.tweak('iota', props={'red': 'rojo', 'blue': 'lagoon'})
expected_disk.tweak('A/mu', props={'red': 'rojo', 'blue': 'lagoon'},
contents="This is the file 'iota'.\n")
- actual_disk_tree = svntest.tree.build_tree_from_wc(wc_dir, 1)
- svntest.tree.compare_trees("disk", actual_disk_tree,
- expected_disk.old_tree())
+ svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True)
# Remove the copy. This should leave the original locally-deleted mu,
# which should have no properties.
@@ -2012,17 +2002,13 @@ def obstructed_subdirs(sbox):
expected_disk = svntest.main.greek_state.copy()
expected_disk.tweak('A/C', props={'red': 'blue'})
- actual_disk_tree = svntest.tree.build_tree_from_wc(wc_dir, load_props=True)
- svntest.tree.compare_trees("disk", actual_disk_tree,
- expected_disk.old_tree())
+ svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True)
# Remove the subdir from disk, and validate the status
svntest.main.safe_rmtree(C_path)
expected_disk.remove('A/C')
- actual_disk_tree = svntest.tree.build_tree_from_wc(wc_dir, load_props=True)
- svntest.tree.compare_trees("disk", actual_disk_tree,
- expected_disk.old_tree())
+ svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True)
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
expected_status.tweak('A/C', status='!M', wc_rev='1')
@@ -2035,9 +2021,7 @@ def obstructed_subdirs(sbox):
expected_disk.add({'A/C': Item(contents='', props={'red': 'blue'})})
expected_status.tweak('A/C', status='~M', wc_rev='1')
- actual_disk_tree = svntest.tree.build_tree_from_wc(wc_dir, load_props=True)
- svntest.tree.compare_trees("disk", actual_disk_tree,
- expected_disk.old_tree())
+ svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True)
svntest.actions.run_and_verify_status(wc_dir, expected_status)
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=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/resolve_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/resolve_tests.py Mon Jan 21 23:37:01 2013
@@ -44,6 +44,13 @@ Wimp = svntest.testcase.Wimp_deco
from merge_tests import set_up_branch
from merge_tests import expected_merge_output
+
+######################################################################
+# Tests
+#
+# Each test must return on success or raise on failure.
+
+#----------------------------------------------------------------------
# 'svn resolve --accept [ base | mine-full | theirs-full ]' was segfaulting
# on 1.6.x. Prior to this test, the bug was only caught by the Ruby binding
# tests, see http://svn.haxx.se/dev/archive-2010-01/0088.shtml.
@@ -243,6 +250,7 @@ def prop_conflict_resolution(sbox):
[], # Prop deleted
['incoming-conflict\n'])
+#----------------------------------------------------------------------
@SkipUnless(svntest.main.is_posix_os)
def auto_resolve_executable_file(sbox):
"resolve file with executable bit set"
@@ -271,6 +279,334 @@ def auto_resolve_executable_file(sbox):
if mode != os.stat(sbox.ospath('iota'))[stat.ST_MODE]:
raise svntest.Failure
+#----------------------------------------------------------------------
+def resolved_on_wc_root(sbox):
+ "resolved on working copy root"
+
+ sbox.build()
+ wc = sbox.wc_dir
+
+ i = os.path.join(wc, 'iota')
+ B = os.path.join(wc, 'A', 'B')
+ g = os.path.join(wc, 'A', 'D', 'gamma')
+
+ # Create some conflicts...
+ # Commit mods
+ svntest.main.file_append(i, "changed iota.\n")
+ svntest.main.file_append(g, "changed gamma.\n")
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'propset', 'foo', 'foo-val', B)
+
+ expected_output = svntest.wc.State(wc, {
+ 'iota' : Item(verb='Sending'),
+ 'A/B' : Item(verb='Sending'),
+ 'A/D/gamma' : Item(verb='Sending'),
+ })
+
+ expected_status = svntest.actions.get_virginal_state(wc, 1)
+ expected_status.tweak('iota', 'A/B', 'A/D/gamma', wc_rev = 2)
+
+ svntest.actions.run_and_verify_commit(wc,
+ expected_output,
+ expected_status,
+ None,
+ wc)
+
+ # Go back to rev 1
+ expected_output = svntest.wc.State(wc, {
+ 'iota' : Item(status='U '),
+ 'A/B' : Item(status=' U'),
+ 'A/D/gamma' : Item(status='U '),
+ })
+ expected_status = svntest.actions.get_virginal_state(wc, 1)
+ expected_disk = svntest.main.greek_state.copy()
+ svntest.actions.run_and_verify_update(wc,
+ expected_output,
+ expected_disk,
+ expected_status,
+ None, None, None, None, None, False,
+ '-r1', wc)
+
+ # Deletions so that the item becomes unversioned and
+ # will have a tree-conflict upon update.
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'rm', i, B, g)
+
+ # Update so that conflicts appear
+ expected_output = svntest.wc.State(wc, {
+ 'iota' : Item(status=' ', treeconflict='C'),
+ 'A/B' : Item(status=' ', treeconflict='C'),
+ 'A/D/gamma' : Item(status=' ', treeconflict='C'),
+ })
+
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.remove('iota',
+ 'A/B',
+ 'A/B/lambda',
+ 'A/B/E', 'A/B/E/alpha', 'A/B/E/beta',
+ 'A/B/F',
+ 'A/D/gamma')
+
+ expected_status = svntest.actions.get_virginal_state(wc, 2)
+ expected_status.tweak('iota', 'A/B', 'A/D/gamma',
+ status='D ', treeconflict='C')
+ expected_status.tweak('A/B/lambda', 'A/B/E', 'A/B/E/alpha', 'A/B/E/beta',
+ 'A/B/F', status='D ')
+ svntest.actions.run_and_verify_update(wc,
+ expected_output,
+ expected_disk,
+ None,
+ None, None, None, None, None, False,
+ wc)
+ svntest.actions.run_and_verify_unquiet_status(wc, expected_status)
+
+ # Resolve recursively
+ svntest.actions.run_and_verify_resolved([i, B, g], '--depth=infinity', wc)
+
+ expected_status.tweak('iota', 'A/B', 'A/D/gamma', treeconflict=None)
+ svntest.actions.run_and_verify_unquiet_status(wc, expected_status)
+
+#----------------------------------------------------------------------
+def resolved_on_deleted_item(sbox):
+ "resolved on deleted item"
+
+ sbox.build()
+ wc = sbox.wc_dir
+
+ A = os.path.join(wc, 'A',)
+ B = os.path.join(wc, 'A', 'B')
+ g = os.path.join(wc, 'A', 'D', 'gamma')
+ A2 = os.path.join(wc, 'A2')
+ B2 = os.path.join(A2, 'B')
+ g2 = os.path.join(A2, 'D', 'gamma')
+
+ A_url = sbox.repo_url + '/A'
+ A2_url = sbox.repo_url + '/A2'
+
+ # make a copy of A
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'cp', A_url, A2_url, '-m', 'm')
+
+ expected_output = svntest.wc.State(wc, {
+ 'A2' : Item(status='A '),
+ 'A2/B' : Item(status='A '),
+ 'A2/B/lambda' : Item(status='A '),
+ 'A2/B/E' : Item(status='A '),
+ 'A2/B/E/alpha' : Item(status='A '),
+ 'A2/B/E/beta' : Item(status='A '),
+ 'A2/B/F' : Item(status='A '),
+ 'A2/mu' : Item(status='A '),
+ 'A2/C' : Item(status='A '),
+ 'A2/D' : Item(status='A '),
+ 'A2/D/gamma' : Item(status='A '),
+ 'A2/D/G' : Item(status='A '),
+ 'A2/D/G/pi' : Item(status='A '),
+ 'A2/D/G/rho' : Item(status='A '),
+ 'A2/D/G/tau' : Item(status='A '),
+ 'A2/D/H' : Item(status='A '),
+ 'A2/D/H/chi' : Item(status='A '),
+ 'A2/D/H/omega' : Item(status='A '),
+ 'A2/D/H/psi' : Item(status='A '),
+ })
+
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.add({
+ 'A2/mu' : Item(contents="This is the file 'mu'.\n"),
+ 'A2/D/gamma' : Item(contents="This is the file 'gamma'.\n"),
+ 'A2/D/H/psi' : Item(contents="This is the file 'psi'.\n"),
+ 'A2/D/H/omega' : Item(contents="This is the file 'omega'.\n"),
+ 'A2/D/H/chi' : Item(contents="This is the file 'chi'.\n"),
+ 'A2/D/G/rho' : Item(contents="This is the file 'rho'.\n"),
+ 'A2/D/G/pi' : Item(contents="This is the file 'pi'.\n"),
+ 'A2/D/G/tau' : Item(contents="This is the file 'tau'.\n"),
+ 'A2/B/lambda' : Item(contents="This is the file 'lambda'.\n"),
+ 'A2/B/F' : Item(),
+ 'A2/B/E/beta' : Item(contents="This is the file 'beta'.\n"),
+ 'A2/B/E/alpha' : Item(contents="This is the file 'alpha'.\n"),
+ 'A2/C' : Item(),
+ })
+
+ expected_status = svntest.actions.get_virginal_state(wc, 2)
+ expected_status.add({
+ 'A2' : Item(),
+ 'A2/B' : Item(),
+ 'A2/B/lambda' : Item(),
+ 'A2/B/E' : Item(),
+ 'A2/B/E/alpha' : Item(),
+ 'A2/B/E/beta' : Item(),
+ 'A2/B/F' : Item(),
+ 'A2/mu' : Item(),
+ 'A2/C' : Item(),
+ 'A2/D' : Item(),
+ 'A2/D/gamma' : Item(),
+ 'A2/D/G' : Item(),
+ 'A2/D/G/pi' : Item(),
+ 'A2/D/G/rho' : Item(),
+ 'A2/D/G/tau' : Item(),
+ 'A2/D/H' : Item(),
+ 'A2/D/H/chi' : Item(),
+ 'A2/D/H/omega' : Item(),
+ 'A2/D/H/psi' : Item(),
+ })
+ expected_status.tweak(status=' ', wc_rev='2')
+
+ svntest.actions.run_and_verify_update(wc,
+ expected_output,
+ expected_disk,
+ expected_status,
+ None, None, None, None, None, False,
+ wc)
+
+ # Create some conflicts...
+
+ # Modify the paths in the one directory.
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'propset', 'foo', 'foo-val', B)
+ svntest.main.file_append(g, "Modified gamma.\n")
+
+ expected_output = svntest.wc.State(wc, {
+ 'A/B' : Item(verb='Sending'),
+ 'A/D/gamma' : Item(verb='Sending'),
+ })
+
+ expected_status.tweak('A/B', 'A/D/gamma', wc_rev='3')
+
+ svntest.actions.run_and_verify_commit(wc,
+ expected_output,
+ expected_status,
+ None,
+ wc)
+
+ # Delete the paths in the second directory.
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'rm', B2, g2)
+
+ expected_output = svntest.wc.State(wc, {
+ 'A2/B' : Item(verb='Deleting'),
+ 'A2/D/gamma' : Item(verb='Deleting'),
+ })
+
+ expected_status.remove('A2/B', 'A2/B/lambda',
+ 'A2/B/E', 'A2/B/E/alpha', 'A2/B/E/beta',
+ 'A2/B/F',
+ 'A2/D/gamma')
+
+ svntest.actions.run_and_verify_commit(wc,
+ expected_output,
+ expected_status,
+ None,
+ A2)
+
+ # Now merge A to A2, creating conflicts...
+
+ expected_output = svntest.wc.State(A2, {
+ 'B' : Item(status=' ', treeconflict='C'),
+ 'D/gamma' : Item(status=' ', treeconflict='C'),
+ })
+ expected_mergeinfo_output = svntest.wc.State(A2, {
+ '' : Item(status=' U')
+ })
+ expected_elision_output = svntest.wc.State(A2, {
+ })
+ expected_disk = svntest.wc.State('', {
+ 'mu' : Item(contents="This is the file 'mu'.\n"),
+ 'D' : Item(),
+ 'D/H' : Item(),
+ 'D/H/psi' : Item(contents="This is the file 'psi'.\n"),
+ 'D/H/omega' : Item(contents="This is the file 'omega'.\n"),
+ 'D/H/chi' : Item(contents="This is the file 'chi'.\n"),
+ 'D/G' : Item(),
+ 'D/G/rho' : Item(contents="This is the file 'rho'.\n"),
+ 'D/G/pi' : Item(contents="This is the file 'pi'.\n"),
+ 'D/G/tau' : Item(contents="This is the file 'tau'.\n"),
+ 'C' : Item(),
+ })
+
+ expected_skip = svntest.wc.State(wc, {
+ })
+
+ expected_status = svntest.wc.State(A2, {
+ '' : Item(status=' M', wc_rev='2'),
+ 'D' : Item(status=' ', wc_rev='2'),
+ 'D/gamma' : Item(status='! ', treeconflict='C'),
+ 'D/G' : Item(status=' ', wc_rev='2'),
+ 'D/G/pi' : Item(status=' ', wc_rev='2'),
+ 'D/G/rho' : Item(status=' ', wc_rev='2'),
+ 'D/G/tau' : Item(status=' ', wc_rev='2'),
+ 'D/H' : Item(status=' ', wc_rev='2'),
+ 'D/H/chi' : Item(status=' ', wc_rev='2'),
+ 'D/H/omega' : Item(status=' ', wc_rev='2'),
+ 'D/H/psi' : Item(status=' ', wc_rev='2'),
+ 'B' : Item(status='! ', treeconflict='C'),
+ 'mu' : Item(status=' ', wc_rev='2'),
+ 'C' : Item(status=' ', wc_rev='2'),
+ })
+
+ svntest.actions.run_and_verify_merge(A2, None, None, A_url, None,
+ expected_output,
+ expected_mergeinfo_output,
+ expected_elision_output,
+ expected_disk, None, expected_skip,
+ None, dry_run = False)
+ svntest.actions.run_and_verify_unquiet_status(A2, expected_status)
+
+ # Now resolve by recursing on the working copy root.
+ svntest.actions.run_and_verify_resolved([B2, g2], '--depth=infinity', wc)
+
+ expected_status.remove('B', 'D/gamma')
+ svntest.actions.run_and_verify_unquiet_status(A2, expected_status)
+
+#----------------------------------------------------------------------
+
+def theirs_conflict_in_subdir(sbox):
+ "resolve to 'theirs-conflict' in sub-directory"
+
+ sbox.build()
+ wc = sbox.wc_dir
+ wc2 = sbox.add_wc_path('wc2')
+ svntest.actions.duplicate_dir(sbox.wc_dir, wc2)
+
+ alpha_path = os.path.join(wc, 'A', 'B', 'E', 'alpha')
+ alpha_path2 = os.path.join(wc2, 'A', 'B', 'E', 'alpha')
+
+ svntest.main.file_append(alpha_path, "Modified alpha.\n")
+ svntest.main.run_svn(None, 'ci', '-m', 'logmsg', wc)
+
+ svntest.main.file_append(alpha_path2, "Modified alpha, too.\n")
+ svntest.main.run_svn(None, 'up', wc2)
+
+ svntest.actions.run_and_verify_resolve([alpha_path2],
+ '--accept=theirs-conflict',
+ alpha_path2)
+
+#----------------------------------------------------------------------
+
+# 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"
+
+ sbox.build()
+ os.chdir(sbox.wc_dir)
+ sbox.wc_dir = ''
+
+ # Commit some changes
+ for c in [2, 3, 4]:
+ svntest.main.file_append('iota', 'Change ' + str(c) + '\n')
+ sbox.simple_commit()
+
+ sbox.simple_update(revision=1)
+
+ # The bug: with a request to merge -c4 then -c3, it merges -c4 which
+ # conflicts then auto-resolves the conflict, then errors out with
+ # 'svn: E155035: Can't merge into conflicted node 'iota'.
+ # ### We need more checking of the result to make this test robust, since
+ # it may not always just error out.
+ svntest.main.run_svn(None, 'merge', '-c4,3', '^/iota', 'iota',
+ '--accept=theirs-conflict')
+
########################################################################
# Run the tests
@@ -280,6 +616,10 @@ test_list = [ None,
automatic_conflict_resolution,
prop_conflict_resolution,
auto_resolve_executable_file,
+ resolved_on_wc_root,
+ resolved_on_deleted_item,
+ theirs_conflict_in_subdir,
+ multi_range_merge_with_accept,
]
if __name__ == '__main__':
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=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/revert_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/revert_tests.py Mon Jan 21 23:37:01 2013
@@ -79,8 +79,7 @@ def revert_replacement_with_props(sbox,
expected_disk.tweak('A/D/G/rho',
props={ 'svn:eol-style': 'LF' })
- actual_disk = svntest.tree.build_tree_from_wc(wc_dir, 1)
- svntest.tree.compare_trees("disk", actual_disk, expected_disk.old_tree())
+ svntest.actions.verify_disk(wc_dir, expected_disk, True)
# Commit props
expected_output = svntest.wc.State(wc_dir, {
@@ -124,8 +123,7 @@ def revert_replacement_with_props(sbox,
expected_disk.tweak('A/D/G/rho',
contents="This is the file 'pi'.\n",
props=props)
- actual_disk = svntest.tree.build_tree_from_wc(wc_dir, 1)
- svntest.tree.compare_trees("disk", actual_disk, expected_disk.old_tree())
+ svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True)
# Now revert
expected_status.tweak('A/D/G/rho', status='R ', copied='+', wc_rev='-')
@@ -144,8 +142,7 @@ def revert_replacement_with_props(sbox,
props={ 'phony-prop': '*' })
expected_disk.tweak('A/D/G/rho',
props={ 'svn:eol-style': 'LF' })
- actual_disk = svntest.tree.build_tree_from_wc(wc_dir, 1)
- svntest.tree.compare_trees("disk", actual_disk, expected_disk.old_tree())
+ svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True)
@@ -511,9 +508,8 @@ def revert_file_merge_replace_with_histo
expected_status.tweak('A/D/G/rho', copied=None, status=' ', wc_rev=3)
svntest.actions.run_and_verify_status(wc_dir, expected_status)
- actual_disk = svntest.tree.build_tree_from_wc(wc_dir, 1)
expected_disk.tweak('A/D/G/rho', contents="new rho\n")
- svntest.tree.compare_trees("disk", actual_disk, expected_disk.old_tree())
+ svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True)
# Make sure the revert removed the copy from information.
expected_infos = [
@@ -578,8 +574,7 @@ def revert_after_second_replace(sbox):
# Check disk status
expected_disk = svntest.main.greek_state.copy()
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
- actual_disk = svntest.tree.build_tree_from_wc(wc_dir, 1)
- svntest.tree.compare_trees("disk", actual_disk, expected_disk.old_tree())
+ svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True)
#----------------------------------------------------------------------
@@ -1594,8 +1589,7 @@ def revert_with_unversioned_targets(sbox
expected_disk.add({
'A/D/H/delta': Item(delta_contents),
})
- actual_disk = svntest.tree.build_tree_from_wc(wc_dir, 1)
- svntest.tree.compare_trees("disk", actual_disk, expected_disk.old_tree())
+ svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True)
def revert_nonexistent(sbox):
'svn revert -R nonexistent'
@@ -1636,8 +1630,10 @@ def revert_obstructing_wc(sbox):
# A is not versioned but exists
})
+ # Use expected_status.old_tree() to avoid doing an entries comparion
svntest.actions.run_and_verify_update(wc_dir,
- expected_output, None, expected_status,
+ expected_output, None,
+ expected_status.old_tree(),
None, None, None,
None, None, None,
wc_dir, '--set-depth', 'infinity')
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/special_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/special_tests.py?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/special_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/special_tests.py Mon Jan 21 23:37:01 2013
@@ -1182,7 +1182,7 @@ def incoming_symlink_changes(sbox):
# Update back to r2, to prepare some local changes
expected_output = svntest.wc.State(wc_dir, {
# s-replace is D + A
- 's-replace' : Item(status='A '),
+ 's-replace' : Item(status='A ', prev_status='D '),
's-in-place' : Item(status='U '),
's-reverse' : Item(status=' U'),
's-type' : Item(status=' U'),
@@ -1203,7 +1203,8 @@ def incoming_symlink_changes(sbox):
sbox.simple_propset('x', 'y', 's-replace', 's-in-place', 's-reverse', 's-type')
expected_output = svntest.wc.State(wc_dir, {
- 's-replace' : Item(status=' ', treeconflict='A'),
+ 's-replace' : Item(prev_status = ' ', prev_treeconflict='C',
+ status=' ', treeconflict='A'),
's-in-place' : Item(status='U '),
's-reverse' : Item(status=' ', treeconflict='C'),
's-type' : Item(status=' ', treeconflict='C'),
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/stat_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/stat_tests.py?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/stat_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/stat_tests.py Mon Jan 21 23:37:01 2013
@@ -1988,6 +1988,40 @@ def status_unversioned_dir(sbox):
svntest.actions.run_and_verify_svn2(None, [], expected_err, 0,
"status", "/")
+def status_case_changed(sbox):
+ "status reporting on case changed nodes directly"
+
+ sbox.build(read_only = True)
+ wc_dir = sbox.wc_dir
+
+ os.rename(sbox.ospath('iota'), sbox.ospath('iOTA'))
+
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.add({
+ 'iOTA' : Item(status='? '),
+ })
+ expected_status.tweak('iota', status='! ')
+
+ # First run status on the directory
+ svntest.actions.run_and_verify_unquiet_status(wc_dir,
+ expected_status)
+
+ # Now on the missing iota directly, which should give the same
+ # result, even on case insenstive filesystems
+ expected_status = svntest.wc.State(wc_dir, {
+ 'iota' : Item(status='! ', wc_rev=1),
+ })
+ svntest.actions.run_and_verify_unquiet_status(sbox.ospath('iota'),
+ expected_status)
+
+ # And on the unversioned iOTA
+ expected_status = svntest.wc.State(wc_dir, {
+ 'iOTA' : Item(status='? '),
+ })
+ svntest.actions.run_and_verify_unquiet_status(sbox.ospath('iOTA'),
+ expected_status)
+
+
########################################################################
# Run the tests
@@ -2033,6 +2067,7 @@ test_list = [ None,
modified_modulo_translation,
status_not_present,
status_unversioned_dir,
+ status_case_changed,
]
if __name__ == '__main__':
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/svnadmin_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/svnadmin_tests.py?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/svnadmin_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/svnadmin_tests.py Mon Jan 21 23:37:01 2013
@@ -230,14 +230,8 @@ def load_and_verify_dumpstream(sbox, exp
"update", "-r%s" % (rev+1),
sbox.wc_dir)
- wc_tree = svntest.tree.build_tree_from_wc(sbox.wc_dir, check_props)
- rev_tree = revs[rev].old_tree()
-
- try:
- svntest.tree.compare_trees("rev/disk", rev_tree, wc_tree)
- except svntest.tree.SVNTreeError:
- svntest.verify.display_trees(None, 'WC TREE', wc_tree, rev_tree)
- raise
+ rev_tree = revs[rev]
+ svntest.actions.verify_disk(sbox.wc_dir, rev_tree, check_props)
def load_dumpstream(sbox, dump, *varargs):
"Load dump text without verification."
@@ -554,11 +548,22 @@ def verify_windows_paths_in_repos(sbox):
exit_code, output, errput = svntest.main.run_svnadmin("verify",
sbox.repo_dir)
- svntest.verify.compare_and_display_lines(
- "Error while running 'svnadmin verify'.",
- 'STDERR', ["* Verified revision 0.\n",
- "* Verified revision 1.\n",
- "* Verified revision 2.\n"], errput)
+
+ # unfortunately, FSFS needs to do more checks than BDB resulting in
+ # different progress output
+ if svntest.main.is_fs_type_fsfs:
+ svntest.verify.compare_and_display_lines(
+ "Error while running 'svnadmin verify'.",
+ 'STDERR', ["* Verifying global structure ...\n",
+ "* Verified revision 0.\n",
+ "* Verified revision 1.\n",
+ "* Verified revision 2.\n"], errput)
+ else:
+ svntest.verify.compare_and_display_lines(
+ "Error while running 'svnadmin verify'.",
+ 'STDERR', ["* Verified revision 0.\n",
+ "* Verified revision 1.\n",
+ "* Verified revision 2.\n"], errput)
#----------------------------------------------------------------------
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/svntest/actions.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/svntest/actions.py?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/svntest/actions.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/svntest/actions.py Mon Jan 21 23:37:01 2013
@@ -455,8 +455,6 @@ def run_and_verify_checkout2(do_remove,
if isinstance(output_tree, wc.State):
output_tree = output_tree.old_tree()
- if isinstance(disk_tree, wc.State):
- disk_tree = disk_tree.old_tree()
# Remove dir if it's already there, unless this is a forced checkout.
# In that case assume we want to test a forced checkout's toleration
@@ -478,17 +476,10 @@ def run_and_verify_checkout2(do_remove,
_log_tree_state("ACTUAL OUTPUT TREE:", actual, wc_dir_name)
raise
- # Create a tree by scanning the working copy
- actual = tree.build_tree_from_wc(wc_dir_name)
-
- # Verify expected disk against actual disk.
- try:
- tree.compare_trees("disk", actual, disk_tree,
- singleton_handler_a, a_baton,
- singleton_handler_b, b_baton)
- except tree.SVNTreeUnequal:
- _log_tree_state("ACTUAL DISK TREE:", actual, wc_dir_name)
- raise
+ if disk_tree:
+ verify_disk(wc_dir_name, disk_tree, False,
+ singleton_handler_a, a_baton,
+ singleton_handler_b, b_baton)
def run_and_verify_checkout(URL, wc_dir_name, output_tree, disk_tree,
singleton_handler_a = None,
@@ -759,10 +750,6 @@ def verify_update(actual_output,
mergeinfo_output_tree = mergeinfo_output_tree.old_tree()
if isinstance(elision_output_tree, wc.State):
elision_output_tree = elision_output_tree.old_tree()
- if isinstance(disk_tree, wc.State):
- disk_tree = disk_tree.old_tree()
- if isinstance(status_tree, wc.State):
- status_tree = status_tree.old_tree()
# Verify actual output against expected output.
if output_tree:
@@ -794,27 +781,35 @@ def verify_update(actual_output,
# Create a tree by scanning the working copy, and verify it
if disk_tree:
- actual_disk = tree.build_tree_from_wc(wc_dir_name, check_props)
- try:
- tree.compare_trees("disk", actual_disk, disk_tree,
- singleton_handler_a, a_baton,
- singleton_handler_b, b_baton)
- except tree.SVNTreeUnequal:
- _log_tree_state("EXPECTED DISK TREE:", disk_tree)
- _log_tree_state("ACTUAL DISK TREE:", actual_disk)
- raise
+ verify_disk(wc_dir_name, disk_tree, check_props,
+ singleton_handler_a, a_baton,
+ singleton_handler_b, b_baton)
# Verify via 'status' command too, if possible.
if status_tree:
run_and_verify_status(wc_dir_name, status_tree)
-def verify_disk(wc_dir_name, disk_tree, check_props=False):
+def verify_disk(wc_dir_name, disk_tree, check_props=False,
+ singleton_handler_a = None, a_baton = None,
+ singleton_handler_b = None, b_baton = None):
"""Verify WC_DIR_NAME against DISK_TREE. If CHECK_PROPS is set,
the comparison will examin props. Returns if successful, raises on
failure."""
- verify_update(None, None, None, wc_dir_name, None, None, None, disk_tree,
- None, check_props=check_props)
+
+ if isinstance(disk_tree, wc.State):
+ disk_tree = disk_tree.old_tree()
+
+ actual_disk = tree.build_tree_from_wc(wc_dir_name, check_props)
+ try:
+ tree.compare_trees("disk", actual_disk, disk_tree,
+ singleton_handler_a, a_baton,
+ singleton_handler_b, b_baton)
+ except tree.SVNTreeUnequal:
+ _log_tree_state("EXPECTED DISK TREE:", disk_tree)
+ _log_tree_state("ACTUAL DISK TREE:", actual_disk)
+ raise
+
@@ -838,8 +833,6 @@ def run_and_verify_update(wc_dir_name,
If ERROR_RE_STRING, the update must exit with error, and the error
message must match regular expression ERROR_RE_STRING.
- Else if ERROR_RE_STRING is None, then:
-
If OUTPUT_TREE is not None, the subcommand output will be verified
against OUTPUT_TREE. If DISK_TREE is not None, the working copy
itself will be verified against DISK_TREE. If STATUS_TREE is not
@@ -864,11 +857,13 @@ def run_and_verify_update(wc_dir_name,
if error_re_string:
rm = re.compile(error_re_string)
+ match = None
for line in errput:
match = rm.search(line)
if match:
- return
- raise main.SVNUnmatchedError
+ break
+ if not match:
+ raise main.SVNUnmatchedError
actual = wc.State.from_checkout(output)
verify_update(actual, None, None, wc_dir_name,
@@ -1171,8 +1166,6 @@ def run_and_verify_patch(dir, patch_path
If ERROR_RE_STRING, 'svn patch' must exit with error, and the error
message must match regular expression ERROR_RE_STRING.
- Else if ERROR_RE_STRING is None, then:
-
The subcommand output will be verified against OUTPUT_TREE, and the
working copy itself will be verified against DISK_TREE. If optional
STATUS_TREE is given, then 'svn status' output will be compared.
@@ -1341,7 +1334,6 @@ def run_and_verify_switch(wc_dir_name,
error_re_string = ".*(" + error_re_string + ")"
expected_err = verify.RegexOutput(error_re_string, match_all=False)
verify.verify_outputs(None, None, errput, None, expected_err)
- return
elif errput:
raise verify.SVNUnexpectedStderr(err)
@@ -1353,7 +1345,7 @@ def run_and_verify_switch(wc_dir_name,
singleton_handler_b, b_baton,
check_props)
-def process_output_for_commit(output):
+def process_output_for_commit(output, error_re_string):
"""Helper for run_and_verify_commit(), also used in the factory."""
# Remove the final output line, and verify that the commit succeeded.
lastline = ""
@@ -1372,7 +1364,7 @@ def process_output_for_commit(output):
cm = re.compile("(Committed|Imported) revision [0-9]+.")
match = cm.search(lastline)
- if not match:
+ if not match and not error_re_string:
logger.warn("ERROR: commit did not succeed.")
logger.warn("The final line from 'svn ci' was:")
logger.warn(lastline)
@@ -1417,8 +1409,6 @@ def run_and_verify_commit(wc_dir_name, o
if isinstance(output_tree, wc.State):
output_tree = output_tree.old_tree()
- if isinstance(status_tree, wc.State):
- status_tree = status_tree.old_tree()
# Commit.
if '-m' not in args and '-F' not in args:
@@ -1431,22 +1421,22 @@ def run_and_verify_commit(wc_dir_name, o
error_re_string = ".*(" + error_re_string + ")"
expected_err = verify.RegexOutput(error_re_string, match_all=False)
verify.verify_outputs(None, None, errput, None, expected_err)
- return
# Else not expecting error:
# Convert the output into a tree.
- output = process_output_for_commit(output)
+ output = process_output_for_commit(output, error_re_string)
actual = tree.build_tree_from_commit(output)
# Verify actual output against expected output.
- try:
- tree.compare_trees("output", actual, output_tree)
- except tree.SVNTreeError:
- verify.display_trees("Output of commit is unexpected",
- "OUTPUT TREE", output_tree, actual)
- _log_tree_state("ACTUAL OUTPUT TREE:", actual, wc_dir_name)
- raise
+ if output_tree:
+ try:
+ tree.compare_trees("output", actual, output_tree)
+ except tree.SVNTreeError:
+ verify.display_trees("Output of commit is unexpected",
+ "OUTPUT TREE", output_tree, actual)
+ _log_tree_state("ACTUAL OUTPUT TREE:", actual, wc_dir_name)
+ raise
# Verify via 'status' command too, if possible.
if status_tree:
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/svntest/sandbox.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/svntest/sandbox.py?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/svntest/sandbox.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/svntest/sandbox.py Mon Jan 21 23:37:01 2013
@@ -318,6 +318,13 @@ class Sandbox:
# '*' is evaluated on Windows
self.simple_propset('svn:special', 'X', target)
+ def simple_add_text(self, text, *targets):
+ """Create files containing TEXT as TARGETS"""
+ assert len(targets) > 0
+ for target in targets:
+ svntest.main.file_write(self.ospath(target), text, mode='wb')
+ self.simple_add(*targets)
+
def simple_copy(self, source, dest):
"""Copy SOURCE to DEST in the WC.
SOURCE and DEST are relpaths relative to the WC."""
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/svntest/tree.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/svntest/tree.py?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/svntest/tree.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/svntest/tree.py Mon Jan 21 23:37:01 2013
@@ -253,6 +253,10 @@ class SVNTreeNode:
# remove the subtree path, skip this node if necessary.
if path.startswith(subtree):
path = path[len(subtree):]
+ elif path + os.sep == subtree:
+ # Many callers set subtree to 'some-path' + os.sep. Don't skip the
+ # root node in that case.
+ path = ''
else:
return 0
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/svntest/wc.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/svntest/wc.py?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/svntest/wc.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/svntest/wc.py Mon Jan 21 23:37:01 2013
@@ -96,6 +96,7 @@ _re_parse_status = re.compile('^([?!MACD
_re_parse_status_ex = re.compile('^ ('
'( \> moved (from (?P<moved_from>.+)|to (?P<moved_to>.*)))'
+ '|( \> swapped places with (?P<swapped_with>.+).*)'
'|(\> (?P<tc>.+))'
')$')
@@ -144,10 +145,11 @@ class State:
"Import state items from a State object, reparent the items to PARENT."
assert isinstance(state, State)
- if parent and parent[-1] != '/':
- parent += '/'
for path, item in state.desc.items():
- path = parent + path
+ if path == '':
+ path = parent
+ else:
+ path = parent + '/' + path
self.desc[path] = item
def remove(self, *paths):
@@ -337,6 +339,13 @@ class State:
# These are only in their parents' THIS_DIR, they don't have entries.
if item.status[0] in '!?' and item.treeconflict == 'C':
del self.desc[path]
+ # Normal externals are not stored in the parent wc, drop the root
+ # and everything in these working copies
+ elif item.status == 'X ' or item.prev_status == 'X ':
+ del self.desc[path]
+ for p, i in self.desc.copy().items():
+ if p.startswith(path + '/'):
+ del self.desc[p]
else:
# when reading the entry structures, we don't examine for text or
# property mods, so clear those flags. we also do not examine the
@@ -355,6 +364,9 @@ class State:
if item.entry_status is not None:
item.status = item.entry_status
item.entry_status = None
+ if item.entry_copied is not None:
+ item.copied = item.entry_copied
+ item.entry_copied = None
if item.writelocked:
# we don't contact the repository, so our only information is what
# is in the working copy. 'K' means we have one and it matches the
@@ -372,6 +384,9 @@ class State:
item.writelocked = None
item.moved_from = None
item.moved_to = None
+ if path == '':
+ item.switched = None
+ item.treeconflict = None
def old_tree(self):
"Return an old-style tree (for compatibility purposes)."
@@ -421,12 +436,6 @@ class State:
if line.startswith('DBG:'):
continue
- # Quit when we hit an externals status announcement.
- ### someday we can fix the externals tests to expect the additional
- ### flood of externals status data.
- if line.startswith('Performing'):
- break
-
match = _re_parse_status.search(line)
if not match or match.group(10) == '-':
@@ -445,12 +454,27 @@ class State:
path = path[len(wc_dir_name) + 1:]
last.tweak(moved_to = to_relpath(path))
+ elif ex_match.group('swapped_with'):
+ path = ex_match.group('swapped_with')
+ if wc_dir_name and path.startswith(wc_dir_name + os.path.sep):
+ path = path[len(wc_dir_name) + 1:]
+
+ last.tweak(moved_to = to_relpath(path))
+ last.tweak(moved_from = to_relpath(path))
# Parse TC description?
# ignore non-matching lines, or items that only exist on repos
continue
+ prev_status = None
+ prev_treeconflict = None
+
+ path = to_relpath(match.group('path'))
+ if path in desc:
+ prev_status = desc[path].status
+ prev_treeconflict = desc[path].treeconflict
+
item = StateItem(status=match.group(1),
locked=not_space(match.group(2)),
copied=not_space(match.group(3)),
@@ -458,8 +482,10 @@ class State:
writelocked=not_space(match.group(5)),
treeconflict=not_space(match.group(6)),
wc_rev=not_space(match.group('wc_rev')),
+ prev_status=prev_status,
+ prev_treeconflict =prev_treeconflict
)
- desc[to_relpath(match.group('path'))] = item
+ desc[path] = item
last = item
return cls('', desc)
@@ -515,12 +541,38 @@ class State:
treeconflict = match.group(3)
else:
treeconflict = None
- desc[to_relpath(match.group(4))] = StateItem(status=match.group(1),
- treeconflict=treeconflict)
+ path = to_relpath(match.group(4))
+ prev_status = None
+ prev_verb = None
+ prev_treeconflict = None
+
+ if path in desc:
+ prev_status = desc[path].status
+ prev_verb = desc[path].verb
+ prev_treeconflict = desc[path].treeconflict
+
+ desc[path] = StateItem(status=match.group(1),
+ treeconflict=treeconflict,
+ prev_status=prev_status,
+ prev_verb=prev_verb,
+ prev_treeconflict=prev_treeconflict)
else:
match = re_extra.search(line)
if match:
- desc[to_relpath(match.group(2))] = StateItem(verb=match.group(1))
+ path = to_relpath(match.group(2))
+ prev_status = None
+ prev_verb = None
+ prev_treeconflict = None
+
+ if path in desc:
+ prev_status = desc[path].status
+ prev_verb = desc[path].verb
+ prev_treeconflict = desc[path].treeconflict
+
+ desc[path] = StateItem(verb=match.group(1),
+ prev_status=prev_status,
+ prev_verb=prev_verb,
+ prev_treeconflict=prev_treeconflict)
return cls('', desc)
@@ -638,6 +690,9 @@ class State:
# entries that are ABSENT don't show up in status
if entry.absent:
continue
+ # entries that are User Excluded don't show up in status
+ if entry.depth == -1:
+ continue
if name and entry.kind == 2:
# stub subdirectory. leave a "missing" StateItem in here. note
# that we can't put the status as "! " because that gets tweaked
@@ -663,6 +718,9 @@ class State:
if implied_url and implied_url != entry.url:
item.switched = 'S'
+ if entry.file_external:
+ item.switched = 'X'
+
return cls('', desc)
@@ -676,9 +734,10 @@ class StateItem:
def __init__(self, contents=None, props=None,
status=None, verb=None, wc_rev=None,
- entry_rev=None, entry_status=None,
+ entry_rev=None, entry_status=None, entry_copied=None,
locked=None, copied=None, switched=None, writelocked=None,
- treeconflict=None, moved_from=None, moved_to=None):
+ treeconflict=None, moved_from=None, moved_to=None,
+ prev_status=None, prev_verb=None, prev_treeconflict=None):
# provide an empty prop dict if it wasn't provided
if props is None:
props = { }
@@ -695,22 +754,26 @@ class StateItem:
self.props = props
# A two-character string from the first two columns of 'svn status'.
self.status = status
+ self.prev_status = prev_status
# The action word such as 'Adding' printed by commands like 'svn update'.
self.verb = verb
+ self.prev_verb = prev_verb
# The base revision number of the node in the WC, as a string.
self.wc_rev = wc_rev
# These will be set when we expect the wc_rev/status to differ from those
# found in the entries code.
self.entry_rev = entry_rev
self.entry_status = entry_status
+ self.entry_copied = entry_copied
# For the following attributes, the value is the status character of that
# field from 'svn status', except using value None instead of status ' '.
self.locked = locked
self.copied = copied
self.switched = switched
self.writelocked = writelocked
- # Value 'C' or ' ', or None as an expected status meaning 'do not check'.
+ # Value 'C', 'A', 'D' or ' ', or None as an expected status meaning 'do not check'.
self.treeconflict = treeconflict
+ self.prev_treeconflict = prev_treeconflict
# Relative paths to the move locations
self.moved_from = moved_from
self.moved_to = moved_to
@@ -751,8 +814,12 @@ class StateItem:
atts = { }
if self.status is not None:
atts['status'] = self.status
+ if self.prev_status is not None:
+ atts['prev_status'] = self.prev_status
if self.verb is not None:
atts['verb'] = self.verb
+ if self.prev_verb is not None:
+ atts['prev_verb'] = self.prev_verb
if self.wc_rev is not None:
atts['wc_rev'] = self.wc_rev
if self.locked is not None:
@@ -765,6 +832,8 @@ class StateItem:
atts['writelocked'] = self.writelocked
if self.treeconflict is not None:
atts['treeconflict'] = self.treeconflict
+ if self.prev_treeconflict is not None:
+ atts['prev_treeconflict'] = self.prev_treeconflict
if self.moved_from is not None:
atts['moved_from'] = self.moved_from
if self.moved_to is not None:
@@ -866,9 +935,12 @@ def repos_join(base, path):
"""Join two repos paths. This generally works for URLs too."""
if base == '':
return path
- if path == '':
+ elif path == '':
return base
- return base + '/' + path
+ elif base[len(base)-1:] == '/':
+ return base + path
+ else:
+ return base + '/' + path
def svn_uri_quote(url):
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/switch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/switch_tests.py?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/switch_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/switch_tests.py Mon Jan 21 23:37:01 2013
@@ -1463,15 +1463,15 @@ def switch_with_obstructing_local_adds(s
expected_status.add({
'A/B/F/gamma' : Item(status='R ', treeconflict='C', wc_rev='1'),
'A/B/F/G' : Item(status='R ', treeconflict='C', wc_rev='1'),
- 'A/B/F/G/pi' : Item(status='A ', wc_rev='-'),
- 'A/B/F/G/tau' : Item(status='A ', wc_rev='-'),
- 'A/B/F/G/upsilon' : Item(status='A ', wc_rev='-'),
+ 'A/B/F/G/pi' : Item(status='A ', wc_rev='-', entry_status='R ', entry_rev='1'),
+ 'A/B/F/G/tau' : Item(status='A ', wc_rev='-', entry_status='R ', entry_rev='1'),
+ 'A/B/F/G/upsilon' : Item(status='A ', wc_rev='-', entry_rev='0'),
'A/B/F/G/rho' : Item(status='D ', wc_rev='1'),
'A/B/F/H' : Item(status=' ', wc_rev='1'),
'A/B/F/H/chi' : Item(status=' ', wc_rev='1'),
'A/B/F/H/omega' : Item(status=' ', wc_rev='1'),
'A/B/F/H/psi' : Item(status=' ', wc_rev='1'),
- 'A/B/F/I' : Item(status='A ', wc_rev='-'),
+ 'A/B/F/I' : Item(status='A ', wc_rev='-', entry_rev='0'),
})
# "Extra" files that we expect to result from the conflicts.
@@ -2213,7 +2213,7 @@ def switch_to_root(sbox):
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
expected_status.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
expected_status.add_state('A/D/G',
- svntest.actions.get_virginal_state(wc_dir, 1))
+ svntest.actions.get_virginal_state(wc_dir + '/A/D/G', 1))
expected_status.tweak('A/D/G', switched = 'S')
svntest.actions.run_and_verify_switch(wc_dir, ADG_path, sbox.repo_url,
expected_output,
@@ -2906,6 +2906,33 @@ def different_node_kind(sbox):
switch_to_file(sbox, 'iota', 'A/C')
switch_to_file(sbox, 'A/D/gamma', 'A/D/G')
+@Issue(3332, 3333)
+def switch_to_spaces(sbox):
+ "switch to a directory with spaces in its name"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ repo_url = sbox.repo_url
+
+ # Paths are normalized in the command processing, so %20 is equivalent to ' '
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'cp', repo_url + '/A',
+ repo_url + '/A%20with space',
+ '-m', '')
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'mv', repo_url + '/A%20with space',
+ repo_url + '/A with%20more spaces',
+ '-m', '')
+
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
+ expected_status.tweak('A', switched='S')
+ expected_status.tweak('', 'iota', wc_rev=1)
+
+ svntest.actions.run_and_verify_switch(sbox.wc_dir, sbox.ospath('A'),
+ repo_url + '/A%20with more%20spaces',
+ None, None, expected_status)
+
########################################################################
# Run the tests
@@ -2946,6 +2973,7 @@ test_list = [ None,
copy_with_switched_subdir,
up_to_old_rev_with_subtree_switched_to_root,
different_node_kind,
+ switch_to_spaces,
]
if __name__ == '__main__':