Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/move_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/move_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/move_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/move_tests.py Fri Jan 14 14:01:45 2022 @@ -125,7 +125,7 @@ def move_file_test(sbox, source, dest, m start_disk: validate the on disk state after the start update against this. start_status: validate the wc status after the start update against this. end_rev: revision to update to, bringing in some update you want to test. - up_output: validate the output of the end update agianst this. + up_output: validate the output of the end update against this. up_disk: validate the on disk state after the end update against this. up_status: validate the wc status after the end update against this. revert_paths: validate the paths reverted. @@ -793,7 +793,7 @@ def build_simple_file_move_tests(sbox, s # move and update with incoming identical move (r16-17) # XXX: It'd be really nice if we actually recognized this and the wc - # showed no conflict at all on udpate. + # showed no conflict at all on update. test = {} test['start_rev'] = 16 test['end_rev'] = 17 @@ -883,7 +883,7 @@ def build_simple_file_move_func(sbox, so # # Each test must return on success or raise on failure. # -# See http://wiki.apache.org/subversion/LocalMoves +# See https://cwiki.apache.org/confluence/display/SVN/LocalMoves def lateral_move_file_test(sbox): "lateral (rename) move of a file test" @@ -1755,7 +1755,7 @@ def move_conflict_markers(sbox): }) expected_disk.remove('iota', 'iota.prej', 'A/B/E', 'A/B/E/alpha', 'A/B/E/beta', - 'A/B/E/dir_conflicts.prej', + 'A/B/E/dir_conflicts.prej', 'A/B/E/beta.prej') expected_disk.add({ 'A/iotb' : Item(contents="This is the file 'iota'.\n"),
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/patch_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/patch_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/patch_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/patch_tests.py Fri Jan 14 14:01:45 2022 @@ -1574,15 +1574,7 @@ def patch_no_svn_eol_style(sbox): patch_file_path = sbox.get_tempname('my.patch') mu_path = sbox.ospath('A/mu') - # CRLF is a string that will match a CRLF sequence read from a text file. - # ### On Windows, we assume CRLF will be read as LF, so it's a poor test. - if os.name == 'nt': - crlf = '\n' - else: - crlf = '\r\n' - - # Strict EOL style matching breaks Windows tests at least with Python 2 - keep_eol_style = not svntest.main.is_os_windows() + crlf = '\r\n' eols = [crlf, '\015', '\n', '\012'] for target_eol in eols: @@ -1603,7 +1595,7 @@ def patch_no_svn_eol_style(sbox): ] # Set mu contents - svntest.main.file_write(mu_path, ''.join(mu_contents)) + svntest.main.file_write(mu_path, ''.join(mu_contents), mode='wb') unidiff_patch = [ "Index: mu", @@ -1647,7 +1639,8 @@ def patch_no_svn_eol_style(sbox): target_eol, ] - svntest.main.file_write(patch_file_path, ''.join(unidiff_patch)) + svntest.main.file_write(patch_file_path, ''.join(unidiff_patch), + mode='wb') expected_output = wc.State(wc_dir, { 'A/mu' : Item(status='U '), @@ -1666,7 +1659,8 @@ def patch_no_svn_eol_style(sbox): expected_disk, expected_status, expected_skip, - [], True, True, keep_eol_style) + [], True, True, + keep_eol_style=True) expected_output = ["Reverted '" + mu_path + "'\n"] svntest.actions.run_and_verify_svn(expected_output, [], @@ -1681,17 +1675,13 @@ def patch_with_svn_eol_style(sbox): patch_file_path = sbox.get_tempname('my.patch') mu_path = sbox.ospath('A/mu') - # CRLF is a string that will match a CRLF sequence read from a text file. - # ### On Windows, we assume CRLF will be read as LF, so it's a poor test. if os.name == 'nt': - crlf = '\n' + native_nl = '\r\n' else: - crlf = '\r\n' - - # Strict EOL style matching breaks Windows tests at least with Python 2 - keep_eol_style = not svntest.main.is_os_windows() + native_nl = '\n' + crlf = '\r\n' - eols = [crlf, '\015', '\n', '\012'] + eols = [crlf, '\015', native_nl, '\012'] eol_styles = ['CRLF', 'CR', 'native', 'LF'] rev = 1 for target_eol, target_eol_style in zip(eols, eol_styles): @@ -1714,7 +1704,7 @@ def patch_with_svn_eol_style(sbox): # Set mu contents svntest.main.run_svn(None, 'rm', mu_path) svntest.main.run_svn(None, 'commit', '-m', 'delete mu', mu_path) - svntest.main.file_write(mu_path, ''.join(mu_contents)) + svntest.main.file_write(mu_path, ''.join(mu_contents), mode='wb') svntest.main.run_svn(None, 'add', mu_path) svntest.main.run_svn(None, 'propset', 'svn:eol-style', target_eol_style, mu_path) @@ -1762,7 +1752,8 @@ def patch_with_svn_eol_style(sbox): target_eol, ] - svntest.main.file_write(patch_file_path, ''.join(unidiff_patch)) + svntest.main.file_write(patch_file_path, ''.join(unidiff_patch), + mode='wb') expected_output = [ 'U %s\n' % sbox.ospath('A/mu'), @@ -1786,7 +1777,7 @@ def patch_with_svn_eol_style(sbox): None, # expected err 1, # check-props 1, # dry-run - keep_eol_style) # keep-eol-style + keep_eol_style=True) expected_output = ["Reverted '" + mu_path + "'\n"] svntest.actions.run_and_verify_svn(expected_output, [], 'revert', '-R', wc_dir) @@ -1800,17 +1791,13 @@ def patch_with_svn_eol_style_uncommitted patch_file_path = sbox.get_tempname('my.patch') mu_path = sbox.ospath('A/mu') - # CRLF is a string that will match a CRLF sequence read from a text file. - # ### On Windows, we assume CRLF will be read as LF, so it's a poor test. if os.name == 'nt': - crlf = '\n' + native_nl = '\r\n' else: - crlf = '\r\n' - - # Strict EOL style matching breaks Windows tests at least with Python 2 - keep_eol_style = not svntest.main.is_os_windows() + native_nl = '\n' + crlf = '\r\n' - eols = [crlf, '\015', '\n', '\012'] + eols = [crlf, '\015', native_nl, '\012'] eol_styles = ['CRLF', 'CR', 'native', 'LF'] for target_eol, target_eol_style in zip(eols, eol_styles): for patch_eol in eols: @@ -1830,7 +1817,7 @@ def patch_with_svn_eol_style_uncommitted ] # Set mu contents - svntest.main.file_write(mu_path, ''.join(mu_contents)) + svntest.main.file_write(mu_path, ''.join(mu_contents), mode='wb') svntest.main.run_svn(None, 'propset', 'svn:eol-style', target_eol_style, mu_path) @@ -1876,7 +1863,8 @@ def patch_with_svn_eol_style_uncommitted target_eol, ] - svntest.main.file_write(patch_file_path, ''.join(unidiff_patch)) + svntest.main.file_write(patch_file_path, ''.join(unidiff_patch), + mode='wb') expected_output = wc.State(wc_dir, { 'A/mu' : Item(status='U '), @@ -1899,7 +1887,7 @@ def patch_with_svn_eol_style_uncommitted None, # expected err 1, # check-props 1, # dry-run - keep_eol_style) # keep-eol-style + keep_eol_style=True) expected_output = ["Reverted '" + mu_path + "'\n"] svntest.actions.run_and_verify_svn(expected_output, [], 'revert', '-R', wc_dir) Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/prop_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/prop_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/prop_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/prop_tests.py Fri Jan 14 14:01:45 2022 @@ -2829,6 +2829,38 @@ def prop_conflict_root(sbox): expected_status, extra_files=extra_files) + +# Test that editing a regular property creates a temporary file named +# "svn-prop.tmp" whereas editing a revprop results in a temporary file +# named "svn-revprop-rN.tmp" (where "N" is the number of the revision +# whose revprop would be edited). +def tmpfile_name_matches_prop_type(sbox): + "propedit tmpfile name matches property type" + + sbox.build(read_only=True) + + # We want the editor invocation to fail -- all we care about is the + # name of the tmpfile left over after that failure. I'm guessing + # you don't have a editor named this on your system: + non_editor = 'af968da2ce9' + + svntest.actions.run_and_verify_svn( + None, + '.*' + re.escape(non_editor) + r'.*svn-revprop-r1\.tmp.*', + 'propedit', '--revprop', + '--editor-cmd', non_editor, + '-r1', 'svn:log', + sbox.repo_url) + + svntest.actions.run_and_verify_svn( + None, + '.*' + re.escape(non_editor) + r'.*svn-prop\.tmp.*', + 'propedit', + '--editor-cmd', non_editor, + 'ignored-propname', + sbox.ospath('A/mu')) + + ######################################################################## # Run the tests @@ -2880,6 +2912,7 @@ test_list = [ None, iprops_list_abspath, wc_propop_on_url, prop_conflict_root, + tmpfile_name_matches_prop_type, ] if __name__ == '__main__': Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/relocate_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/relocate_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/relocate_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/relocate_tests.py Fri Jan 14 14:01:45 2022 @@ -417,8 +417,8 @@ def prefix_partial_component(sbox): wc_dir) svntest.actions.run_and_verify_info([{ 'URL' : '.*.yyyother$' }], wc_dir) - - + + ######################################################################## # Run the tests Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/revert_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/revert_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/revert_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/revert_tests.py Fri Jan 14 14:01:45 2022 @@ -46,6 +46,23 @@ Item = svntest.wc.StateItem ###################################################################### # Helpers +def expected_output_revert(reverted_paths, skipped_paths=[]): + return svntest.verify.UnorderedRegexListOutput( + ["Reverted '%s'\n" % re.escape(path) for path in reverted_paths] + + ["Skipped '%s'.*\n" % re.escape(path) for path in skipped_paths]) + +def run_and_verify_revert(targets, options=[], + reverted_paths=None, skipped_paths=[]): + """Run 'svn revert OPTIONS TARGETS'. Verify that the printed output matches + REVERTED_PATHS and SKIPPED_PATHS. If REVERTED_PATHS is None, it defaults + to TARGETS. + """ + if reverted_paths is None: + reverted_paths = targets + expected_output = expected_output_revert(reverted_paths, skipped_paths) + svntest.actions.run_and_verify_svn(expected_output, [], + *(['revert'] + options + targets)) + def revert_replacement_with_props(sbox, wc_copy): """Helper implementing the core of revert_{repos,wc}_to_wc_replace_with_props(). @@ -129,9 +146,7 @@ def revert_replacement_with_props(sbox, svntest.actions.run_and_verify_status(wc_dir, expected_status) expected_status.tweak('A/D/G/rho', status=' ', copied=None, wc_rev='2') - expected_output = ["Reverted '" + rho_path + "'\n"] - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', '-R', wc_dir) + run_and_verify_revert([wc_dir], ['-R'], [rho_path]) svntest.actions.run_and_verify_status(wc_dir, expected_status) # Check disk status @@ -356,8 +371,7 @@ def revert_replaced_file_without_props(s svntest.actions.run_and_verify_status(wc_dir, expected_status) # revert file1 - svntest.actions.run_and_verify_svn(["Reverted '" + file1_path + "'\n"], - [], 'revert', file1_path) + run_and_verify_revert([file1_path]) # test that file1 really was reverted expected_status.tweak('file1', status=' ', wc_rev=2) @@ -402,10 +416,7 @@ def revert_moved_file(sbox): actions.run_and_verify_unquiet_status(wc_dir, expected_status) # svn revert iota - expected_stdout = ["Reverted '" + iota + "'\n"] - - actions.run_and_verify_svn2(expected_stdout, [], 0, 'revert', - iota) + run_and_verify_revert([iota]) # svn st expected_status.tweak('iota', status=' ', moved_to=None) @@ -644,9 +655,7 @@ def revert_propset__dir(sbox): wc_dir = sbox.wc_dir a_path = os.path.join(wc_dir, 'A') svntest.main.run_svn(None, 'propset', 'foo', 'x', a_path) - expected_output = re.escape("Reverted '" + a_path + "'") - svntest.actions.run_and_verify_svn(expected_output, [], "revert", - a_path) + run_and_verify_revert([a_path]) def revert_propset__file(sbox): "revert a simple propset on a file" @@ -655,9 +664,7 @@ def revert_propset__file(sbox): wc_dir = sbox.wc_dir iota_path = os.path.join(wc_dir, 'iota') svntest.main.run_svn(None, 'propset', 'foo', 'x', iota_path) - expected_output = re.escape("Reverted '" + iota_path + "'") - svntest.actions.run_and_verify_svn(expected_output, [], "revert", - iota_path) + run_and_verify_revert([iota_path]) def revert_propdel__dir(sbox): "revert a simple propdel on a dir" @@ -669,9 +676,7 @@ def revert_propdel__dir(sbox): svntest.main.run_svn(None, 'commit', '-m', 'ps', a_path) svntest.main.run_svn(None, 'propdel', 'foo', a_path) - expected_output = re.escape("Reverted '" + a_path + "'") - svntest.actions.run_and_verify_svn(expected_output, [], "revert", - a_path) + run_and_verify_revert([a_path]) def revert_propdel__file(sbox): "revert a simple propdel on a file" @@ -683,9 +688,7 @@ def revert_propdel__file(sbox): svntest.main.run_svn(None, 'commit', '-m', 'ps', iota_path) svntest.main.run_svn(None, 'propdel', 'foo', iota_path) - expected_output = re.escape("Reverted '" + iota_path + "'") - svntest.actions.run_and_verify_svn(expected_output, [], "revert", - iota_path) + run_and_verify_revert([iota_path]) def revert_replaced_with_history_file_1(sbox): "revert a committed replace-with-history == no-op" @@ -776,9 +779,7 @@ def status_of_missing_dir_after_revert(s A_D_G_path = os.path.join(wc_dir, "A", "D", "G") svntest.actions.run_and_verify_svn(None, [], "rm", A_D_G_path) - expected_output = re.escape("Reverted '" + A_D_G_path + "'") - svntest.actions.run_and_verify_svn(expected_output, [], "revert", - A_D_G_path) + run_and_verify_revert([A_D_G_path]) expected_status = svntest.actions.get_virginal_state(wc_dir, 1) expected_status.tweak('A/D/G/rho', 'A/D/G/pi', 'A/D/G/tau', @@ -877,11 +878,7 @@ def status_of_missing_dir_after_revert_r revert_paths = [G_path] + [os.path.join(G_path, child) for child in ['alpha', 'beta', 'pi', 'rho', 'tau']] - expected_output = svntest.verify.UnorderedOutput([ - "Reverted '%s'\n" % path for path in revert_paths]) - - svntest.actions.run_and_verify_svn(expected_output, [], "revert", "-R", - G_path) + run_and_verify_revert([G_path], ["-R"], revert_paths) svntest.actions.run_and_verify_svn([], [], "status", wc_dir) @@ -947,12 +944,6 @@ def revert_tree_conflicts_in_updated_fil G2_tau = os.path.join(G2, 'tau') # Expectations - expected_output = svntest.verify.UnorderedOutput( - ["Reverted '%s'\n" % G_pi, - "Reverted '%s'\n" % G_rho, - "Reverted '%s'\n" % G_tau, - ]) - expected_status = svntest.actions.get_virginal_state(wc_dir, 2) expected_status.tweak('A/D/G/pi', status=' ') expected_status.remove('A/D/G/rho') @@ -965,23 +956,15 @@ def revert_tree_conflicts_in_updated_fil expected_disk.remove('A/D/G/tau') # Revert individually in wc - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', G_pi, G_rho, G_tau) + run_and_verify_revert([G_pi, G_rho, G_tau]) svntest.actions.run_and_verify_status(wc_dir, expected_status) svntest.actions.verify_disk(wc_dir, expected_disk) # Expectations - expected_output = svntest.verify.UnorderedOutput( - ["Reverted '%s'\n" % G2_pi, - "Reverted '%s'\n" % G2_rho, - "Reverted '%s'\n" % G2_tau, - ]) - expected_status.wc_dir = wc_dir_2 # Revert recursively in wc 2 - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', '-R', G2) + run_and_verify_revert([G2], ['-R'], [G2_pi, G2_rho, G2_tau]) svntest.actions.run_and_verify_status(wc_dir_2, expected_status) svntest.actions.verify_disk(wc_dir_2, expected_disk) @@ -1049,9 +1032,7 @@ def revert_child_of_copy(sbox): svntest.actions.run_and_verify_status(wc_dir, expected_status) # First revert removes text change, child is still copied - expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B/E2/beta')] - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', sbox.ospath('A/B/E2/beta')) + run_and_verify_revert(sbox.ospaths(['A/B/E2/beta'])) expected_status.tweak('A/B/E2/beta', status=' ') svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1074,9 +1055,7 @@ def revert_non_recusive_after_delete(sbo svntest.actions.run_and_verify_status(wc_dir, expected_status) # This appears to work but gets the op-depth wrong - expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B')] - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', sbox.ospath('A/B')) + run_and_verify_revert(sbox.ospaths(['A/B'])) expected_status.tweak('A/B', status=' ') svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1086,9 +1065,7 @@ def revert_non_recusive_after_delete(sbo svntest.actions.run_and_verify_status(wc_dir, expected_status) # Since the op-depth was wrong A/B/E erroneously remains deleted - expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B/E')] - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', sbox.ospath('A/B/E')) + run_and_verify_revert(sbox.ospaths(['A/B/E'])) expected_status.tweak('A/B/E', status=' ') svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1134,17 +1111,13 @@ def revert_permissions_only(sbox): os.chmod(sbox.ospath('A/B/E/alpha'), svntest.main.S_ALL_READ) # read-only is_readonly(sbox.ospath('A/B/E/alpha')) - expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B/E/alpha')] - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', sbox.ospath('A/B/E/alpha')) + run_and_verify_revert(sbox.ospaths(['A/B/E/alpha'])) is_writable(sbox.ospath('A/B/E/alpha')) if svntest.main.is_posix_os(): os.chmod(sbox.ospath('A/B/E/beta'), svntest.main.S_ALL_RWX) # executable is_executable(sbox.ospath('A/B/E/beta')) - expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B/E/beta')] - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', sbox.ospath('A/B/E/beta')) + run_and_verify_revert(sbox.ospaths(['A/B/E/beta'])) is_non_executable(sbox.ospath('A/B/E/beta')) svntest.actions.run_and_verify_svn(None, [], @@ -1167,17 +1140,13 @@ def revert_permissions_only(sbox): os.chmod(sbox.ospath('A/B/E/alpha'), svntest.main.S_ALL_RW) # not read-only is_writable(sbox.ospath('A/B/E/alpha')) - expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B/E/alpha')] - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', sbox.ospath('A/B/E/alpha')) + run_and_verify_revert(sbox.ospaths(['A/B/E/alpha'])) is_readonly(sbox.ospath('A/B/E/alpha')) if svntest.main.is_posix_os(): os.chmod(sbox.ospath('A/B/E/beta'), svntest.main.S_ALL_RW) # not executable is_non_executable(sbox.ospath('A/B/E/beta')) - expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B/E/beta')] - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', sbox.ospath('A/B/E/beta')) + run_and_verify_revert(sbox.ospaths(['A/B/E/beta'])) is_executable(sbox.ospath('A/B/E/beta')) # copied file is always writeable @@ -1212,14 +1181,8 @@ def revert_copy_depth_files(sbox): }) svntest.actions.run_and_verify_status(wc_dir, expected_status) - expected_output = svntest.verify.UnorderedOutput([ - "Reverted '%s'\n" % sbox.ospath(path) for path in ['A/B/E2', - 'A/B/E2/alpha', - 'A/B/E2/beta']]) - - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', '--depth', 'files', - sbox.ospath('A/B/E2')) + run_and_verify_revert(sbox.ospaths(['A/B/E2']), ['--depth', 'files'], + sbox.ospaths(['A/B/E2', 'A/B/E2/alpha', 'A/B/E2/beta'])) expected_status.remove('A/B/E2', 'A/B/E2/alpha', 'A/B/E2/beta') svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1242,12 +1205,8 @@ def revert_nested_add_depth_immediates(s }) svntest.actions.run_and_verify_status(wc_dir, expected_status) - expected_output = svntest.verify.UnorderedOutput([ - "Reverted '%s'\n" % sbox.ospath(path) for path in ['A/X', 'A/X/Y']]) - - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', '--depth', 'immediates', - sbox.ospath('A/X')) + run_and_verify_revert(sbox.ospaths(['A/X']), ['--depth', 'immediates'], + sbox.ospaths(['A/X', 'A/X/Y'])) expected_status.remove('A/X', 'A/X/Y') svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1299,9 +1258,7 @@ def revert_empty_actual(sbox): wc_dir = sbox.wc_dir # Non-recursive code path works - svntest.actions.run_and_verify_svn(["Reverted '%s'\n" % sbox.ospath('alpha')], - [], - 'revert', sbox.ospath('alpha')) + run_and_verify_revert(sbox.ospaths(['alpha'])) expected_status = svntest.actions.get_virginal_state(wc_dir, 2) svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1316,9 +1273,7 @@ def revert_empty_actual_recursive(sbox): # Recursive code path fails, the superfluous actual node suppresses the # notification - svntest.actions.run_and_verify_svn(["Reverted '%s'\n" % sbox.ospath('alpha')], - [], - 'revert', '-R', sbox.ospath('alpha')) + run_and_verify_revert(sbox.ospaths(['alpha']), ['-R']) expected_status = svntest.actions.get_virginal_state(wc_dir, 2) svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1433,7 +1388,7 @@ def revert_tree_conflicts_with_replaceme cd_and_status_u('A/D/H') # Revert everything (i.e., accept "theirs-full"). - svntest.actions.run_and_verify_revert([ + reverted_paths = [ wc('A/B/E'), wc('A/B/E/alpha'), # incoming & local wc('A/B/E/beta'), @@ -1450,7 +1405,8 @@ def revert_tree_conflicts_with_replaceme wc('A/D/H/loc_psi'), wc('A/D/gamma'), wc('A/mu'), - ], '-R', wc_dir) + ] + run_and_verify_revert([wc_dir], ['-R'], reverted_paths) # Remove a few unversioned files that revert left behind. os.remove(wc('A/B/E/loc_beta')) @@ -1511,10 +1467,7 @@ def revert_no_text_change_conflict(sbox) create_no_text_change_conflict(sbox) wc_dir = sbox.wc_dir - svntest.actions.run_and_verify_svn(["Reverted '%s'\n" - % sbox.ospath('A/B/E/alpha')], - [], - 'revert', sbox.ospath('A/B/E/alpha')) + run_and_verify_revert(sbox.ospaths(['A/B/E/alpha'])) expected_status = svntest.actions.get_virginal_state(wc_dir, 1) svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1526,10 +1479,7 @@ def revert_no_text_change_conflict_recur create_no_text_change_conflict(sbox) wc_dir = sbox.wc_dir - svntest.actions.run_and_verify_svn(["Reverted '%s'\n" - % sbox.ospath('A/B/E/alpha')], - [], - 'revert', '-R', wc_dir) + run_and_verify_revert(sbox.ospaths(['A/B/E/alpha']), ['-R']) expected_status = svntest.actions.get_virginal_state(wc_dir, 1) svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1560,13 +1510,8 @@ def revert_with_unversioned_targets(sbox f.write(psi_contents) # revert - expected_output = svntest.verify.UnorderedOutput([ - "Reverted '%s'\n" % sbox.ospath('A/D/H/chi'), - "Skipped '%s'\n" % sbox.ospath('A/D/H/delta'), - "Reverted '%s'\n" % sbox.ospath('A/D/H/psi'), - ]) - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', chi_path, delta_path, psi_path) + run_and_verify_revert([chi_path, delta_path, psi_path], [], + [chi_path, psi_path], [delta_path]) # verify status expected_status = svntest.actions.get_virginal_state(wc_dir, 1) @@ -1585,8 +1530,8 @@ def revert_with_unversioned_targets(sbox def revert_nonexistent(sbox): 'svn revert -R nonexistent' sbox.build(read_only=True) - svntest.actions.run_and_verify_svn('Skipped.*nonexistent', [], - 'revert', '-R', sbox.ospath('nonexistent')) + run_and_verify_revert(sbox.ospaths(['nonexistent']), ['-R'], + [], sbox.ospaths(['nonexistent'])) @Issue(4168) def revert_obstructing_wc(sbox): @@ -1641,6 +1586,33 @@ def revert_moved_dir_partial(sbox): sbox.simple_move('A', 'A_') svntest.actions.run_and_verify_svn(None, [], 'revert', sbox.ospath('A')) +@XFail() +@Issue(4798) +def revert_remove_added(sbox): + "revert_remove_added" + + sbox.build(empty=True, read_only=True) + + # We'll test the items named with a '1' as direct targets to 'revert', + # and items named with a '2' as items found by recursion. + sbox.simple_mkdir('D1', 'D2') + sbox.simple_add_text('This is a new file.', + 'D1/file', 'file1', + 'D2/file', 'file2') + + run_and_verify_revert(sbox.ospaths(['D1']), ['--remove-added', '-R'], + sbox.ospaths(['D1/file', 'D1'])) + assert(not os.path.exists(sbox.ospath('D1'))) + + run_and_verify_revert(sbox.ospaths(['file1']), ['--remove-added'], + sbox.ospaths(['file1'])) + assert(not os.path.exists(sbox.ospath('file1'))) + + run_and_verify_revert(sbox.ospaths(['.']), ['--remove-added', '-R'], + sbox.ospaths(['D2/file', 'D2', 'file2'])) + assert(not os.path.exists(sbox.ospath('file2'))) + assert(not os.path.exists(sbox.ospath('D2'))) + ######################################################################## # Run the tests @@ -1683,6 +1655,7 @@ test_list = [ None, revert_nonexistent, revert_obstructing_wc, revert_moved_dir_partial, + revert_remove_added, ] if __name__ == '__main__': Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/shelf_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/shelf_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/shelf_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/shelf_tests.py Fri Jan 14 14:01:45 2022 @@ -46,6 +46,10 @@ Issue = svntest.testcase.Issue_deco Wimp = svntest.testcase.Wimp_deco Item = wc.StateItem +def shelf3_enabled(): + v = os.getenv('SVN_EXPERIMENTAL_COMMANDS') + return v is not None and v.find('shelf3') >= 0 + #---------------------------------------------------------------------- def state_from_status(wc_dir, @@ -126,6 +130,12 @@ def shelve_unshelve_verify(sbox, modifie ]) svntest.actions.run_and_verify_svn(expected_output, [], 'x-shelves') + # Diff; ensure something comes out and it doesn't crash + svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [], + 'x-shelf-diff', 'foo') + svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [], + 'x-shelf-diff', '--summarize', 'foo') + # Unshelve; check the original modifications are here again svntest.actions.run_and_verify_svn(None, [], 'x-unshelve', 'foo') @@ -153,6 +163,7 @@ def shelve_unshelve(sbox, modifier, cann # # Each test must return on success or raise on failure. +@SkipUnless(shelf3_enabled) def shelve_text_mods(sbox): "shelve text mods" @@ -163,6 +174,7 @@ def shelve_text_mods(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_prop_changes(sbox): "shelve prop changes" @@ -174,6 +186,7 @@ def shelve_prop_changes(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_adds(sbox): "shelve adds" @@ -187,6 +200,7 @@ def shelve_adds(sbox): #---------------------------------------------------------------------- @Issue(4709) +@SkipUnless(shelf3_enabled) def shelve_deletes(sbox): "shelve deletes" @@ -197,6 +211,7 @@ def shelve_deletes(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_replace(sbox): "shelve replace" @@ -209,6 +224,7 @@ def shelve_replace(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_empty_adds(sbox): "shelve empty adds" sbox.build(empty=True) @@ -222,6 +238,7 @@ def shelve_empty_adds(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_empty_deletes(sbox): "shelve empty deletes" sbox.build(empty=True) @@ -237,6 +254,7 @@ def shelve_empty_deletes(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_from_inner_path(sbox): "shelve from inner path" @@ -297,6 +315,7 @@ def save_revert_restore(sbox, modifier1, #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def checkpoint_basic(sbox): "checkpoint basic" @@ -312,6 +331,7 @@ def checkpoint_basic(sbox): #---------------------------------------------------------------------- @Issue(3747) +@SkipUnless(shelf3_enabled) def shelve_mergeinfo(sbox): "shelve mergeinfo" @@ -323,6 +343,7 @@ def shelve_mergeinfo(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def unshelve_refuses_if_conflicts(sbox): "unshelve refuses if conflicts" @@ -366,6 +387,7 @@ def unshelve_refuses_if_conflicts(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_binary_file_mod(sbox): "shelve binary file mod" @@ -387,6 +409,7 @@ def shelve_binary_file_mod(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_binary_file_add(sbox): "shelve binary file add" @@ -408,6 +431,7 @@ def shelve_binary_file_add(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_binary_file_del(sbox): "shelve binary file del" @@ -429,6 +453,7 @@ def shelve_binary_file_del(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_binary_file_replace(sbox): "shelve binary file replace" @@ -451,6 +476,7 @@ def shelve_binary_file_replace(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_with_log_message(sbox): "shelve with log message" @@ -500,6 +526,7 @@ def run_and_verify_shelf_status(wc_dir, run_and_verify_status(wc_dir, expected_status, changelists=['svn:shelf:' + shelf]) +@SkipUnless(shelf3_enabled) def shelf_status(sbox): "shelf status" @@ -525,6 +552,8 @@ def shelf_status(sbox): #---------------------------------------------------------------------- +@XFail() +@SkipUnless(shelf3_enabled) def shelve_mkdir(sbox): "shelve mkdir" @@ -534,10 +563,11 @@ def shelve_mkdir(sbox): sbox.simple_mkdir('D', 'D/D2') sbox.simple_propset('p', 'v', 'D', 'D/D2') - shelve_unshelve(sbox, modifier, cannot_shelve=True) + shelve_unshelve(sbox, modifier) #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_rmdir(sbox): "shelve rmdir" @@ -548,10 +578,12 @@ def shelve_rmdir(sbox): def modifier(sbox): sbox.simple_rm('A/C', 'A/D/G') - shelve_unshelve(sbox, modifier, cannot_shelve=True) + shelve_unshelve(sbox, modifier) #---------------------------------------------------------------------- +@XFail() +@SkipUnless(shelf3_enabled) def shelve_replace_dir(sbox): "shelve replace dir" @@ -563,10 +595,11 @@ def shelve_replace_dir(sbox): sbox.simple_rm('A/C', 'A/D/G') sbox.simple_mkdir('A/C', 'A/C/D2') - shelve_unshelve(sbox, modifier, cannot_shelve=True) + shelve_unshelve(sbox, modifier) #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_file_copy(sbox): "shelve file copy" @@ -576,10 +609,11 @@ def shelve_file_copy(sbox): sbox.simple_copy('iota', 'A/ii') sbox.simple_propset('p', 'v', 'A/ii') - shelve_unshelve(sbox, modifier, cannot_shelve=True) + shelve_unshelve(sbox, modifier) #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def shelve_dir_copy(sbox): "shelve dir copy" @@ -589,10 +623,11 @@ def shelve_dir_copy(sbox): sbox.simple_copy('A/B', 'BB') sbox.simple_propset('p', 'v', 'BB') - shelve_unshelve(sbox, modifier, cannot_shelve=True) + shelve_unshelve(sbox, modifier) #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def list_shelves(sbox): "list_shelves" @@ -635,6 +670,7 @@ def list_shelves(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def refuse_to_shelve_conflict(sbox): "refuse to shelve conflict" @@ -643,31 +679,21 @@ def refuse_to_shelve_conflict(sbox): os.chdir(sbox.wc_dir) sbox.wc_dir = '' - # create a tree conflict victim at an unversioned path + # create a conflict sbox.simple_mkdir('topdir') sbox.simple_commit() - sbox.simple_mkdir('topdir/subdir') - sbox.simple_commit() - sbox.simple_update() - sbox.simple_rm('topdir') - sbox.simple_commit() sbox.simple_update() svntest.actions.run_and_verify_svn( None, [], - 'merge', '-c2', '.', '--ignore-ancestry', '--accept', 'postpone') + 'merge', '-c1', '.', '--ignore-ancestry', '--accept', 'postpone') + # check that we did create a conflict svntest.actions.run_and_verify_svn( - None, 'svn: E155015:.*existing.*conflict.*', + None, 'svn: E155035:.*conflict.*', 'merge', '-c1', '.', '--ignore-ancestry', '--accept', 'postpone') # attempt to shelve - expected_out = svntest.verify.RegexListOutput([ - r'--- .*', - r'--- .*', - r'\? C topdir', - r' > .*', - r' > not shelved']) - svntest.actions.run_and_verify_svn(expected_out, - '.* 1 path could not be shelved', + expected_err = "svn: E155015: .* '.*topdir' remains in conflict" + svntest.actions.run_and_verify_svn(None, expected_err, 'x-shelf-save', 'foo') os.chdir(was_cwd) @@ -711,6 +737,8 @@ def unshelve_with_merge(sbox, setup, mod os.chdir(was_cwd) +@XFail() +@SkipUnless(shelf3_enabled) def unshelve_text_mod_merge(sbox): "unshelve text mod merge" @@ -735,6 +763,8 @@ def unshelve_text_mod_merge(sbox): #---------------------------------------------------------------------- +@XFail() +@SkipUnless(shelf3_enabled) def unshelve_text_mod_conflict(sbox): "unshelve text mod conflict" @@ -765,6 +795,8 @@ def unshelve_text_mod_conflict(sbox): #---------------------------------------------------------------------- +@XFail() +@SkipUnless(shelf3_enabled) def unshelve_undeclared_binary_mod_conflict(sbox): "unshelve undeclared binary mod conflict" @@ -795,6 +827,8 @@ def unshelve_undeclared_binary_mod_confl #---------------------------------------------------------------------- +@XFail() +@SkipUnless(shelf3_enabled) def unshelve_binary_mod_conflict(sbox): "unshelve binary mod conflict" @@ -824,6 +858,7 @@ def unshelve_binary_mod_conflict(sbox): #---------------------------------------------------------------------- +@SkipUnless(shelf3_enabled) def unshelve_text_prop_merge(sbox): "unshelve text prop merge" @@ -845,6 +880,8 @@ def unshelve_text_prop_merge(sbox): #---------------------------------------------------------------------- +@XFail() +@SkipUnless(shelf3_enabled) def unshelve_text_prop_conflict(sbox): "unshelve text prop conflict" @@ -903,7 +940,10 @@ def run_and_verify_shelf_diff_summarize( svntest.verify.display_trees(None, 'DIFF OUTPUT TREE', output_tree, actual) raise +#---------------------------------------------------------------------- + # Exercise a very basic case of shelf-diff. +@SkipUnless(shelf3_enabled) def shelf_diff_simple(sbox): "shelf diff simple" @@ -918,6 +958,8 @@ def shelf_diff_simple(sbox): sbox.simple_propset('p2', 'v', 'A/mu') def modifier1(sbox): + sbox.simple_rm('A/B/lambda') + sbox.simple_add_text('This is a new file.\n', 'A/B/new') sbox.simple_append('A/mu', 'New line.\n') sbox.simple_propset('p1', 'changed', 'A/mu') @@ -933,7 +975,15 @@ def shelf_diff_simple(sbox): 'x-shelf-save', 'foo') # basic svn-style diff - expected_output = make_diff_header('A/mu', 'revision 2', 'working copy') + [ + expected_output = make_diff_header('A/B/lambda', 'revision 2', 'nonexistent') + [ + "@@ -1 +0,0 @@\n", + "-This is the file 'lambda'.\n" + ] + expected_output += make_diff_header('A/B/new', 'nonexistent', 'working copy') + [ + "@@ -0,0 +1 @@\n", + "+This is a new file.\n" + ] + expected_output += make_diff_header('A/mu', 'revision 2', 'working copy') + [ "@@ -1 +1,2 @@\n", " This is the file 'mu'.\n", "+New line.\n", @@ -944,10 +994,30 @@ def shelf_diff_simple(sbox): # basic summary diff expected_diff = svntest.wc.State(wc_dir, { + 'A/B/lambda': Item(status='D '), + 'A/B/new': Item(status='A '), 'A/mu': Item(status='MM'), }) run_and_verify_shelf_diff_summarize(expected_diff, 'foo') +#---------------------------------------------------------------------- + +@XFail() +@Issue(4827) +@SkipUnless(shelf3_enabled) +def shelve_with_kw_translation(sbox): + "shelve with kw translation" + sbox.build(empty=True) + sbox.simple_add_text('$Rev$\n', 'file') + sbox.simple_propset('svn:keywords', 'rev', 'file') + sbox.simple_commit() + sbox.simple_update() + + def modifier(sbox): + sbox.simple_append('file', 'New line\n') + + shelve_unshelve(sbox, modifier) + ######################################################################## # Run the tests @@ -985,6 +1055,7 @@ test_list = [ None, unshelve_text_prop_merge, unshelve_text_prop_conflict, shelf_diff_simple, + shelve_with_kw_translation, ] if __name__ == '__main__': Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/stat_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/stat_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/stat_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/stat_tests.py Fri Jan 14 14:01:45 2022 @@ -1606,7 +1606,7 @@ def status_dash_u_deleted_directories(sb os.path.join("B", "E", "alpha"), "D 1 1 jrandom %s\n" % \ os.path.join("B", "E", "beta"), - "D 1 1 jrandom %s\n" % + "D 1 1 jrandom %s\n" % os.path.join("B", "F"), "Status against revision: 1\n" ]) svntest.actions.run_and_verify_svn(expected, Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svnadmin_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svnadmin_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svnadmin_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svnadmin_tests.py Fri Jan 14 14:01:45 2022 @@ -1726,7 +1726,7 @@ def verify_non_utf8_paths(sbox): # also fix up the 'created path' field fp_new.write(b"cpath: /\xE6\n") elif line == b"_0.0.t0-0 add-file true true /A\n": - # and another occurrance + # and another occurrence fp_new.write(b"_0.0.t0-0 add-file true true /\xE6\n") else: fp_new.write(line) @@ -3177,7 +3177,7 @@ def load_txdelta(sbox): sbox.build(empty=True) - # This dumpfile produced a BDB repository that generated cheksum + # This dumpfile produced a BDB repository that generated checksum # mismatches on read caused by the improper handling of # svn_txdelta_target ops. The bug was fixed by r1640832. @@ -3220,7 +3220,7 @@ def load_no_svndate_r0(sbox): b"Content-length: 10\n", b"\n", b"PROPS-END\n", b"\n"] svntest.actions.run_and_verify_load(sbox.repo_dir, dump_old) - + # svn:date should have been removed svntest.actions.run_and_verify_svnlook([], [], 'proplist', '--revprop', '-r0', @@ -3859,7 +3859,7 @@ def dump_no_canonicalize_svndate(sbox): sbox.repo_url) dump_lines = svntest.actions.run_and_verify_dump(sbox.repo_dir) - assert propval + '\n' in dump_lines + assert propval.encode() + b'\n' in dump_lines def check_recover_prunes_rep_cache(sbox, enable_rep_sharing): """Check 'recover' prunes the rep-cache while enable-rep-sharing is @@ -3920,6 +3920,145 @@ def recover_prunes_rep_cache_when_disabl check_recover_prunes_rep_cache(sbox, enable_rep_sharing=False) +@Issue(4760) +def dump_include_copied_directory(sbox): + "include copied directory with nested nodes" + + sbox.build(create_wc=False) + + svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [], "copy", + sbox.repo_url + '/A/D', + sbox.repo_url + '/COPY', + "-m", "Create branch.") + + # Dump repository with only /COPY path included. + _, dump, _ = svntest.actions.run_and_verify_svnadmin(None, [], + 'dump', '-q', + '--include', '/COPY', + sbox.repo_dir) + + # Load repository from dump. + sbox2 = sbox.clone_dependent() + sbox2.build(create_wc=False, empty=True) + load_and_verify_dumpstream(sbox2, None, [], None, False, dump) + + # Check log. + expected_output = svntest.verify.RegexListOutput([ + '-+\\n', + 'r2\ .*\n', + # Only '/COPY' is added + re.escape('Changed paths:\n'), + re.escape(' A /COPY'), + re.escape(' A /COPY/G'), + re.escape(' A /COPY/G/pi'), + re.escape(' A /COPY/G/rho'), + re.escape(' A /COPY/G/tau'), + re.escape(' A /COPY/H'), + re.escape(' A /COPY/H/chi'), + re.escape(' A /COPY/H/omega'), + re.escape(' A /COPY/H/psi'), + re.escape(' A /COPY/gamma'), + '-+\\n', + 'r1\ .*\n', + '-+\\n' + ]) + svntest.actions.run_and_verify_svn(expected_output, [], + 'log', '-v', '-q', sbox2.repo_url) + +def load_normalize_node_props(sbox): + "svnadmin load --normalize node props" + + dump_str = b"""SVN-fs-dump-format-version: 2 + +UUID: dc40867b-38f6-0310-9f5f-f81aa277e06f + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2005-05-03T19:09:41.129900Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 99 +Content-length: 99 + +K 7 +svn:log +V 0 + +K 10 +svn:author +V 2 +pl +K 8 +svn:date +V 27 +2005-05-03T19:10:19.975578Z +PROPS-END + +Node-path:\x20 +Node-kind: dir +Node-action: change +Prop-content-length: 32 +Content-length: 32 + +K 10 +svn:ignore +V 3 +\n\r\n +PROPS-END + + +""" + sbox.build(empty=True) + + # Try to load the dumpstream, expecting a failure (because of mixed + # EOLs in the svn:ignore property value). + exp_err = svntest.verify.RegexListOutput(['svnadmin: E125005:.*', + 'svnadmin: E125017:.*'], + match_all=False) + load_and_verify_dumpstream(sbox, [], exp_err, dumpfile_revisions, + False, dump_str, '--ignore-uuid') + + # Now try it again with prop normalization. + svntest.actions.load_repo(sbox, dump_str=dump_str, + bypass_prop_validation=False, + normalize_props=True) + # We should get the normalized property value. + exit_code, output, _ = svntest.main.run_svn(None, 'pg', 'svn:ignore', + '--no-newline', + sbox.repo_url) + svntest.verify.verify_exit_code(None, exit_code, 0) + if output != ['\n', '\n']: + raise svntest.Failure("Unexpected property value %s" % output) + +@SkipUnless(svntest.main.is_fs_type_fsfs) +@SkipUnless(svntest.main.fs_has_rep_sharing) +@SkipUnless(svntest.main.python_sqlite_can_read_without_rowid) +def build_repcache(sbox): + "svnadmin build-repcache" + + sbox.build(create_wc = False) + + # Remember and remove the existing rep-cache. + rep_cache = read_rep_cache(sbox.repo_dir) + rep_cache_path = os.path.join(sbox.repo_dir, 'db', 'rep-cache.db') + os.remove(rep_cache_path) + + # Build a new rep-cache and compare with the original one. + expected_output = ["* Processed revision 1.\n"] + svntest.actions.run_and_verify_svnadmin(expected_output, [], + "build-repcache", sbox.repo_dir) + + new_rep_cache = read_rep_cache(sbox.repo_dir) + if new_rep_cache != rep_cache: + raise svntest.Failure + + ######################################################################## # Run the tests @@ -3997,6 +4136,9 @@ test_list = [ None, dump_no_canonicalize_svndate, recover_prunes_rep_cache_when_enabled, recover_prunes_rep_cache_when_disabled, + dump_include_copied_directory, + load_normalize_node_props, + build_repcache, ] if __name__ == '__main__': Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svnauthz_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svnauthz_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svnauthz_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svnauthz_tests.py Fri Jan 14 14:01:45 2022 @@ -896,6 +896,105 @@ def svnauthz_compat_mode_repo_test(sbox) repo_url + "/zilch" ) + +@Issue(4793) +def svnauthz_inverted_selector_test(sbox): + "test inverted selector rights" + + # build an authz file + authz_content = ("[groups]\n" + "grouped = grouper\n" + + "[aliases]\n" + "aliased = aliaser\n" + + "[A:/]\n" + "@grouped = r\n" + "~@grouped = rw\n" + + "[B:/]\n" + "&aliased = r\n" + "~&aliased = rw\n" + + "[C:/]\n" + "user = r\n" + "~user = rw\n" + + "[D:/]\n" + "~@grouped = rw\n" + "not-grouper = r\n" + + "[E:/]\n" + "~&aliased = rw\n" + "not-aliaser = r\n" + + "[F:/]\n" + "~user = rw\n" + "not-user = r\n") + + (authz_fd, authz_path) = tempfile.mkstemp() + svntest.main.file_write(authz_path, authz_content) + + def accessof(repos, user, expected_stdout): + return svntest.actions.run_and_verify_svnauthz( + expected_stdout, None, 0, False, 'accessof', + '--repository', repos, '--username', user, authz_path) + + accessof('A', 'grouper', 'r') + accessof('A', 'not-grouper', 'rw') + + accessof('B', 'aliaser', 'r') + accessof('B', 'not-aliaser', 'rw') + + accessof('C', 'user', 'r') + accessof('C', 'not-user', 'rw') + + accessof('D', 'grouper', 'no') + accessof('D', 'not-grouper', 'r') + accessof('D', 'other', 'rw') + + accessof('E', 'aliaser', 'no') + accessof('E', 'not-aliaser', 'r') + accessof('E', 'other', 'rw') + + accessof('F', 'user', 'no') + accessof('F', 'not-user', 'r') + accessof('F', 'other', 'rw') + + os.close(authz_fd) + os.remove(authz_path) + + +@Issues(4802, 4803) +def svnauthz_empty_group_test(sbox): + "test empty group definition" + + # build an authz file + authz_content = ("[groups]\n" + "group1 =\n" + "group2 = @group1\n" + "group3 = @group2, user\n" + + + "[A:/]\n" + "@group1 = rw\n" + "@group2 = rw\n" + "@group3 = r\n") + + (authz_fd, authz_path) = tempfile.mkstemp() + svntest.main.file_write(authz_path, authz_content) + + expected_stderr = svntest.verify.RegexOutput( + r".*warning: W220003:.*", match_all=False) + + svntest.actions.run_and_verify_svnauthz( + [], expected_stderr, 0, False, 'validate', authz_path) + + svntest.actions.run_and_verify_svnauthz( + 'r', expected_stderr, 0, False, 'accessof', + '--repository', 'A', '--username', 'user', authz_path) + + ######################################################################## # Run the tests @@ -914,6 +1013,8 @@ test_list = [ None, svnauthz_accessof_txn_test, svnauthz_compat_mode_file_test, svnauthz_compat_mode_repo_test, + svnauthz_inverted_selector_test, + svnauthz_empty_group_test, ] if __name__ == '__main__': Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svndumpfilter_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svndumpfilter_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svndumpfilter_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svndumpfilter_tests.py Fri Jan 14 14:01:45 2022 @@ -71,7 +71,7 @@ def filter_and_return_output(dump, bufsi # Since we call svntest.main.run_command_stdin() in binary mode, # normalize the stderr line endings on Windows ourselves. if sys.platform == 'win32': - errput = map(lambda x : x.replace('\r\n', '\n'), errput) + errput = [x.replace('\r\n', '\n') for x in errput] return output, errput @@ -608,7 +608,7 @@ def match_empty_prefix(sbox): '--quiet', *dumpargs) if filtered_err: - raise verify.UnexpectedStderr(filtered_err) + raise SVNExpectedStderr(filtered_err) # Load the filtered dump into a repo and check the result sbox.build(empty=True) Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svneditor.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svneditor.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svneditor.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svneditor.py Fri Jan 14 14:01:45 2022 @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # svneditor.py: a mock $SVN_EDITOR for the Subversion test suite # Propchange: subversion/branches/multi-wc-format/subversion/tests/cmdline/svneditor.py ('svn:executable' removed) Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svnfsfs_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svnfsfs_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svnfsfs_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svnfsfs_tests.py Fri Jan 14 14:01:45 2022 @@ -185,7 +185,7 @@ def test_stats(sbox): '.*\d+ bytes in .*\d+ file property representations', '.*\d+ average delta chain length', '.*\d+ bytes in header & footer overhead' ], - '.* representation statistics:' : + '.* representation statistics:' : ['.*\d+ bytes in .*\d+ reps', '.*\d+ bytes in .*\d+ shared reps', '.*\d+ bytes expanded size', Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svnmover_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svnmover_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svnmover_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svnmover_tests.py Fri Jan 14 14:01:45 2022 @@ -1545,7 +1545,7 @@ def replace_via_rm_cp(sbox): """replace by deleting and copying""" sbox_build_svnmover(sbox) - + expected_eids = svntest.wc.State('', { 'B0' : Item(eid=0), 'B0/X' : Item(eid=1), @@ -1572,7 +1572,7 @@ def replace_via_rm_cp(sbox): test_svnmover_verify_log(sbox.repo_url, ['D /top0/X/A', 'A /top0/X/A (from /top0/X/A:1)']) - + @XFail() # After making a commit, svnmover currently can't (within the same execution) # look up paths in the revision it just committed. Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svnmucc_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svnmucc_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svnmucc_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svnmucc_tests.py Fri Jan 14 14:01:45 2022 @@ -534,7 +534,8 @@ def svnmucc_type_errors(sbox): 'put', sbox.ospath('file'), 'A') xtest_svnmucc(sbox.repo_url, - ["svnmucc: E160020: Path 'Z' already exists"], + ["svnmucc: E160020: Path 'Z' already exists, or was created " + "by an earlier operation"], '-m', '', 'mkdir', 'A/Z', 'put', sbox.ospath('file'), 'A/Z') @@ -576,7 +577,8 @@ def svnmucc_propset_and_put(sbox): # Put same file twice (non existing) xtest_svnmucc(sbox.repo_url, - ["svnmucc: E160020: Path 't3' already exists"], + ["svnmucc: E160020: Path 't3' already exists, or was created " + "by an earlier operation"], '-m', '', 'put', sbox.ospath('file'), 't3', 'put', sbox.ospath('file'), 't3') Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svnrdump_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svnrdump_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svnrdump_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svnrdump_tests.py Fri Jan 14 14:01:45 2022 @@ -991,6 +991,36 @@ def load_non_deltas_with_props(sbox): actual = map(str.strip, out) svntest.verify.compare_and_display_lines(None, 'PROPS', expected, actual) +def load_invalid_svn_date_revprop_in_r0(sbox): + "load: invalid svn:date revprop in r0" + svnrdump_tests_dir = os.path.join(os.path.dirname(sys.argv[0]), + 'svnrdump_tests_data') + sbox.build(create_wc=False, empty=True) + svntest.actions.enable_revprop_changes(sbox.repo_dir) + expected_err = svntest.verify.RegexListOutput( + ['.* E125005: Wrong or unexpected property value.*'], + match_all=False) + dumpfile = "bad-date-r0.dump" + dumpfile_path = os.path.join(svnrdump_tests_dir, dumpfile) + run_and_verify_svnrdump_load(dumpfile_path, + [], expected_err, 1, + sbox.repo_url) + +def load_invalid_svn_date_revprop_in_r1(sbox): + "load: invalid svn:date revprop in r1" + svnrdump_tests_dir = os.path.join(os.path.dirname(sys.argv[0]), + 'svnrdump_tests_data') + sbox.build(create_wc=False, empty=True) + svntest.actions.enable_revprop_changes(sbox.repo_dir) + expected_err = svntest.verify.RegexListOutput( + ['.* E125005: Wrong or unexpected property value.*'], + match_all=False) + dumpfile = "bad-date-r0.dump" + dumpfile_path = os.path.join(svnrdump_tests_dir, dumpfile) + run_and_verify_svnrdump_load(dumpfile_path, + [], expected_err, 1, + sbox.repo_url) + ######################################################################## # Run the tests @@ -1052,6 +1082,8 @@ test_list = [ None, load_non_deltas_replace_copy_with_props, dump_replace_with_copy, load_non_deltas_with_props, + load_invalid_svn_date_revprop_in_r0, + load_invalid_svn_date_revprop_in_r1, ] if __name__ == '__main__': Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svnserveautocheck.sh URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svnserveautocheck.sh?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svnserveautocheck.sh (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svnserveautocheck.sh Fri Jan 14 14:01:45 2022 @@ -74,6 +74,28 @@ fail() { exit 1 } +query() { + printf "%s" "$SCRIPT: $1 (y/n)? [$2] " + if [ -n "$BASH_VERSION" ]; then + read -n 1 -t 32 + else + # + prog=" +import select as s +import sys +import tty, termios +tty.setcbreak(sys.stdin.fileno(), termios.TCSANOW) +if s.select([sys.stdin.fileno()], [], [], 32)[0]: + sys.stdout.write(sys.stdin.read(1)) +" + stty_state=`stty -g` + REPLY=`$PYTHON -u -c "$prog" "$@"` + stty $stty_state + fi + echo + [ "${REPLY:-$2}" = 'y' ] +} + # Compute ABS_BUILDDIR and ABS_SRCDIR. if [ -x subversion/svn/svn ]; then # cwd is build tree root @@ -92,19 +114,27 @@ if [ ! -e $ABS_SRCDIR/subversion/include fail "Run this script from the root of Subversion's build tree!" fi +# Create a directory for the PID and log files. If you change this, also make +# sure to change the svn:ignore entry for it and "make check-clean". +SVNSERVE_ROOT="$ABS_BUILDDIR/subversion/tests/cmdline/svnserve-$(date '+%Y%m%d-%H%M%S')" +mkdir "$SVNSERVE_ROOT" \ + || fail "couldn't create temporary directory '$SVNSERVE_ROOT'" + # If you change this, also make sure to change the svn:ignore entry # for it and "make check-clean". -SVNSERVE_PID=$ABS_BUILDDIR/subversion/tests/svnserveautocheck.pid +SVNSERVE_PID=$SVNSERVE_ROOT/svnserve.pid +SVNSERVE_LOG=$SVNSERVE_ROOT/svnserve.log SERVER_CMD="$ABS_BUILDDIR/subversion/svnserve/svnserve" rm -f $SVNSERVE_PID +rm -f $SVNSERVE_LOG random_port() { if [ -n "$BASH_VERSION" ]; then echo $(($RANDOM+1024)) else - $PYTHON -c 'import random; print random.randint(1024, 2**16-1)' + $PYTHON -c 'import random; print(random.randint(1024, 2**16-1))' fi } @@ -140,6 +170,7 @@ fi --listen-host 127.0.0.1 \ --listen-port $SVNSERVE_PORT \ --pid-file $SVNSERVE_PID \ + --log-file $SVNSERVE_LOG \ $SVNSERVE_ARGS & BASE_URL=svn://127.0.0.1:$SVNSERVE_PORT @@ -155,5 +186,11 @@ else cd - > /dev/null fi +query 'Browse server log' n \ + && less "$SVNSERVE_LOG" + +query 'Delete svnserve root directory' y \ + && rm -fr "$SVNSERVE_ROOT/" + really_cleanup exit $r Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/actions.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/actions.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/actions.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/actions.py Fri Jan 14 14:01:45 2022 @@ -64,27 +64,15 @@ def no_relocate_validation(): def do_relocate_validation(): os.environ['SVN_I_LOVE_CORRUPTED_WORKING_COPIES_SO_DISABLE_RELOCATE_VALIDATION'] = 'no' -def setup_pristine_greek_repository(): - """Create the pristine repository and 'svn import' the greek tree""" - - # these directories don't exist out of the box, so we may have to create them - if not os.path.exists(main.general_wc_dir): - os.makedirs(main.general_wc_dir) - - if not os.path.exists(main.general_repo_dir): - os.makedirs(main.general_repo_dir) # this also creates all the intermediate dirs - - if not os.path.exists(main.other_dav_root_dir): - os.makedirs(main.other_dav_root_dir) - if not os.path.exists(main.non_dav_root_dir): - os.makedirs(main.non_dav_root_dir) - +def _setup_pristine_repo(tree_state, + repos_dir, dump_dir, repos_url, + use_precooked=True): # If there's no pristine repos, create one. - if not os.path.exists(main.pristine_greek_repos_dir): - if main.options.fsfs_version is not None: - main.unpack_greek_repos(main.pristine_greek_repos_dir) + if not os.path.exists(repos_dir): + if use_precooked and main.options.fsfs_version is not None: + main.unpack_greek_repos(repos_dir) else: - main.create_repos(main.pristine_greek_repos_dir) + main.create_repos(repos_dir) # if this is dav, gives us access rights to import the greek tree. if main.is_ra_type_dav(): @@ -92,15 +80,14 @@ def setup_pristine_greek_repository(): main.file_write(authz_file, "[/]\n* = rw\n") # dump the greek tree to disk. - main.greek_state.write_to_disk(main.greek_dump_dir) + tree_state.write_to_disk(dump_dir) # import the greek tree, using l:foo/p:bar ### todo: svn should not be prompting for auth info when using ### repositories with no auth/auth requirements _, output, _ = main.run_svn(None, 'import', '-m', 'Log message for revision 1.', - main.greek_dump_dir, - main.pristine_greek_repos_url) + dump_dir, repos_url) # verify the printed output of 'svn import'. lastline = output.pop().strip() @@ -112,7 +99,7 @@ def setup_pristine_greek_repository(): sys.exit(1) output_tree = wc.State.from_commit(output) - expected_output_tree = main.greek_state.copy(main.greek_dump_dir) + expected_output_tree = tree_state.copy(dump_dir) expected_output_tree.tweak(verb='Adding', contents=None) @@ -127,9 +114,36 @@ def setup_pristine_greek_repository(): # Finally, disallow any changes to the "pristine" repos. error_msg = "Don't modify the pristine repository" - create_failing_hook(main.pristine_greek_repos_dir, 'start-commit', error_msg) - create_failing_hook(main.pristine_greek_repos_dir, 'pre-lock', error_msg) - create_failing_hook(main.pristine_greek_repos_dir, 'pre-revprop-change', error_msg) + create_failing_hook(repos_dir, 'start-commit', error_msg) + create_failing_hook(repos_dir, 'pre-lock', error_msg) + create_failing_hook(repos_dir, 'pre-revprop-change', error_msg) + +def setup_pristine_repositories(): + """Create the pristine repository and 'svn import' the greek tree""" + + # these directories don't exist out of the box, so we may have to create them + if not os.path.exists(main.general_wc_dir): + os.makedirs(main.general_wc_dir) + + if not os.path.exists(main.general_repo_dir): + os.makedirs(main.general_repo_dir) # this also creates all the intermediate dirs + + if not os.path.exists(main.other_dav_root_dir): + os.makedirs(main.other_dav_root_dir) + if not os.path.exists(main.non_dav_root_dir): + os.makedirs(main.non_dav_root_dir) + + _setup_pristine_repo(main.greek_state, + main.pristine_greek_repos_dir, + main.greek_dump_dir, + main.pristine_greek_repos_url) + + # NOTE: We don't use precooked trojan repositories. + _setup_pristine_repo(main.trojan_state, + main.pristine_trojan_repos_dir, + main.trojan_dump_dir, + main.pristine_trojan_repos_url, + use_precooked=False) ###################################################################### @@ -149,23 +163,19 @@ def guarantee_empty_repository(path, min # Used by every test, so that they can run independently of one # another. Every time this routine is called, it recursively copies # the `pristine repos' to a new location. -# Note: make sure setup_pristine_greek_repository was called once before -# using this function. -def guarantee_greek_repository(path, minor_version): - """Guarantee that a local svn repository exists at PATH, containing - nothing but the greek-tree at revision 1.""" - - if path == main.pristine_greek_repos_dir: +# Note: make sure setup_pristine_repositories was called once before +# using these functions. +def _guarantee_repos(path, repos_dir, minor_version, use_precooked=True): + if path == repos_dir: logger.error("attempt to overwrite the pristine repos! Aborting.") sys.exit(1) # copy the pristine repository to PATH. main.safe_rmtree(path) - if (main.options.fsfs_version is not None): + if (use_precooked and main.options.fsfs_version is not None): failed = main.unpack_greek_repos(path) else: - failed = main.copy_repos(main.pristine_greek_repos_dir, - path, 1, 1, minor_version) + failed = main.copy_repos(repos_dir, path, 1, 1, minor_version) if failed: logger.error("copying repository failed.") sys.exit(1) @@ -176,6 +186,18 @@ def guarantee_greek_repository(path, min # give the repository a unique UUID run_and_verify_svnadmin([], [], 'setuuid', path) +def guarantee_greek_repository(path, minor_version): + """Guarantee that a local svn repository exists at PATH, containing + nothing but the greek-tree at revision 1.""" + + _guarantee_repos(path, main.pristine_greek_repos_dir, minor_version) + +def guarantee_trojan_repository(path, minor_version): + """Guarantee that a local svn repository exists at PATH, containing + nothing but the trojan-tree at revision 1.""" + + _guarantee_repos(path, main.pristine_trojan_repos_dir, minor_version, False) + def run_and_verify_atomic_ra_revprop_change(expected_stdout, expected_stderr, expected_exit, @@ -396,7 +418,7 @@ def run_and_verify_svnrdump(dumpfile_con # Since main.run_svnrdump() uses binary mode, normalize the stderr # line endings on Windows ourselves. if sys.platform == 'win32': - err = map(lambda x : x.replace('\r\n', '\n'), err) + err = [x.replace('\r\n', '\n') for x in err] # Ignore "consider upgrade" warnings to allow regression tests to pass # when run against a 1.6 mod_dav_svn. @@ -464,7 +486,7 @@ def run_and_verify_svnsync(expected_stdo def run_and_verify_svnsync2(expected_stdout, expected_stderr, expected_exit, *varargs): - """Run svnmucc command and check its output and exit code.""" + """Run svnsync command and check its output and exit code.""" exit_code, out, err = main.run_svnsync(*varargs) @@ -485,7 +507,8 @@ def load_repo(sbox, dumpfile_path = None normalize_props = False): "Loads the dumpfile into sbox" if not dump_str: - dump_str = open(dumpfile_path, "rb").read() + with open(dumpfile_path, "rb") as fp: + dump_str = fp.read() # Create a virgin repos and working copy main.safe_rmtree(sbox.repo_dir, 1) @@ -1901,7 +1924,7 @@ def _run_and_verify_resolve(cmd, expecte "Merge conflicts in '" + path + "' marked as resolved.\n" for path in expected_paths]), verify.UnorderedRegexListOutput([ - "Conflict in property.*at '" + path + "' marked as resolved.\n" \ + "Conflict in property.*at '" + re.escape(path) + "' marked as resolved.\n" \ for path in expected_paths]), verify.UnorderedOutput([ "Tree conflict at '" + path + "' marked as resolved.\n" for path in @@ -1942,7 +1965,7 @@ def run_and_verify_revert(expected_paths # This allows a test to *quickly* bootstrap itself. def make_repo_and_wc(sbox, create_wc=True, read_only=False, empty=False, - minor_version=None): + minor_version=None, tree=None): """Create a fresh repository and check out a WC from it. If EMPTY is True, the repository and WC will be empty and at revision 0, otherwise they will contain the 'Greek Tree' at revision 1. @@ -1967,9 +1990,17 @@ def make_repo_and_wc(sbox, create_wc=Tru guarantee_empty_repository(sbox.repo_dir, minor_version) expected_state = svntest.wc.State('', {}) else: - if not read_only: - guarantee_greek_repository(sbox.repo_dir, minor_version) - expected_state = main.greek_state + if tree == 'greek': + if not read_only: + guarantee_greek_repository(sbox.repo_dir, minor_version) + expected_state = main.greek_state + elif tree == 'trojan': + if not read_only: + guarantee_trojan_repository(sbox.repo_dir, minor_version) + expected_state = main.trojan_state + else: + raise ValueError("'tree' must be 'greek' or 'trojan'" + " but was '%s'" % str(tree)) if create_wc: # Generate the expected output tree. @@ -2003,14 +2034,21 @@ def duplicate_dir(wc_name, wc_copy_name) -def get_virginal_state(wc_dir, rev): +def get_virginal_state(wc_dir, rev, tree='greek'): "Return a virginal greek tree state for a WC and repos at revision REV." rev = str(rev) ### maybe switch rev to an integer? # copy the greek tree, shift it to the new wc_dir, insert a root elem, # then tweak all values - state = main.greek_state.copy() + if tree == 'greek': + state = main.greek_state.copy() + elif tree == 'trojan': + state = main.trojan_state.copy() + else: + raise ValueError("'tree' must be 'greek' or 'trojan'" + " but was '%s'" % str(tree)) + state.wc_dir = wc_dir state.desc[''] = wc.StateItem() state.tweak(contents=None, status=' ', wc_rev=rev) @@ -2039,7 +2077,9 @@ def get_wc_base_rev(wc_dir): def load_dumpfile(filename): "Return the contents of the FILENAME assuming that it is a dump file" - return open(filename, "rb").readlines() + with open(filename, "rb") as fp: + dump_str = fp.readlines() + return dump_str def hook_failure_message(hook_name): """Return the error message that the client prints for failure of the @@ -2144,7 +2184,7 @@ def set_prop(name, value, path, expected file = None else: raise TypeError(value) - + if file is None: propset += (name, value, path) else: Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/main.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/main.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/main.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/main.py Fri Jan 14 14:01:45 2022 @@ -55,8 +55,9 @@ except ImportError: import svntest from svntest import Failure from svntest import Skip +from svntest.wc import StateItem as Item -SVN_VER_MINOR = 12 +SVN_VER_MINOR = 15 ###################################################################### # @@ -128,7 +129,10 @@ else: if windows: svneditor_script = os.path.join(sys.path[0], 'svneditor.bat') else: - svneditor_script = os.path.join(sys.path[0], 'svneditor.py') + # This script is in the build tree, not in the source tree. + svneditor_script = os.path.join(os.path.dirname( + os.path.dirname(os.path.abspath('.'))), + 'tests/cmdline/svneditor.sh') # Username and password used by the working copies wc_author = 'jrandom' @@ -199,6 +203,7 @@ svnmover_binary = os.path.abspath('../.. # Location to the pristine repository, will be calculated from test_area_url # when we know what the user specified for --url. pristine_greek_repos_url = None +pristine_trojan_repos_url = None # Global variable to track all of our options options = None @@ -235,7 +240,9 @@ temp_dir = os.path.join(work_dir, 'local # (derivatives of the tmp dir.) pristine_greek_repos_dir = os.path.join(temp_dir, "repos") +pristine_trojan_repos_dir = os.path.join(temp_dir, "trojan") greek_dump_dir = os.path.join(temp_dir, "greekfiles") +trojan_dump_dir = os.path.join(temp_dir, "trojanfiles") default_config_dir = os.path.abspath(os.path.join(temp_dir, "config")) # @@ -245,28 +252,57 @@ default_config_dir = os.path.abspath(os. # call main.greek_state.copy(). That method will return a copy of this # State object which can then be edited. # -_item = svntest.wc.StateItem greek_state = svntest.wc.State('', { - 'iota' : _item("This is the file 'iota'.\n"), - 'A' : _item(), - 'A/mu' : _item("This is the file 'mu'.\n"), - 'A/B' : _item(), - 'A/B/lambda' : _item("This is the file 'lambda'.\n"), - 'A/B/E' : _item(), - 'A/B/E/alpha' : _item("This is the file 'alpha'.\n"), - 'A/B/E/beta' : _item("This is the file 'beta'.\n"), - 'A/B/F' : _item(), - 'A/C' : _item(), - 'A/D' : _item(), - 'A/D/gamma' : _item("This is the file 'gamma'.\n"), - 'A/D/G' : _item(), - 'A/D/G/pi' : _item("This is the file 'pi'.\n"), - 'A/D/G/rho' : _item("This is the file 'rho'.\n"), - 'A/D/G/tau' : _item("This is the file 'tau'.\n"), - 'A/D/H' : _item(), - 'A/D/H/chi' : _item("This is the file 'chi'.\n"), - 'A/D/H/psi' : _item("This is the file 'psi'.\n"), - 'A/D/H/omega' : _item("This is the file 'omega'.\n"), + 'iota' : Item("This is the file 'iota'.\n"), + 'A' : Item(), + 'A/mu' : Item("This is the file 'mu'.\n"), + 'A/B' : Item(), + 'A/B/lambda' : Item("This is the file 'lambda'.\n"), + 'A/B/E' : Item(), + 'A/B/E/alpha' : Item("This is the file 'alpha'.\n"), + 'A/B/E/beta' : Item("This is the file 'beta'.\n"), + 'A/B/F' : Item(), + 'A/C' : Item(), + 'A/D' : Item(), + 'A/D/gamma' : Item("This is the file 'gamma'.\n"), + 'A/D/G' : Item(), + 'A/D/G/pi' : Item("This is the file 'pi'.\n"), + 'A/D/G/rho' : Item("This is the file 'rho'.\n"), + 'A/D/G/tau' : Item("This is the file 'tau'.\n"), + 'A/D/H' : Item(), + 'A/D/H/chi' : Item("This is the file 'chi'.\n"), + 'A/D/H/psi' : Item("This is the file 'psi'.\n"), + 'A/D/H/omega' : Item("This is the file 'omega'.\n"), + }) + +# Likewise our pristine trojan-tree state (for peg revision parsing tests) +# NOTE: We don't use precooked trojan repositories. +trojan_state = svntest.wc.State('', { + 'iota' : Item("This is the file 'iota'.\n"), + '@zeta' : Item("This is the file 'zeta'.\n"), + '_@theta' : Item("This is the file 'theta'.\n"), + '.@kappa' : Item("This is the file 'kappa'.\n"), + 'lambda@' : Item("This is the file 'lambda'.\n"), + '@omicron@' : Item("This is the file 'omicron'.\n"), + '@' : Item(), + '@@' : Item(), + '_@' : Item(), + '.@' : Item(), + 'A' : Item(), + 'A/@@' : Item("This is the file 'A/@@'.\n"), + 'A/alpha' : Item("This is the file 'alpha'.\n"), + 'A/@omega@' : Item("This is the file 'omega'.\n"), + 'B' : Item(), + 'B/@' : Item("This is the file 'B/@'.\n"), + 'B/@beta' : Item("This is the file 'beta'.\n"), + 'B/pi@' : Item("This is the file 'pi'.\n"), + 'G' : Item(), + 'G/_@' : Item("This is the file 'G/_@'.\n"), + 'G/_@gamma' : Item("This is the file 'gamma'.\n"), + 'D' : Item(), + 'D/.@' : Item("This is the file 'D/.@'.\n"), + 'D/.@delta' : Item("This is the file 'delta'.\n"), + 'E' : Item(), }) @@ -494,10 +530,10 @@ def wait_on_pipe(waiter, binary_mode, st # We always expect STDERR to be strings, not byte-arrays. if not isinstance(stderr, str): - stderr = stderr.decode("utf-8") + stderr = stderr.decode("utf-8", 'surrogateescape') if not binary_mode: if not isinstance(stdout, str): - stdout = stdout.decode("utf-8") + stdout = stdout.decode("utf-8", 'surrogateescape') # Normalize Windows line endings if in text mode. if windows: @@ -709,9 +745,9 @@ def trust_ssl_cert(cfgdir, ssl_cert, ssl """ cert_rep = '' - fp = open(ssl_cert, 'r') - for line in fp.readlines()[1:-1]: - cert_rep = cert_rep + line.strip() + with open(ssl_cert, 'r') as fp: + for line in fp.readlines()[1:-1]: + cert_rep = cert_rep + line.strip() parsed_url = urlparse(ssl_url) netloc_url = '%s://%s' % (parsed_url.scheme, parsed_url.netloc) @@ -869,8 +905,6 @@ def run_entriesdump(path): ### report on this? or continue to just skip it? return None - class Entry(object): - pass entries = { } exec(''.join(filter_dbg(stdout_lines))) return entries @@ -894,8 +928,6 @@ def run_entriesdump_tree(path): ### report on this? or continue to just skip it? return None - class Entry(object): - pass dirs = { } exec(''.join(filter_dbg(stdout_lines))) return dirs @@ -1318,30 +1350,29 @@ def create_http_connection(url, debuglev h.set_debuglevel(debuglevel) return h -def write_restrictive_svnserve_conf(repo_dir, anon_access="none"): +def write_restrictive_svnserve_conf(repo_dir, anon_access="none", + separate_groups_db=False): "Create a restrictive authz file ( no anynomous access )." fp = open(get_svnserve_conf_file_path(repo_dir), 'w') - fp.write("[general]\nanon-access = %s\nauth-access = write\n" - "authz-db = authz\n" % anon_access) + fp.write("[general]\n" + "anon-access = %s\n" + "auth-access = write\n" + "authz-db = authz\n" % anon_access); + if separate_groups_db: + fp.write("groups-db = groups\n") if options.enable_sasl: - fp.write("realm = svntest\n[sasl]\nuse-sasl = true\n"); + fp.write("realm = svntest\n" + "[sasl]\n", + "use-sasl = true\n"); else: fp.write("password-db = passwd\n") fp.close() -def write_restrictive_svnserve_conf_with_groups(repo_dir, - anon_access="none"): +def write_restrictive_svnserve_conf_with_groups(repo_dir, anon_access="none"): "Create a restrictive configuration with groups stored in a separate file." - fp = open(get_svnserve_conf_file_path(repo_dir), 'w') - fp.write("[general]\nanon-access = %s\nauth-access = write\n" - "authz-db = authz\ngroups-db = groups\n" % anon_access) - if options.enable_sasl: - fp.write("realm = svntest\n[sasl]\nuse-sasl = true\n"); - else: - fp.write("password-db = passwd\n") - fp.close() + return write_restrictive_svnserve_conf(repo_dir, anon_access, True) # Warning: because mod_dav_svn uses one shared authz file for all # repositories, you *cannot* use write_authz_file in any test that @@ -1662,7 +1693,6 @@ def is_plaintext_password_storage_disabl return False return True - # https://issues.apache.org/bugzilla/show_bug.cgi?id=56480 # https://issues.apache.org/bugzilla/show_bug.cgi?id=55397 __mod_dav_url_quoting_broken_versions = frozenset([ @@ -1686,6 +1716,10 @@ def is_httpd_authz_provider_enabled(): return (v[0] == '2' and int(v[1]) >= 3) or int(v[0]) > 2 return None +def is_remote_http_connection_allowed(): + return options.allow_remote_http_connection + + ###################################################################### @@ -1766,6 +1800,8 @@ class TestSpawningThread(threading.Threa args.append('--fsfs-compression=' + options.fsfs_compression) if options.fsfs_dir_deltification: args.append('--fsfs-dir-deltification=' + options.fsfs_dir_deltification) + if options.allow_remote_http_connection: + args.append('--allow-remote-http-connection') if options.svn_bin: args.append('--bin=' + options.svn_bin) @@ -2047,6 +2083,23 @@ class AbbreviatedFormatter(logging.Forma record.levelshort = self._level_short[record.levelno] return logging.Formatter.format(self, record) + +class LoggingStdoutHandler(logging.StreamHandler): + """ + The handler is always writing using sys.stdout at call time rather than the + value of sys.stdout at construction time. + + Inspired by logging._StderrHandler on Python 3. + """ + + def __init__(self, level=logging.NOTSET): + logging.Handler.__init__(self, level) + + @property + def stream(self): + return sys.stdout + + def _create_parser(usage=None): """Return a parser for our test suite.""" @@ -2184,6 +2237,8 @@ def _create_parser(usage=None): help='Set compression type (for fsfs)') parser.add_option('--fsfs-dir-deltification', action='store', type='str', help='Set directory deltification option (for fsfs)') + parser.add_option('--allow-remote-http-connection', action='store_true', + help='Run tests that connect to remote HTTP(S) servers') # most of the defaults are None, but some are other values, set them here parser.set_defaults( @@ -2237,7 +2292,7 @@ def parse_options(arglist=sys.argv[1:], datefmt='%Y-%m-%d %H:%M:%S') else: formatter = AbbreviatedFormatter('%(levelshort)s: %(message)s') - handler = logging.StreamHandler(sys.stdout) + handler = LoggingStdoutHandler() handler.setFormatter(formatter) logger.addHandler(handler) @@ -2353,6 +2408,7 @@ def execute_tests(test_list, serial_only global pristine_url global pristine_greek_repos_url + global pristine_trojan_repos_url global other_dav_root_url global non_dav_root_url global svn_binary @@ -2434,6 +2490,12 @@ def execute_tests(test_list, serial_only pristine_greek_repos_dir.replace( os.path.sep, '/')) + # Calculate pristine_trojan_repos_url from test_area_url. + pristine_trojan_repos_url = options.test_area_url + '/' + \ + svntest.wc.svn_uri_quote( + pristine_trojan_repos_dir.replace( + os.path.sep, '/')) + other_dav_root_url = options.test_area_url + '/fsdavroot' non_dav_root_url = options.test_area_url + '/nodavroot' @@ -2530,8 +2592,8 @@ def execute_tests(test_list, serial_only http_proxy=options.http_proxy, exclusive_wc_locks=options.exclusive_wc_locks) - # Setup the pristine repository - svntest.actions.setup_pristine_greek_repository() + # Setup the pristine repositories + svntest.actions.setup_pristine_repositories() # Run the tests. exit_code = _internal_run_tests(test_list, testnums, options.parallel,
