diff options
Diffstat (limited to 'subversion/tests/cmdline/copy_tests.py')
-rwxr-xr-x | subversion/tests/cmdline/copy_tests.py | 1114 |
1 files changed, 762 insertions, 352 deletions
diff --git a/subversion/tests/cmdline/copy_tests.py b/subversion/tests/cmdline/copy_tests.py index d28e848..39a686b 100755 --- a/subversion/tests/cmdline/copy_tests.py +++ b/subversion/tests/cmdline/copy_tests.py @@ -25,7 +25,9 @@ ###################################################################### # General modules -import stat, os, re, shutil +import stat, os, re, shutil, logging, sys + +logger = logging.getLogger() # Our testing module import svntest @@ -61,7 +63,7 @@ or a url (when false) copy source is used.""" wc_dir = sbox.wc_dir # File scheduled for deletion - rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') + rho_path = sbox.ospath('A/D/G/rho') svntest.actions.run_and_verify_svn(None, None, [], 'rm', rho_path) # Status before attempting copies @@ -71,7 +73,7 @@ or a url (when false) copy source is used.""" # The copy shouldn't fail if wc_copy: - pi_src = os.path.join(wc_dir, 'A', 'D', 'G', 'pi') + pi_src = sbox.ospath('A/D/G/pi') else: pi_src = sbox.repo_url + '/A/D/G/pi' @@ -105,12 +107,12 @@ def copy_replace_with_props(sbox, wc_copy): # Use a temp file to set properties with wildcards in their values # otherwise Win32/VS2005 will expand them - prop_path = os.path.join(wc_dir, 'proptmp') + prop_path = sbox.ospath('proptmp') svntest.main.file_append(prop_path, '*') # Set props on file which is copy-source later on - pi_path = os.path.join(wc_dir, 'A', 'D', 'G', 'pi') - rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') + pi_path = sbox.ospath('A/D/G/pi') + rho_path = sbox.ospath('A/D/G/rho') svntest.actions.run_and_verify_svn(None, None, [], 'ps', 'phony-prop', '-F', prop_path, pi_path) @@ -125,8 +127,7 @@ def copy_replace_with_props(sbox, wc_copy): 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, { @@ -154,7 +155,7 @@ def copy_replace_with_props(sbox, wc_copy): # The copy shouldn't fail if wc_copy: - pi_src = os.path.join(wc_dir, 'A', 'D', 'G', 'pi') + pi_src = sbox.ospath('A/D/G/pi') else: pi_src = sbox.repo_url + '/A/D/G/pi' @@ -170,8 +171,7 @@ def copy_replace_with_props(sbox, wc_copy): 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 commit and verify expected_status.tweak('A/D/G/rho', status='R ', copied='+', wc_rev='-') @@ -268,14 +268,14 @@ def basic_copy_and_move_files(sbox): sbox.build() wc_dir = sbox.wc_dir - mu_path = os.path.join(wc_dir, 'A', 'mu') - iota_path = os.path.join(wc_dir, 'iota') - rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') - D_path = os.path.join(wc_dir, 'A', 'D') - alpha_path = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha') - H_path = os.path.join(wc_dir, 'A', 'D', 'H') - F_path = os.path.join(wc_dir, 'A', 'B', 'F') - alpha2_path = os.path.join(wc_dir, 'A', 'C', 'alpha2') + mu_path = sbox.ospath('A/mu') + iota_path = sbox.ospath('iota') + rho_path = sbox.ospath('A/D/G/rho') + D_path = sbox.ospath('A/D') + alpha_path = sbox.ospath('A/B/E/alpha') + H_path = sbox.ospath('A/D/H') + F_path = sbox.ospath('A/B/F') + alpha2_path = sbox.ospath('A/C/alpha2') # Make local mods to mu and rho svntest.main.file_append(mu_path, 'appended mu text') @@ -369,8 +369,8 @@ def receive_copy_in_update(sbox): svntest.actions.duplicate_dir(wc_dir, wc_backup) # Define a zillion paths in both working copies. - G_path = os.path.join(wc_dir, 'A', 'D', 'G') - newG_path = os.path.join(wc_dir, 'A', 'B', 'newG') + G_path = sbox.ospath('A/D/G') + newG_path = sbox.ospath('A/B/newG') # Copy directory A/D to A/B/newG svntest.actions.run_and_verify_svn(None, None, [], 'cp', G_path, newG_path) @@ -447,7 +447,7 @@ def resurrect_deleted_dir(sbox): sbox.build() wc_dir = sbox.wc_dir - G_path = os.path.join(wc_dir, 'A', 'D', 'G') + G_path = sbox.ospath('A/D/G') # Delete directory A/D/G, commit that as r2. svntest.actions.run_and_verify_svn(None, None, [], 'rm', '--force', @@ -500,7 +500,7 @@ def copy_deleted_dir_into_prefix(sbox): sbox.build() wc_dir = sbox.wc_dir - D_path = os.path.join(wc_dir, 'A', 'D') + D_path = sbox.ospath('A/D') # Delete directory A/D, commit that as r2. svntest.actions.run_and_verify_svn(None, None, [], 'rm', '--force', @@ -575,7 +575,7 @@ def no_wc_copy_overwrites(sbox): wc_dir = sbox.wc_dir # File simply missing - tau_path = os.path.join(wc_dir, 'A', 'D', 'G', 'tau') + tau_path = sbox.ospath('A/D/G/tau') os.remove(tau_path) # Status before attempting copies @@ -584,8 +584,8 @@ def no_wc_copy_overwrites(sbox): svntest.actions.run_and_verify_status(wc_dir, expected_status) # These copies should fail - pi_path = os.path.join(wc_dir, 'A', 'D', 'G', 'pi') - rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') + pi_path = sbox.ospath('A/D/G/pi') + rho_path = sbox.ospath('A/D/G/rho') svntest.actions.run_and_verify_svn(None, None, svntest.verify.AnyOutput, 'cp', pi_path, rho_path) svntest.actions.run_and_verify_svn(None, None, svntest.verify.AnyOutput, @@ -604,13 +604,13 @@ def copy_modify_commit(sbox): sbox.build() wc_dir = sbox.wc_dir - B_path = os.path.join(wc_dir, 'A', 'B') - B2_path = os.path.join(wc_dir, 'A', 'B2') + B_path = sbox.ospath('A/B') + B2_path = sbox.ospath('A/B2') svntest.actions.run_and_verify_svn(None, None, [], 'cp', B_path, B2_path) - alpha_path = os.path.join(wc_dir, 'A', 'B2', 'E', 'alpha') + alpha_path = sbox.ospath('A/B2/E/alpha') svntest.main.file_append(alpha_path, "modified alpha") expected_output = svntest.wc.State(wc_dir, { @@ -636,7 +636,7 @@ def copy_files_with_properties(sbox): wc_dir = sbox.wc_dir # Set a property on a file - rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') + rho_path = sbox.ospath('A/D/G/rho') svntest.actions.run_and_verify_svn(None, None, [], 'propset', 'pname', 'pval', rho_path) @@ -655,12 +655,12 @@ def copy_files_with_properties(sbox): 'propset', 'pname2', 'pval2', rho_path) # WC to WC copy of file with committed and uncommitted properties - rho_wc_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho_wc') + rho_wc_path = sbox.ospath('A/D/G/rho_wc') svntest.actions.run_and_verify_svn(None, None, [], 'copy', rho_path, rho_wc_path) # REPOS to WC copy of file with properties - rho_url_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho_url') + rho_url_path = sbox.ospath('A/D/G/rho_url') rho_url = sbox.repo_url + '/A/D/G/rho' svntest.actions.run_and_verify_svn(None, None, [], 'copy', rho_url, rho_url_path) @@ -706,16 +706,16 @@ def copy_delete_commit(sbox): sbox.build() wc_dir = sbox.wc_dir - B_path = os.path.join(wc_dir, 'A', 'B') - B2_path = os.path.join(wc_dir, 'A', 'B2') + B_path = sbox.ospath('A/B') + B2_path = sbox.ospath('A/B2') # copy a tree svntest.actions.run_and_verify_svn(None, None, [], 'cp', B_path, B2_path) # delete two files - lambda_path = os.path.join(wc_dir, 'A', 'B2', 'lambda') - alpha_path = os.path.join(wc_dir, 'A', 'B2', 'E', 'alpha') + lambda_path = sbox.ospath('A/B2/lambda') + alpha_path = sbox.ospath('A/B2/E/alpha') svntest.actions.run_and_verify_svn(None, None, [], 'rm', alpha_path, lambda_path) @@ -733,11 +733,11 @@ def copy_delete_commit(sbox): # copy a tree svntest.actions.run_and_verify_svn(None, None, [], 'cp', - os.path.join(wc_dir, 'A', 'B'), - os.path.join(wc_dir, 'A', 'B3')) + sbox.ospath('A/B'), + sbox.ospath('A/B3')) # delete a directory - E_path = os.path.join(wc_dir, 'A', 'B3', 'E') + E_path = sbox.ospath('A/B3/E') svntest.actions.run_and_verify_svn(None, None, [], 'rm', E_path) # commit copied tree containing a deleted directory @@ -759,17 +759,19 @@ def mv_and_revert_directory(sbox): sbox.build(read_only = True) wc_dir = sbox.wc_dir - E_path = os.path.join(wc_dir, 'A', 'B', 'E') - F_path = os.path.join(wc_dir, 'A', 'B', 'F') + E_path = sbox.ospath('A/B/E') + F_path = sbox.ospath('A/B/F') new_E_path = os.path.join(F_path, 'E') # Issue 931: move failed to lock the directory being deleted svntest.actions.run_and_verify_svn(None, None, [], 'move', E_path, F_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', status='D ') + expected_status.tweak('A/B/E/alpha', 'A/B/E/beta', status='D ') + expected_status.tweak('A/B/E', status='D ', moved_to='A/B/F/E') expected_status.add({ - 'A/B/F/E' : Item(status='A ', wc_rev='-', copied='+'), + 'A/B/F/E' : Item(status='A ', wc_rev='-', copied='+', + moved_from='A/B/E'), 'A/B/F/E/alpha' : Item(status=' ', wc_rev='-', copied='+'), 'A/B/F/E/beta' : Item(status=' ', wc_rev='-', copied='+'), }) @@ -779,6 +781,7 @@ def mv_and_revert_directory(sbox): svntest.actions.run_and_verify_svn(None, None, [], 'revert', '--recursive', new_E_path) expected_status.remove('A/B/F/E', 'A/B/F/E/alpha', 'A/B/F/E/beta') + expected_status.tweak('A/B/E', moved_to=None) svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -795,8 +798,8 @@ def copy_preserve_executable_bit(sbox): wc_dir = sbox.wc_dir # Create two paths - newpath1 = os.path.join(wc_dir, 'newfile1') - newpath2 = os.path.join(wc_dir, 'newfile2') + newpath1 = sbox.ospath('newfile1') + newpath2 = sbox.ospath('newfile2') # Create the first file. svntest.main.file_append(newpath1, "a new file") @@ -812,7 +815,7 @@ def copy_preserve_executable_bit(sbox): mode2 = os.stat(newpath1)[stat.ST_MODE] if mode1 == mode2: - print("setting svn:executable did not change file's permissions") + logger.warn("setting svn:executable did not change file's permissions") raise svntest.Failure # Commit the file @@ -827,7 +830,7 @@ def copy_preserve_executable_bit(sbox): # The mode on the original and copied file should be identical if mode2 != mode3: - print("permissions on the copied file are not identical to original file") + logger.warn("permissions on the copied file are not identical to original file") raise svntest.Failure #---------------------------------------------------------------------- @@ -839,13 +842,13 @@ def wc_to_repos(sbox): sbox.build() wc_dir = sbox.wc_dir - beta_path = os.path.join(wc_dir, "A", "B", "E", "beta") + beta_path = sbox.ospath('A/B/E/beta') beta2_url = sbox.repo_url + "/A/B/E/beta2" - H_path = os.path.join(wc_dir, "A", "D", "H") + H_path = sbox.ospath('A/D/H') H2_url = sbox.repo_url + "/A/D/H2" # modify some items to be copied - svntest.main.file_append(os.path.join(wc_dir, 'A', 'D', 'H', 'omega'), + svntest.main.file_append(sbox.ospath('A/D/H/omega'), "new otext\n") svntest.actions.run_and_verify_svn(None, None, [], 'propset', 'foo', 'bar', beta_path) @@ -904,7 +907,7 @@ def wc_to_repos(sbox): #---------------------------------------------------------------------- # Issue 1090: various use-cases of 'svn cp URL wc' where the # repositories might be different, or be the same repository. -@Issues(1090,1444) +@Issues(1090, 1444, 3590) def repos_to_wc(sbox): "repository to working-copy copy" @@ -922,7 +925,7 @@ def repos_to_wc(sbox): # we should get some scheduled additions *with history*. E_url = sbox.repo_url + "/A/B/E" pi_url = sbox.repo_url + "/A/D/G/pi" - pi_path = os.path.join(wc_dir, 'pi') + pi_path = sbox.ospath('pi') svntest.actions.run_and_verify_svn(None, None, [], 'copy', E_url, wc_dir) svntest.actions.run_and_verify_svn(None, None, [], 'copy', pi_url, wc_dir) @@ -942,19 +945,19 @@ def repos_to_wc(sbox): # Modification will only show up if timestamps differ exit_code, out, err = svntest.main.run_svn(None, 'diff', pi_path) if err or not out: - print("diff failed") + logger.warn("diff failed") raise svntest.Failure for line in out: if line == '+zig\n': # Crude check for diff-like output break else: - print("diff output incorrect %s" % out) + logger.warn("diff output incorrect %s" % out) raise svntest.Failure # Revert everything and verify. svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R', wc_dir) - svntest.main.safe_rmtree(os.path.join(wc_dir, 'E')) + svntest.main.safe_rmtree(sbox.ospath('E')) expected_output = svntest.actions.get_virginal_state(wc_dir, 1) svntest.actions.run_and_verify_status(wc_dir, expected_output) @@ -974,7 +977,7 @@ def repos_to_wc(sbox): # Revert everything and verify. svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R', wc_dir) - svntest.main.safe_rmtree(os.path.join(wc_dir, 'C')) + svntest.main.safe_rmtree(sbox.ospath('C')) expected_output = svntest.actions.get_virginal_state(wc_dir, 1) svntest.actions.run_and_verify_status(wc_dir, expected_output) @@ -985,17 +988,29 @@ def repos_to_wc(sbox): E_url = other_repo_url + "/A/B/E" pi_url = other_repo_url + "/A/D/G/pi" - # Expect an error in the directory case until we allow this copy to succeed. - expected_error = "svn: E200007: Source URL '.*foreign repository" - svntest.actions.run_and_verify_svn(None, None, expected_error, + # Finally, for 1.8 we allow this copy to succeed. + expected_output = svntest.verify.UnorderedOutput([ + '--- Copying from foreign repository URL \'%s\':\n' % E_url, + 'A %s\n' % sbox.ospath('E'), + 'A %s\n' % sbox.ospath('E/beta'), + 'A %s\n' % sbox.ospath('E/alpha'), + ]) + svntest.actions.run_and_verify_svn(None, expected_output, [], 'copy', E_url, wc_dir) - # But file case should work fine. - svntest.actions.run_and_verify_svn(None, None, [], 'copy', pi_url, wc_dir) + expected_output = [ + '--- Copying from foreign repository URL \'%s\':\n' % pi_url, + 'A %s\n' % sbox.ospath('pi'), + ] + svntest.actions.run_and_verify_svn(None, expected_output, [], + 'copy', pi_url, wc_dir) expected_output = svntest.actions.get_virginal_state(wc_dir, 1) expected_output.add({ - 'pi' : Item(status='A ', wc_rev='0', entry_rev='1'), + 'pi' : Item(status='A ', wc_rev='0'), + 'E' : Item(status='A ', wc_rev='0'), + 'E/beta' : Item(status='A ', wc_rev='0'), + 'E/alpha' : Item(status='A ', wc_rev='0'), }) svntest.actions.run_and_verify_status(wc_dir, expected_output) @@ -1007,7 +1022,7 @@ def repos_to_wc(sbox): # Copy a directory to a pre-existing WC directory. # The source directory should be copied *under* the target directory. B_url = sbox.repo_url + "/A/B" - D_dir = os.path.join(wc_dir, 'A', 'D') + D_dir = sbox.ospath('A/D') svntest.actions.run_and_verify_svn(None, None, [], 'copy', B_url, D_dir) @@ -1240,7 +1255,7 @@ def diff_repos_to_wc_copy(sbox): wc_dir = sbox.wc_dir iota_repos_path = sbox.repo_url + '/iota' - target_wc_path = os.path.join(wc_dir, 'new_file') + target_wc_path = sbox.ospath('new_file') # Copy a file from the repository to the working copy. svntest.actions.run_and_verify_svn(None, None, [], 'cp', @@ -1264,8 +1279,8 @@ def repos_to_wc_copy_eol_keywords(sbox): wc_dir = sbox.wc_dir iota_repos_path = sbox.repo_url + '/iota' - iota_wc_path = os.path.join(wc_dir, 'iota') - target_wc_path = os.path.join(wc_dir, 'new_file') + iota_wc_path = sbox.ospath('iota') + target_wc_path = sbox.ospath('new_file') # Modify iota to make it checkworthy. svntest.main.file_write(iota_wc_path, @@ -1321,7 +1336,7 @@ def revision_kinds_local_source(sbox): sbox.build() wc_dir = sbox.wc_dir - mu_path = os.path.join(wc_dir, 'A', 'mu') + mu_path = sbox.ospath('A/mu') # Make a file with different content in each revision and WC; BASE != HEAD. expected_output = svntest.wc.State(wc_dir, { @@ -1367,12 +1382,11 @@ def revision_kinds_local_source(sbox): if line.rstrip() == "Copied From Rev: " + str(from_rev): break else: - print("%s should have been copied from revision %s" % (dst, from_rev)) + logger.warn("%s should have been copied from revision %s" % (dst, from_rev)) raise svntest.Failure # Check that the new files have the right contents - actual_disk = svntest.tree.build_tree_from_wc(wc_dir) - svntest.tree.compare_trees("disk", actual_disk, expected_disk.old_tree()) + svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) #------------------------------------------------------------- @@ -1383,8 +1397,8 @@ def copy_over_missing_file(sbox): sbox.build(read_only = True) wc_dir = sbox.wc_dir - mu_path = os.path.join(wc_dir, 'A', 'mu') - iota_path = os.path.join(wc_dir, 'iota') + mu_path = sbox.ospath('A/mu') + iota_path = sbox.ospath('iota') iota_url = sbox.repo_url + "/iota" # Make the target missing. @@ -1418,7 +1432,7 @@ def repos_to_wc_1634(sbox): wc_dir = sbox.wc_dir # First delete a subdirectory and commit. - E_path = os.path.join(wc_dir, 'A', 'B', 'E') + E_path = sbox.ospath('A/B/E') svntest.actions.run_and_verify_svn(None, None, [], 'delete', E_path) expected_output = svntest.wc.State(wc_dir, { 'A/B/E' : Item(verb='Deleting'), @@ -1502,7 +1516,7 @@ def wc_to_wc_copy_between_different_repos(sbox): # Attempt a copy between different repositories. exit_code, out, err = svntest.main.run_svn(1, 'cp', os.path.join(wc2_dir, 'A'), - os.path.join(wc_dir, 'A', 'B')) + sbox.ospath('A/B')) for line in err: if line.find("it is not from repository") != -1: break @@ -1518,8 +1532,8 @@ def wc_to_wc_copy_deleted(sbox): sbox.build() wc_dir = sbox.wc_dir - B_path = os.path.join(wc_dir, 'A', 'B') - B2_path = os.path.join(wc_dir, 'A', 'B2') + B_path = sbox.ospath('A/B') + B2_path = sbox.ospath('A/B2') # Schedule for delete svntest.actions.run_and_verify_svn(None, None, [], 'rm', @@ -1625,7 +1639,7 @@ def url_to_non_existent_url_path(sbox): if re.match (msg, err_line): break else: - print("message \"%s\" not found in error output: %s" % (msg, err)) + logger.warn("message \"%s\" not found in error output: %s" % (msg, err)) raise svntest.Failure @@ -1718,14 +1732,14 @@ def mixed_wc_to_url(sbox): wc_dir = sbox.wc_dir Z_url = sbox.repo_url + '/A/D/Z' Z2_url = sbox.repo_url + '/A/D/Z2' - G_path = os.path.join(wc_dir, 'A', 'D', 'G') - B_path = os.path.join(wc_dir, 'A', 'B') - X_path = os.path.join(wc_dir, 'A', 'D', 'G', 'X') - Y_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Y') - E_path = os.path.join(wc_dir, 'A', 'D', 'G', 'X', 'E') - alpha_path = os.path.join(wc_dir, 'A', 'D', 'G', 'X', 'E', 'alpha') - pi_path = os.path.join(wc_dir, 'A', 'D', 'G', 'pi') - rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') + G_path = sbox.ospath('A/D/G') + B_path = sbox.ospath('A/B') + X_path = sbox.ospath('A/D/G/X') + Y_path = sbox.ospath('A/D/G/Y') + E_path = sbox.ospath('A/D/G/X/E') + alpha_path = sbox.ospath('A/D/G/X/E/alpha') + pi_path = sbox.ospath('A/D/G/pi') + rho_path = sbox.ospath('A/D/G/rho') # Remove A/D/G/pi, then commit that removal. svntest.actions.run_and_verify_svn(None, None, [], 'rm', pi_path) @@ -1787,10 +1801,10 @@ def mixed_wc_to_url(sbox): svntest.actions.run_and_verify_svn(None, None, [], 'co', Z_url, wc_dir) - if os.path.exists(os.path.join(wc_dir, 'pi')): + if os.path.exists(sbox.ospath('pi')): raise svntest.Failure("Path 'pi' exists but should be gone.") - fp = open(os.path.join(wc_dir, 'rho'), 'r') + fp = open(sbox.ospath('rho'), 'r') found_it = 0 for line in fp.readlines(): if re.match("^Second modification to rho.", line): @@ -1833,7 +1847,7 @@ def delete_replaced_file(sbox): wc_dir = sbox.wc_dir # File scheduled for deletion. - rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') + rho_path = sbox.ospath('A/D/G/rho') svntest.actions.run_and_verify_svn(None, None, [], 'rm', rho_path) # Status before attempting copies @@ -1842,7 +1856,7 @@ def delete_replaced_file(sbox): svntest.actions.run_and_verify_status(wc_dir, expected_status) # Copy 'pi' over 'rho' with history. - pi_src = os.path.join(wc_dir, 'A', 'D', 'G', 'pi') + pi_src = sbox.ospath('A/D/G/pi') svntest.actions.run_and_verify_svn(None, None, [], 'cp', pi_src, rho_path) # Check that file copied. @@ -1866,22 +1880,24 @@ def mv_unversioned_file(sbox): sbox.build(read_only = True) wc_dir = sbox.wc_dir - unver_path_1 = os.path.join(wc_dir, 'unversioned1') - dest_path_1 = os.path.join(wc_dir, 'dest') + unver_path_1 = sbox.ospath('unversioned1') + dest_path_1 = sbox.ospath('dest') svntest.main.file_append(unver_path_1, "an unversioned file") - unver_path_2 = os.path.join(wc_dir, 'A', 'unversioned2') - dest_path_2 = os.path.join(wc_dir, 'A', 'dest_forced') + unver_path_2 = sbox.ospath('A/unversioned2') + dest_path_2 = sbox.ospath('A/dest_forced') svntest.main.file_append(unver_path_2, "another unversioned file") # Try to move an unversioned file. svntest.actions.run_and_verify_svn(None, None, - ".*unversioned1.* is not under version control.*", + ".*unversioned1' " + + "(does not exist|is not under version control)", 'mv', unver_path_1, dest_path_1) # Try to forcibly move an unversioned file. svntest.actions.run_and_verify_svn(None, None, - ".*unversioned2.* is not under version control.*", + ".*unversioned2.* " + + "(does not exist|is not under version control)", 'mv', unver_path_2, dest_path_2) @@ -1923,7 +1939,7 @@ def force_move(sbox): os.chdir(was_cwd) # check for the new content - file_handle = open(os.path.join(wc_dir, "dest"), "r") + file_handle = open(sbox.ospath('dest'), "r") modified_file_content = file_handle.readlines() file_handle.close() # Error if we dont find the modified contents... @@ -1958,9 +1974,9 @@ def copy_copied_file_and_dir(sbox): sbox.build() wc_dir = sbox.wc_dir - rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') - rho_copy_path_1 = os.path.join(wc_dir, 'A', 'D', 'rho_copy_1') - rho_copy_path_2 = os.path.join(wc_dir, 'A', 'B', 'F', 'rho_copy_2') + rho_path = sbox.ospath('A/D/G/rho') + rho_copy_path_1 = sbox.ospath('A/D/rho_copy_1') + rho_copy_path_2 = sbox.ospath('A/B/F/rho_copy_2') # Copy A/D/G/rho to A/D/rho_copy_1 svntest.actions.run_and_verify_svn(None, None, [], 'cp', @@ -1970,9 +1986,9 @@ def copy_copied_file_and_dir(sbox): svntest.actions.run_and_verify_svn(None, None, [], 'cp', rho_copy_path_1, rho_copy_path_2) - E_path = os.path.join(wc_dir, 'A', 'B', 'E') - E_path_copy_1 = os.path.join(wc_dir, 'A', 'B', 'F', 'E_copy_1') - E_path_copy_2 = os.path.join(wc_dir, 'A', 'D', 'G', 'E_copy_2') + E_path = sbox.ospath('A/B/E') + E_path_copy_1 = sbox.ospath('A/B/F/E_copy_1') + E_path_copy_2 = sbox.ospath('A/D/G/E_copy_2') # Copy A/B/E to A/B/F/E_copy_1 svntest.actions.run_and_verify_svn(None, None, [], 'cp', @@ -2016,9 +2032,9 @@ def move_copied_file_and_dir(sbox): sbox.build() wc_dir = sbox.wc_dir - rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') - rho_copy_path = os.path.join(wc_dir, 'A', 'D', 'rho_copy') - rho_copy_move_path = os.path.join(wc_dir, 'A', 'B', 'F', 'rho_copy_moved') + rho_path = sbox.ospath('A/D/G/rho') + rho_copy_path = sbox.ospath('A/D/rho_copy') + rho_copy_move_path = sbox.ospath('A/B/F/rho_copy_moved') # Copy A/D/G/rho to A/D/rho_copy svntest.actions.run_and_verify_svn(None, None, [], 'cp', @@ -2028,9 +2044,9 @@ def move_copied_file_and_dir(sbox): svntest.actions.run_and_verify_svn(None, None, [], 'mv', rho_copy_path, rho_copy_move_path) - E_path = os.path.join(wc_dir, 'A', 'B', 'E') - E_path_copy = os.path.join(wc_dir, 'A', 'B', 'F', 'E_copy') - E_path_copy_move = os.path.join(wc_dir, 'A', 'D', 'G', 'E_copy_moved') + E_path = sbox.ospath('A/B/E') + E_path_copy = sbox.ospath('A/B/F/E_copy') + E_path_copy_move = sbox.ospath('A/D/G/E_copy_moved') # Copy A/B/E to A/B/F/E_copy svntest.actions.run_and_verify_svn(None, None, [], 'cp', @@ -2071,9 +2087,9 @@ def move_moved_file_and_dir(sbox): sbox.build() wc_dir = sbox.wc_dir - rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') - rho_move_path = os.path.join(wc_dir, 'A', 'D', 'rho_moved') - rho_move_moved_path = os.path.join(wc_dir, 'A', 'B', 'F', 'rho_move_moved') + rho_path = sbox.ospath('A/D/G/rho') + rho_move_path = sbox.ospath('A/D/rho_moved') + rho_move_moved_path = sbox.ospath('A/B/F/rho_move_moved') # Move A/D/G/rho to A/D/rho_moved svntest.actions.run_and_verify_svn(None, None, [], 'mv', @@ -2083,9 +2099,9 @@ def move_moved_file_and_dir(sbox): svntest.actions.run_and_verify_svn(None, None, [], 'mv', rho_move_path, rho_move_moved_path) - E_path = os.path.join(wc_dir, 'A', 'B', 'E') - E_path_moved = os.path.join(wc_dir, 'A', 'B', 'F', 'E_moved') - E_path_move_moved = os.path.join(wc_dir, 'A', 'D', 'G', 'E_move_moved') + E_path = sbox.ospath('A/B/E') + E_path_moved = sbox.ospath('A/B/F/E_moved') + E_path_move_moved = sbox.ospath('A/D/G/E_move_moved') # Copy A/B/E to A/B/F/E_moved svntest.actions.run_and_verify_svn(None, None, [], 'mv', @@ -2106,7 +2122,7 @@ def move_moved_file_and_dir(sbox): # Create expected status tree expected_status = svntest.actions.get_virginal_state(wc_dir, 1) expected_status.add({ - 'A/D/G/E_move_moved/' : Item(status=' ', wc_rev=2), + 'A/D/G/E_move_moved' : Item(status=' ', wc_rev=2), 'A/D/G/E_move_moved/alpha' : Item(status=' ', wc_rev=2), 'A/D/G/E_move_moved/beta' : Item(status=' ', wc_rev=2), 'A/B/F/rho_move_moved' : Item(status=' ', wc_rev=2), @@ -2130,14 +2146,14 @@ def move_file_within_moved_dir(sbox): sbox.build() wc_dir = sbox.wc_dir - D_path = os.path.join(wc_dir, 'A', 'D') - D_path_moved = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved') + D_path = sbox.ospath('A/D') + D_path_moved = sbox.ospath('A/B/F/D_moved') # Move A/B/D to A/B/F/D_moved svntest.actions.run_and_verify_svn(None, None, [], 'mv', D_path, D_path_moved) - chi_path = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved', 'H', 'chi') + chi_path = sbox.ospath('A/B/F/D_moved/H/chi') chi_moved_path = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved', 'H', 'chi_moved') chi_moved_again_path = os.path.join(wc_dir, 'A', 'B', 'F', @@ -2199,17 +2215,17 @@ def move_file_out_of_moved_dir(sbox): sbox.build() wc_dir = sbox.wc_dir - D_path = os.path.join(wc_dir, 'A', 'D') - D_path_moved = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved') + D_path = sbox.ospath('A/D') + D_path_moved = sbox.ospath('A/B/F/D_moved') # Move A/B/D to A/B/F/D_moved svntest.actions.run_and_verify_svn(None, None, [], 'mv', D_path, D_path_moved) - chi_path = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved', 'H', 'chi') + chi_path = sbox.ospath('A/B/F/D_moved/H/chi') chi_moved_path = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved', 'H', 'chi_moved') - chi_moved_again_path = os.path.join(wc_dir, 'A', 'C', 'chi_moved_again') + chi_moved_again_path = sbox.ospath('A/C/chi_moved_again') # Move A/B/F/D_moved/H/chi to A/B/F/D_moved/H/chi_moved # then move that to A/C/chi_moved_again @@ -2267,15 +2283,15 @@ def move_dir_within_moved_dir(sbox): sbox.build() wc_dir = sbox.wc_dir - D_path = os.path.join(wc_dir, 'A', 'D') - D_path_moved = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved') + D_path = sbox.ospath('A/D') + D_path_moved = sbox.ospath('A/B/F/D_moved') # Move A/D to A/B/F/D_moved svntest.actions.run_and_verify_svn(None, None, [], 'mv', D_path, D_path_moved) - H_path = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved', 'H') - H_moved_path = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved', 'H_moved') + H_path = sbox.ospath('A/B/F/D_moved/H') + H_moved_path = sbox.ospath('A/B/F/D_moved/H_moved') H_moved_again_path = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved', 'H_moved_again') @@ -2335,16 +2351,16 @@ def move_dir_out_of_moved_dir(sbox): sbox.build() wc_dir = sbox.wc_dir - D_path = os.path.join(wc_dir, 'A', 'D') - D_path_moved = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved') + D_path = sbox.ospath('A/D') + D_path_moved = sbox.ospath('A/B/F/D_moved') # Move A/D to A/B/F/D_moved svntest.actions.run_and_verify_svn(None, None, [], 'mv', D_path, D_path_moved) - H_path = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved', 'H') - H_moved_path = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved', 'H_moved') - H_moved_again_path = os.path.join(wc_dir, 'A', 'C', 'H_moved_again') + H_path = sbox.ospath('A/B/F/D_moved/H') + H_moved_path = sbox.ospath('A/B/F/D_moved/H_moved') + H_moved_again_path = sbox.ospath('A/C/H_moved_again') # Move A/B/F/D_moved/H to A/B/F/D_moved/H_moved # then move that to A/C/H_moved_again @@ -2404,8 +2420,8 @@ def move_file_back_and_forth(sbox): sbox.build() wc_dir = sbox.wc_dir - rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') - rho_move_path = os.path.join(wc_dir, 'A', 'D', 'rho_moved') + rho_path = sbox.ospath('A/D/G/rho') + rho_move_path = sbox.ospath('A/D/rho_moved') # Move A/D/G/rho away from and then back to its original path svntest.actions.run_and_verify_svn(None, None, [], 'mv', @@ -2415,19 +2431,11 @@ def move_file_back_and_forth(sbox): # Check expected status before commit expected_status = svntest.actions.get_virginal_state(wc_dir, 1) - expected_status.add({ - 'A/D/G/rho' : Item(status='R ', copied='+', wc_rev='-'), - }) svntest.actions.run_and_verify_status(wc_dir, expected_status) - # Commit, and check expected output and status - expected_output = svntest.wc.State(wc_dir, { - 'A/D/G/rho' : Item(verb='Replacing'), - }) + # Try to commit and find out that there is nothing to commit. + expected_output = [] expected_status = svntest.actions.get_virginal_state(wc_dir, 1) - expected_status.add({ - 'A/D/G/rho' : Item(status=' ', wc_rev=2), - }) svntest.actions.run_and_verify_commit(wc_dir, expected_output, expected_status, @@ -2444,8 +2452,8 @@ def move_dir_back_and_forth(sbox): sbox.build(read_only = True) wc_dir = sbox.wc_dir - D_path = os.path.join(wc_dir, 'A', 'D') - D_move_path = os.path.join(wc_dir, 'D_moved') + D_path = sbox.ospath('A/D') + D_move_path = sbox.ospath('D_moved') # Move A/D to D_moved svntest.actions.run_and_verify_svn(None, None, [], 'mv', @@ -2454,34 +2462,11 @@ def move_dir_back_and_forth(sbox): # Move the moved dir: D_moved back to its starting # location at A/D. - if svntest.main.wc_is_singledb(wc_dir): - # In single-db target is gone on-disk after it was moved away, so this - # move works ok - expected_err = [] - else: - # In !SINGLE_DB the target of the copy exists on-dir, so svn tries - # to move the file below the deleted directory - expected_err = '.*Cannot copy to .*as it is scheduled for deletion' - - svntest.actions.run_and_verify_svn(None, None, expected_err, - 'mv', D_move_path, D_path) + svntest.actions.run_and_verify_svn(None, None, [], 'mv', D_move_path, D_path) - if svntest.main.wc_is_singledb(wc_dir): - # Verify that the status indicates a replace with history - expected_status = svntest.actions.get_virginal_state(wc_dir, 1) - expected_status.add({ - 'A/D' : Item(status='R ', copied='+', wc_rev='-'), - 'A/D/G' : Item(status=' ', copied='+', wc_rev='-'), - 'A/D/G/pi' : Item(status=' ', copied='+', wc_rev='-'), - 'A/D/G/rho' : Item(status=' ', copied='+', wc_rev='-'), - 'A/D/G/tau' : Item(status=' ', copied='+', wc_rev='-'), - 'A/D/gamma' : Item(status=' ', copied='+', wc_rev='-'), - 'A/D/H' : Item(status=' ', copied='+', wc_rev='-'), - 'A/D/H/chi' : Item(status=' ', copied='+', wc_rev='-'), - 'A/D/H/omega' : Item(status=' ', copied='+', wc_rev='-'), - 'A/D/H/psi' : Item(status=' ', copied='+', wc_rev='-'), - }) - svntest.actions.run_and_verify_status(wc_dir, expected_status) + # Verify that the status indicates a replace with history + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + svntest.actions.run_and_verify_status(wc_dir, expected_status) def copy_move_added_paths(sbox): "copy and move added paths without commits" @@ -2490,12 +2475,12 @@ def copy_move_added_paths(sbox): wc_dir = sbox.wc_dir # Create a new file and schedule it for addition - upsilon_path = os.path.join(wc_dir, 'A', 'D', 'upsilon') + upsilon_path = sbox.ospath('A/D/upsilon') svntest.main.file_write(upsilon_path, "This is the file 'upsilon'\n") svntest.actions.run_and_verify_svn(None, None, [], 'add', upsilon_path) # Create a dir with children and schedule it for addition - I_path = os.path.join(wc_dir, 'A', 'D', 'I') + I_path = sbox.ospath('A/D/I') J_path = os.path.join(I_path, 'J') eta_path = os.path.join(I_path, 'eta') theta_path = os.path.join(I_path, 'theta') @@ -2508,7 +2493,7 @@ def copy_move_added_paths(sbox): svntest.actions.run_and_verify_svn(None, None, [], 'add', I_path) # Create another dir and schedule it for addition - K_path = os.path.join(wc_dir, 'K') + K_path = sbox.ospath('K') os.mkdir(K_path) svntest.actions.run_and_verify_svn(None, None, [], 'add', K_path) @@ -2547,8 +2532,8 @@ def copy_move_added_paths(sbox): # Move added file A/D/upsilon to upsilon, # then move it again to A/upsilon - upsilon_move_path = os.path.join(wc_dir, 'upsilon') - upsilon_move_path_2 = os.path.join(wc_dir, 'A', 'upsilon') + upsilon_move_path = sbox.ospath('upsilon') + upsilon_move_path_2 = sbox.ospath('A/upsilon') svntest.actions.run_and_verify_svn(None, None, [], 'mv', upsilon_path, upsilon_move_path) svntest.actions.run_and_verify_svn(None, None, [], 'mv', @@ -2556,8 +2541,8 @@ def copy_move_added_paths(sbox): # Move added dir A/D/I to A/B/I, # then move it again to A/D/H/I - I_move_path = os.path.join(wc_dir, 'A', 'B', 'I') - I_move_path_2 = os.path.join(wc_dir, 'A', 'D', 'H', 'I') + I_move_path = sbox.ospath('A/B/I') + I_move_path_2 = sbox.ospath('A/D/H/I') svntest.actions.run_and_verify_svn(None, None, [], 'mv', I_path, I_move_path) svntest.actions.run_and_verify_svn(None, None, [], 'mv', @@ -2607,15 +2592,15 @@ def copy_move_added_paths(sbox): # Run_and_verify_commit() doesn't handle status of unversioned paths # so manually confirm unversioned paths got copied and moved too. unversioned_paths = [ - os.path.join(wc_dir, 'A', 'D', 'H', 'I', 'unversioned1'), - os.path.join(wc_dir, 'A', 'D', 'H', 'I', 'L_UNVERSIONED'), + sbox.ospath('A/D/H/I/unversioned1'), + sbox.ospath('A/D/H/I/L_UNVERSIONED'), os.path.join(wc_dir, 'A', 'D', 'H', 'I', 'L_UNVERSIONED', 'unversioned3'), - os.path.join(wc_dir, 'A', 'D', 'H', 'I', 'J', 'unversioned2'), - os.path.join(wc_dir, 'K', 'I', 'unversioned1'), - os.path.join(wc_dir, 'K', 'I', 'L_UNVERSIONED'), - os.path.join(wc_dir, 'K', 'I', 'L_UNVERSIONED', 'unversioned3'), - os.path.join(wc_dir, 'K', 'I', 'J', 'unversioned2')] + sbox.ospath('A/D/H/I/J/unversioned2'), + sbox.ospath('K/I/unversioned1'), + sbox.ospath('K/I/L_UNVERSIONED'), + sbox.ospath('K/I/L_UNVERSIONED/unversioned3'), + sbox.ospath('K/I/J/unversioned2')] for path in unversioned_paths: if not os.path.exists(path): raise svntest.Failure("Unversioned path '%s' not found." % path) @@ -2627,14 +2612,14 @@ def copy_added_paths_with_props(sbox): wc_dir = sbox.wc_dir # Create a new file, schedule it for addition and set properties - upsilon_path = os.path.join(wc_dir, 'A', 'D', 'upsilon') + upsilon_path = sbox.ospath('A/D/upsilon') svntest.main.file_write(upsilon_path, "This is the file 'upsilon'\n") svntest.actions.run_and_verify_svn(None, None, [], 'add', upsilon_path) svntest.actions.run_and_verify_svn(None, None, [], 'propset', 'foo', 'bar', upsilon_path) # Create a dir and schedule it for addition and set properties - I_path = os.path.join(wc_dir, 'A', 'D', 'I') + I_path = sbox.ospath('A/D/I') os.mkdir(I_path) svntest.actions.run_and_verify_svn(None, None, [], 'add', I_path) svntest.actions.run_and_verify_svn(None, None, [], 'propset', @@ -2655,20 +2640,15 @@ def copy_added_paths_with_props(sbox): 'A/D/I' : Item(props={'foo' : 'bar'}), }) - # Read disk state with props - 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.old_tree(), True) # Copy added dir I to dir A/C - I_copy_path = os.path.join(wc_dir, 'A', 'C', 'I') + I_copy_path = sbox.ospath('A/C/I') svntest.actions.run_and_verify_svn(None, None, [], 'cp', I_path, I_copy_path) # Copy added file A/upsilon into dir A/C - upsilon_copy_path = os.path.join(wc_dir, 'A', 'C', 'upsilon') + upsilon_copy_path = sbox.ospath('A/C/upsilon') svntest.actions.run_and_verify_svn(None, None, [], 'cp', upsilon_path, upsilon_copy_path) @@ -2701,12 +2681,7 @@ def copy_added_paths_with_props(sbox): expected_status, None, wc_dir) - # Read disk state with props - 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.old_tree(), True) def copy_added_paths_to_URL(sbox): "copy added path to URL" @@ -2715,12 +2690,12 @@ def copy_added_paths_to_URL(sbox): wc_dir = sbox.wc_dir # Create a new file and schedule it for addition - upsilon_path = os.path.join(wc_dir, 'A', 'D', 'upsilon') + upsilon_path = sbox.ospath('A/D/upsilon') svntest.main.file_write(upsilon_path, "This is the file 'upsilon'\n") svntest.actions.run_and_verify_svn(None, None, [], 'add', upsilon_path) # Create a dir with children and schedule it for addition - I_path = os.path.join(wc_dir, 'A', 'D', 'I') + I_path = sbox.ospath('A/D/I') J_path = os.path.join(I_path, 'J') eta_path = os.path.join(I_path, 'eta') theta_path = os.path.join(I_path, 'theta') @@ -2857,7 +2832,7 @@ def move_to_relative_paths(sbox): sbox.build() wc_dir = sbox.wc_dir - E_path = os.path.join(wc_dir, 'A', 'B', 'E') + E_path = sbox.ospath('A/B/E') rel_path = os.path.join('..', '..', '..') current_dir = os.getcwd() @@ -2867,8 +2842,9 @@ def move_to_relative_paths(sbox): expected_status = svntest.actions.get_virginal_state(wc_dir, 1) expected_status.add({ - 'beta' : Item(status='A ', copied='+', wc_rev='-'), - 'A/B/E/beta' : Item(status='D ', wc_rev='1') + 'beta' : Item(status='A ', copied='+', wc_rev='-', + moved_from='A/B/E/beta'), + 'A/B/E/beta' : Item(status='D ', wc_rev='1', moved_to='beta') }) svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -2879,7 +2855,7 @@ def move_from_relative_paths(sbox): sbox.build(read_only = True) wc_dir = sbox.wc_dir - F_path = os.path.join(wc_dir, 'A', 'B', 'F') + F_path = sbox.ospath('A/B/F') beta_rel_path = os.path.join('..', 'E', 'beta') current_dir = os.getcwd() @@ -2889,8 +2865,9 @@ def move_from_relative_paths(sbox): expected_status = svntest.actions.get_virginal_state(wc_dir, 1) expected_status.add({ - 'A/B/F/beta' : Item(status='A ', copied='+', wc_rev='-'), - 'A/B/E/beta' : Item(status='D ', wc_rev='1') + 'A/B/F/beta' : Item(status='A ', copied='+', wc_rev='-', + moved_from='A/B/E/beta'), + 'A/B/E/beta' : Item(status='D ', wc_rev='1', moved_to='A/B/F/beta') }) svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -2901,7 +2878,7 @@ def copy_to_relative_paths(sbox): sbox.build(read_only = True) wc_dir = sbox.wc_dir - E_path = os.path.join(wc_dir, 'A', 'B', 'E') + E_path = sbox.ospath('A/B/E') rel_path = os.path.join('..', '..', '..') current_dir = os.getcwd() @@ -2922,7 +2899,7 @@ def copy_from_relative_paths(sbox): sbox.build(read_only = True) wc_dir = sbox.wc_dir - F_path = os.path.join(wc_dir, 'A', 'B', 'F') + F_path = sbox.ospath('A/B/F') beta_rel_path = os.path.join('..', 'E', 'beta') current_dir = os.getcwd() @@ -2947,11 +2924,11 @@ def move_multiple_wc(sbox): sbox.build() wc_dir = sbox.wc_dir - chi_path = os.path.join(wc_dir, 'A', 'D', 'H', 'chi') - psi_path = os.path.join(wc_dir, 'A', 'D', 'H', 'psi') - omega_path = os.path.join(wc_dir, 'A', 'D', 'H', 'omega') - E_path = os.path.join(wc_dir, 'A', 'B', 'E') - C_path = os.path.join(wc_dir, 'A', 'C') + chi_path = sbox.ospath('A/D/H/chi') + psi_path = sbox.ospath('A/D/H/psi') + omega_path = sbox.ospath('A/D/H/omega') + E_path = sbox.ospath('A/B/E') + C_path = sbox.ospath('A/C') # Move chi, psi, omega and E to A/C svntest.actions.run_and_verify_svn(None, None, [], 'mv', chi_path, psi_path, @@ -3002,11 +2979,11 @@ def copy_multiple_wc(sbox): sbox.build() wc_dir = sbox.wc_dir - chi_path = os.path.join(wc_dir, 'A', 'D', 'H', 'chi') - psi_path = os.path.join(wc_dir, 'A', 'D', 'H', 'psi') - omega_path = os.path.join(wc_dir, 'A', 'D', 'H', 'omega') - E_path = os.path.join(wc_dir, 'A', 'B', 'E') - C_path = os.path.join(wc_dir, 'A', 'C') + chi_path = sbox.ospath('A/D/H/chi') + psi_path = sbox.ospath('A/D/H/psi') + omega_path = sbox.ospath('A/D/H/omega') + E_path = sbox.ospath('A/B/E') + C_path = sbox.ospath('A/C') # Copy chi, psi, omega and E to A/C svntest.actions.run_and_verify_svn(None, None, [], 'cp', chi_path, psi_path, @@ -3177,7 +3154,7 @@ def copy_multiple_repo_wc(sbox): psi_url = sbox.repo_url + '/A/D/H/psi' omega_with_space_url = sbox.repo_url + '/A/D/H/omega 2' E_url = sbox.repo_url + '/A/B/E' - C_path = os.path.join(wc_dir, 'A', 'C') + C_path = sbox.ospath('A/C') # We need this in order to check that we don't end up with URI-encoded # paths in the WC (issue #2955) @@ -3223,10 +3200,10 @@ def copy_multiple_wc_repo(sbox): sbox.build() wc_dir = sbox.wc_dir - chi_path = os.path.join(wc_dir, 'A', 'D', 'H', 'chi') - psi_path = os.path.join(wc_dir, 'A', 'D', 'H', 'psi') - omega_path = os.path.join(wc_dir, 'A', 'D', 'H', 'omega') - E_path = os.path.join(wc_dir, 'A', 'B', 'E') + chi_path = sbox.ospath('A/D/H/chi') + psi_path = sbox.ospath('A/D/H/psi') + omega_path = sbox.ospath('A/D/H/omega') + E_path = sbox.ospath('A/B/E') C_url = sbox.repo_url + '/A/C' # Perform the copy and check the output @@ -3281,10 +3258,10 @@ def copy_peg_rev_local_files(sbox): sbox.build() wc_dir = sbox.wc_dir - psi_path = os.path.join(wc_dir, 'A', 'D', 'H', 'psi') - new_iota_path = os.path.join(wc_dir, 'new_iota') - iota_path = os.path.join(wc_dir, 'iota') - sigma_path = os.path.join(wc_dir, 'sigma') + psi_path = sbox.ospath('A/D/H/psi') + new_iota_path = sbox.ospath('new_iota') + iota_path = sbox.ospath('iota') + sigma_path = sbox.ospath('sigma') psi_text = "This is the file 'psi'.\n" iota_text = "This is the file 'iota'.\n" @@ -3323,8 +3300,7 @@ def copy_peg_rev_local_files(sbox): 'sigma' : Item(contents=psi_text, props={}), }) - actual_disk = svntest.tree.build_tree_from_wc(wc_dir, 3) - svntest.tree.compare_trees("disk", actual_disk, expected_disk.old_tree()) + svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) #---------------------------------------------------------------------- @@ -3338,10 +3314,10 @@ def copy_peg_rev_local_dirs(sbox): sbox.build() wc_dir = sbox.wc_dir - E_path = os.path.join(wc_dir, 'A', 'B', 'E') - G_path = os.path.join(wc_dir, 'A', 'D', 'G') - I_path = os.path.join(wc_dir, 'A', 'D', 'I') - J_path = os.path.join(wc_dir, 'A', 'J') + E_path = sbox.ospath('A/B/E') + G_path = sbox.ospath('A/D/G') + I_path = sbox.ospath('A/D/I') + J_path = sbox.ospath('A/J') alpha_path = os.path.join(E_path, 'alpha') # Make some changes to the repository @@ -3406,8 +3382,7 @@ def copy_peg_rev_local_dirs(sbox): 'A/J/beta' : Item(contents="This is the file 'beta'.\n"), }) - actual_disk = svntest.tree.build_tree_from_wc(wc_dir, 5) - svntest.tree.compare_trees("disk", actual_disk, expected_disk.old_tree()) + svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) #---------------------------------------------------------------------- @@ -3421,9 +3396,9 @@ def copy_peg_rev_url(sbox): sbox.build() wc_dir = sbox.wc_dir - psi_path = os.path.join(wc_dir, 'A', 'D', 'H', 'psi') - new_iota_path = os.path.join(wc_dir, 'new_iota') - iota_path = os.path.join(wc_dir, 'iota') + psi_path = sbox.ospath('A/D/H/psi') + new_iota_path = sbox.ospath('new_iota') + iota_path = sbox.ospath('iota') iota_url = sbox.repo_url + '/iota' sigma_url = sbox.repo_url + '/sigma' @@ -3444,11 +3419,12 @@ def copy_peg_rev_url(sbox): wc_dir) # Copy using a peg rev - # Add peg rev '@HEAD' to sigma_url when copying which tests for issue #3651. + # Add an empty peg specifier ('@') to sigma_url when copying, to test for + # issue #3651 "svn copy does not eat peg revision within copy target path". svntest.actions.run_and_verify_svn(None, None, [], 'cp', iota_url + '@HEAD', '-r', '1', - sigma_url + '@HEAD', '-m', 'rev 3') + sigma_url + '@', '-m', 'rev 3') # Validate the copy destination's mergeinfo (we expect none). svntest.actions.run_and_verify_svn(None, [], [], @@ -3483,8 +3459,8 @@ def old_dir_wc_to_wc(sbox): sbox.build() wc_dir = sbox.wc_dir - E = os.path.join(wc_dir, 'A', 'B', 'E') - E2 = os.path.join(wc_dir, 'E2') + E = sbox.ospath('A/B/E') + E2 = sbox.ospath('E2') E_url = sbox.repo_url + '/A/B/E' alpha_url = E_url + '/alpha' @@ -3529,8 +3505,8 @@ def copy_make_parents_wc_wc(sbox): sbox.build() wc_dir = sbox.wc_dir - iota_path = os.path.join(wc_dir, 'iota') - new_iota_path = os.path.join(wc_dir, 'X', 'Y', 'Z', 'iota') + iota_path = sbox.ospath('iota') + new_iota_path = sbox.ospath('X/Y/Z/iota') # Copy iota svntest.actions.run_and_verify_svn(None, None, [], 'cp', '--parents', @@ -3571,7 +3547,7 @@ def copy_make_parents_repo_wc(sbox): wc_dir = sbox.wc_dir iota_url = sbox.repo_url + '/iota' - new_iota_path = os.path.join(wc_dir, 'X', 'Y', 'Z', 'iota') + new_iota_path = sbox.ospath('X/Y/Z/iota') # Copy iota svntest.actions.run_and_verify_svn(None, None, [], @@ -3613,7 +3589,7 @@ def copy_make_parents_wc_repo(sbox): sbox.build() wc_dir = sbox.wc_dir - iota_path = os.path.join(wc_dir, 'iota') + iota_path = sbox.ospath('iota') new_iota_url = sbox.repo_url + '/X/Y/Z/iota' # Copy iota @@ -3804,7 +3780,7 @@ def allow_unversioned_parent_for_copy_src(sbox): # Make the "other" working copy wc2_dir = sbox.add_wc_path('other') svntest.actions.duplicate_dir(wc_dir, wc2_dir) - copy_to_path = os.path.join(wc_dir, 'A', 'copy_of_wc2') + copy_to_path = sbox.ospath('A/copy_of_wc2') # Copy the wc-in-unversioned-parent working copy to our original wc. svntest.actions.run_and_verify_svn(None, @@ -3908,14 +3884,14 @@ def double_parents_with_url(sbox): # Used to cause corruption not fixable by 'svn cleanup'. -def copy_into_absent_dir(sbox): - "copy file into absent dir" +def copy_into_missing_dir(sbox): + "copy file into missing dir" sbox.build(read_only = True) wc_dir = sbox.wc_dir - A_path = os.path.join(wc_dir, 'A') - iota_path = os.path.join(wc_dir, 'iota') + A_path = sbox.ospath('A') + iota_path = sbox.ospath('iota') # Remove 'A' svntest.main.safe_rmtree(A_path) @@ -3966,8 +3942,8 @@ def find_copyfrom_information_upstairs(sbox): sbox.build() wc_dir = sbox.wc_dir - A_path = os.path.join(wc_dir, 'A') - A2_path = os.path.join(wc_dir, 'A2') + A_path = sbox.ospath('A') + A2_path = sbox.ospath('A2') B2_path = os.path.join(A2_path, 'B') svntest.actions.run_and_verify_svn(None, None, [], 'cp', A_path, A2_path) @@ -4018,25 +3994,25 @@ def path_move_and_copy_between_wcs_2475(sbox): expected_wc) # Copy a file from wc to wc2 - mu_path = os.path.join(sbox.wc_dir, 'A', 'mu') + mu_path = sbox.ospath('A/mu') E_path = os.path.join(wc2_dir, 'A', 'B', 'E') svntest.main.run_svn(None, 'cp', mu_path, E_path) # Copy a folder from wc to wc2 - C_path = os.path.join(sbox.wc_dir, 'A', 'C') + C_path = sbox.ospath('A/C') B_path = os.path.join(wc2_dir, 'A', 'B') svntest.main.run_svn(None, 'cp', C_path, B_path) # Move a file from wc to wc2 - mu_path = os.path.join(sbox.wc_dir, 'A', 'mu') + mu_path = sbox.ospath('A/mu') B_path = os.path.join(wc2_dir, 'A', 'B') svntest.main.run_svn(None, 'mv', mu_path, B_path) # Move a folder from wc to wc2 - C_path = os.path.join(sbox.wc_dir, 'A', 'C') + C_path = sbox.ospath('A/C') D_path = os.path.join(wc2_dir, 'A', 'D') svntest.main.run_svn(None, 'mv', C_path, D_path) @@ -4092,8 +4068,8 @@ def commit_copy_depth_empty(sbox): "copy a wcdir, then commit it with --depth empty" sbox.build() - a = os.path.join(sbox.wc_dir, 'A') - new_a = os.path.join(sbox.wc_dir, 'new_A') + a = sbox.ospath('A') + new_a = sbox.ospath('new_A') svntest.actions.run_and_verify_svn(None, None, [], 'cp', a, new_a) @@ -4106,8 +4082,8 @@ def copy_below_copy(sbox): "copy a dir below a copied dir" sbox.build() - A = os.path.join(sbox.wc_dir, 'A') - new_A = os.path.join(sbox.wc_dir, 'new_A') + A = sbox.ospath('A') + new_A = sbox.ospath('new_A') new_A_D = os.path.join(new_A, 'D') new_A_new_D = os.path.join(new_A, 'new_D') new_A_mu = os.path.join(new_A, 'mu') @@ -4170,8 +4146,8 @@ def move_below_move(sbox): "move a dir below a moved dir" sbox.build() - A = os.path.join(sbox.wc_dir, 'A') - new_A = os.path.join(sbox.wc_dir, 'new_A') + A = sbox.ospath('A') + new_A = sbox.ospath('new_A') new_A_D = os.path.join(new_A, 'D') new_A_new_D = os.path.join(new_A, 'new_D') new_A_mu = os.path.join(new_A, 'mu') @@ -4236,7 +4212,7 @@ def reverse_merge_move(sbox): rav_svn = svntest.actions.run_and_verify_svn wc_dir = sbox.wc_dir - a_dir = os.path.join(wc_dir, 'A') + a_dir = sbox.ospath('A') a_repo_url = sbox.repo_url + '/A' sbox.build() @@ -4289,12 +4265,12 @@ def nonrecursive_commit_of_copy(sbox): sbox.build() wc_dir = sbox.wc_dir - main.run_svn(None, 'cp', os.path.join(wc_dir, 'A'), - os.path.join(wc_dir, 'A_new')) - main.run_svn(None, 'cp', os.path.join(wc_dir, 'A/D/G'), - os.path.join(wc_dir, 'A_new/G_new')) - main.run_svn(None, 'rm', os.path.join(wc_dir, 'A_new/C')) - main.run_svn(None, 'rm', os.path.join(wc_dir, 'A_new/B/E')) + main.run_svn(None, 'cp', sbox.ospath('A'), + sbox.ospath('A_new')) + main.run_svn(None, 'cp', sbox.ospath('A/D/G'), + sbox.ospath('A_new/G_new')) + main.run_svn(None, 'rm', sbox.ospath('A_new/C')) + main.run_svn(None, 'rm', sbox.ospath('A_new/B/E')) expected_status = svntest.actions.get_virginal_state(wc_dir, 1) expected_status.add({ @@ -4354,19 +4330,20 @@ def nonrecursive_commit_of_copy(sbox): # and then renaming the subdir, breaks history of the moved files. @Issue(3474) def copy_added_dir_with_copy(sbox): - """copy of new dir with copied file keeps history""" + """copy/mv of new dir with copied file keeps history""" - sbox.build() + sbox.build(read_only=True) wc_dir = sbox.wc_dir - new_dir = os.path.join(wc_dir, 'NewDir'); - new_dir2 = os.path.join(wc_dir, 'NewDir2'); + new_dir = sbox.ospath('NewDir') + new_dir2 = sbox.ospath('NewDir2') + new_dir3 = sbox.ospath('NewDir3') # Alias for svntest.actions.run_and_verify_svn rav_svn = svntest.actions.run_and_verify_svn rav_svn(None, None, [], 'mkdir', new_dir) - rav_svn(None, None, [], 'cp', os.path.join(wc_dir, 'A', 'mu'), new_dir) + rav_svn(None, None, [], 'cp', sbox.ospath('A/mu'), new_dir) rav_svn(None, None, [], 'cp', new_dir, new_dir2) expected_status = svntest.actions.get_virginal_state(wc_dir, 1) @@ -4381,8 +4358,17 @@ def copy_added_dir_with_copy(sbox): svntest.actions.run_and_verify_status(wc_dir, expected_status) + # move of added dir also retains copy history of children + rav_svn(None, None, [], 'mv', new_dir, new_dir3) + expected_status.remove('NewDir', 'NewDir/mu') + expected_status.add( + { + 'NewDir3' : Item(status='A ', wc_rev='0'), + 'NewDir3/mu' : Item(status='A ', copied='+', wc_rev='-'), + }) + svntest.actions.run_and_verify_status(wc_dir, expected_status) + -@SkipUnless(svntest.main.is_posix_os) @Issue(3303) def copy_broken_symlink(sbox): """copy broken symlink""" @@ -4392,14 +4378,14 @@ def copy_broken_symlink(sbox): sbox.build() wc_dir = sbox.wc_dir - new_symlink = os.path.join(wc_dir, 'new_symlink'); - copied_symlink = os.path.join(wc_dir, 'copied_symlink'); - os.symlink('linktarget', new_symlink) + new_symlink = sbox.ospath('new_symlink') + copied_symlink = sbox.ospath('copied_symlink') # Alias for svntest.actions.run_and_verify_svn rav_svn = svntest.actions.run_and_verify_svn - rav_svn(None, None, [], 'add', new_symlink) + sbox.simple_add_symlink('linktarget', 'new_symlink') + rav_svn(None, None, [], 'cp', new_symlink, copied_symlink) # Check whether both new_symlink and copied_symlink are added to the @@ -4432,22 +4418,27 @@ def move_dir_containing_move(sbox): sbox.ospath('A/B_tmp')) expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) - expected_status.tweak('A/B', - 'A/B/E', + expected_status.tweak('A/B', status='D ', moved_to='A/B_tmp') + expected_status.tweak('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', 'A/B/F', 'A/B/lambda', status='D ') expected_status.add({ - 'A/B_tmp' : Item(status='A ', copied='+', wc_rev='-'), + 'A/B_tmp' : Item(status='A ', copied='+', wc_rev='-', + moved_from='A/B'), # alpha has a revision that isn't reported by status. 'A/B_tmp/E' : Item(status=' ', copied='+', wc_rev='-'), - 'A/B_tmp/E/alpha' : Item(status='D ', copied='+', wc_rev='-'), - 'A/B_tmp/E/alpha_moved' : Item(status='A ', copied='+', wc_rev='-'), + 'A/B_tmp/E/alpha' : Item(status='D ', copied='+', wc_rev='-', + moved_to='A/B_tmp/E/alpha_moved'), + 'A/B_tmp/E/alpha_moved' : Item(status='A ', copied='+', wc_rev='-', + moved_from='A/B_tmp/E/alpha'), 'A/B_tmp/E/beta' : Item(status=' ', copied='+', wc_rev='-'), - 'A/B_tmp/F' : Item(status='D ', copied='+', wc_rev='-'), - 'A/B_tmp/F_moved' : Item(status='A ', copied='+', wc_rev='-'), + 'A/B_tmp/F' : Item(status='D ', copied='+', wc_rev='-', + moved_to='A/B_tmp/F_moved'), + 'A/B_tmp/F_moved' : Item(status='A ', copied='+', wc_rev='-', + moved_from='A/B_tmp/F'), 'A/B_tmp/lambda' : Item(status=' ', copied='+', wc_rev='-'), }) @@ -4456,6 +4447,7 @@ def move_dir_containing_move(sbox): svntest.actions.run_and_verify_svn(None, None, [], 'mv', sbox.ospath('A/B_tmp'), sbox.ospath('A/B_moved')) + expected_status.tweak('A/B', moved_to='A/B_moved') expected_status.remove('A/B_tmp', 'A/B_tmp/E', 'A/B_tmp/E/alpha', @@ -4465,13 +4457,18 @@ def move_dir_containing_move(sbox): 'A/B_tmp/F_moved', 'A/B_tmp/lambda') expected_status.add({ - 'A/B_moved' : Item(status='A ', copied='+', wc_rev='-'), + 'A/B_moved' : Item(status='A ', copied='+', wc_rev='-', + moved_from='A/B'), 'A/B_moved/E' : Item(status=' ', copied='+', wc_rev='-'), - 'A/B_moved/E/alpha' : Item(status='D ', copied='+', wc_rev='-'), - 'A/B_moved/E/alpha_moved' : Item(status='A ', copied='+', wc_rev='-'), + 'A/B_moved/E/alpha' : Item(status='D ', copied='+', wc_rev='-', + moved_to='A/B_moved/E/alpha_moved'), + 'A/B_moved/E/alpha_moved' : Item(status='A ', copied='+', wc_rev='-', + moved_from='A/B_moved/E/alpha'), 'A/B_moved/E/beta' : Item(status=' ', copied='+', wc_rev='-'), - 'A/B_moved/F' : Item(status='D ', copied='+', wc_rev='-'), - 'A/B_moved/F_moved' : Item(status='A ', copied='+', wc_rev='-'), + 'A/B_moved/F' : Item(status='D ', copied='+', wc_rev='-', + moved_to='A/B_moved/F_moved'), + 'A/B_moved/F_moved' : Item(status='A ', copied='+', wc_rev='-', + moved_from='A/B_moved/F'), 'A/B_moved/lambda' : Item(status=' ', copied='+', wc_rev='-'), }) @@ -4501,6 +4498,8 @@ def move_dir_containing_move(sbox): 'A/B/lambda', 'A/B_moved/E/alpha', 'A/B_moved/F') + expected_status.tweak('A/B_moved', 'A/B_moved/E/alpha_moved', + 'A/B_moved/F_moved', moved_from=None) svntest.actions.run_and_verify_commit(sbox.wc_dir, expected_output, expected_status, @@ -4513,12 +4512,12 @@ def copy_dir_with_space(sbox): wc_dir = sbox.wc_dir svntest.actions.run_and_verify_svn(None, None, [], 'cp', - os.path.join(wc_dir, 'A', 'B', 'E'), - os.path.join(wc_dir, 'E with spaces')) + sbox.ospath('A/B/E'), + sbox.ospath('E with spaces')) svntest.actions.run_and_verify_svn(None, None, [], 'cp', - os.path.join(wc_dir, 'A', 'B', 'E', 'alpha'), - os.path.join(wc_dir, 'E with spaces', 'al pha')) + sbox.ospath('A/B/E/alpha'), + sbox.ospath('E with spaces/al pha')) expected_status = svntest.actions.get_virginal_state(wc_dir, 1) expected_output = svntest.wc.State(wc_dir, { @@ -4537,13 +4536,13 @@ def copy_dir_with_space(sbox): None, wc_dir) svntest.actions.run_and_verify_svn(None, None, [], 'cp', - os.path.join(wc_dir, 'E with spaces'), - os.path.join(wc_dir, 'E also spaces') + sbox.ospath('E with spaces'), + sbox.ospath('E also spaces') ) svntest.actions.run_and_verify_svn(None, None, [], 'cp', - os.path.join(wc_dir, 'E with spaces/al pha'), - os.path.join(wc_dir, 'E also spaces/al b') + sbox.ospath('E with spaces/al pha'), + sbox.ospath('E also spaces/al b') ) expected_output = svntest.wc.State(wc_dir, { @@ -4563,13 +4562,13 @@ def copy_dir_with_space(sbox): None, wc_dir) svntest.actions.run_and_verify_svn(None, None, [], 'mv', - os.path.join(wc_dir, 'E with spaces'), - os.path.join(wc_dir, 'E new spaces') + sbox.ospath('E with spaces'), + sbox.ospath('E new spaces') ) svntest.actions.run_and_verify_svn(None, None, [], 'mv', - os.path.join(wc_dir, 'E new spaces/al pha'), - os.path.join(wc_dir, 'E also spaces/al c') + sbox.ospath('E new spaces/al pha'), + sbox.ospath('E also spaces/al c') ) expected_output = svntest.wc.State(wc_dir, { @@ -4602,8 +4601,8 @@ def changed_data_should_match_checkout(sbox): sbox.build() wc_dir = sbox.wc_dir - A_B_E = os.path.join(wc_dir, 'A', 'B', 'E') - E_new = os.path.join(wc_dir, 'E_new') + A_B_E = sbox.ospath('A/B/E') + E_new = sbox.ospath('E_new') verify_dir = sbox.add_wc_path('verify') @@ -4633,8 +4632,8 @@ def changed_dir_data_should_match_checkout(sbox): sbox.build() wc_dir = sbox.wc_dir - A_B = os.path.join(wc_dir, 'A', 'B') - B_new = os.path.join(wc_dir, 'B_new') + A_B = sbox.ospath('A/B') + B_new = sbox.ospath('B_new') verify_dir = sbox.add_wc_path('verify') @@ -4665,7 +4664,7 @@ def changed_dir_data_should_match_checkout(sbox): def move_added_nodes(sbox): """move added nodes""" - sbox.build() + sbox.build(read_only=True) svntest.actions.run_and_verify_svn(None, None, [], 'mkdir', sbox.ospath('X'), @@ -4703,9 +4702,9 @@ def copy_over_deleted_dir(sbox): "copy a directory over a deleted directory" sbox.build(read_only = True) - main.run_svn(None, 'rm', os.path.join(sbox.wc_dir, 'A/B')) - main.run_svn(None, 'cp', os.path.join(sbox.wc_dir, 'A/D'), - os.path.join(sbox.wc_dir, 'A/B')) + main.run_svn(None, 'rm', sbox.ospath('A/B')) + main.run_svn(None, 'cp', sbox.ospath('A/D'), + sbox.ospath('A/B')) @Issue(3314) def mixed_rev_copy_del(sbox): @@ -4733,13 +4732,23 @@ def mixed_rev_copy_del(sbox): svntest.main.run_svn(None, 'up', wc_dir) expected_status.tweak(wc_rev=2) svntest.actions.run_and_verify_status(wc_dir, expected_status) - svntest.main.run_svn(None, 'up', '-r1', - sbox.ospath('A/B/E/alpha'), - sbox.ospath('A/B/E/beta')) + + expected_output = svntest.wc.State(wc_dir, { + 'A/B/E/alpha' : Item(status='A '), + }) + expected_status.add({ 'A/B/E/alpha' : Item(status=' ', wc_rev=1), }) expected_status.tweak('A/B/E/beta', wc_rev=1) + svntest.actions.run_and_verify_update(wc_dir, + expected_output, None, + expected_status, [], + None, None, None, None, None, + '-r1', + sbox.ospath('A/B/E/alpha'), + sbox.ospath('A/B/E/beta')) + svntest.actions.run_and_verify_status(wc_dir, expected_status) # Copy A/B/E to A/B/E_copy @@ -4779,7 +4788,7 @@ def mixed_rev_copy_del(sbox): def copy_delete_undo(sbox, use_revert): "copy, delete child, undo" - sbox.build() + sbox.build(read_only=True) wc_dir = sbox.wc_dir # Copy directory with children @@ -4802,7 +4811,7 @@ def copy_delete_undo(sbox, use_revert): if (use_revert): svntest.main.run_svn(wc_dir, 'revert', '--recursive', sbox.ospath('A/B/E-copied')) - svntest.main.safe_rmtree(os.path.join(wc_dir, 'A/B/E-copied')) + svntest.main.safe_rmtree(sbox.ospath('A/B/E-copied')) else: svntest.main.run_svn(wc_dir, 'rm', '--force', sbox.ospath('A/B/E-copied')) expected_status.remove('A/B/E-copied', @@ -4834,7 +4843,7 @@ def copy_delete_revert(sbox): def delete_replace_delete(sbox): "delete a directory scheduled for replacement" - sbox.build() + sbox.build(read_only=True) wc_dir = sbox.wc_dir # Delete directory with children @@ -4950,7 +4959,7 @@ def copy_wc_over_deleted_other_kind(sbox): def move_wc_and_repo_dir_to_itself(sbox): "move wc and repo dir to itself" sbox.build(read_only = True) - wc_dir = os.path.join(sbox.wc_dir, 'A') + wc_dir = sbox.ospath('A') repo_url = sbox.repo_url + '/A' # try to move wc dir to itself @@ -4983,19 +4992,19 @@ def copy_wc_url_with_absent(sbox): # A/D excluded svntest.main.run_svn(None, 'up', '--set-depth', 'exclude', - os.path.join(sbox.wc_dir, 'A/D')) + sbox.ospath('A/D')) # Test issue #3314 after copy sbox.simple_copy('A', 'A_copied') - svntest.main.run_svn(None, 'ci', os.path.join(sbox.wc_dir, 'A_copied'), + svntest.main.run_svn(None, 'ci', sbox.ospath('A_copied'), '-m', 'Commit A_copied') # This tests issue #2763 - svntest.main.run_svn(None, 'cp', os.path.join(sbox.wc_dir, 'A'), + svntest.main.run_svn(None, 'cp', sbox.ospath('A'), '^/A_tagged', '-m', 'Tag A') # And perform a normal commit - svntest.main.run_svn(None, 'ci', os.path.join(sbox.wc_dir, 'A'), + svntest.main.run_svn(None, 'ci', sbox.ospath('A'), '-m', 'Commit A') expected_output = svntest.wc.State(wc_dir, { @@ -5069,20 +5078,20 @@ def copy_wc_url_with_absent(sbox): 'D/G/rho' : Item(status=' ', wc_rev='6'), } - expected_status = svntest.wc.State(os.path.join(wc_dir, 'A_copied'), items) - svntest.actions.run_and_verify_status(os.path.join(wc_dir, 'A_copied'), + expected_status = svntest.wc.State(sbox.ospath('A_copied'), items) + svntest.actions.run_and_verify_status(sbox.ospath('A_copied'), expected_status) - expected_status = svntest.wc.State(os.path.join(wc_dir, 'A_tagged'), items) - svntest.actions.run_and_verify_status(os.path.join(wc_dir, 'A_tagged'), + expected_status = svntest.wc.State(sbox.ospath('A_tagged'), items) + svntest.actions.run_and_verify_status(sbox.ospath('A_tagged'), expected_status) expected_status.add({ 'no' : Item(status=' ', wc_rev='6') }) - expected_status = svntest.wc.State(os.path.join(wc_dir, 'A'), items) - svntest.actions.run_and_verify_status(os.path.join(wc_dir, 'A'), + expected_status = svntest.wc.State(sbox.ospath('A'), items) + svntest.actions.run_and_verify_status(sbox.ospath('A'), expected_status) @@ -5133,9 +5142,9 @@ def deleted_file_with_case_clash(sbox): sbox.build(read_only = True) wc_dir = sbox.wc_dir - iota_path = os.path.join(wc_dir, 'iota') - iota2_path = os.path.join(wc_dir, 'iota2') - IOTA_path = os.path.join(wc_dir, 'IOTA') + iota_path = sbox.ospath('iota') + iota2_path = sbox.ospath('iota2') + IOTA_path = sbox.ospath('IOTA') iota_url = sbox.repo_url + '/iota' # Perform a case-only rename in two steps. @@ -5144,8 +5153,8 @@ def deleted_file_with_case_clash(sbox): expected_status = svntest.actions.get_virginal_state(wc_dir, 1) expected_status.add({ - 'iota' : Item(status='D ', wc_rev=1), - 'IOTA' : Item(status='A ', copied='+', wc_rev='-'), + 'iota' : Item(status='D ', wc_rev=1, moved_to='IOTA'), + 'IOTA' : Item(status='A ', copied='+', wc_rev='-', moved_from='iota'), }) svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -5195,10 +5204,10 @@ def case_only_rename(sbox): sbox.build() wc_dir = sbox.wc_dir - iota_path = os.path.join(wc_dir, 'iota') - IoTa_path = os.path.join(wc_dir, 'IoTa') - B_path = os.path.join(wc_dir, 'A/B') - b_path = os.path.join(wc_dir, 'A/b') + iota_path = sbox.ospath('iota') + IoTa_path = sbox.ospath('IoTa') + B_path = sbox.ospath('A/B') + b_path = sbox.ospath('A/b') # Perform a couple of case-only renames. svntest.main.run_svn(None, 'move', iota_path, IoTa_path) @@ -5207,15 +5216,16 @@ def case_only_rename(sbox): # Create expected status. expected_status = svntest.actions.get_virginal_state(wc_dir, 1) expected_status.add({ - 'iota' : Item(status='D ', wc_rev=1), - 'IoTa' : Item(status='A ', copied='+', wc_rev='-'), - 'A/B' : Item(status='D ', wc_rev='1'), + + 'iota' : Item(status='D ', wc_rev=1, moved_to='IoTa'), + 'IoTa' : Item(status='A ', copied='+', wc_rev='-', moved_from='iota'), + 'A/B' : Item(status='D ', wc_rev='1', moved_to='A/b'), 'A/B/lambda' : Item(status='D ', wc_rev='1'), 'A/B/E' : Item(status='D ', wc_rev='1'), 'A/B/E/alpha' : Item(status='D ', wc_rev='1'), 'A/B/E/beta' : Item(status='D ', wc_rev='1'), 'A/B/F' : Item(status='D ', wc_rev='1'), - 'A/b' : Item(status='A ', copied='+', wc_rev='-'), + 'A/b' : Item(status='A ', copied='+', wc_rev='-', moved_from='A/B'), 'A/b/E' : Item(status=' ', copied='+', wc_rev='-'), 'A/b/E/beta' : Item(status=' ', copied='+', wc_rev='-'), 'A/b/E/alpha' : Item(status=' ', copied='+', wc_rev='-'), @@ -5453,12 +5463,21 @@ def copy_deleted_dir(sbox): sbox.simple_rm('iota') sbox.simple_rm('A') + # E145000 - SVN_ERR_NODE_UNKNOWN_KIND + # E155035 - SVN_ERR_WC_PATH_UNEXPECTED_STATUS + # E155010 - SVN_ERR_WC_PATH_NOT_FOUND + svntest.actions.run_and_verify_svn(None, None, - 'svn: E145000: Path.* does not exist', + 'svn: (E145000|E155035|E155010): ' + + '(Path \'.*iota\' does not exist)|' + + '(Deleted node .*iota\' copied)', 'cp', sbox.ospath('iota'), sbox.ospath('new_iota')) + svntest.actions.run_and_verify_svn(None, None, - 'svn: E145000: Path.* does not exist', + 'svn: (E145000|E155035|E155010): ' + + '(Path \'.*D\' does not exist)|' + + '(Deleted node .*D\' copied)', 'cp', sbox.ospath('A/D'), sbox.ospath('new_D')) @@ -5466,16 +5485,397 @@ def copy_deleted_dir(sbox): os.mkdir(sbox.ospath('A')) os.mkdir(sbox.ospath('A/D')) - # These two invocations raise an assertion. + # At one time these two invocations raised an assertion. svntest.actions.run_and_verify_svn(None, None, - 'svn: E155035: Deleted node.* can\'t be.*', + 'svn: (E155035|E155010): ' + + '(Path \'.*iota\' does not exist)|' + + '(Deleted node.* .*iota\' can\'t be.*)', 'cp', sbox.ospath('iota'), sbox.ospath('new_iota')) svntest.actions.run_and_verify_svn(None, None, - 'svn: E155035: Deleted node.* can\'t be.*', + 'svn: (E155035|E155010): ' + + '(Path \'.*D\' does not exist)|' + + '(Deleted node.* .*D\' can\'t be.*)', 'cp', sbox.ospath('A/D'), sbox.ospath('new_D')) +@Issue(3631) +def commit_copied_half_of_move(sbox): + "attempt to commit the copied part of move" + sbox.build(read_only = True) + wc_dir = sbox.wc_dir + + iota_path = sbox.ospath('iota') + D_path = sbox.ospath('A/D') + + # iota -> A/D/iota; verify we cannot commit just A/D/iota + svntest.actions.run_and_verify_svn(None, None, [], 'mv', iota_path, D_path) + expected_error = "svn: E200009: Cannot commit '.*%s' because it was " \ + "moved from '.*%s'" % (re.escape(sbox.ospath('A/D/iota')), + re.escape(iota_path)) + svntest.actions.run_and_verify_svn(None, None, expected_error, + 'commit', '-m', 'foo', + os.path.join(D_path, 'iota')) + + # verify we cannot commit just A/D + expected_error = "svn: E200009: Cannot commit '.*%s' because it was " \ + "moved from '.*%s'" % (re.escape(sbox.ospath('A/D/iota')), + re.escape(iota_path)) + svntest.actions.run_and_verify_svn(None, None, expected_error, + 'commit', '-m', 'foo', D_path) + + # A/D -> A/C/D; verify we cannot commit just A/C + C_path = sbox.ospath('A/C') + + svntest.actions.run_and_verify_svn(None, None, [], 'mv', D_path, C_path) + expected_error = "svn: E200009: Cannot commit '.*%s' because it was moved " \ + "from '.*%s'" % (re.escape(os.path.join(C_path, "D")), + re.escape(D_path)) + svntest.actions.run_and_verify_svn(None, None, expected_error, + 'commit', '-m', 'foo', C_path) + + # A/C/D/iota -> A/iota; verify that iota's moved-from hasn't changed + D_iota_path = sbox.ospath('A/C/D/iota') + A_iota_path = sbox.ospath('A/iota') + svntest.actions.run_and_verify_svn(None, None, [], 'mv', D_iota_path, + A_iota_path) + expected_error = "svn: E200009: Cannot commit '.*%s' because it was " \ + "moved from '.*%s'" % (re.escape(A_iota_path), + re.escape(iota_path)) + svntest.actions.run_and_verify_svn(None, None, expected_error, + 'commit', '-m', 'foo', A_iota_path) + + +@Issue(3631) +def commit_deleted_half_of_move(sbox): + "attempt to commit the deleted part of move" + sbox.build(read_only = True) + wc_dir = sbox.wc_dir + + iota_path = sbox.ospath('iota') + A_path = sbox.ospath('A') + D_path = sbox.ospath('A/D') + + # iota -> A/D/iota; verify we cannot commit just iota + svntest.actions.run_and_verify_svn(None, None, [], 'mv', iota_path, D_path) + + expected_error = "svn: E200009: Cannot commit '.*%s' because it was moved " \ + "to '.*%s'" % (re.escape(iota_path), + re.escape(os.path.join(D_path, "iota"))) + svntest.actions.run_and_verify_svn(None, None, expected_error, + 'commit', '-m', 'foo', iota_path) + + # A/D -> C; verify we cannot commit just A + C_path = sbox.ospath('C') + + svntest.actions.run_and_verify_svn(None, None, [], 'mv', D_path, C_path) + expected_error = "svn: E200009: Cannot commit '.*%s' because it was moved " \ + "to '.*%s'" % (re.escape(D_path), re.escape(C_path)) + svntest.actions.run_and_verify_svn(None, None, expected_error, + 'commit', '-m', 'foo', A_path) + +@Issue(4026) +def wc_wc_copy_incomplete(sbox): + "wc-to-wc copy of an incomplete directory" + + sbox.build() + wc_dir = sbox.wc_dir + + # We don't know what order the copy will do children of A/B so + # remove files so that only subdirs remain then all children can be + # marked incomplete. + sbox.simple_rm('A/B/lambda') + sbox.simple_commit() + sbox.simple_update() + + # We don't know whether copy will do E or F first, so make both + # incomplete + svntest.actions.set_incomplete(sbox.ospath('A/B/E'), 2) + svntest.actions.set_incomplete(sbox.ospath('A/B/F'), 2) + + # Copy fails with no changes to wc + svntest.actions.run_and_verify_svn(None, None, + 'svn: E155035: Cannot handle status', + 'copy', + sbox.ospath('A/B/E'), + sbox.ospath('A/B/E2')) + expected_status = svntest.actions.get_virginal_state(wc_dir, 2) + expected_status.remove('A/B/lambda') + expected_status.tweak('A/B/E', 'A/B/F', status='! ') + svntest.actions.run_and_verify_status(wc_dir, expected_status) + + # Copy fails part way through + svntest.actions.run_and_verify_svn(None, None, + 'svn: E155035: Cannot handle status', + 'copy', + sbox.ospath('A/B'), + sbox.ospath('A/B2')) + + expected_status.add({ + 'A/B2' : Item(status='A ', copied='+', wc_rev='-'), + 'A/B2/E' : Item(status='! ', wc_rev='-'), + 'A/B2/F' : Item(status='! ', wc_rev='-'), + }) + ### Can't get this to work as copied status of E and F in 1.6 + ### entries tree doesn't match 1.7 status tree + #svntest.actions.run_and_verify_status(wc_dir, expected_status) + + # Commit preserves incomplete status + expected_output = svntest.wc.State(wc_dir, { + 'A/B2': Item(verb='Adding'), + }) + expected_status.tweak('A/B2', + status=' ', copied=None, wc_rev=3) + expected_status.tweak('A/B2/E', 'A/B2/F', + status='! ', copied=None, wc_rev=3) + ### E and F are status '!' but the test code ignores them? + expected_status.remove('A/B2/E', 'A/B2/F') + svntest.actions.run_and_verify_commit(wc_dir, + expected_output, + expected_status, + None, wc_dir) + expected_status.add({ + 'A/B2/E' : Item(status='! ', wc_rev=3), + 'A/B2/F' : Item(status='! ', wc_rev=3), + }) + + # Update makes things complete + expected_output = svntest.wc.State(wc_dir, { + 'A/B2/E' : Item(status='A '), + 'A/B2/E/alpha' : Item(status='A '), + 'A/B2/E/beta' : Item(status='A '), + 'A/B2/F' : Item(status='A '), + }) + expected_status.tweak(wc_rev=3, status=' ') + expected_status.add({ + 'A/B2/E/alpha' : Item(status=' ', wc_rev=3), + 'A/B2/E/beta' : Item(status=' ', wc_rev=3), + }) + svntest.actions.run_and_verify_update(wc_dir, + expected_output, + None, + expected_status) + +def three_nested_moves(sbox): + "three nested moves" + + sbox.build() + wc_dir = sbox.wc_dir + + svntest.actions.run_and_verify_svn(None, None, [], 'mv', + sbox.ospath('A/B'), + sbox.ospath('A/B2')) + svntest.actions.run_and_verify_svn(None, None, [], 'mv', + sbox.ospath('A/B2/E'), + sbox.ospath('A/B2/E2')) + svntest.actions.run_and_verify_svn(None, None, [], 'mv', + sbox.ospath('A/B2/E2/alpha'), + sbox.ospath('A/B2/E2/alpha2')) + + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + expected_status.add({ + 'A/B2' : Item(status=' ', wc_rev=2), + 'A/B2/E2' : Item(status=' ', wc_rev=2), + 'A/B2/E2/alpha2' : Item(status=' ', wc_rev=2), + 'A/B2/E2/beta' : Item(status=' ', wc_rev=2), + 'A/B2/F' : Item(status=' ', wc_rev=2), + 'A/B2/lambda' : Item(status=' ', wc_rev=2), + }) + expected_status.remove('A/B', 'A/B/E', 'A/B/E/alpha', 'A/B/E/beta', + 'A/B/F', 'A/B/lambda') + expected_output = svntest.wc.State(wc_dir, { + 'A/B' : Item(verb='Deleting'), + 'A/B2' : Item(verb='Adding'), + 'A/B2/E' : Item(verb='Deleting'), + 'A/B2/E2' : Item(verb='Adding'), + 'A/B2/E2/alpha' : Item(verb='Deleting'), + 'A/B2/E2/alpha2' : Item(verb='Adding'), + }) + + svntest.actions.run_and_verify_commit(wc_dir, + expected_output, + expected_status, + None, wc_dir) + +def copy_to_unversioned_parent(sbox): + "copy to unversioned parent" + + sbox.build() + + # This succeeds + #svntest.actions.run_and_verify_svn(None, None, [], 'cp', '--parents', + # sbox.ospath('A/B'), + # sbox.ospath('New/B2')) + + # And this currently fails with The node '.*Unversioned' was not found, + # while it should succeed or returns some error that a GUI client can use. + os.mkdir(sbox.ospath('Unversioned')) + svntest.actions.run_and_verify_svn(None, None, [], 'cp', '--parents', + sbox.ospath('A/B'), + sbox.ospath('Unversioned/B2')) + +def copy_text_conflict(sbox): + "copy with a text conflict should not copy markers" + + sbox.build() + wc_dir = sbox.wc_dir + + mu_path = sbox.ospath('A/mu') + svntest.main.file_append(mu_path, 'appended mu text') + + sbox.simple_commit() + svntest.main.file_append(mu_path, 'appended mu text') + + sbox.simple_update(revision='1') + + svntest.actions.run_and_verify_svn(None, None, [], 'cp', + sbox.ospath('A'), + sbox.ospath('A_copied')) + + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + expected_status.tweak('A/mu', status='C ') + expected_status.add({ + # The markers in A + 'A/mu.mine' : Item(status='? '), + 'A/mu.r1' : Item(status='? '), + 'A/mu.r2' : Item(status='? '), + # And what is copied (without markers) + 'A_copied' : Item(status='A ', copied='+', wc_rev='-'), + 'A_copied/C' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/B' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/B/lambda' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/B/E' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/B/E/alpha': Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/B/E/beta' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/B/F' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/D' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/D/G' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/D/G/tau' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/D/G/rho' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/D/G/pi' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/D/H' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/D/H/omega': Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/D/H/psi' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/D/H/chi' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/D/gamma' : Item(status=' ', copied='+', wc_rev='-'), + 'A_copied/mu' : Item(status='M ', copied='+', wc_rev='-'), + }) + svntest.actions.run_and_verify_unquiet_status(wc_dir, expected_status) + +@Issue(2843) +def copy_over_excluded(sbox): + "copy on top of excluded should give error" + + sbox.build(read_only = True) + wc_dir = sbox.wc_dir + + svntest.actions.run_and_verify_svn(None, None, [], + 'update', '--set-depth', 'exclude', + sbox.ospath('A/D')) + + expected_error = "svn: E155000: Path '.*D' exists.*excluded.*" + + svntest.actions.run_and_verify_svn(None, None, expected_error, + 'cp', + sbox.repo_url + '/A/C', + sbox.ospath('A/D')) + + expected_error = "svn: E155000: Path '.*D' exists.*excluded.*" + svntest.actions.run_and_verify_svn(None, None, expected_error, + 'cp', + sbox.ospath('A/C'), + sbox.ospath('A/D')) + +def copy_relocate(sbox): + "copy from a relocated location" + + sbox.build() + wc_dir = sbox.wc_dir + + tmp_dir = sbox.add_wc_path('relocated') + + shutil.copytree(sbox.repo_dir, tmp_dir) + + url = 'file://' + + if sys.platform == 'win32': + url += '/' + + url += os.path.abspath(tmp_dir).replace(os.path.sep, '/') + + svntest.actions.run_and_verify_svn(None, None, [], + 'relocate', url, wc_dir) + + copiedpath = sbox.ospath('AA') + svntest.actions.run_and_verify_svn(None, None, [], + 'cp', url + '/A', copiedpath) + + svntest.actions.run_and_verify_svn(None, None, [], + 'info', copiedpath) + +def ext_wc_copy_deleted(sbox): + "copy deleted tree from separate wc" + + sbox.build() + + wc_dir = sbox.wc_dir + wc2_dir = sbox.add_wc_path('2') + + sbox.simple_rm('A/B') + sbox.simple_commit() + + svntest.actions.run_and_verify_svn(None, None, [], + 'up', '--set-depth', 'exclude', + sbox.ospath('A/D')) + + svntest.actions.run_and_verify_svn(None, None, [], + 'co', sbox.repo_url, wc2_dir, '-r', 1) + + svntest.actions.run_and_verify_svn(None, None, [], + 'cp', sbox.path('A'), os.path.join(wc2_dir,'AA')) + + expected_output = expected_output = svntest.wc.State(wc2_dir, { + 'AA' : Item(verb='Adding'), + 'AA/B' : Item(verb='Deleting'), + }) + + svntest.actions.run_and_verify_commit(wc2_dir, + expected_output, None, None, + wc2_dir) + +def copy_subtree_deleted(sbox): + "copy to-be-deleted subtree" + + sbox.build() + wc_dir = sbox.wc_dir + wc2_dir = sbox.add_wc_path('2') + svntest.actions.duplicate_dir(wc_dir, wc2_dir) + + sbox.simple_rm('A/B') + + # Commit copy within a working copy + sbox.simple_copy('A', 'AA') + expected_output = expected_output = svntest.wc.State(wc_dir, { + 'AA' : Item(verb='Adding'), + 'AA/B' : Item(verb='Deleting'), + }) + svntest.actions.run_and_verify_commit(wc_dir, + expected_output, None, None, + sbox.ospath('AA')) + + # Commit copy between working copies + svntest.actions.run_and_verify_svn(None, None, [], + 'cp', sbox.path('A'), + os.path.join(wc2_dir,'AA2')) + expected_output = expected_output = svntest.wc.State(wc2_dir, { + 'AA2' : Item(verb='Adding'), + 'AA2/B' : Item(verb='Deleting'), + }) + svntest.actions.run_and_verify_commit(wc2_dir, + expected_output, None, None, + wc2_dir) + + ######################################################################## # Run the tests @@ -5553,7 +5953,7 @@ test_list = [ None, allow_unversioned_parent_for_copy_src, unneeded_parents, double_parents_with_url, - copy_into_absent_dir, + copy_into_missing_dir, find_copyfrom_information_upstairs, path_move_and_copy_between_wcs_2475, path_copy_in_repo_2475, @@ -5586,6 +5986,16 @@ test_list = [ None, case_only_rename, copy_and_move_conflicts, copy_deleted_dir, + commit_copied_half_of_move, + commit_deleted_half_of_move, + wc_wc_copy_incomplete, + three_nested_moves, + copy_to_unversioned_parent, + copy_text_conflict, + copy_over_excluded, + copy_relocate, + ext_wc_copy_deleted, + copy_subtree_deleted, ] if __name__ == '__main__': |