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 2010/09/15 21:32:38 UTC
svn commit: r997472 [39/41] - in /subversion/branches/py-tests-as-modules:
./ build/ build/ac-macros/ build/generator/ build/generator/templates/
contrib/server-side/ notes/ notes/tree-conflicts/ notes/wc-ng/
subversion/bindings/javahl/native/ subversi...
Modified: subversion/branches/py-tests-as-modules/subversion/tests/cmdline/switch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/tests/cmdline/switch_tests.py?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/tests/cmdline/switch_tests.py (original)
+++ subversion/branches/py-tests-as-modules/subversion/tests/cmdline/switch_tests.py Wed Sep 15 19:32:26 2010
@@ -29,6 +29,7 @@ import shutil, re, os
# Our testing module
import svntest
+from svntest import verify, actions, main
# (abbreviation)
Skip = svntest.testcase.Skip
@@ -37,6 +38,8 @@ XFail = svntest.testcase.XFail
Item = svntest.wc.StateItem
from svntest.main import SVN_PROP_MERGEINFO, server_has_mergeinfo
+from externals_tests import change_external
+
### Bummer. It would be really nice to have easy access to the URL
### member of our entries files so that switches could be testing by
@@ -564,7 +567,10 @@ def relocate_deleted_missing_copied(sbox
'A/D2/H/omega' : Item(status=' ', wc_rev='-', copied='+'),
'A/D2/H/psi' : Item(status=' ', wc_rev='-', copied='+'),
})
- expected_status.tweak('A/B/F', status='! ', wc_rev='?')
+ if svntest.main.wc_is_singledb(wc_dir):
+ expected_status.tweak('A/B/F', status='! ', wc_rev='1')
+ else:
+ expected_status.tweak('A/B/F', status='! ', wc_rev='?')
svntest.actions.run_and_verify_status(wc_dir, expected_status)
# Relocate
@@ -578,20 +584,28 @@ def relocate_deleted_missing_copied(sbox
# Deleted and missing entries should be preserved, so update should
# show only A/B/F being reinstated
- expected_output = svntest.wc.State(wc_dir, {
- 'A/B/F' : Item(status='A '),
- })
+ if svntest.main.wc_is_singledb(wc_dir):
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/B/F' : Item(verb='Restored'),
+ })
+ else:
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/B/F' : Item(status='A '),
+ })
expected_disk = svntest.main.greek_state.copy()
expected_disk.remove('A/mu')
expected_disk.add({
'A/D2' : Item(),
'A/D2/gamma' : Item("This is the file 'gamma'.\n"),
- 'A/D2/G' : Item(),
'A/D2/H' : Item(),
'A/D2/H/chi' : Item("This is the file 'chi'.\n"),
'A/D2/H/omega' : Item("This is the file 'omega'.\n"),
'A/D2/H/psi' : Item("This is the file 'psi'.\n"),
})
+ if not svntest.main.wc_is_singledb(wc_dir):
+ expected_disk.add({
+ 'A/D2/G' : Item(),
+ })
expected_status.add({
'A/B/F' : Item(status=' ', wc_rev='2'),
})
@@ -802,35 +816,92 @@ def bad_intermediate_urls(sbox):
"bad intermediate urls in use"
sbox.build()
wc_dir = sbox.wc_dir
+ url = sbox.repo_url
+
+ A = os.path.join(wc_dir, 'A')
+ A_Z = os.path.join(wc_dir, 'A', 'Z')
+ url_A_C = url + '/A/C'
+ url_A_C_A = url + '/A/C/A'
+ url_A_C_A_Z = url + '/A/C/A/Z'
# We'll be switching our working copy to (a modified) A/C in the Greek tree.
# First, make an extra subdirectory in C to match one in the root, plus
# another one inside of that.
- C_url = sbox.repo_url + '/A/C'
- C_A_url = sbox.repo_url + '/A/C/A'
- C_A_Z_url = sbox.repo_url + '/A/C/A/Z'
svntest.actions.run_and_verify_svn(None,
['\n', 'Committed revision 2.\n'], [],
'mkdir', '-m', 'log msg',
- C_A_url, C_A_Z_url)
+ url_A_C_A, url_A_C_A_Z)
# Now, we'll drop a conflicting path under the root.
- A_path = os.path.join(wc_dir, 'A')
- A_Z_path = os.path.join(A_path, 'Z')
- svntest.main.file_append(A_Z_path, 'Look, Mom, no ... switch success.')
+ svntest.main.file_append(A_Z, 'Look, Mom, a ... tree conflict.')
- # This switch should fail for reasons of obstruction.
- exit_code, out, err = svntest.main.run_svn(1, 'switch',
- C_url, wc_dir)
- if not err:
- raise svntest.Failure
+ #svntest.factory.make(sbox, """
+ # svn switch url/A/C wc_dir
+ # # svn info A
+ # # check that we can recover from the tree conflict
+ # rm A/Z
+ # svn up
+ # """)
+ #exit(0)
+
+ # svn switch url/A/C wc_dir
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/mu' : Item(status='D '),
+ 'A/Z' : Item(status=' ', treeconflict='C'),
+ 'A/C' : Item(status='D '),
+ 'A/B' : Item(status='D '),
+ 'A/D' : Item(status='D '),
+ 'iota' : Item(status='D '),
+ })
+
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.remove('iota', 'A/B', 'A/B/E', 'A/B/E/beta', 'A/B/E/alpha',
+ 'A/B/F', 'A/B/lambda', 'A/D', 'A/D/G', 'A/D/G/rho', 'A/D/G/pi',
+ 'A/D/G/tau', 'A/D/H', 'A/D/H/psi', 'A/D/H/omega', 'A/D/H/chi',
+ 'A/D/gamma', 'A/mu', 'A/C')
+ expected_disk.add({
+ 'A/Z' : Item(contents="Look, Mom, a ... tree conflict."),
+ })
- # However, the URL for A should now reflect A/C/A, not something else.
+ expected_status = actions.get_virginal_state(wc_dir, 2)
+ expected_status.remove('iota', 'A/B', 'A/B/E', 'A/B/E/beta', 'A/B/E/alpha',
+ 'A/B/F', 'A/B/lambda', 'A/D', 'A/D/G', 'A/D/G/rho', 'A/D/G/pi',
+ 'A/D/G/tau', 'A/D/H', 'A/D/H/psi', 'A/D/H/omega', 'A/D/H/chi',
+ 'A/D/gamma', 'A/mu', 'A/C')
+ expected_status.add({
+ 'A/Z' : Item(status='? ', treeconflict='C'),
+ })
+
+ actions.run_and_verify_switch(wc_dir, wc_dir, url_A_C, expected_output,
+ expected_disk, expected_status, None, None, None, None, None, False)
+
+
+ # However, the URL for wc/A should now reflect ^/A/C/A, not something else.
expected_infos = [
{ 'URL' : '.*/A/C/A$' },
]
- svntest.actions.run_and_verify_info(expected_infos, A_path)
+ svntest.actions.run_and_verify_info(expected_infos, A)
+
+
+ # check that we can recover from the tree conflict
+ # rm A/Z
+ os.remove(A_Z)
+
+ # svn up
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/Z' : Item(status='A '),
+ })
+
+ expected_disk.tweak('A/Z', contents=None)
+
+ expected_status.tweak(status=' ', wc_rev='2')
+ expected_status.tweak('A/Z', treeconflict=None)
+
+ actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+ expected_status, None, None, None, None, None, False, wc_dir)
+
+
#----------------------------------------------------------------------
@@ -839,42 +910,84 @@ def bad_intermediate_urls(sbox):
def obstructed_switch(sbox):
"obstructed switch"
+ #svntest.factory.make(sbox, """svn cp -m msgcopy url/A/B/E url/A/B/Esave
+ # svn rm A/B/E/alpha
+ # svn commit
+ # echo "hello" >> A/B/E/alpha
+ # svn switch url/A/B/Esave A/B/E
+ # svn status
+ # svn info A/B/E/alpha""")
sbox.build()
wc_dir = sbox.wc_dir
+ url = sbox.repo_url
- E_url = sbox.repo_url + '/A/B/E'
- E_url2 = sbox.repo_url + '/A/B/Esave'
- svntest.actions.run_and_verify_svn(None,
- ['\n', 'Committed revision 2.\n'], [],
- 'cp', '-m', 'msgcopy', E_url, E_url2)
+ A_B_E = os.path.join(wc_dir, 'A', 'B', 'E')
+ A_B_E_alpha = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha')
+ url_A_B_E = url + '/A/B/E'
+ url_A_B_Esave = url + '/A/B/Esave'
- E_path = os.path.join(wc_dir, 'A', 'B', 'E')
- alpha_path = os.path.join(E_path, 'alpha')
- svntest.actions.run_and_verify_svn(None, None, [], 'rm', alpha_path)
- expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ # svn cp -m msgcopy url/A/B/E url/A/B/Esave
+ expected_stdout = verify.UnorderedOutput([
+ '\n',
+ 'Committed revision 2.\n',
+ ])
+
+ actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'cp', '-m',
+ 'msgcopy', url_A_B_E, url_A_B_Esave)
+
+ # svn rm A/B/E/alpha
+ expected_stdout = ['D ' + A_B_E_alpha + '\n']
+
+ actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'rm',
+ A_B_E_alpha)
+
+ # svn commit
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/B/E/alpha' : Item(verb='Deleting'),
+ })
+
+ expected_status = actions.get_virginal_state(wc_dir, 1)
expected_status.remove('A/B/E/alpha')
+
+ actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+ None, wc_dir)
+
+ # echo "hello" >> A/B/E/alpha
+ main.file_append(A_B_E_alpha, 'hello')
+
+ # svn switch url/A/B/Esave A/B/E
expected_output = svntest.wc.State(wc_dir, {
- 'A/B/E/alpha' : Item(verb='Deleting'),
- })
- svntest.actions.run_and_verify_commit(wc_dir,
- expected_output, expected_status,
- None, wc_dir)
+ 'A/B/E/alpha' : Item(status=' ', treeconflict='C'),
+ })
- svntest.main.file_append(alpha_path, "hello")
- exit_code, out, err = svntest.main.run_svn(1, 'sw', E_url2, E_path)
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.tweak('A/B/E/alpha', contents='hello')
- for line in err:
- if line.find("file of the same name already exists") != -1:
- break
- else:
- raise svntest.Failure
+ expected_status.add({
+ 'A/B/E/alpha' : Item(status='? ', treeconflict='C'),
+ })
+ expected_status.tweak('A/B/E', wc_rev='3', switched='S')
+ expected_status.tweak('A/B/E/beta', wc_rev='3')
- os.remove(alpha_path)
- svntest.actions.run_and_verify_svn(None, None, [], 'sw', E_url2, E_path)
- expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
- expected_status.tweak('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', wc_rev=3)
- expected_status.tweak('A/B/E', switched='S')
- svntest.actions.run_and_verify_status(wc_dir, expected_status)
+ actions.run_and_verify_switch(wc_dir, A_B_E, url_A_B_Esave,
+ expected_output, expected_disk, expected_status, None, None, None, None,
+ None, False)
+
+ # svn status
+ expected_status.add({
+ 'A/B/Esave' : Item(status=' '),
+ 'A/B/Esave/beta' : Item(status=' '),
+ 'A/B/Esave/alpha' : Item(status=' '),
+ })
+
+ actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+ # svn info A/B/E/alpha
+ expected_stdout = verify.RegexOutput(
+ ".*local unversioned, incoming add upon switch",
+ match_all=False)
+ actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'info',
+ A_B_E_alpha)
#----------------------------------------------------------------------
@@ -1230,194 +1343,248 @@ def forced_switch(sbox):
'--force')
#----------------------------------------------------------------------
-
+# This test currently XFails for serf as the different order of
+# operations is not handled here.
def forced_switch_failures(sbox):
"forced switch detects tree conflicts"
- sbox.build()
+ # svntest.factory.make(sbox,
+ # """
+ # # Add a directory to obstruct a file.
+ # mkdir A/B/F/pi
+ #
+ # # Add a file to obstruct a directory.
+ # echo "The file 'H'" > A/C/H
+ #
+ # # Test three cases where forced switch should cause a tree conflict
+ #
+ # # 1) A forced switch that tries to add a file when an unversioned
+ # # directory of the same name already exists. (Currently fails)
+ # svn switch --force url/A/D A/C
+ #
+ # # 2) A forced switch that tries to add a dir when a file of the same
+ # # name already exists. (Tree conflict)
+ # svn switch --force url/A/D/G A/B/F
+ # svn info A/B/F/pi
+ #
+ # # 3) A forced update that tries to add a directory when a versioned
+ # # directory of the same name already exists.
+ #
+ # # Make dir A/D/H/I in repos.
+ # svn mkdir -m "Log message" url/A/D/H/I
+ #
+ # # Make A/D/G/I and co A/D/H/I into it.
+ # mkdir A/D/G/I
+ # svn co url/A/D/H/I A/D/G/I
+ #
+ # # Try the forced switch. A/D/G/I obstructs the dir A/D/G/I coming
+ # # from the repos, causing an error.
+ # svn switch --force url/A/D/H A/D/G
+ #
+ # # Delete all three obstructions and finish the update.
+ # rm -rf A/D/G/I
+ # rm A/B/F/pi
+ # rm A/C/H
+ #
+ # # A/B/F is switched to A/D/G
+ # # A/C is switched to A/D
+ # # A/D/G is switched to A/D/H
+ # svn up
+ # """)
+ # exit(0)
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ url = sbox.repo_url
+
+ A_B_F = os.path.join(wc_dir, 'A', 'B', 'F')
+ A_B_F_pi = os.path.join(wc_dir, 'A', 'B', 'F', 'pi')
+ A_C = os.path.join(wc_dir, 'A', 'C')
+ A_C_H = os.path.join(wc_dir, 'A', 'C', 'H')
+ A_D_G = os.path.join(wc_dir, 'A', 'D', 'G')
+ A_D_G_I = os.path.join(wc_dir, 'A', 'D', 'G', 'I')
+ url_A_D = url + '/A/D'
+ url_A_D_G = url + '/A/D/G'
+ url_A_D_H = url + '/A/D/H'
+ url_A_D_H_I = url + '/A/D/H/I'
# Add a directory to obstruct a file.
- pi_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'pi')
- os.mkdir(pi_path)
+ # mkdir A/B/F/pi
+ os.makedirs(A_B_F_pi)
# Add a file to obstruct a directory.
- H_path = os.path.join(sbox.wc_dir, 'A', 'C', 'H')
- svntest.main.file_write(H_path, "The file 'H'\n")
+ # echo "The file 'H'" > A/C/H
+ main.file_write(A_C_H, "The file 'H'\n")
# Test three cases where forced switch should cause a tree conflict
-
# 1) A forced switch that tries to add a file when an unversioned
# directory of the same name already exists. (Currently fails)
+ # svn switch --force url/A/D A/C
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/C/G' : Item(status='A '),
+ 'A/C/G/pi' : Item(status='A '),
+ 'A/C/G/rho' : Item(status='A '),
+ 'A/C/G/tau' : Item(status='A '),
+ 'A/C/gamma' : Item(status='A '),
+ 'A/C/H' : Item(status=' ', treeconflict='C'),
+ })
+
expected_disk = svntest.main.greek_state.copy()
expected_disk.add({
- 'A/C' : Item(),
- 'A/C/gamma' : Item("This is the file 'gamma'.\n"),
- 'A/C/H' : Item("The file 'H'\n"),
+ 'A/C/gamma' : Item(contents="This is the file 'gamma'.\n"),
'A/C/G' : Item(),
- 'A/C/G/rho' : Item("This is the file 'rho'.\n"),
- 'A/C/G/pi' : Item("This is the file 'pi'.\n"),
- 'A/C/G/tau' : Item("This is the file 'tau'.\n"),
- })
- expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+ 'A/C/G/pi' : Item(contents="This is the file 'pi'.\n"),
+ 'A/C/G/rho' : Item(contents="This is the file 'rho'.\n"),
+ 'A/C/G/tau' : Item(contents="This is the file 'tau'.\n"),
+ 'A/C/H' : Item(contents="The file 'H'\n"),
+ 'A/B/F/pi' : Item(),
+ })
+
+ expected_status = actions.get_virginal_state(wc_dir, 1)
expected_status.add({
- 'A/C' : Item(status='! ', wc_rev='1', switched='S'),
'A/C/G' : Item(status=' ', wc_rev='1'),
- 'A/C/G/pi' : Item(status=' ', wc_rev='1'),
'A/C/G/rho' : Item(status=' ', wc_rev='1'),
'A/C/G/tau' : Item(status=' ', wc_rev='1'),
+ 'A/C/G/pi' : Item(status=' ', wc_rev='1'),
+ 'A/C/H' : Item(status='? ', treeconflict='C'),
'A/C/gamma' : Item(status=' ', wc_rev='1'),
- })
- svntest.actions.run_and_verify_switch(sbox.wc_dir,
- os.path.join(sbox.wc_dir, 'A', 'C'),
- sbox.repo_url + "/A/D",
- None, None, None,
- ".*Failed to add directory .*" + \
- ": a non-directory object of the" + \
- " same name already exists\n",
- None, None, None, None, 0, '--force')
+ })
+ expected_status.tweak('A/C', switched='S')
+
+ actions.run_and_verify_switch(wc_dir, A_C, url_A_D, expected_output,
+ expected_disk, expected_status, None, None, None, None, None, False,
+ '--force')
+
# 2) A forced switch that tries to add a dir when a file of the same
- # name already exists. (Currently fails)
+ # name already exists. (Tree conflict)
+ # svn switch --force url/A/D/G A/B/F
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/B/F/rho' : Item(status='A '),
+ 'A/B/F/pi' : Item(status=' ', treeconflict='C'),
+ 'A/B/F/tau' : Item(status='A '),
+ })
+
expected_disk.add({
- 'A/B/F/pi' : Item(),
- })
+ 'A/B/F/rho' : Item(contents="This is the file 'rho'.\n"),
+ 'A/B/F/tau' : Item(contents="This is the file 'tau'.\n"),
+ })
+
expected_status.add({
- 'A/B/F' : Item(status='! ', wc_rev='1', switched='S'),
- })
- svntest.actions.run_and_verify_switch(sbox.wc_dir,
- os.path.join(sbox.wc_dir,
- 'A', 'B', 'F'),
- sbox.repo_url + "/A/D/G",
- None, None, None,
- ".*Failed to add file .*" + \
- ": a non-file object of the " + \
- "same name already exists\n",
- None, None, None, None, 0, '--force')
+ 'A/B/F/tau' : Item(status=' ', wc_rev='1'),
+ 'A/B/F/pi' : Item(status='? ', treeconflict='C'),
+ 'A/B/F/rho' : Item(status=' ', wc_rev='1'),
+ })
+ expected_status.tweak('A/B/F', switched='S')
+
+ actions.run_and_verify_switch(wc_dir, A_B_F, url_A_D_G, expected_output,
+ expected_disk, expected_status, None, None, None, None, None, False,
+ '--force')
+
+ # svn info A/B/F/pi
+ expected_stdout = verify.ExpectedOutput(
+ 'Tree conflict: local unversioned, incoming add upon switch\n',
+ match_all=False)
+
+ actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'info',
+ A_B_F_pi)
+
# 3) A forced update that tries to add a directory when a versioned
# directory of the same name already exists.
-
# Make dir A/D/H/I in repos.
- I_url = sbox.repo_url + "/A/D/H/I"
- exit_code, so, se = svntest.actions.run_and_verify_svn(
- "Unexpected error during mkdir",
- ['\n', 'Committed revision 2.\n'], [],
- "mkdir", I_url, "-m", "Log Message")
+ # svn mkdir -m "Log message" url/A/D/H/I
+ expected_stdout = verify.UnorderedOutput([
+ '\n',
+ 'Committed revision 2.\n',
+ ])
+
+ actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'mkdir',
+ '-m', 'Log message', url_A_D_H_I)
# Make A/D/G/I and co A/D/H/I into it.
- I_path = os.path.join(sbox.wc_dir, 'A', 'D', 'G', 'I')
- os.mkdir(I_path)
- exit_code, so, se = svntest.actions.run_and_verify_svn(
- "Unexpected error during co",
- ['Checked out revision 2.\n'], [],
- "co", I_url, I_path)
+ # mkdir A/D/G/I
+ os.makedirs(A_D_G_I)
+
+ # svn co url/A/D/H/I A/D/G/I
+ expected_output = svntest.wc.State(wc_dir, {})
+
+ expected_disk.add({
+ 'A/D/G/I' : Item(),
+ })
+
+ exit_code, so, se = svntest.actions.run_and_verify_svn(
+ "Unexpected error during co",
+ ['Checked out revision 2.\n'], [],
+ "co", url_A_D_H_I, A_D_G_I)
# Try the forced switch. A/D/G/I obstructs the dir A/D/G/I coming
# from the repos, causing an error.
- G_path = os.path.join(sbox.wc_dir, 'A', 'D', 'G')
- svntest.actions.run_and_verify_switch(sbox.wc_dir,
- G_path,
- sbox.repo_url + "/A/D/H",
- None, None, None,
- "Failed to add directory '.*I'."
- "*already exists",
- None, None, None, None, False,
- '--force')
+ # svn switch --force url/A/D/H A/D/G
+ expected_error = ('Failed to add directory.*' + re.escape(A_D_G_I) +
+ '.*a separate working copy.*already exists')
+
+ actions.run_and_verify_switch(wc_dir, A_D_G, url_A_D_H, None, None, None,
+ expected_error, None, None, None, None, False, '--force')
# Delete all three obstructions and finish the update.
- svntest.main.safe_rmtree(I_path)
- svntest.main.safe_rmtree(pi_path)
- os.remove(H_path)
+ # rm -rf A/D/G/I
+ main.safe_rmtree(A_D_G_I)
- # For our expected disk start with the standard greek tree.
- expected_disk = svntest.main.greek_state.copy()
+ # rm A/B/F/pi
+ main.safe_rmtree(A_B_F_pi)
+
+ # rm A/C/H
+ os.remove(A_C_H)
- ### There has to be a simpler way to do this...but it will do for now.
# A/B/F is switched to A/D/G
- new_A_B_F = svntest.wc.State('', {
- "A/B/F" : Item(),
- "A/B/F/rho" : Item("This is the file 'rho'.\n"),
- "A/B/F/pi" : Item("This is the file 'pi'.\n"),
- "A/B/F/tau" : Item("This is the file 'tau'.\n"),
- })
# A/C is switched to A/D
- new_A_C = svntest.wc.State('', {
- "A/C" : Item(),
- "A/C/gamma" : Item("This is the file 'gamma'.\n"),
- "A/C/G" : Item(),
- "A/C/G/pi" : Item("This is the file 'pi'.\n"),
- "A/C/G/rho" : Item("This is the file 'rho'.\n"),
- "A/C/G/tau" : Item("This is the file 'tau'.\n"),
- "A/C/H" : Item(),
- "A/C/H/chi" : Item("This is the file 'chi'.\n"),
- "A/C/H/I" : Item(),
- "A/C/H/omega" : Item("This is the file 'omega'.\n"),
- "A/C/H/psi" : Item("This is the file 'psi'.\n"),
- })
# A/D/G is switched to A/D/H
- new_A_D_G = svntest.wc.State('', {
- "A/D/G" : Item(),
- "A/D/G/chi" : Item("This is the file 'chi'.\n"),
- "A/D/G/omega" : Item("This is the file 'omega'.\n"),
- "A/D/G/I" : Item(),
- "A/D/G/psi" : Item("This is the file 'psi'.\n"),
- "A/D/H" : Item(),
- "A/D/H/chi" : Item("This is the file 'chi'.\n"),
- "A/D/H/omega" : Item("This is the file 'omega'.\n"),
- "A/D/H/I" : Item(),
- "A/D/H/psi" : Item("This is the file 'psi'.\n"),
- "iota" : Item("This is the file 'iota'.\n"),
- })
- # Remove the three switched subtrees and replace with their new contents.
- expected_disk.remove('A/B/F', 'A/C',
- 'A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
- expected_disk.add_state('', new_A_B_F)
- expected_disk.add_state('', new_A_C)
- expected_disk.add_state('', new_A_D_G)
-
- expected_status = svntest.wc.State(sbox.wc_dir, {
- "" : Item(),
- "A" : Item(),
- "A/B" : Item(),
- "A/B/lambda" : Item(),
- "A/B/E" : Item(),
- "A/B/E/alpha" : Item(),
- "A/B/E/beta" : Item(),
- "A/B/F" : Item(switched='S'),
- "A/B/F/rho" : Item(),
- "A/B/F/pi" : Item(),
- "A/B/F/tau" : Item(),
- "A/mu" : Item(),
- "A/C" : Item(switched='S'),
- "A/C/gamma" : Item(),
- "A/C/G" : Item(),
- "A/C/G/pi" : Item(),
- "A/C/G/rho" : Item(),
- "A/C/G/tau" : Item(),
- "A/C/H" : Item(),
- "A/C/H/chi" : Item(),
- "A/C/H/I" : Item(),
- "A/C/H/omega" : Item(),
- "A/C/H/psi" : Item(),
- "A/D" : Item(),
- "A/D/gamma" : Item(),
- "A/D/G" : Item(switched='S'),
- "A/D/G/chi" : Item(),
- "A/D/G/omega" : Item(),
- "A/D/G/I" : Item(),
- "A/D/G/psi" : Item(),
- "A/D/H" : Item(),
- "A/D/H/chi" : Item(),
- "A/D/H/omega" : Item(),
- "A/D/H/I" : Item(),
- "A/D/H/psi" : Item(),
- "iota" : Item(),
- })
- expected_status.tweak(status=' ', wc_rev=2)
- svntest.actions.run_and_verify_update(sbox.wc_dir,
- None,
- expected_disk,
- expected_status,
- None, None, None, None, None, False)
+ # svn up
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/C/H' : Item(status='A '),
+ 'A/C/H/omega' : Item(status='A '),
+ 'A/C/H/chi' : Item(status='A '),
+ 'A/C/H/I' : Item(status='A '),
+ 'A/C/H/psi' : Item(status='A '),
+ 'A/D/G/omega' : Item(status='A '),
+ 'A/D/G/I' : Item(status='A '),
+ 'A/D/G/psi' : Item(status='A '),
+ 'A/D/H/I' : Item(status='A '),
+ 'A/B/F/pi' : Item(status='A '),
+ })
+
+ expected_disk.remove('A/D/G/tau', 'A/D/G/rho', 'A/D/G/pi')
+ expected_disk.add({
+ 'A/D/H/I' : Item(),
+ 'A/D/G/omega' : Item(contents="This is the file 'omega'.\n"),
+ 'A/D/G/psi' : Item(contents="This is the file 'psi'.\n"),
+ 'A/D/G/chi' : Item(contents="This is the file 'chi'.\n"),
+ 'A/C/H/I' : Item(),
+ 'A/C/H/omega' : Item(contents="This is the file 'omega'.\n"),
+ 'A/C/H/psi' : Item(contents="This is the file 'psi'.\n"),
+ 'A/C/H/chi' : Item(contents="This is the file 'chi'.\n"),
+ })
+ expected_disk.tweak('A/C/H', contents=None)
+ expected_disk.tweak('A/B/F/pi', contents="This is the file 'pi'.\n")
+
+ expected_status.remove('A/D/G/tau', 'A/D/G/rho', 'A/D/G/pi')
+ expected_status.add({
+ 'A/D/G/omega' : Item(status=' ', wc_rev='2'),
+ 'A/D/G/I' : Item(status=' ', wc_rev='2'),
+ 'A/D/G/psi' : Item(status=' ', wc_rev='2'),
+ 'A/D/G/chi' : Item(status=' ', wc_rev='2'),
+ 'A/D/H/I' : Item(status=' ', wc_rev='2'),
+ 'A/C/H/psi' : Item(status=' ', wc_rev='2'),
+ 'A/C/H/omega' : Item(status=' ', wc_rev='2'),
+ 'A/C/H/chi' : Item(status=' ', wc_rev='2'),
+ 'A/C/H/I' : Item(status=' ', wc_rev='2'),
+ })
+ expected_status.tweak(wc_rev='2', status=' ')
+ expected_status.tweak('A/B/F/pi', 'A/C/H', treeconflict=None)
+ expected_status.tweak('A/D/G', switched='S')
+
+ actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+ expected_status, None, None, None, None, None, False, wc_dir)
+
def switch_with_obstructing_local_adds(sbox):
"switch tolerates WC adds"
@@ -1455,11 +1622,8 @@ def switch_with_obstructing_local_adds(s
# Setup expected results of switch.
expected_output = svntest.wc.State(sbox.wc_dir, {
- "A/B/F/gamma" : Item(status='E '),
- "A/B/F/G" : Item(status='E '),
- "A/B/F/G/pi" : Item(status='C '),
- "A/B/F/G/rho" : Item(status='A '),
- "A/B/F/G/tau" : Item(status='E '),
+ "A/B/F/gamma" : Item(status=' ', treeconflict='C'),
+ "A/B/F/G" : Item(status=' ', treeconflict='C'),
"A/B/F/H" : Item(status='A '),
"A/B/F/H/chi" : Item(status='A '),
"A/B/F/H/omega" : Item(status='A '),
@@ -1470,13 +1634,7 @@ def switch_with_obstructing_local_adds(s
expected_disk.add({
"A/B/F/gamma" : Item("This is the file 'gamma'.\n"),
"A/B/F/G" : Item(),
- "A/B/F/G/pi" : Item("\n".join(["<<<<<<< .mine",
- "This is the OBSTRUCTING file 'pi'.",
- "=======",
- "This is the file 'pi'.",
- ">>>>>>> .r1",
- ""])),
- "A/B/F/G/rho" : Item("This is the file 'rho'.\n"),
+ "A/B/F/G/pi" : Item("This is the OBSTRUCTING file 'pi'.\n"),
"A/B/F/G/tau" : Item("This is the file 'tau'.\n"),
"A/B/F/G/upsilon" : Item("This is the unversioned file 'upsilon'.\n"),
"A/B/F/H" : Item(),
@@ -1488,18 +1646,17 @@ def switch_with_obstructing_local_adds(s
expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
expected_status.tweak('A/B/F', switched='S')
expected_status.add({
- "A/B/F/gamma" : Item(status=' ', wc_rev=1),
- "A/B/F/G" : Item(status=' ', wc_rev=1),
- "A/B/F/G/pi" : Item(status='C ', wc_rev=1),
- "A/B/F/G/rho" : Item(status=' ', wc_rev=1),
- "A/B/F/G/tau" : Item(status=' ', wc_rev=1),
- "A/B/F/G/upsilon" : Item(status='A ', wc_rev=0),
- "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=0),
- })
+ 'A/B/F/gamma' : Item(status='R ', treeconflict='C', wc_rev='1'),
+ 'A/B/F/G' : Item(status='A ', treeconflict='C', wc_rev='0'),
+ 'A/B/F/G/pi' : Item(status='A ', wc_rev='0'),
+ 'A/B/F/G/tau' : Item(status='A ', wc_rev='0'),
+ 'A/B/F/G/upsilon' : Item(status='A ', wc_rev='0'),
+ '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='0'),
+ })
# "Extra" files that we expect to result from the conflicts.
extra_files = ['pi\.r0', 'pi\.r1', 'pi\.mine']
@@ -1653,8 +1810,6 @@ def mergeinfo_switch_elision(sbox):
'F' : Item(),
})
expected_skip = svntest.wc.State(B_COPY_1_path, { })
- saved_cwd = os.getcwd()
-
svntest.actions.run_and_verify_merge(B_COPY_1_path, '2', '4',
sbox.repo_url + '/A/B', None,
expected_output,
@@ -1701,8 +1856,6 @@ def mergeinfo_switch_elision(sbox):
'beta' : Item("New content"),
})
expected_skip = svntest.wc.State(E_COPY_2_path, { })
- saved_cwd = os.getcwd()
-
svntest.actions.run_and_verify_merge(E_COPY_2_path, '2', '4',
sbox.repo_url + '/A/B/E', None,
expected_output,
@@ -2319,6 +2472,8 @@ j = os.path.join
def tree_conflicts_on_switch_1_1(sbox):
"tree conflicts 1.1: tree del, leaf edit on switch"
+ sbox.build()
+
# use case 1, as in notes/tree-conflicts/use-cases.txt
# 1.1) local tree delete, incoming leaf edit
@@ -2336,6 +2491,10 @@ def tree_conflicts_on_switch_1_1(sbox):
})
expected_disk = disk_empty_dirs.copy()
+ if svntest.main.wc_is_singledb(sbox.wc_dir):
+ expected_disk.remove('D/D1', 'DF/D1', 'DD/D1', 'DD/D1/D2',
+ 'DDF/D1', 'DDF/D1/D2',
+ 'DDD/D1', 'DDD/D1/D2', 'DDD/D1/D2/D3')
# The files delta, epsilon, and zeta are incoming additions, but since
# they are all within locally deleted trees they should also be schedule
@@ -2403,6 +2562,8 @@ def tree_conflicts_on_switch_1_1(sbox):
def tree_conflicts_on_switch_1_2(sbox):
"tree conflicts 1.2: tree del, leaf del on switch"
+ sbox.build()
+
# 1.2) local tree delete, incoming leaf delete
expected_output = deep_trees_conflict_output.copy()
@@ -2442,6 +2603,10 @@ def tree_conflicts_on_switch_1_2(sbox):
expected_disk.remove('D/D1',
'DD/D1/D2',
'DDD/D1/D2/D3')
+ if svntest.main.wc_is_singledb(sbox.wc_dir):
+ expected_disk.remove('DF/D1', 'DD/D1',
+ 'DDF/D1', 'DDF/D1/D2',
+ 'DDD/D1', 'DDD/D1/D2')
expected_info = {
'F/alpha' : {
@@ -2925,6 +3090,33 @@ def copy_with_switched_subdir(sbox):
# should either be the tree of E, or nothing at all.
svntest.actions.run_and_verify_status(wc_dir, state)
+### regression test for issue #3597
+def relocate_with_relative_externals(sbox):
+ "relocate a directory containing relative externals"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ # Add a relative external.
+ change_external(os.path.join(wc_dir, 'A', 'B'), "^/A/D/G G-ext", commit=True)
+ svntest.actions.run_and_verify_svn(None, None, [], 'update', wc_dir)
+
+ # Move our repository to another location.
+ repo_dir = sbox.repo_dir
+ repo_url = sbox.repo_url
+ other_repo_dir, other_repo_url = sbox.add_repo_path('other')
+ svntest.main.copy_repos(repo_dir, other_repo_dir, 2, 0)
+ svntest.main.safe_rmtree(repo_dir, 1)
+
+ # Now relocate our working copy.
+ svntest.actions.run_and_verify_svn(None, None, [], 'switch', '--relocate',
+ repo_url, other_repo_url, wc_dir)
+
+ # Check the URL of the external -- was it updated to point to the
+ # .other repository URL?
+ svntest.actions.run_and_verify_info([{ 'URL' : '.*.other/A/D/G$' }],
+ os.path.join(wc_dir, 'A', 'B', 'G-ext'))
+
########################################################################
# Run the tests
@@ -2951,7 +3143,8 @@ test_list = [ None,
switch_change_repos_root,
relocate_and_propset,
forced_switch,
- forced_switch_failures,
+ XFail(forced_switch_failures,
+ svntest.main.is_ra_type_dav_serf),
switch_scheduled_add,
SkipUnless(mergeinfo_switch_elision, server_has_mergeinfo),
switch_with_obstructing_local_adds,
@@ -2969,7 +3162,8 @@ test_list = [ None,
single_file_relocate,
relocate_with_switched_children,
XFail(copy_with_switched_subdir),
- ]
+ XFail(relocate_with_relative_externals),
+ ]
if __name__ == '__main__':
svntest.main.run_tests(test_list)
Modified: subversion/branches/py-tests-as-modules/subversion/tests/cmdline/trans_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/tests/cmdline/trans_tests.py?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/tests/cmdline/trans_tests.py (original)
+++ subversion/branches/py-tests-as-modules/subversion/tests/cmdline/trans_tests.py Wed Sep 15 19:32:26 2010
@@ -868,9 +868,10 @@ def props_only_file_update(sbox):
# We used to leave some temporary files around. Make sure that we don't.
temps = os.listdir(os.path.join(wc_dir, svntest.main.get_admin_name(), 'tmp'))
- temps.remove('prop-base')
- temps.remove('props')
- temps.remove('text-base')
+ if os.path.exists(os.path.join(wc_dir, svntest.main.get_admin_name(),
+ 'tmp', 'props')):
+ temps.remove('prop-base')
+ temps.remove('props')
if temps:
print('Temporary files leftover: %s' % (', '.join(temps),))
raise svntest.Failure
Modified: subversion/branches/py-tests-as-modules/subversion/tests/cmdline/tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/tests/cmdline/tree_conflict_tests.py?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/tests/cmdline/tree_conflict_tests.py (original)
+++ subversion/branches/py-tests-as-modules/subversion/tests/cmdline/tree_conflict_tests.py Wed Sep 15 19:32:26 2010
@@ -51,7 +51,7 @@ def verbose_print(line):
# If verbose mode is enabled, print the (assumed newline-terminated) LINES.
def verbose_printlines(lines):
- if main.verbose_mode:
+ if main.options.verbose:
for line in lines:
sys.stdout.write(line)
@@ -107,6 +107,7 @@ def incoming_paths(root_dir, parent_dir)
'F1' : os.path.join(root_dir, "F1"),
'F' : os.path.join(parent_dir, "F"),
'F2' : os.path.join(parent_dir, "F2-in"),
+ 'F3' : os.path.join(root_dir, "F3"),
'D1' : os.path.join(root_dir, "D1"),
'D' : os.path.join(parent_dir, "D"),
'D2' : os.path.join(parent_dir, "D2-in"),
@@ -120,6 +121,7 @@ def localmod_paths(root_dir, parent_dir)
'F1' : os.path.join(root_dir, "F1"),
'F' : os.path.join(parent_dir, "F"),
'F2' : os.path.join(parent_dir, "F2-local"),
+ 'F3' : os.path.join(root_dir, "F3"),
'D1' : os.path.join(root_dir, "D1"),
'D' : os.path.join(parent_dir, "D"),
'D2' : os.path.join(parent_dir, "D2-local"),
@@ -127,8 +129,9 @@ def localmod_paths(root_dir, parent_dir)
# Perform the action MODACTION on the WC items given by PATHS. The
# available actions can be seen within this function.
-def modify(modaction, paths):
+def modify(modaction, paths, is_init=True):
F1 = paths['F1'] # existing file to copy from
+ F3 = paths['F3'] # existing file to copy from
F = paths['F'] # target file
F2 = paths['F2'] # non-existing file to copy/move to
D1 = paths['D1'] # existing dir to copy from
@@ -161,7 +164,10 @@ def modify(modaction, paths):
main.run_svn(None, 'add', D)
main.run_svn(None, 'pset', 'dprop2', 'A prop of added dir D.', D)
elif modaction == 'fC': # file Copy (from F1)
- main.run_svn(None, 'copy', F1, F)
+ if is_init:
+ main.run_svn(None, 'copy', F1, F)
+ else:
+ main.run_svn(None, 'copy', F3, F)
elif modaction == 'dC': # dir Copy (from D1)
main.run_svn(None, 'copy', D1, D)
elif modaction == 'fM': # file Move (to F2)
@@ -199,6 +205,7 @@ def modify(modaction, paths):
# File names:
# F1 = any existing file
+# F3 = any existing file
# F = the file-path being acted on
# F2 = any non-existent file-path
# D1 = any existing dir
@@ -316,8 +323,10 @@ def set_up_repos(wc_dir, br_dir, scenari
# create the file F1 and dir D1 which the tests regard as pre-existing
paths = incoming_paths(wc_dir, wc_dir) # second arg is bogus but unimportant
F1 = paths['F1'] # existing file to copy from
+ F3 = paths['F3'] # existing file to copy from
main.file_write(F1, "This is initially file F1.\n")
- main.run_svn(None, 'add', F1)
+ main.file_write(F3, "This is initially file F3.\n")
+ main.run_svn(None, 'add', F1, F3)
D1 = paths['D1'] # existing dir to copy from
main.run_svn(None, 'mkdir', D1)
@@ -411,7 +420,7 @@ def ensure_tree_conflict(sbox, operation
verbose_print("--- Making local mods")
for modaction in loc_action:
- modify(modaction, localmod_paths(".", target_path))
+ modify(modaction, localmod_paths(".", target_path), is_init=False)
if commit_local_mods:
run_and_verify_svn(None, AnyOutput, [],
'commit', target_path,
@@ -695,102 +704,11 @@ def merge_dir_add_onto_not_none(sbox):
#----------------------------------------------------------------------
-def keep_local_del_tc_inside(sbox):
- "--keep-local del on dir with TCs inside"
- # A/C <- delete with --keep-local
- # A + C A/C/dir
- # A + C A/C/file
-
- sbox.build()
- wc_dir = sbox.wc_dir
-
- C = os.path.join(wc_dir, "A", "C")
- dir = os.path.join(wc_dir, "A", "C", "dir")
- file = os.path.join(wc_dir, "A", "C", "file")
-
- # Add dir
- main.run_svn(None, 'mkdir', dir)
-
- # Add file
- content = "This is the file 'file'.\n"
- main.file_append(file, content)
- main.run_svn(None, 'add', file)
-
- main.run_svn(None, 'commit', '-m', 'Add dir and file', wc_dir)
-
- # Remove dir and file in r3.
- main.run_svn(None, 'delete', dir, file)
- main.run_svn(None, 'commit', '-m', 'Remove dir and file', wc_dir)
-
- # Warp back to -r2, dir and file coming back.
- main.run_svn(None, 'update', '-r2', wc_dir)
-
- # Set a meaningless prop on each dir and file
- run_and_verify_svn(None,
- ["property 'propname' set on '" + dir + "'\n"],
- [], 'ps', 'propname', 'propval', dir)
- run_and_verify_svn(None,
- ["property 'propname' set on '" + file + "'\n"],
- [], 'ps', 'propname', 'propval', file)
-
- # Update WC to HEAD, tree conflicts result dir and file
- # because there are local mods on the props.
- expected_output = wc.State(wc_dir, {
- 'A/C/dir' : Item(status=' ', treeconflict='C'),
- 'A/C/file' : Item(status=' ', treeconflict='C'),
- })
-
- expected_disk = main.greek_state.copy()
- expected_disk.add({
- 'A/C/dir' : Item(props={'propname' : 'propval'}),
- 'A/C/file' : Item(contents=content, props={'propname' : 'propval'}),
- })
-
- expected_status = get_virginal_state(wc_dir, 2)
- expected_status.tweak(wc_rev='3')
- expected_status.add({
- 'A/C/dir' : Item(status='A ', wc_rev='-', copied='+', treeconflict='C'),
- 'A/C/file' : Item(status='A ', wc_rev='-', copied='+', treeconflict='C'),
- })
- run_and_verify_update(wc_dir,
- expected_output, expected_disk, expected_status,
- None, None, None, None, None, 1,
- wc_dir)
-
- # Delete A/C with --keep-local, in effect disarming the tree-conflicts.
- run_and_verify_svn(None,
- verify.UnorderedOutput(['D ' + C + '\n',
- 'D ' + dir + '\n',
- 'D ' + file + '\n']),
- [], 'delete', C, '--keep-local')
-
- # Verify deletion status
- # Note: the tree conflicts are still in the status.
- expected_status.tweak('A/C', status='D ')
- expected_status.tweak('A/C/dir', status='? ', copied=None, wc_rev=None)
- expected_status.tweak('A/C/file', status='? ', copied=None, wc_rev=None)
-
- run_and_verify_status(wc_dir, expected_status)
-
- # Commit, remove the "disarmed" tree-conflict.
- expected_output = wc.State(wc_dir, { 'A/C' : Item(verb='Deleting') })
-
- expected_status.remove('A/C', 'A/C/dir', 'A/C/file')
-
- run_and_verify_commit(wc_dir,
- expected_output, expected_status, None,
- wc_dir)
-
-#----------------------------------------------------------------------
-
def force_del_tc_inside(sbox):
"--force del on dir with TCs inside"
### This test is currently marked XFail because we don't remove tree
### conflicts upon "delete --force" yet. They linger and block
### the commit.
- ### This should be handled the same as with --keep-local, but
- ### the code does not have the proper antennae for that yet.
- ### Fixing that separately.
# A/C <- delete with --force
# A + C A/C/dir
@@ -878,95 +796,6 @@ def force_del_tc_inside(sbox):
#----------------------------------------------------------------------
-def keep_local_del_tc_is_target(sbox):
- "--keep-local del on tree-conflicted targets"
- # A/C
- # A + C A/C/dir <- delete with --keep-local
- # A + C A/C/file <- delete with --keep-local
- ### This test currently XFails because the tree-conflicts on dir and
- ### file remain in the WC but were supposed to be unversioned by a commit
- ### (because of a delete --keep-local).
-
- sbox.build()
- wc_dir = sbox.wc_dir
-
- C = os.path.join(wc_dir, "A", "C")
- dir = os.path.join(wc_dir, "A", "C", "dir")
- file = os.path.join(wc_dir, "A", "C", "file")
-
- # Add dir
- main.run_svn(None, 'mkdir', dir)
-
- # Add file
- content = "This is the file 'file'.\n"
- main.file_append(file, content)
- main.run_svn(None, 'add', file)
-
- main.run_svn(None, 'commit', '-m', 'Add dir and file', wc_dir)
-
- # Remove dir and file in r3.
- main.run_svn(None, 'delete', dir, file)
- main.run_svn(None, 'commit', '-m', 'Remove dir and file', wc_dir)
-
- # Warp back to -r2, dir and file coming back.
- main.run_svn(None, 'update', '-r2', wc_dir)
-
- # Set a meaningless prop on each dir and file
- run_and_verify_svn(None,
- ["property 'propname' set on '" + dir + "'\n"],
- [], 'ps', 'propname', 'propval', dir)
- run_and_verify_svn(None,
- ["property 'propname' set on '" + file + "'\n"],
- [], 'ps', 'propname', 'propval', file)
-
- # Update WC to HEAD, tree conflicts result dir and file
- # because there are local mods on the props.
- expected_output = wc.State(wc_dir, {
- 'A/C/dir' : Item(status=' ', treeconflict='C'),
- 'A/C/file' : Item(status=' ', treeconflict='C'),
- })
-
- expected_disk = main.greek_state.copy()
- expected_disk.add({
- 'A/C/dir' : Item(props={'propname' : 'propval'}),
- 'A/C/file' : Item(contents=content, props={'propname' : 'propval'}),
- })
-
- expected_status = get_virginal_state(wc_dir, 2)
- expected_status.tweak(wc_rev='3')
- expected_status.add({
- 'A/C/dir' : Item(status='A ', wc_rev='-', copied='+', treeconflict='C'),
- 'A/C/file' : Item(status='A ', wc_rev='-', copied='+', treeconflict='C'),
- })
- run_and_verify_update(wc_dir,
- expected_output, expected_disk, expected_status,
- None, None, None, None, None, 1,
- wc_dir)
-
- # Delete nodes with --keep-local, in effect disarming the tree-conflicts.
- run_and_verify_svn(None,
- ['D ' + dir + '\n',
- 'D ' + file + '\n'],
- [],
- 'delete', dir, file, '--keep-local')
-
- expected_status.tweak('A/C/dir', status='? ', copied=None, wc_rev=None)
- expected_status.tweak('A/C/file', status='? ', copied=None, wc_rev=None)
- run_and_verify_status(wc_dir, expected_status)
-
- # Commit, remove the "disarmed" tree-conflict.
- expected_output = wc.State(wc_dir, {})
-
- ### This is why this test currently XFails. We want the conflicts
- ### on the unversioned nodes to go away.
- expected_status.remove('A/C/dir', 'A/C/file')
-
- run_and_verify_commit(wc_dir,
- expected_output, expected_status, None,
- wc_dir)
-
-#----------------------------------------------------------------------
-
def force_del_tc_is_target(sbox):
"--force del on tree-conflicted targets"
# A/C
@@ -1125,7 +954,10 @@ def query_absent_tree_conflicted_dir(sbo
## svn: Expected node '/.../tree_conflict_tests-20/A/C' to be added.
# using status:
- run_and_verify_status(C_C_path, None)
+ expected_output = wc.State(wc_dir, {
+ 'A/C/C' : Item(status='? ', treeconflict='C'),
+ })
+ run_and_verify_status(C_C_path, expected_output)
# using info:
run_and_verify_svn(None, None, [], 'info', C_C_path)
@@ -1251,11 +1083,9 @@ test_list = [ None,
XFail(merge_dir_del_onto_not_same),
merge_dir_del_onto_not_dir,
merge_dir_add_onto_not_none,
- keep_local_del_tc_inside,
XFail(force_del_tc_inside),
- XFail(keep_local_del_tc_is_target),
XFail(force_del_tc_is_target),
- XFail(query_absent_tree_conflicted_dir),
+ query_absent_tree_conflicted_dir,
XFail(up_add_onto_add_revert),
XFail(lock_update_only),
]
Modified: subversion/branches/py-tests-as-modules/subversion/tests/cmdline/update_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/tests/cmdline/update_tests.py?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/tests/cmdline/update_tests.py (original)
+++ subversion/branches/py-tests-as-modules/subversion/tests/cmdline/update_tests.py Wed Sep 15 19:32:26 2010
@@ -26,10 +26,11 @@
# General modules
import sys, re, os, subprocess
+import time
# Our testing module
import svntest
-from svntest import wc
+from svntest import wc, actions, verify
from merge_tests import expected_merge_output
from merge_tests import set_up_branch
@@ -324,17 +325,23 @@ def update_missing(sbox):
svntest.main.safe_rmtree(E_path)
svntest.main.safe_rmtree(H_path)
+ # In single-db mode all missing items will just be restored
+ if svntest.main.wc_is_singledb(wc_dir):
+ A_or_Restored = Item(verb='Restored')
+ else:
+ A_or_Restored = Item(status='A ')
+
# Create expected output tree for an update of the missing items by name
expected_output = svntest.wc.State(wc_dir, {
'A/mu' : Item(verb='Restored'),
'A/D/G/rho' : Item(verb='Restored'),
- 'A/B/E' : Item(status='A '),
- 'A/B/E/alpha' : Item(status='A '),
- 'A/B/E/beta' : Item(status='A '),
- 'A/D/H' : Item(status='A '),
- 'A/D/H/chi' : Item(status='A '),
- 'A/D/H/omega' : Item(status='A '),
- 'A/D/H/psi' : Item(status='A '),
+ 'A/B/E' : A_or_Restored,
+ 'A/B/E/alpha' : A_or_Restored,
+ 'A/B/E/beta' : A_or_Restored,
+ 'A/D/H' : A_or_Restored,
+ 'A/D/H/chi' : A_or_Restored,
+ 'A/D/H/omega' : A_or_Restored,
+ 'A/D/H/psi' : A_or_Restored,
})
# Create expected disk tree for the update.
@@ -793,15 +800,25 @@ def obstructed_update_alters_wc_props(sb
# Update the WC to that newer rev to trigger the obstruction.
#print "Updating WC"
- expected_output = svntest.wc.State(wc_dir, {})
+ # svntest.factory.make(sbox, 'svn update')
+ # exit(0)
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/foo' : Item(status=' ', treeconflict='C'),
+ })
+
expected_disk = svntest.main.greek_state.copy()
- expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
- error_re = 'Failed to add directory.*object of the same name already exists'
- svntest.actions.run_and_verify_update(wc_dir,
- expected_output,
- expected_disk,
- expected_status,
- error_re)
+ expected_disk.add({
+ 'A/foo' : Item(contents="an obstruction"),
+ })
+
+ expected_status = actions.get_virginal_state(wc_dir, 2)
+ expected_status.add({
+ 'A/foo' : Item(status='? ', treeconflict='C'),
+ })
+
+ actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+ expected_status, None, None, None, None, None, False, wc_dir)
+
# Remove the file which caused the obstruction.
#print "Removing obstruction"
@@ -1062,6 +1079,17 @@ def update_deleted_missing_dir(sbox):
'A/D/H' : Item(status='D '),
})
+ # In single-db mode the missing items are restored before the update
+ if svntest.main.wc_is_singledb(wc_dir):
+ expected_output.add({
+ 'A/D/H/psi' : Item(verb='Restored'),
+ 'A/D/H/omega' : Item(verb='Restored'),
+ 'A/D/H/chi' : Item(verb='Restored'),
+ 'A/B/E/beta' : Item(verb='Restored'),
+ 'A/B/E/alpha' : Item(verb='Restored')
+ # A/B/E and A/D/H are also restored, but are then overriden by the delete
+ })
+
# Create expected disk tree for the update.
expected_disk = svntest.main.greek_state.copy()
expected_disk.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta')
@@ -1087,6 +1115,12 @@ def update_deleted_missing_dir(sbox):
# This time we're updating the whole working copy
expected_status.tweak(wc_rev=2)
+ # And now we don't expect restore operations
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/B/E' : Item(status='D '),
+ 'A/D/H' : Item(status='D '),
+ })
+
# Do the update, on the whole working copy this time
svntest.actions.run_and_verify_update(wc_dir,
expected_output,
@@ -1134,12 +1168,23 @@ def another_hudson_problem(sbox):
# Update missing directory to receive the delete, this should mark G
# as 'deleted' and should not alter gamma's entry.
+ if not svntest.main.wc_is_singledb(wc_dir):
+ expected_output = ['D '+G_path+'\n',
+ 'Updated to revision 3.\n',
+ ]
+ else:
+ expected_output = ['Restored \'' + G_path + '\'\n',
+ 'Restored \'' + G_path + os.path.sep + 'pi\'\n',
+ 'Restored \'' + G_path + os.path.sep + 'rho\'\n',
+ 'Restored \'' + G_path + os.path.sep + 'tau\'\n',
+ 'D '+G_path+'\n',
+ 'Updated to revision 3.\n',
+ ]
+
# Sigh, I can't get run_and_verify_update to work (but not because
# of issue 919 as far as I can tell)
svntest.actions.run_and_verify_svn(None,
- ['D '+G_path+'\n',
- 'Updated to revision 3.\n',
- ], [],
+ expected_output, [],
'up', G_path)
# Both G and gamma should be 'deleted', update should produce no output
@@ -1545,6 +1590,9 @@ def nested_in_read_only(sbox):
sbox.build()
wc_dir = sbox.wc_dir
+ if svntest.main.wc_is_singledb(wc_dir):
+ raise svntest.Skip('Unsupported in single-db')
+
# Delete/commit a file
alpha_path = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha')
svntest.actions.run_and_verify_svn(None, None, [], 'rm', alpha_path)
@@ -2147,46 +2195,126 @@ def forced_update_failures(sbox):
# A forced update that tries to add a file when an unversioned directory
# of the same name already exists should fail.
- F_Path = os.path.join(wc_backup, 'A', 'B', 'F')
- svntest.actions.run_and_verify_update(F_Path, None, None, None,
- ".*Failed to add file.*" + \
- "a non-file object of the " + \
- "same name already exists",
- None, None, None, None, 0, F_Path,
- '--force')
+ #svntest.factory.make(sbox, """svn up --force $WC_DIR.backup/A/B/F""")
+ #exit(0)
+ backup_A_B_F = os.path.join(wc_backup, 'A', 'B', 'F')
+
+ # svn up --force $WC_DIR.backup/A/B/F
+ expected_output = svntest.wc.State(wc_backup, {
+ 'A/B/F/nu' : Item(status=' ', treeconflict='C'),
+ })
+
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.add({
+ 'A/B/F/nu' : Item(),
+ 'A/C/I' :
+ Item(contents="This is the file 'I'...shouldn't I be a dir?\n"),
+ })
+
+ expected_status = actions.get_virginal_state(wc_backup, 1)
+ expected_status.add({
+ 'A/B/F/nu' : Item(status='? ', treeconflict='C'),
+ })
+ expected_status.tweak('A/B/F', wc_rev='2')
+
+ actions.run_and_verify_update(wc_backup, expected_output,
+ expected_disk, expected_status, None, None, None, None, None, False,
+ '--force', backup_A_B_F)
+
# A forced update that tries to add a directory when an unversioned file
# of the same name already exists should fail.
- C_Path = os.path.join(wc_backup, 'A', 'C')
- svntest.actions.run_and_verify_update(C_Path, None, None, None,
- ".*Failed to add directory.*" + \
- "a non-directory object of the " + \
- "same name already exists",
- None, None, None, None, 0, C_Path,
- '--force')
-
- # Clean-up what we have done so far. Remove the unversioned file A/C/I
- # and the unversioned directory A/B/F/nu. Then update the backup to
- # r2, except for A/C, update that to r1 so A/C/I isn't present.
- # working copy.
- os.remove(I_path)
- os.rmdir(nu_path)
- svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
- 'up', wc_backup)
- svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
- 'up', '-r', '1', C_Path)
-
- # Checkout %URL%/A/C/I@2 directly to A/C/I. A/C, being at r1, views
- # this as an unversioned object.
- I_url = sbox.repo_url + "/A/C/I"
- exit_code, so, se = svntest.actions.run_and_verify_svn(
- "Unexpected error during co",
- ['Checked out revision 2.\n'], [],
- "co", I_url, I_path)
- svntest.actions.run_and_verify_update(C_Path, None, None, None,
- "Failed to add directory '.*I'.*already exists",
- None, None, None, None, 0, C_Path,
- '--force')
+ # svntest.factory.make(sbox, """
+ # svn up --force wc_dir_backup/A/C
+ # rm -rf wc_dir_backup/A/C/I wc_dir_backup/A/B/F/nu
+ # svn up wc_dir_backup
+ # svn up -r1 wc_dir_backup/A/C
+ # svn co url/A/C/I wc_dir_backup/A/C/I
+ # svn up --force wc_dir_backup/A/C
+ # """)
+ # exit(0)
+ url = sbox.repo_url
+ wc_dir_backup = sbox.wc_dir + '.backup'
+
+ backup_A_B_F_nu = os.path.join(wc_dir_backup, 'A', 'B', 'F', 'nu')
+ backup_A_C = os.path.join(wc_dir_backup, 'A', 'C')
+ backup_A_C_I = os.path.join(wc_dir_backup, 'A', 'C', 'I')
+ url_A_C_I = url + '/A/C/I'
+
+ # svn up --force wc_dir_backup/A/C
+ expected_output = svntest.wc.State(wc_dir_backup, {
+ 'A/C/I' : Item(status=' ', treeconflict='C'),
+ })
+
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.add({
+ 'A/B/F/nu' : Item(),
+ 'A/C/I' :
+ Item(contents="This is the file 'I'...shouldn't I be a dir?\n"),
+ })
+
+ expected_status = actions.get_virginal_state(wc_dir_backup, 1)
+ expected_status.add({
+ 'A/C/I' : Item(status='? ', treeconflict='C'),
+ 'A/B/F/nu' : Item(status='? ', treeconflict='C'),
+ })
+ expected_status.tweak('A/C', 'A/B/F', wc_rev='2')
+
+ actions.run_and_verify_update(wc_dir_backup, expected_output,
+ expected_disk, expected_status, None, None, None, None, None, False,
+ '--force', backup_A_C)
+
+ # rm -rf wc_dir_backup/A/C/I wc_dir_backup/A/B/F/nu
+ os.remove(backup_A_C_I)
+ svntest.main.safe_rmtree(backup_A_B_F_nu)
+
+ # svn up wc_dir_backup
+ expected_output = svntest.wc.State(wc_dir_backup, {
+ 'A/C/I' : Item(status='A '),
+ 'A/B/F/nu' : Item(status='A '),
+ })
+
+ expected_disk.tweak('A/B/F/nu', contents="This is the file 'nu'\n")
+ expected_disk.tweak('A/C/I', contents=None)
+
+ expected_status.tweak(wc_rev='2', status=' ')
+ expected_status.tweak('A/C/I', 'A/B/F/nu', treeconflict=None)
+
+ actions.run_and_verify_update(wc_dir_backup, expected_output,
+ expected_disk, expected_status, None, None, None, None, None, False,
+ wc_dir_backup)
+
+ # svn up -r1 wc_dir_backup/A/C
+ expected_output = svntest.wc.State(wc_dir_backup, {
+ 'A/C/I' : Item(status='D '),
+ })
+
+ expected_disk.remove('A/C/I')
+
+ expected_status.remove('A/C/I')
+ expected_status.tweak('A/C', wc_rev='1')
+
+ actions.run_and_verify_update(wc_dir_backup, expected_output,
+ expected_disk, expected_status, None, None, None, None, None, False,
+ '-r1', backup_A_C)
+
+ # svn co url/A/C/I wc_dir_backup/A/C/I
+ expected_output = svntest.wc.State(wc_dir_backup, {})
+
+ expected_disk = svntest.wc.State(wc_dir, {})
+
+ actions.run_and_verify_checkout2(False, url_A_C_I, backup_A_C_I,
+ expected_output, expected_disk, None, None, None, None)
+
+ # svn up --force wc_dir_backup/A/C
+ expected_error = (
+ "svn: Failed to add directory .*I.*working copy with the same name "
+ + "already exists"
+ )
+
+ actions.run_and_verify_update(wc_dir_backup, None, None, None,
+ expected_error, None, None, None, None, False, '--force', backup_A_C)
+
#----------------------------------------------------------------------
# Test for issue #2556. The tests maps a virtual drive to a working copy
@@ -2803,44 +2931,17 @@ def update_with_obstructing_additions(sb
})
expected_status.tweak('', 'iota', status=' ', wc_rev=4)
- expected_status.tweak('omicron', status='A ', copied='+', wc_rev='-',
+ expected_status.tweak('omicron', status='R ', copied='+', wc_rev='-',
treeconflict='C')
- ### ugh. this update will leave the working copy in a BROKEN state.
- ### the incoming add is flagged as a tree conflict against our local-copy.
- ### the file will be "skipped" during the update, and the file will be
- ### dropped on the floor. 'omicron' is then left in the same "local-copy"
- ### scheduling state (schedule-add). however, this is incorrect because
- ### the directory says it is r4 which *includes* an 'omicron', yet we
- ### have discarded all knowledge of it. the update *should* place the
- ### incoming 'omicron' into the "revert base" and mark our local copy as
- ### a schedule-replace.
- ###
- ### see: http://svn.haxx.se/dev/archive-2009-04/0760.shtml
svntest.actions.run_and_verify_update(wc_dir, expected_output,
expected_disk, expected_status,
None, None, None, None, None, False,
wc_dir, '-N')
# Resolve the tree conflict.
- svntest.main.run_svn(None, 'resolve', '--accept', 'working', omicron_path)
+ svntest.main.run_svn(None, 'resolved', omicron_path)
- ### in wc-1, I believe we see the local-copy as a different revision
- ### than the parent directory (entry->revision is overloaded; normally,
- ### it is supposed to represent the BASE revision; we drop a copyfrom
- ### rev in there, making it appear different from the parent), so we
- ### send the mixed-rev in the update report (UNVERIFIED; this is
- ### speculation on cause; the effect is known, as follows). given the
- ### mixed-rev report, the server will send down another add, reporting
- ### another conflict.
- ###
- ### in wc-ng, a local-copy does not have a revision (it hasn't been
- ### committed yet!). further, all BASE information has been lost, so
- ### there is no knowledge of a BASE 'omicron', which is not-present or
- ### at an old revision, or whatever. thus, wc-ng sees "r4" for the
- ### directory and thinks there are no sub-items to report as different.
- ### the server returns with "you're up to date" rather than sending
- ### another add. thus, no conflict occurs on 'omicron'.
expected_output = wc.State(wc_dir, { })
expected_status.tweak('omicron', treeconflict=None)
@@ -4235,20 +4336,34 @@ def restarted_update_should_delete_dir_p
expected_status, None, other_wc)
# Back in the first working copy, create an obstructing path and
- # update. The update will be interrupted, resulting in an incomplete
- # dir which still has the property.
+ # update. The update will flag a tree conflict.
svntest.main.file_write(zeta_path, 'Obstructing file\n')
- error_re = 'Failed to add file.*file of the same name already exists'
- svntest.actions.run_and_verify_update(wc_dir, None, None, None,
- error_re)
+ #svntest.factory.make(sbox, 'svn up')
+ #exit(0)
+ # svn up
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A' : Item(status=' U'),
+ 'A/zeta' : Item(status=' ', treeconflict='C'),
+ })
+
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.add({
+ 'A/zeta' : Item(contents="Obstructing file\n"),
+ })
+
+ expected_status = actions.get_virginal_state(wc_dir, 3)
+ expected_status.add({
+ 'A/zeta' : Item(status='? ', treeconflict='C'),
+ })
+
+ actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+ expected_status, None, None, None, None, None, False, wc_dir)
# Now, delete the obstructing path and rerun the update.
- # A's property should disappear.
os.unlink(zeta_path)
expected_output = svntest.wc.State(wc_dir, {
- 'A' : Item(status=' U'),
'A/zeta' : Item(status='A '),
})
@@ -4304,6 +4419,8 @@ def tree_conflicts_on_update_1_1(sbox):
# use case 1, as in notes/tree-conflicts/use-cases.txt
# 1.1) local tree delete, incoming leaf edit
+ sbox.build()
+
expected_output = deep_trees_conflict_output.copy()
expected_output.add({
'DDF/D1/D2' : Item(status='D '),
@@ -4318,6 +4435,10 @@ def tree_conflicts_on_update_1_1(sbox):
})
expected_disk = disk_empty_dirs.copy()
+ if svntest.main.wc_is_singledb(sbox.wc_dir):
+ expected_disk.remove('D/D1', 'DF/D1', 'DD/D1', 'DD/D1/D2',
+ 'DDF/D1', 'DDF/D1/D2',
+ 'DDD/D1', 'DDD/D1/D2', 'DDD/D1/D2/D3')
# The files delta, epsilon, and zeta are incoming additions, but since
# they are all within locally deleted trees they should also be schedule
@@ -4386,6 +4507,8 @@ def tree_conflicts_on_update_1_2(sbox):
# 1.2) local tree delete, incoming leaf delete
+ sbox.build()
+
expected_output = deep_trees_conflict_output.copy()
expected_output.add({
'DDD/D1/D2' : Item(status='D '),
@@ -4423,6 +4546,10 @@ def tree_conflicts_on_update_1_2(sbox):
expected_disk.remove('D/D1',
'DD/D1/D2',
'DDD/D1/D2/D3')
+ if svntest.main.wc_is_singledb(sbox.wc_dir):
+ expected_disk.remove('DF/D1', 'DD/D1',
+ 'DDF/D1', 'DDF/D1/D2',
+ 'DDD/D1', 'DDD/D1/D2')
expected_info = {
'F/alpha' : {
@@ -4827,8 +4954,6 @@ def tree_conflicts_on_update_3(sbox):
#----------------------------------------------------------------------
# Test for issue #3354 'update fails when file with local mods is moved
# and modified'
-#
-# Marked as XFail until issue #3354 is resolved.
def update_moves_and_modifies_an_edited_file(sbox):
"update moves and modifies a file with edits"
@@ -5470,6 +5595,160 @@ def mergeinfo_updates_merge_with_local_m
'pg', SVN_PROP_MERGEINFO, '-R',
A_COPY_path)
+#----------------------------------------------------------------------
+# Test for receiving modified properties on added files that were originally
+# moved from somewhere else. (Triggers locate_copyfrom behavior)
+def add_moved_file_has_props(sbox):
+ """update adding moved file receives modified props"""
+ sbox.build()
+
+ wc_dir = sbox.wc_dir
+
+ G = os.path.join(os.path.join(wc_dir, 'A', 'D', 'G'))
+ pi = os.path.join(G, 'pi')
+ G_new = os.path.join(wc_dir, 'G_new')
+
+ # Give pi some property
+ svntest.main.run_svn(None, 'ps', 'svn:eol-style', 'native', pi)
+ svntest.main.run_svn(None, 'ci', wc_dir, '-m', 'added eol-style')
+
+ svntest.actions.run_and_verify_svn(None, 'At revision 2.', [], 'up', wc_dir)
+
+ # Now move pi to a different place
+ svntest.main.run_svn(None, 'mkdir', G_new)
+ svntest.main.run_svn(None, 'mv', pi, G_new)
+ svntest.main.run_svn(None, 'ci', wc_dir, '-m', 'Moved pi to G_new')
+
+ svntest.actions.run_and_verify_svn(None, 'At revision 3.', [], 'up', wc_dir)
+
+
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
+ expected_status.remove('A/D/G/pi')
+ expected_status.add({
+ 'G_new' : Item (status=' ', wc_rev=3),
+ 'G_new/pi' : Item (status=' ', wc_rev=3),
+ })
+
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+ svntest.main.run_svn(None, 'up', '-r', '0', G_new)
+ svntest.main.run_svn(None, 'up', wc_dir)
+
+ # This shouldn't show property modifications, but at r982550 it did.
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+#----------------------------------------------------------------------
+# Test for receiving modified properties on added files that were originally
+# moved from somewhere else. (Triggers locate_copyfrom behavior). This is
+# an extended variant that has another property change on the new path
+def add_moved_file_has_props2(sbox):
+ """update adding moved node receives 2* props"""
+ sbox.build()
+
+ wc_dir = sbox.wc_dir
+
+ G = os.path.join(os.path.join(wc_dir, 'A', 'D', 'G'))
+ pi = os.path.join(G, 'pi')
+ G_new = os.path.join(wc_dir, 'G_new')
+
+ # Give pi some property
+ svntest.main.run_svn(None, 'ps', 'svn:eol-style', 'native', pi)
+ svntest.main.run_svn(None, 'ci', wc_dir, '-m', 'added eol-style')
+
+ svntest.actions.run_and_verify_svn(None, 'At revision 2.', [], 'up', wc_dir)
+
+ # Now move pi to a different place
+ svntest.main.run_svn(None, 'mkdir', G_new)
+ svntest.main.run_svn(None, 'mv', pi, G_new)
+ svntest.main.run_svn(None, 'ps', 'svn:eol-style', 'CR', os.path.join(G_new, 'pi'))
+
+ svntest.main.run_svn(None, 'ci', wc_dir, '-m', 'Moved pi to G_new')
+
+ svntest.actions.run_and_verify_svn(None, 'At revision 3.', [], 'up', wc_dir)
+
+
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
+ expected_status.remove('A/D/G/pi')
+ expected_status.add({
+ 'G_new' : Item (status=' ', wc_rev=3),
+ 'G_new/pi' : Item (status=' ', wc_rev=3),
+ })
+
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+ svntest.main.run_svn(None, 'up', '-r', '0', G_new)
+ svntest.main.run_svn(None, 'up', wc_dir)
+
+ # This shouldn't show local modifications, but currently it
+ # shows a property conflict on G_new/pi.
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+
+# A regression test for a 1.7-dev crash upon updating a WC to a different
+# revision when it contained an excluded dir.
+def update_with_excluded_subdir(sbox):
+ """update with an excluded subdir"""
+ sbox.build()
+
+ wc_dir = sbox.wc_dir
+
+ G = os.path.join(os.path.join(wc_dir, 'A', 'D', 'G'))
+
+ # Make the directory 'G' excluded.
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/D/G' : Item(status='D '),
+ })
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
+ svntest.actions.run_and_verify_update(wc_dir, expected_output,
+ expected_disk, expected_status,
+ None, None, None, None, None, False,
+ '--set-depth=exclude', G)
+
+ # Commit a new revision so there is something to update to.
+ svntest.main.run_svn(None, 'mkdir', '-m', '', sbox.repo_url + '/New')
+
+ # Test updating the WC.
+ expected_output = svntest.wc.State(wc_dir, {
+ 'New' : Item(status='A ') })
+ expected_disk.add({
+ 'New' : Item() })
+ expected_status.add({
+ 'New' : Item(status=' ') })
+ expected_status.tweak(wc_rev=2)
+ svntest.actions.run_and_verify_update(wc_dir, expected_output,
+ expected_disk, expected_status)
+
+#----------------------------------------------------------------------
+# Test for issue #3471 'svn up touches file w/ lock & svn:keywords property'
+#
+# Marked as XFail until the issue is fixed.
+def update_with_file_lock_and_keywords_property_set(sbox):
+ """update with file lock & keywords property set"""
+ sbox.build()
+
+ wc_dir = sbox.wc_dir
+
+ mu_path = os.path.join(wc_dir, 'A', 'mu')
+ svntest.main.file_append(mu_path, '$Id$')
+ svntest.main.run_svn(None, 'ps', 'svn:keywords', 'Id', mu_path)
+ svntest.main.run_svn(None, 'lock', mu_path)
+ mu_ts_before_update = os.path.getmtime(mu_path)
+
+ # Make sure we are at a different timestamp to really notice a mtime change
+ time.sleep(1)
+
+ # Issue #3471 manifests itself here; The timestamp of 'mu' gets updated
+ # to the time of the last "svn up".
+ sbox.simple_update()
+ mu_ts_after_update = os.path.getmtime(mu_path)
+ if (mu_ts_before_update != mu_ts_after_update):
+ print("The timestamp of 'mu' before and after update does not match.")
+ raise svntest.Failure
+
+
#######################################################################
# Run the tests
@@ -5538,6 +5817,10 @@ test_list = [ None,
XFail(update_deleted_locked_files),
XFail(update_empty_hides_entries),
mergeinfo_updates_merge_with_local_mods,
+ add_moved_file_has_props,
+ XFail(add_moved_file_has_props2),
+ update_with_excluded_subdir,
+ XFail(update_with_file_lock_and_keywords_property_set)
]
if __name__ == '__main__':
Modified: subversion/branches/py-tests-as-modules/subversion/tests/cmdline/upgrade_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/tests/cmdline/upgrade_tests.py?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/tests/cmdline/upgrade_tests.py (original)
+++ subversion/branches/py-tests-as-modules/subversion/tests/cmdline/upgrade_tests.py Wed Sep 15 19:32:26 2010
@@ -37,6 +37,7 @@ import tarfile
import tempfile
import svntest
+from svntest import wc
Item = svntest.wc.StateItem
XFail = svntest.testcase.XFail
@@ -52,12 +53,16 @@ def get_current_format():
return int(re.search("\n#define SVN_WC__VERSION (\d+)\n", format_file).group(1))
-def replace_sbox_with_tarfile(sbox, tar_filename):
+def replace_sbox_with_tarfile(sbox, tar_filename,
+ dir=None):
try:
svntest.main.safe_rmtree(sbox.wc_dir)
except OSError, e:
pass
+ if not dir:
+ dir = tar_filename.split('.')[0]
+
tarpath = os.path.join(os.path.dirname(sys.argv[0]), 'upgrade_tests_data',
tar_filename)
t = tarfile.open(tarpath, 'r:bz2')
@@ -65,8 +70,7 @@ def replace_sbox_with_tarfile(sbox, tar_
for member in t.getmembers():
t.extract(member, extract_dir)
- shutil.move(os.path.join(extract_dir, tar_filename.split('.')[0]),
- sbox.wc_dir)
+ shutil.move(os.path.join(extract_dir, dir), sbox.wc_dir)
def check_format(sbox, expected_format):
@@ -82,9 +86,19 @@ def check_format(sbox, expected_format):
raise svntest.Failure("found format '%d'; expected '%d'; in wc '%s'" %
(found_format, expected_format, root))
+ if svntest.main.wc_is_singledb(sbox.wc_dir):
+ dirs[:] = []
+
if dot_svn in dirs:
dirs.remove(dot_svn)
+def check_pristine(sbox, files):
+ for file in files:
+ file_path = sbox.ospath(file)
+ file_text = open(file_path, 'r').read()
+ file_pristine = open(svntest.wc.text_base_path(file_path), 'r').read()
+ if (file_text != file_pristine):
+ raise svntest.Failure("pristine mismatch for '%s'" % (file))
def check_dav_cache(dir_path, wc_id, expected_dav_caches):
dot_svn = svntest.main.get_admin_name()
@@ -104,6 +118,60 @@ def check_dav_cache(dir_path, wc_id, exp
db.close()
+# Very simple working copy property diff handler for single line textual properties
+# Should probably be moved to svntest/actions.py after some major refactoring.
+def simple_property_verify(dir_path, expected_props):
+
+ # Shows all items in dict1 that are not also in dict2
+ def diff_props(dict1, dict2, name, match):
+
+ equal = True;
+ for key in dict1:
+ node = dict1[key]
+ node2 = dict2.get(key, None)
+ if node2:
+ for prop in node:
+ v1 = node[prop]
+ v2 = node2.get(prop, None)
+
+ if not v2:
+ print('\'%s\' property on \'%s\' not found in %s' %
+ (prop, key, name))
+ equal = False
+ if match and v1 != v2:
+ print('Expected \'%s\' on \'%s\' to be \'%s\', but found \'%s\'' %
+ (prop, key, v1, v2))
+ equal = False
+ else:
+ print('\'%s\': %s not found in %s' % (key, dict1[key], name))
+ equal = False
+
+ return equal
+
+
+ exit_code, output, errput = svntest.main.run_svn(None, 'proplist', '-R',
+ '-v', dir_path)
+
+ actual_props = {}
+ target = None
+ name = None
+
+ for i in output:
+ if i.startswith('Properties on '):
+ target = i[15+len(dir_path)+1:-3].replace(os.path.sep, '/')
+ elif not i.startswith(' '):
+ name = i.strip()
+ else:
+ v = actual_props.get(target, {})
+ v[name] = i.strip()
+ actual_props[target] = v
+
+ v1 = diff_props(expected_props, actual_props, 'actual', True)
+ v2 = diff_props(actual_props, expected_props, 'expected', False)
+
+ if not v1 or not v2:
+ print('Actual properties: %s' % actual_props)
+ raise svntest.Failure("Properties unequal")
def run_and_verify_status_no_server(wc_dir, expected_status):
"same as svntest.actions.run_and_verify_status(), but without '-u'"
@@ -142,6 +210,7 @@ def basic_upgrade(sbox):
# Now check the contents of the working copy
expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
+ check_pristine(sbox, ['iota', 'A/mu'])
def upgrade_with_externals(sbox):
"upgrade with externals"
@@ -160,6 +229,8 @@ def upgrade_with_externals(sbox):
# Actually check the format number of the upgraded working copy
check_format(sbox, get_current_format())
+ check_pristine(sbox, ['iota', 'A/mu',
+ 'A/D/x/lambda', 'A/D/x/E/alpha'])
def upgrade_1_5_body(sbox, subcommand):
replace_sbox_with_tarfile(sbox, 'upgrade_1_5.tar.bz2')
@@ -180,6 +251,7 @@ def upgrade_1_5_body(sbox, subcommand):
# Now check the contents of the working copy
expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
+ check_pristine(sbox, ['iota', 'A/mu'])
def upgrade_1_5(sbox):
@@ -341,6 +413,238 @@ def basic_upgrade_1_0(sbox):
svntest.actions.run_and_verify_info(expected_infos,
os.path.join(sbox.wc_dir, 'DELETED'))
+ check_pristine(sbox, ['iota', 'A/mu', 'A/D/H/zeta'])
+
+# Helper function for the x3 tests.
+def do_x3_upgrade(sbox):
+ # Attempt to use the working copy, this should give an error
+ expected_stderr = wc_is_too_old_regex
+ svntest.actions.run_and_verify_svn(None, None, expected_stderr,
+ 'info', sbox.wc_dir)
+
+
+ # Now upgrade the working copy
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'upgrade', sbox.wc_dir)
+
+ # Actually check the format number of the upgraded working copy
+ check_format(sbox, get_current_format())
+
+ # Now check the contents of the working copy
+ expected_status = svntest.wc.State(sbox.wc_dir,
+ {
+ '' : Item(status=' ', wc_rev='2'),
+ 'A' : Item(status=' ', wc_rev='2'),
+ 'A/D' : Item(status=' ', wc_rev='2'),
+ 'A/D/H' : Item(status=' ', wc_rev='2'),
+ 'A/D/H/omega' : Item(status=' ', wc_rev='2'),
+ 'A/D/H/psi' : Item(status='D ', wc_rev='2'),
+ 'A/D/H/new' : Item(status='A ', copied='+', wc_rev='-'),
+ 'A/D/H/chi' : Item(status='R ', copied='+', wc_rev='-'),
+ 'A/D/gamma' : Item(status='D ', wc_rev='2'),
+ 'A/D/G' : Item(status=' ', wc_rev='2'),
+ 'A/B_new' : Item(status='A ', copied='+', wc_rev='-'),
+ 'A/B_new/B' : Item(status='A ', copied='+', wc_rev='-'),
+ 'A/B_new/B/E' : Item(status=' M', copied='+', wc_rev='-'),
+ 'A/B_new/B/E/alpha' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/B_new/B/E/beta' : Item(status='R ', copied='+', wc_rev='-'),
+ 'A/B_new/B/new' : Item(status='A ', copied='+', wc_rev='-'),
+ 'A/B_new/B/lambda' : Item(status='R ', copied='+', wc_rev='-'),
+ 'A/B_new/B/F' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/B_new/E' : Item(status=' M', copied='+', wc_rev='-'),
+ 'A/B_new/E/alpha' : Item(status=' M', copied='+', wc_rev='-'),
+ 'A/B_new/E/beta' : Item(status='RM', copied='+', wc_rev='-'),
+ 'A/B_new/lambda' : Item(status='R ', copied='+', wc_rev='-'),
+ 'A/B_new/new' : Item(status='A ', copied='+', wc_rev='-'),
+ 'A/B_new/F' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/B' : Item(status=' ', wc_rev='2'),
+ 'A/B/E' : Item(status=' ', wc_rev='2'),
+ 'A/B/E/beta' : Item(status='RM', copied='+', wc_rev='-'),
+ 'A/B/E/alpha' : Item(status=' M', wc_rev='2'),
+ 'A/B/F' : Item(status=' ', wc_rev='2'),
+ 'A/B/lambda' : Item(status='R ', copied='+', wc_rev='-'),
+ 'A/B/new' : Item(status='A ', copied='+', wc_rev='-'),
+ 'A/G_new' : Item(status='A ', copied='+', wc_rev='-'),
+ 'A/G_new/rho' : Item(status='R ', copied='+', wc_rev='-'),
+ 'iota' : Item(status=' ', wc_rev='2'),
+ 'A_new' : Item(status='A ', wc_rev='0'),
+ 'A_new/alpha' : Item(status='A ', copied='+', wc_rev='-'),
+ })
+ run_and_verify_status_no_server(sbox.wc_dir, expected_status)
+
+ simple_property_verify(sbox.wc_dir, {
+ 'A/B_new/E/beta' : {'x3' : '3x',
+ 'svn:eol-style': 'native'},
+ 'A/B/E/beta' : {'s' : 't',
+ 'svn:eol-style': 'native'},
+ 'A/B_new/B/E/alpha' : {'svn:eol-style': 'native'},
+ 'A/B/E/alpha' : {'q': 'r',
+ 'svn:eol-style': 'native'},
+ 'A_new/alpha' : {'svn:eol-style': 'native'},
+ 'A/B_new/B/new' : {'svn:eol-style': 'native'},
+ 'A/B_new/E/alpha' : {'svn:eol-style': 'native',
+ 'u': 'v'},
+ 'A/B_new/B/E' : {'q': 'r'},
+ 'A/B_new/lambda' : {'svn:eol-style': 'native'},
+ 'A/B_new/E' : {'x3': '3x'},
+ 'A/B_new/new' : {'svn:eol-style': 'native'},
+ 'A/B/lambda' : {'svn:eol-style': 'native'},
+ 'A/B_new/B/E/beta' : {'svn:eol-style': 'native'},
+ 'A/B_new/B/lambda' : {'svn:eol-style': 'native'},
+ 'A/B/new' : {'svn:eol-style': 'native'},
+ 'A/G_new/rho' : {'svn:eol-style': 'native'}
+ })
+
+ svntest.actions.run_and_verify_svn(None, 'Reverted.*', [],
+ 'revert', '-R', sbox.wc_dir)
+
+ expected_status = svntest.wc.State(sbox.wc_dir,
+ {
+ '' : Item(status=' ', wc_rev='2'),
+ 'A' : Item(status=' ', wc_rev='2'),
+ 'A/D' : Item(status=' ', wc_rev='2'),
+ 'A/D/H' : Item(status=' ', wc_rev='2'),
+ 'A/D/H/omega' : Item(status=' ', wc_rev='2'),
+ 'A/D/H/psi' : Item(status=' ', wc_rev='2'),
+ 'A/D/H/chi' : Item(status=' ', wc_rev='2'),
+ 'A/D/gamma' : Item(status=' ', wc_rev='2'),
+ 'A/D/G' : Item(status=' ', wc_rev='2'),
+ 'A/B' : Item(status=' ', wc_rev='2'),
+ 'A/B/F' : Item(status=' ', wc_rev='2'),
+ 'A/B/E' : Item(status=' ', wc_rev='2'),
+ 'A/B/E/beta' : Item(status=' ', wc_rev='2'),
+ 'A/B/E/alpha' : Item(status=' ', wc_rev='2'),
+ 'A/B/lambda' : Item(status=' ', wc_rev='2'),
+ 'iota' : Item(status=' ', wc_rev='2'),
+ })
+ run_and_verify_status_no_server(sbox.wc_dir, expected_status)
+
+ simple_property_verify(sbox.wc_dir, {
+ 'A/B/E/beta' : {'svn:eol-style': 'native'},
+# 'A/B/lambda' : {'svn:eol-style': 'native'},
+ 'A/B/E/alpha' : {'svn:eol-style': 'native'}
+ })
+
+def x3_1_4_0(sbox):
+ "3x same wc upgrade 1.4.0 test"
+
+ sbox.build(create_wc = False)
+ replace_sbox_with_tarfile(sbox, 'wc-3x-1.4.0.tar.bz2', dir='wc-1.4.0')
+
+ do_x3_upgrade(sbox)
+
+def x3_1_4_6(sbox):
+ "3x same wc upgrade 1.4.6 test"
+
+ sbox.build(create_wc = False)
+ replace_sbox_with_tarfile(sbox, 'wc-3x-1.4.6.tar.bz2', dir='wc-1.4.6')
+
+ do_x3_upgrade(sbox)
+
+def x3_1_6_12(sbox):
+ "3x same wc upgrade 1.6.12 test"
+
+ sbox.build(create_wc = False)
+ replace_sbox_with_tarfile(sbox, 'wc-3x-1.6.12.tar.bz2', dir='wc-1.6.12')
+
+ do_x3_upgrade(sbox)
+
+def missing_dirs(sbox):
+ "missing directories and obstructing files"
+
+ # tarball wc looks like:
+ # svn co URL wc
+ # svn cp wc/A/B wc/A/B_new
+ # rm -rf wc/A/B/E wc/A/D wc/A/B_new/E wc/A/B_new/F
+ # touch wc/A/D wc/A/B_new/F
+
+ sbox.build(create_wc = False)
+ replace_sbox_with_tarfile(sbox, 'missing-dirs.tar.bz2')
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'upgrade', sbox.wc_dir)
+ expected_status = svntest.wc.State(sbox.wc_dir,
+ {
+ '' : Item(status=' ', wc_rev='1'),
+ 'A' : Item(status=' ', wc_rev='1'),
+ 'A/mu' : Item(status=' ', wc_rev='1'),
+ 'A/C' : Item(status=' ', wc_rev='1'),
+ 'A/D' : Item(status='~ ', wc_rev='?'),
+ 'A/B' : Item(status=' ', wc_rev='1'),
+ 'A/B/F' : Item(status=' ', wc_rev='1'),
+ 'A/B/E' : Item(status='! ', wc_rev='?'),
+ 'A/B/lambda' : Item(status=' ', wc_rev='1'),
+ 'iota' : Item(status=' ', wc_rev='1'),
+ 'A/B_new' : Item(status='A ', wc_rev='-', copied='+'),
+ 'A/B_new/E' : Item(status='! ', wc_rev='?'),
+ 'A/B_new/F' : Item(status='~ ', wc_rev='?'),
+ 'A/B_new/lambda' : Item(status=' ', wc_rev='-', copied='+'),
+ })
+ if svntest.main.wc_is_singledb(sbox.wc_dir):
+ expected_status.tweak('A/D', 'A/B_new/F', status='! ')
+ run_and_verify_status_no_server(sbox.wc_dir, expected_status)
+
+def missing_dirs2(sbox):
+ "missing directories and obstructing dirs"
+
+ sbox.build(create_wc = False)
+ replace_sbox_with_tarfile(sbox, 'missing-dirs.tar.bz2')
+ os.remove(sbox.ospath('A/D'))
+ os.remove(sbox.ospath('A/B_new/F'))
+ os.mkdir(sbox.ospath('A/D'))
+ os.mkdir(sbox.ospath('A/B_new/F'))
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'upgrade', sbox.wc_dir)
+ expected_status = svntest.wc.State(sbox.wc_dir,
+ {
+ '' : Item(status=' ', wc_rev='1'),
+ 'A' : Item(status=' ', wc_rev='1'),
+ 'A/mu' : Item(status=' ', wc_rev='1'),
+ 'A/C' : Item(status=' ', wc_rev='1'),
+ 'A/D' : Item(status='~ ', wc_rev='?'),
+ 'A/B' : Item(status=' ', wc_rev='1'),
+ 'A/B/F' : Item(status=' ', wc_rev='1'),
+ 'A/B/E' : Item(status='! ', wc_rev='?'),
+ 'A/B/lambda' : Item(status=' ', wc_rev='1'),
+ 'iota' : Item(status=' ', wc_rev='1'),
+ 'A/B_new' : Item(status='A ', wc_rev='-', copied='+'),
+ 'A/B_new/E' : Item(status='! ', wc_rev='?'),
+ 'A/B_new/F' : Item(status='~ ', wc_rev='?'),
+ 'A/B_new/lambda' : Item(status=' ', wc_rev='-', copied='+'),
+ })
+ if svntest.main.wc_is_singledb(sbox.wc_dir):
+ expected_status.tweak('A/D', 'A/B_new/F', status='! ')
+ run_and_verify_status_no_server(sbox.wc_dir, expected_status)
+
+def delete_and_keep_local(sbox):
+ "check status delete and delete --keep-local"
+
+ sbox.build(create_wc = False)
+ replace_sbox_with_tarfile(sbox, 'wc-delete.tar.bz2')
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'upgrade', sbox.wc_dir)
+
+ expected_status = svntest.wc.State(sbox.wc_dir,
+ {
+ '' : Item(status=' ', wc_rev='0'),
+ 'Normal' : Item(status=' ', wc_rev='1'),
+ 'Deleted-Keep-Local': Item(status='D ', wc_rev='1'),
+ 'Deleted' : Item(status='D ', wc_rev='1'),
+ })
+
+ run_and_verify_status_no_server(sbox.wc_dir, expected_status)
+
+ # Deleted-Keep-Local should still exist after the upgrade
+ if not os.path.exists(os.path.join(sbox.wc_dir, 'Deleted-Keep-Local')):
+ raise svntest.Failure('wc/Deleted-Keep-Local should exist')
+
+ # Deleted-Keep-Local should be removed after the upgrade as it was
+ # schedule delete and doesn't contain unversioned changes.
+ if os.path.exists(os.path.join(sbox.wc_dir, 'Deleted')):
+ raise svntest.Failure('wc/Deleted should not exist')
+
+
+
########################################################################
# Run the tests
@@ -352,7 +656,15 @@ test_list = [ None,
update_1_5,
logs_left_1_5,
upgrade_wcprops,
- basic_upgrade_1_0
+ basic_upgrade_1_0,
+ # Upgrading from 1.4.0-1.4.5 with specific states fails
+ # See issue #2530
+ XFail(x3_1_4_0),
+ x3_1_4_6,
+ x3_1_6_12,
+ missing_dirs,
+ missing_dirs2,
+ XFail(delete_and_keep_local),
]
Propchange: subversion/branches/py-tests-as-modules/subversion/tests/libsvn_client/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Wed Sep 15 19:32:26 2010
@@ -2,3 +2,4 @@
client-test
*.lo
test-patch*
+test-wc*