diff options
Diffstat (limited to 'subversion/tests/cmdline/stat_tests.py')
-rwxr-xr-x | subversion/tests/cmdline/stat_tests.py | 546 |
1 files changed, 381 insertions, 165 deletions
diff --git a/subversion/tests/cmdline/stat_tests.py b/subversion/tests/cmdline/stat_tests.py index 27094f7..6e706ef 100755 --- a/subversion/tests/cmdline/stat_tests.py +++ b/subversion/tests/cmdline/stat_tests.py @@ -29,6 +29,9 @@ import os import re import time import datetime +import logging + +logger = logging.getLogger() # Our testing module import svntest @@ -80,8 +83,8 @@ def status_update_with_nested_adds(sbox): svntest.actions.duplicate_dir(wc_dir, wc_backup) # Create newdir and newfile - newdir_path = os.path.join(wc_dir, 'newdir') - newfile_path = os.path.join(wc_dir, 'newdir', 'newfile') + newdir_path = sbox.ospath('newdir') + newfile_path = sbox.ospath('newdir/newfile') os.makedirs(newdir_path) svntest.main.file_append(newfile_path, 'new text') @@ -176,7 +179,6 @@ def status_type_change(sbox): sbox.build(read_only = True) wc_dir = sbox.wc_dir - single_db = svntest.main.wc_is_singledb(wc_dir) os.chdir(wc_dir) @@ -186,8 +188,7 @@ def status_type_change(sbox): os.rename('A', 'iota') os.rename('was_iota', 'A') - if single_db: - expected_output = [ + expected_output = [ '~ A\n', '! A/mu\n', '! A/B\n', @@ -208,14 +209,9 @@ def status_type_change(sbox): '! A/D/H/omega\n', '! A/D/H/psi\n', '~ iota\n', - ] + ] - expected_output = [s.replace('/', os.path.sep) for s in expected_output] - else: - expected_output = [ - '~ A\n', - '~ iota\n', - ] + expected_output = [s.replace('/', os.path.sep) for s in expected_output] svntest.actions.run_and_verify_svn(None, UnorderedOutput(expected_output), [], 'status') @@ -225,10 +221,9 @@ def status_type_change(sbox): os.remove('A') os.mkdir('A') - if single_db: - # A is a directory again, so it is no longer missing, but it's - # descendants are - expected_output = [ + # A is a directory again, so it is no longer missing, but it's + # descendants are + expected_output = [ '! A/mu\n', '! A/B\n', '! A/B/lambda\n', @@ -248,15 +243,9 @@ def status_type_change(sbox): '! A/D/H/omega\n', '! A/D/H/psi\n', '~ iota\n', - ] - # Fix separator for Windows - expected_output = [s.replace('/', os.path.sep) for s in expected_output] - else: - # A misses its administrative area, so it is missing - expected_output = [ - '~ A\n', - '~ iota\n', - ] + ] + # Fix separator for Windows + expected_output = [s.replace('/', os.path.sep) for s in expected_output] svntest.actions.run_and_verify_svn(None, UnorderedOutput(expected_output), [], 'status') @@ -266,14 +255,6 @@ def status_type_change(sbox): svntest.main.safe_rmtree('iota') os.mkdir('iota') - if not svntest.main.wc_is_singledb('.'): - # A misses its administrative area, so it is still missing and - # iota is still obstructed - expected_output = [ - '~ A\n', - '~ iota\n', - ] - svntest.actions.run_and_verify_svn(None, UnorderedOutput(expected_output), [], 'status') @@ -284,7 +265,6 @@ def status_type_change_to_symlink(sbox): sbox.build(read_only = True) wc_dir = sbox.wc_dir - single_db = svntest.main.wc_is_singledb(wc_dir) os.chdir(wc_dir) @@ -294,8 +274,7 @@ def status_type_change_to_symlink(sbox): svntest.main.safe_rmtree('A/D') os.symlink('bar', 'A/D') - if single_db: - expected_output = [ + expected_output = [ '~ A/D\n', '! A/D/gamma\n', '! A/D/G\n', @@ -307,12 +286,7 @@ def status_type_change_to_symlink(sbox): '! A/D/H/omega\n', '! A/D/H/psi\n', '~ iota\n', - ] - else: - expected_output = [ - '~ A/D\n', - '~ iota\n', - ] + ] svntest.actions.run_and_verify_svn(None, UnorderedOutput(expected_output), [], 'status') @@ -644,7 +618,7 @@ def get_last_changed_date(path): for line in out: if re.match("^Last Changed Date", line): return line - print("Didn't find Last Changed Date for " + path) + logger.warn("Didn't find Last Changed Date for %s", path) raise svntest.Failure # Helper for timestamp_behaviour test @@ -655,8 +629,17 @@ def get_text_timestamp(path): for line in out: if re.match("^Text Last Updated", line): return line - print("Didn't find text-time for " + path) - raise svntest.Failure + logger.warn("Didn't find text-time for %s", path) + raise svntest.Failure("didn't find text-time") + +def no_text_timestamp(path): + "ensure no text-time for path using svn info" + exit_code, out, err = svntest.actions.run_and_verify_svn(None, None, [], + 'info', path) + for line in out: + if re.match("^Text Last Updated", line): + logger.warn("Found text-time for %s", path) + raise svntest.Failure("found text-time") # Helper for timestamp_behaviour test def text_time_behaviour(wc_dir, wc_path, status_path, expected_status, cmd): @@ -704,8 +687,8 @@ def timestamp_behaviour(sbox): sbox.build() 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') expected_status = svntest.actions.get_virginal_state(wc_dir, 1) svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -789,9 +772,9 @@ use-commit-times = yes or fmt[23:25] != iota_ts[23:25]): # NOTE: the two strings below won't *exactly* match (see just above), # but the *numeric* portions of them should. - print("File timestamp on 'iota' does not match.") - print(" EXPECTED: %s" % iota_ts) - print(" ACTUAL: %s" % fmt) + logger.warn("File timestamp on 'iota' does not match.") + logger.warn(" EXPECTED: %s", iota_ts) + logger.warn(" ACTUAL: %s", fmt) raise svntest.Failure #---------------------------------------------------------------------- @@ -811,12 +794,9 @@ def status_on_unversioned_dotdot(sbox): os.mkdir(new_subsub) os.chdir(new_subsub) - exit_code, out, err = svntest.main.run_svn(1, 'st', '..') - for line in err: - if line.find('svn: warning: W155007: \'..\' is not a working copy') != -1: - break - else: - raise svntest.Failure + svntest.actions.run_and_verify_svn2(None, None, + "svn: warning: W155(010|007):.*'.*'.*not", + 0, 'st', '..') #---------------------------------------------------------------------- @@ -860,7 +840,7 @@ def status_on_partially_nonrecursive_wc(sbox): D_url = top_url + '/A/D' G_url = top_url + '/A/D/G' H_url = top_url + '/A/D/H' - rho = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') + rho = sbox.ospath('A/D/G/rho') # Commit a change to A/D/G/rho. This will be our equivalent of # whatever change it was that happened between r213 and HEAD in the @@ -887,7 +867,7 @@ def missing_dir_in_anchor(sbox): sbox.build(read_only = True) wc_dir = sbox.wc_dir - foo_path = os.path.join(wc_dir, 'foo') + foo_path = sbox.ospath('foo') svntest.actions.run_and_verify_svn(None, None, [], 'mkdir', foo_path) expected_status = svntest.actions.get_virginal_state(wc_dir, 1) expected_status.add({ @@ -936,7 +916,7 @@ def status_in_xml(sbox): 'cp', '-m', 'repo-to-repo copy', sbox.repo_url + '/iota', sbox.repo_url + '/iota2') - + file_path = sbox.ospath('iota2') expected_entries = {file_path : {'wcprops' : 'none', @@ -968,7 +948,7 @@ def status_ignored_dir(sbox): "status on ignored directory" sbox.build() wc_dir = sbox.wc_dir - new_dir = os.path.join(wc_dir, "dir.o") + new_dir = sbox.ospath('dir.o') new_dir_url = sbox.repo_url + "/dir.o" svntest.actions.run_and_verify_svn("Create dir", "\n|Committed revision 2.", [], @@ -986,15 +966,19 @@ def status_ignored_dir(sbox): #---------------------------------------------------------------------- -@Issue(2030) -def status_unversioned_dir(sbox): - "status on unversioned dir" +def status_unversioned_dir_in_wc(sbox): + "status on unversioned dir in working copy" sbox.build(read_only = True) - dir = sbox.repo_dir - expected_err = "svn: warning: W155007: '.*(/|\\\\)" + os.path.basename(dir) + \ - "' is not a working copy" + + # Create two unversioned directories within the test working copy + path = sbox.ospath('1/2') + os.makedirs(path) + + expected_err = "svn: warning: (W155007|W155010): .*'.*(/|\\\\)" + \ + os.path.basename(path) + \ + "' was not found" svntest.actions.run_and_verify_svn2(None, [], expected_err, 0, - "status", dir, dir) + "status", path) #---------------------------------------------------------------------- @@ -1002,58 +986,45 @@ def status_missing_dir(sbox): "status with a versioned directory missing" sbox.build(read_only = True) wc_dir = sbox.wc_dir - a_d_g = os.path.join(wc_dir, "A", "D", "G") + a_d_g = sbox.ospath('A/D/G') # ok, blow away the A/D/G directory svntest.main.safe_rmtree(a_d_g) - if svntest.main.wc_is_singledb(wc_dir): - expected = [ + expected = [ '! A/D/G\n', '! A/D/G/rho\n', '! A/D/G/pi\n', '! A/D/G/tau\n', - ] - expected = [ s.replace('A/D/G', a_d_g).replace('/', os.path.sep) - for s in expected ] - else: - expected = ["! " + a_d_g + "\n"] + ] + expected = [ s.replace('A/D/G', a_d_g).replace('/', os.path.sep) + for s in expected ] svntest.actions.run_and_verify_svn(None, UnorderedOutput(expected), [], "status", wc_dir) - if svntest.main.wc_is_singledb(wc_dir): - expected = [ + expected = [ "! 1 " + a_d_g + "\n", "! 1 " + os.path.join(a_d_g, "rho") + "\n", "! 1 " + os.path.join(a_d_g, "pi") + "\n", "! 1 " + os.path.join(a_d_g, "tau") + "\n", - "Status against revision: 1\n" ] - else: - expected = [ - " * " + os.path.join(a_d_g, "pi") + "\n", - " * " + os.path.join(a_d_g, "rho") + "\n", - " * " + os.path.join(a_d_g, "tau") + "\n", - "! * ? " + a_d_g + "\n", - " * 1 " + os.path.join(wc_dir, "A", "D") + "\n", - "Status against revision: 1\n" ] + "Status against revision: 1\n" + ] # now run status -u, we should be able to do this without crashing svntest.actions.run_and_verify_svn(None, UnorderedOutput(expected), [], "status", "-u", wc_dir) # Finally run an explicit status request directly on the missing directory. - if svntest.main.wc_is_singledb(wc_dir): - expected = [ + expected = [ "! A/D/G\n", "! A/D/G/rho\n", "! A/D/G/pi\n", "! A/D/G/tau\n", ] - expected = [ s.replace('A/D/G', a_d_g).replace('/', os.path.sep) - for s in expected ] - else: - expected = ["! " + a_d_g + "\n"] + expected = [ s.replace('A/D/G', a_d_g).replace('/', os.path.sep) + for s in expected ] + svntest.actions.run_and_verify_svn(None, UnorderedOutput(expected), [], "status", a_d_g) @@ -1074,7 +1045,7 @@ def status_add_plus_conflict(sbox): svntest.actions.run_and_verify_svn(None, None, [], 'update', wc_dir) - branch_file = os.path.join(wc_dir, 'branch', 'file') + branch_file = sbox.ospath('branch/file') svntest.main.file_write(branch_file, "line 1\nline2\nline3\n", 'wb+') @@ -1096,7 +1067,7 @@ def status_add_plus_conflict(sbox): 'commit', branch_file, '-m', 'rev 5') - trunk_dir = os.path.join(wc_dir, 'trunk') + trunk_dir = sbox.ospath('trunk') svntest.actions.run_and_verify_svn(None, None, [], 'merge', @@ -1107,15 +1078,13 @@ def status_add_plus_conflict(sbox): branch_url, '-r', '4:5', trunk_dir) lines = [ - "? " + os.path.join(wc_dir, "trunk", "file.merge-left.r4") + "\n", - "? " + os.path.join(wc_dir, "trunk", "file.merge-right.r5") + "\n", - "? " + os.path.join(wc_dir, "trunk", "file.working") + "\n", - "C + " + os.path.join(wc_dir, "trunk", "file") + "\n", - "Summary of conflicts:\n", - " Text conflicts: 1\n", - ] + "? " + sbox.ospath('trunk/file.merge-left.r4') + "\n", + "? " + sbox.ospath('trunk/file.merge-right.r5') + "\n", + "? " + sbox.ospath('trunk/file.working') + "\n", + "C + " + sbox.ospath('trunk/file') + "\n", + ] + svntest.main.summary_of_conflicts(text_conflicts=1) if svntest.main.server_has_mergeinfo(): - lines.append(" M " + os.path.join(wc_dir, "trunk") + "\n") + lines.append(" M " + sbox.ospath('trunk') + "\n") expected_output = svntest.verify.UnorderedOutput(lines) @@ -1129,7 +1098,7 @@ def inconsistent_eol(sbox): sbox.build() wc_dir = sbox.wc_dir - iota_path = os.path.join(wc_dir, "iota") + iota_path = sbox.ospath('iota') svntest.main.file_write(iota_path, "line 1\nline 2\n", "wb") @@ -1137,7 +1106,7 @@ def inconsistent_eol(sbox): "property 'svn:eol-style' set on.*iota", [], 'propset', 'svn:eol-style', 'native', - os.path.join(wc_dir, 'iota')) + sbox.ospath('iota')) expected_output = svntest.wc.State(wc_dir, { 'iota' : Item(verb='Sending'), @@ -1161,7 +1130,7 @@ def status_update_with_incoming_props(sbox): sbox.build() wc_dir = sbox.wc_dir - A_path = os.path.join(wc_dir, 'A') + A_path = sbox.ospath('A') # Add a property to the root folder and a subdir svntest.main.run_svn(None, 'propset', 'red', 'rojo', wc_dir) @@ -1214,7 +1183,7 @@ def status_update_with_incoming_props(sbox): expected = svntest.verify.UnorderedOutput( [" 1 1 jrandom " + - os.path.join(wc_dir, "iota") + "\n", + sbox.ospath('iota') + "\n", " * 1 1 jrandom " + A_path + "\n", " * 1 1 jrandom " + wc_dir + "\n", "Status against revision: 2\n" ]) @@ -1260,7 +1229,7 @@ def status_update_verbose_with_incoming_props(sbox): sbox.build() wc_dir = sbox.wc_dir - A_path = os.path.join(wc_dir, 'A') + A_path = sbox.ospath('A') D_path = os.path.join(A_path, 'D') B_path = os.path.join(A_path, 'B') E_path = os.path.join(A_path, 'B', 'E') @@ -1328,7 +1297,7 @@ def status_update_verbose_with_incoming_props(sbox): " " + common + os.path.join(A_path, 'mu') + "\n", " " + common + os.path.join(A_path, 'C') + "\n", " " + common + A_path + "\n", - " " + common + os.path.join(wc_dir, 'iota') + "\n", + " " + common + sbox.ospath('iota') + "\n", " *" + common + wc_dir + "\n", "Status against revision: 2\n" ]) @@ -1345,7 +1314,7 @@ def status_nonrecursive_update(sbox): sbox.build() wc_dir = sbox.wc_dir - A_path = os.path.join(wc_dir, 'A') + A_path = sbox.ospath('A') D_path = os.path.join(A_path, 'D') mu_path = os.path.join(A_path, 'mu') gamma_path = os.path.join(D_path, 'gamma') @@ -1384,7 +1353,7 @@ def status_nonrecursive_update(sbox): '-r', '1', wc_dir) # Check the remote status of folder A (non-recursively) - xout = [" * 1 " + os.path.join(wc_dir, "A", "mu") + "\n", + xout = [" * 1 " + sbox.ospath('A/mu') + "\n", "Status against revision: 2\n" ] svntest.actions.run_and_verify_svn(None, @@ -1429,7 +1398,7 @@ def status_depth_local(sbox): sbox.build(read_only = True) wc_dir = sbox.wc_dir - A_path = os.path.join(wc_dir, 'A') + A_path = sbox.ospath('A') D_path = os.path.join(A_path, 'D') mu_path = os.path.join(A_path, 'mu') @@ -1437,8 +1406,8 @@ def status_depth_local(sbox): # make some changes to the greek tree change_files(wc_dir, ['A/mu', 'A/D/gamma']) - svntest.main.run_svn(None, 'propset', 'svn:test', 'value', A_path) - svntest.main.run_svn(None, 'propset', 'svn:test', 'value', D_path) + svntest.main.run_svn(None, 'propset', '--force', 'svn:test', 'value', A_path) + svntest.main.run_svn(None, 'propset', '--force', 'svn:test', 'value', D_path) # for all the possible types of depth, check the status @@ -1488,7 +1457,7 @@ def status_depth_update(sbox): sbox.build() wc_dir = sbox.wc_dir - A_path = os.path.join(wc_dir, 'A') + A_path = sbox.ospath('A') D_path = os.path.join(A_path, 'D') mu_path = os.path.join(A_path, 'mu') @@ -1497,8 +1466,8 @@ def status_depth_update(sbox): # add some files, change directory properties change_files_and_commit(wc_dir, ['A/mu', 'A/D/gamma']) svntest.main.run_svn(None, 'up', wc_dir) - svntest.main.run_svn(None, 'propset', 'svn:test', 'value', A_path) - svntest.main.run_svn(None, 'propset', 'svn:test', 'value', D_path) + svntest.main.run_svn(None, 'propset', '--force', 'svn:test', 'value', A_path) + svntest.main.run_svn(None, 'propset', '--force', 'svn:test', 'value', D_path) svntest.main.run_svn(None, 'ci', '-m', 'log message', wc_dir) # update to r1 @@ -1559,7 +1528,7 @@ def status_depth_update(sbox): #---------------------------------------------------------------------- def status_depth_update_local_modifications(sbox): "run 'status --depth=X -u' with local changes" - + sbox.build() wc_dir = sbox.wc_dir A_path = sbox.ospath('A') @@ -1568,8 +1537,8 @@ def status_depth_update_local_modifications(sbox): mu_path = os.path.join(A_path, 'mu') gamma_path = os.path.join(D_path, 'gamma') - svntest.main.run_svn(None, 'propset', 'svn:test', 'value', A_path) - svntest.main.run_svn(None, 'propset', 'svn:test', 'value', D_path) + svntest.main.run_svn(None, 'propset', '--force', 'svn:test', 'value', A_path) + svntest.main.run_svn(None, 'propset', '--force', 'svn:test', 'value', D_path) svntest.main.file_append(mu_path, 'modified') svntest.main.file_append(gamma_path, 'modified') @@ -1640,7 +1609,7 @@ def status_dash_u_deleted_directories(sbox): sbox.build() wc_dir = sbox.wc_dir - A_path = os.path.join(wc_dir, 'A') + A_path = sbox.ospath('A') B_path = os.path.join(A_path, 'B') # delete the B directory @@ -1727,8 +1696,7 @@ def status_dash_u_type_change(sbox): svntest.main.safe_rmtree('A') os.mkdir('A') - if svntest.main.wc_is_singledb('.'): - output =[ + output = [ "! 1 A/mu\n", "! 1 A/B\n", "! 1 A/B/lambda\n", @@ -1749,16 +1717,11 @@ def status_dash_u_type_change(sbox): "! 1 A/D/H/psi\n", "~ 1 iota\n", "Status against revision: 1\n" - ] + ] - expected = svntest.verify.UnorderedOutput( + expected = svntest.verify.UnorderedOutput( [s.replace('/', os.path.sep) for s in output]) - else: - expected = svntest.verify.UnorderedOutput( - ["~ 1 iota\n", - "~ ? A\n", - "Status against revision: 1\n" ]) svntest.actions.run_and_verify_svn(None, expected, @@ -1776,7 +1739,7 @@ def status_with_tree_conflicts(sbox): svntest.actions.build_greek_tree_conflicts(sbox) wc_dir = sbox.wc_dir - G = os.path.join(wc_dir, 'A', 'D', 'G') + G = sbox.ospath('A/D/G') pi = os.path.join(G, 'pi') rho = os.path.join(G, 'rho') tau = os.path.join(G, 'tau') @@ -1784,14 +1747,12 @@ def status_with_tree_conflicts(sbox): # check status of G expected = svntest.verify.UnorderedOutput( ["A + C %s\n" % rho, - " > local edit, incoming delete upon update\n", + " > local file edit, incoming file delete upon update\n", "D C %s\n" % pi, - " > local delete, incoming edit upon update\n", + " > local file delete, incoming file edit upon update\n", "! C %s\n" % tau, - " > local delete, incoming delete upon update\n", - "Summary of conflicts:\n", - " Tree conflicts: 3\n", - ]) + " > local file delete, incoming file delete upon update\n", + ] + svntest.main.summary_of_conflicts(tree_conflicts=3)) svntest.actions.run_and_verify_svn(None, expected, @@ -1802,15 +1763,12 @@ def status_with_tree_conflicts(sbox): expected = svntest.verify.UnorderedOutput( [" 2 2 jrandom %s\n" % G, "D C 2 2 jrandom %s\n" % pi, - " > local delete, incoming edit upon update\n", + " > local file delete, incoming file edit upon update\n", "A + C - 1 jrandom %s\n" % rho, - " > local edit, incoming delete upon update\n", + " > local file edit, incoming file delete upon update\n", "! C %s\n" % tau, - " > local delete, incoming delete upon update\n", - "Summary of conflicts:\n", - " Tree conflicts: 3\n", - ]) - + " > local file delete, incoming file delete upon update\n", + ] + svntest.main.summary_of_conflicts(tree_conflicts=3)) svntest.actions.run_and_verify_svn(None, expected, @@ -1842,18 +1800,19 @@ def status_with_tree_conflicts(sbox): # check if the path should be a victim m = re.search('tree-conflicted="true"', entry) if (m is None) and should_be_victim[path]: - print("ERROR: expected '%s' to be a tree conflict victim." % path) - print("ACTUAL STATUS OUTPUT:") - print(output_str) + logger.warn("ERROR: expected '%s' to be a tree conflict victim.", path) + logger.warn("ACTUAL STATUS OUTPUT:") + logger.warn(output_str) raise svntest.Failure if m and not should_be_victim[path]: - print("ERROR: did NOT expect '%s' to be a tree conflict victim." % path) - print("ACTUAL STATUS OUTPUT:") - print(output_str) + logger.warn("ERROR: did NOT expect '%s' to be a tree conflict victim.", + path) + logger.warn("ACTUAL STATUS OUTPUT:") + logger.warn(output_str) raise svntest.Failure if real_entry_count != len(should_be_victim): - print("ERROR: 'status --xml' output is incomplete.") + logger.warn("ERROR: 'status --xml' output is incomplete.") raise svntest.Failure @@ -1865,21 +1824,13 @@ def status_nested_wc_old_format(sbox): sbox.build(read_only = True) wc_dir = sbox.wc_dir - os.mkdir(os.path.join(wc_dir, 'subdir')) - os.mkdir(os.path.join(wc_dir, 'subdir', '.svn')) - svntest.main.file_append(os.path.join(wc_dir, 'subdir', '.svn', 'format'), + os.mkdir(sbox.ospath('subdir')) + os.mkdir(sbox.ospath('subdir/.svn')) + svntest.main.file_append(sbox.ospath('subdir/.svn/format'), '10\n') # format 10 was the Subversion 1.6 format os.chdir(wc_dir) svntest.actions.run_and_verify_svn(None, [ "? subdir\n" ], [], 'st') -######################################################################## -# Run the tests - - -def simple_lock(sbox, relpath): - path = os.path.join(sbox.wc_dir, relpath) - svntest.actions.run_and_verify_svn(None, None, [], 'lock', path) - #---------------------------------------------------------------------- # Regression test for issue #3855 "status doesn't show 'K' on a locked # deleted node". @@ -1888,10 +1839,11 @@ def status_locked_deleted(sbox): "status with locked deleted file" sbox.build() - iota_path = os.path.join(sbox.wc_dir, 'iota') + iota_path = sbox.ospath('iota') sbox.simple_rm('iota') - simple_lock(sbox, 'iota') + svntest.actions.run_and_verify_svn(None, None, [], 'lock', + os.path.join(sbox.wc_dir, 'iota')) svntest.actions.run_and_verify_svn(None, ['D K %s\n' % iota_path], [], 'status', iota_path) @@ -1980,6 +1932,32 @@ def wclock_status(sbox): svntest.actions.run_and_verify_svn(None, expected_output, [], 'status', wc_dir) + +@Issue(4072) +@XFail() +def modified_modulo_translation(sbox): + "modified before translation, unmodified after" + + sbox.build() + wc_dir = sbox.wc_dir + + # iota is a shell script. + sbox.simple_propset('svn:eol-style', 'LF', 'iota') + sbox.simple_commit() + + # CRLF it. + open(sbox.ospath('iota'), 'wb').write("This is the file 'iota'.\r\n") + + # Run status. Expect some output. + # TODO: decide how such files should show in the output; whether they + # always show, or only with some --flag; and adjust this accordingly. + svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [], + 'status', wc_dir) + + # Expect the file to be renormalized (to LF) after a revert. + sbox.simple_revert('iota') + svntest.actions.run_and_verify_svn(None, [], [], 'status', wc_dir) + def status_not_present(sbox): "no status on not-present and excluded nodes" @@ -1991,7 +1969,7 @@ def status_not_present(sbox): svntest.main.run_svn(None, 'up', '--set-depth', 'exclude', sbox.ospath('A/mu'), sbox.ospath('A/B')) sbox.simple_commit() - + svntest.actions.run_and_verify_svn(None, [], [],'status', sbox.ospath('iota'), sbox.ospath('A/B'), @@ -1999,6 +1977,237 @@ def status_not_present(sbox): sbox.ospath('A/mu'), sbox.ospath('no-file')) +# Skip this test is a .svn dir exists in the root directory +@Skip(lambda: os.path.exists("/%s" % svntest.main.get_admin_name())) +def status_unversioned_dir(sbox): + "status on unversioned dir" + sbox.build(read_only = True, create_wc = False) + + # Run svn status on "/", which we assume exists and isn't a WC. + # This should work on UNIX-like systems and Windows systems + expected_err = "svn: warning: W1550(07|10): .*'.*(/|\\\\)" + \ + "' is not a working copy" + svntest.actions.run_and_verify_svn2(None, [], expected_err, 0, + "status", "/") + +def status_case_changed(sbox): + "status reporting on case changed nodes directly" + + sbox.build(read_only = True) + wc_dir = sbox.wc_dir + + os.rename(sbox.ospath('iota'), sbox.ospath('iOTA')) + + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + expected_status.add({ + 'iOTA' : Item(status='? '), + }) + expected_status.tweak('iota', status='! ') + + # First run status on the directory + svntest.actions.run_and_verify_unquiet_status(wc_dir, + expected_status) + + # Now on the missing iota directly, which should give the same + # result, even on case insenstive filesystems + expected_status = svntest.wc.State(wc_dir, { + 'iota' : Item(status='! ', wc_rev=1), + }) + svntest.actions.run_and_verify_unquiet_status(sbox.ospath('iota'), + expected_status) + + # And on the unversioned iOTA + expected_status = svntest.wc.State(wc_dir, { + 'iOTA' : Item(status='? '), + }) + svntest.actions.run_and_verify_unquiet_status(sbox.ospath('iOTA'), + expected_status) + + +def move_update_timestamps(sbox): + "timestamp behaviour for move-update" + + sbox.build() + wc_dir = sbox.wc_dir + + sbox.simple_append('A/B/E/beta', 'X\nY\nZ\n', truncate=True) + sbox.simple_commit() + sbox.simple_append('A/B/E/alpha', 'modified alpha') + sbox.simple_append('A/B/E/beta', 'XX\nY\nZ\n', truncate=True) + sbox.simple_commit() + sbox.simple_update('', 2) + + sbox.simple_append('A/B/E/beta', 'local beta') + src_time = get_text_timestamp(sbox.ospath('A/B/E/alpha')) + sbox.simple_move("A/B/E", "A/B/E2") + alpha_dst_time = get_text_timestamp(sbox.ospath('A/B/E2/alpha')) + beta_dst_time = get_text_timestamp(sbox.ospath('A/B/E2/beta')) + if src_time != alpha_dst_time: + raise svntest.Failure("move failed to copy timestamp") + + expected_output = svntest.wc.State(wc_dir, { + 'A/B/E' : Item(status=' ', treeconflict='C'), + 'A/B/E/alpha' : Item(status=' ', treeconflict='U'), + 'A/B/E/beta' : Item(status=' ', treeconflict='U'), + }) + expected_status = svntest.actions.get_virginal_state(wc_dir, 3) + expected_status.tweak('A/B/E', + status='D ', treeconflict='C', moved_to='A/B/E2') + expected_status.tweak('A/B/E/alpha', 'A/B/E/beta', status='D ') + expected_status.add({ + 'A/B/E2' : Item(status='A ', wc_rev='-', copied='+', + moved_from='A/B/E'), + 'A/B/E2/alpha' : Item(status=' ', wc_rev='-', copied='+'), + 'A/B/E2/beta' : Item(status='M ', wc_rev='-', copied='+'), + }) + expected_disk = svntest.main.greek_state.copy() + expected_disk.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta') + expected_disk.add({ + 'A/B/E2' : Item(), + 'A/B/E2/alpha' : Item("This is the file 'alpha'.\n"), + 'A/B/E2/beta' : Item("X\nY\nZ\nlocal beta"), + }) + svntest.actions.run_and_verify_update(wc_dir, + expected_output, + expected_disk, + expected_status) + + time.sleep(1.1) + svntest.actions.run_and_verify_svn("resolve failed", None, [], + 'resolve', + '--accept=mine-conflict', + sbox.ospath('A/B/E')) + expected_status.tweak('A/B/E', treeconflict=None) + expected_status.tweak('A/B/E2/beta', status='M ') + svntest.actions.run_and_verify_status(wc_dir, expected_status) + expected_disk.tweak('A/B/E2/beta', contents="XX\nY\nZ\nlocal beta") + expected_disk.tweak('A/B/E2/alpha', contents="This is the file 'alpha'.\nmodified alpha") + svntest.actions.verify_disk(wc_dir, expected_disk) + + # alpha is pristine so gets a new timestamp + new_time = get_text_timestamp(sbox.ospath('A/B/E2/alpha')) + if new_time == alpha_dst_time: + raise svntest.Failure("move failed to update timestamp") + + # beta is modified so timestamp is removed + no_text_timestamp(sbox.ospath('A/B/E2/beta')) + +@Issue(4398) +def status_path_handling(sbox): + "relative/absolute path handling" + + sbox.build(read_only=True) + + # target is a relative path to a subdir + wc_dir = sbox.wc_dir + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + svntest.actions.run_and_verify_status(wc_dir, expected_status) + + # target is an absolute path to a subdir + cwd = os.getcwd() + abs_wc_dir = os.path.join(cwd, wc_dir) + expected_status = svntest.actions.get_virginal_state(abs_wc_dir, 1) + svntest.actions.run_and_verify_status(abs_wc_dir, expected_status) + + # target is an absolute path to a parent dir + os.chdir(sbox.ospath('A/B')) + expected_status = svntest.actions.get_virginal_state(abs_wc_dir, 1) + svntest.actions.run_and_verify_status(abs_wc_dir, expected_status) + + # target is a relative path to a parent dir + rel_wc_dir = os.path.join('..', '..') + expected_status = svntest.actions.get_virginal_state(rel_wc_dir, 1) + svntest.actions.run_and_verify_status(rel_wc_dir, expected_status) + +def status_move_missing_direct(sbox): + "move information when status is called directly" + + sbox.build() + sbox.simple_copy('A', 'Z') + sbox.simple_commit('') + sbox.simple_update('') + + sbox.simple_move('Z', 'ZZ') + sbox.simple_move('A', 'Z') + sbox.simple_move('Z/B', 'ZB') + sbox.simple_mkdir('Z/B') + sbox.simple_move('ZB/E', 'Z/B/E') + + # Somehow 'svn status' now shows different output for 'ZB/E' + # when called directly and via an ancestor, as this handles + # multi-layer in a different way + + # Note that the status output may change over different Subversion revisions, + # but the status on a node should be identical anyway 'svn status' is called + # on it. + + expected_output = [ + 'A + %s\n' % sbox.ospath('ZB'), + ' > moved from %s\n' % os.path.join('..', 'Z', 'B'), + 'D + %s\n' % sbox.ospath('ZB/E'), + ' > moved to %s\n' % os.path.join('..', 'Z', 'B', 'E'), + ] + svntest.actions.run_and_verify_svn(None, expected_output, [], 'status', + sbox.ospath('ZB'), '--depth', 'immediates') + + # And calling svn status on just 'ZB/E' should have the same result for this node + # except that we calculate the relative path from a different base + expected_output = [ + 'D + %s\n' % sbox.ospath('ZB/E'), + ' > moved to %s\n' % os.path.join('..', '..', 'Z', 'B', 'E'), + ] + svntest.actions.run_and_verify_svn(None, expected_output, [], 'status', + sbox.ospath('ZB/E'), '--depth', 'empty') + +def status_move_missing_direct_base(sbox): + "move when status is called directly with base" + + sbox.build() + sbox.simple_copy('A', 'Z') + sbox.simple_mkdir('Q') + sbox.simple_mkdir('Q/ZB') + sbox.simple_mkdir('Q/ZB/E') + sbox.simple_commit('') + sbox.simple_update('') + + sbox.simple_rm('Q') + sbox.simple_mkdir('Q') + + sbox.simple_move('Z', 'ZZ') + sbox.simple_move('A', 'Z') + sbox.simple_move('Z/B', 'Q/ZB') + sbox.simple_mkdir('Z/B') + sbox.simple_move('Q/ZB/E', 'Z/B/E') + + # Somehow 'svn status' now shows different output for 'Q/ZB/E' + # when called directly and via an ancestor, as this handles + # multi-layer in a different way + + # Note that the status output may change over different Subversion revisions, + # but the status on a node should be identical anyway 'svn status' is called + # on it. + + # This test had a different result as status_move_missing_direct at the time of + # writing this test. + + expected_output = [ + 'A + %s\n' % sbox.ospath('Q/ZB'), + ' > moved from %s\n' % os.path.join('..', '..', 'Z', 'B'), + 'D + %s\n' % sbox.ospath('Q/ZB/E'), + ' > moved to %s\n' % os.path.join('..', '..', 'Z', 'B', 'E'), + ] + svntest.actions.run_and_verify_svn(None, expected_output, [], 'status', + sbox.ospath('Q/ZB'), '--depth', 'immediates') + + # And calling svn status on just 'ZB/E' should have the same result for this node, + # except that the moved_to information is calculated from the node itself + expected_output = [ + 'D + %s\n' % sbox.ospath('Q/ZB/E'), + ' > moved to %s\n' % os.path.join('..', '..', '..', 'Z', 'B', 'E'), + ] + svntest.actions.run_and_verify_svn(None, expected_output, [], 'status', + sbox.ospath('Q/ZB/E'), '--depth', 'empty') + ######################################################################## # Run the tests @@ -2023,7 +2232,7 @@ test_list = [ None, missing_dir_in_anchor, status_in_xml, status_ignored_dir, - status_unversioned_dir, + status_unversioned_dir_in_wc, status_missing_dir, status_nonrecursive_update_different_cwd, status_add_plus_conflict, @@ -2041,7 +2250,14 @@ test_list = [ None, status_locked_deleted, wc_wc_copy_timestamp, wclock_status, + modified_modulo_translation, status_not_present, + status_unversioned_dir, + status_case_changed, + move_update_timestamps, + status_path_handling, + status_move_missing_direct, + status_move_missing_direct_base, ] if __name__ == '__main__': |