Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/mergetrees.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/mergetrees.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/mergetrees.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/mergetrees.py Fri Jan 14 14:01:45 2022 @@ -253,69 +253,48 @@ def set_up_branch(sbox, branch_only = Fa expected_status = actions.get_virginal_state(wc_dir, 1) expected_disk = main.greek_state.copy() + def path_join(head, tail): + if not head: return tail + if not tail: return head + return head + '/' + tail + + def greek_file_item(path): + if path[-1:].islower(): + basename = re.sub('.*/', '', path) + return Item("This is the file '" + basename + "'.\n") + return Item() + + A_paths = [ + "", + "B", + "B/lambda", + "B/E", + "B/E/alpha", + "B/E/beta", + "B/F", + "mu", + "C", + "D", + "D/gamma", + "D/G", + "D/G/pi", + "D/G/rho", + "D/G/tau", + "D/H", + "D/H/chi", + "D/H/omega", + "D/H/psi", + ] def copy_A(dest_name, rev): expected = verify.UnorderedOutput( - ["A " + os.path.join(wc_dir, dest_name, "B") + "\n", - "A " + os.path.join(wc_dir, dest_name, "B", "lambda") + "\n", - "A " + os.path.join(wc_dir, dest_name, "B", "E") + "\n", - "A " + os.path.join(wc_dir, dest_name, "B", "E", "alpha") + "\n", - "A " + os.path.join(wc_dir, dest_name, "B", "E", "beta") + "\n", - "A " + os.path.join(wc_dir, dest_name, "B", "F") + "\n", - "A " + os.path.join(wc_dir, dest_name, "mu") + "\n", - "A " + os.path.join(wc_dir, dest_name, "C") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "gamma") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "G") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "G", "pi") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "G", "rho") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "G", "tau") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "H") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "H", "chi") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "H", "omega") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "H", "psi") + "\n", - "Checked out revision " + str(rev - 1) + ".\n", - "A " + os.path.join(wc_dir, dest_name) + "\n"]) - expected_status.add({ - dest_name + "/B" : Item(status=' ', wc_rev=rev), - dest_name + "/B/lambda" : Item(status=' ', wc_rev=rev), - dest_name + "/B/E" : Item(status=' ', wc_rev=rev), - dest_name + "/B/E/alpha" : Item(status=' ', wc_rev=rev), - dest_name + "/B/E/beta" : Item(status=' ', wc_rev=rev), - dest_name + "/B/F" : Item(status=' ', wc_rev=rev), - dest_name + "/mu" : Item(status=' ', wc_rev=rev), - dest_name + "/C" : Item(status=' ', wc_rev=rev), - dest_name + "/D" : Item(status=' ', wc_rev=rev), - dest_name + "/D/gamma" : Item(status=' ', wc_rev=rev), - dest_name + "/D/G" : Item(status=' ', wc_rev=rev), - dest_name + "/D/G/pi" : Item(status=' ', wc_rev=rev), - dest_name + "/D/G/rho" : Item(status=' ', wc_rev=rev), - dest_name + "/D/G/tau" : Item(status=' ', wc_rev=rev), - dest_name + "/D/H" : Item(status=' ', wc_rev=rev), - dest_name + "/D/H/chi" : Item(status=' ', wc_rev=rev), - dest_name + "/D/H/omega" : Item(status=' ', wc_rev=rev), - dest_name + "/D/H/psi" : Item(status=' ', wc_rev=rev), - dest_name : Item(status=' ', wc_rev=rev)}) - expected_disk.add({ - dest_name : Item(), - dest_name + '/B' : Item(), - dest_name + '/B/lambda' : Item("This is the file 'lambda'.\n"), - dest_name + '/B/E' : Item(), - dest_name + '/B/E/alpha' : Item("This is the file 'alpha'.\n"), - dest_name + '/B/E/beta' : Item("This is the file 'beta'.\n"), - dest_name + '/B/F' : Item(), - dest_name + '/mu' : Item("This is the file 'mu'.\n"), - dest_name + '/C' : Item(), - dest_name + '/D' : Item(), - dest_name + '/D/gamma' : Item("This is the file 'gamma'.\n"), - dest_name + '/D/G' : Item(), - dest_name + '/D/G/pi' : Item("This is the file 'pi'.\n"), - dest_name + '/D/G/rho' : Item("This is the file 'rho'.\n"), - dest_name + '/D/G/tau' : Item("This is the file 'tau'.\n"), - dest_name + '/D/H' : Item(), - dest_name + '/D/H/chi' : Item("This is the file 'chi'.\n"), - dest_name + '/D/H/omega' : Item("This is the file 'omega'.\n"), - dest_name + '/D/H/psi' : Item("This is the file 'psi'.\n"), - }) + [ "A " + sbox.ospath(path_join(dest_name, p)) + "\n" + for p in A_paths ]) + expected_status.add( + { path_join(dest_name, p) : Item(status=' ', wc_rev=rev) + for p in A_paths }) + expected_disk.add( + { path_join(dest_name, p) : greek_file_item(p) + for p in A_paths }) # Make a branch A_COPY to merge into. actions.run_and_verify_svn(expected, [], 'copy',
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/sandbox.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/sandbox.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/sandbox.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/sandbox.py Fri Jan 14 14:01:45 2022 @@ -102,7 +102,7 @@ class Sandbox: self.was_cwd = os.getcwd() - def _set_name(self, name, read_only=False, empty=False): + def _set_name(self, name, read_only=False, empty=False, tree=None): """A convenience method for renaming a sandbox, useful when working with multiple repositories in the same unit test.""" if not name is None: @@ -117,8 +117,15 @@ class Sandbox: self.repo_dir.replace(os.path.sep, '/'))) self.add_test_path(self.repo_dir) else: - self.repo_dir = svntest.main.pristine_greek_repos_dir - self.repo_url = svntest.main.pristine_greek_repos_url + if tree == 'greek': + self.repo_dir = svntest.main.pristine_greek_repos_dir + self.repo_url = svntest.main.pristine_greek_repos_url + elif tree == 'trojan': + self.repo_dir = svntest.main.pristine_trojan_repos_dir + self.repo_url = svntest.main.pristine_trojan_repos_url + else: + raise ValueError("'tree' must be 'greek' or 'trojan'" + " but was '%s'" % str(tree)) if self.repo_url.startswith("http"): self.authz_file = os.path.join(svntest.main.work_dir, "authz") @@ -146,26 +153,31 @@ class Sandbox: return clone def build(self, name=None, create_wc=True, read_only=False, empty=False, - minor_version=None): - """Make a 'Greek Tree' repo (or refer to the central one if READ_ONLY), - or make an empty repo if EMPTY is true, + minor_version=None, tree='greek'): + """Make a 'Greek Tree' or 'Trojan Tree' repo (or refer to the central + one if READ_ONLY), or make an empty repo if EMPTY is true, and check out a WC from it (unless CREATE_WC is false). Change the sandbox's name to NAME. See actions.make_repo_and_wc() for details.""" - self._set_name(name, read_only, empty) + self._set_name(name, read_only, empty, tree) self._ensure_authz() svntest.actions.make_repo_and_wc(self, create_wc, read_only, empty, - minor_version) + minor_version, tree) self._is_built = True def _ensure_authz(self): "make sure the repository is accessible" + def get_content(f): + with open(f, 'r') as fp: + content = fp.read() + return content + if self.repo_url.startswith("http"): default_authz = "[/]\n* = rw\n" if (svntest.main.options.parallel == 0 and (not os.path.isfile(self.authz_file) - or open(self.authz_file,'r').read() != default_authz)): + or get_content(self.authz_file) != default_authz)): tmp_authz_file = os.path.join(svntest.main.work_dir, "authz-" + self.name) with open(tmp_authz_file, 'w') as f: Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/testcase.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/testcase.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/testcase.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/testcase.py Fri Jan 14 14:01:45 2022 @@ -222,8 +222,8 @@ class _Wimp(_XFail): RESULT_SKIP: (2, TextColors.success('SKIP: '), True), } - def __init__(self, wip, test_case, cond_func=lambda: True): - _XFail.__init__(self, test_case, cond_func, wip) + def __init__(self, wip, test_case, cond_func=lambda: True, issues=None): + _XFail.__init__(self, test_case, cond_func, wip, issues) class _Skip(TestCase): Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/tree.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/tree.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/tree.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/tree.py Fri Jan 14 14:01:45 2022 @@ -553,7 +553,9 @@ def get_text(path): if not os.path.isfile(path): return None - return open(path, 'r').read() + with open(path, 'r') as fp: + content = fp.read() + return content def get_child(node, name): Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/wc.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/wc.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/wc.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/svntest/wc.py Fri Jan 14 14:01:45 2022 @@ -28,6 +28,7 @@ import sys import re import logging import pprint +import io if sys.version_info[0] >= 3: # Python >=3.0 @@ -686,11 +687,20 @@ class State: if os.path.isfile(node): try: if keep_eol_style: - contents = open(node, 'r', newline='').read() + with io.open(node, 'r', newline='', encoding='utf-8') as fp: + contents = fp.read() else: - contents = open(node, 'r').read() + with io.open(node, 'r', encoding='utf-8') as fp: + contents = fp.read() + if not isinstance(contents, str): + # Python 2: contents is read as an unicode object, + # but we expect it is a str. + contents = contents.encode() except: - contents = open(node, 'rb').read() + # If the file contains non UTF-8 character, we treat its + # content as binary represented as a bytes object. + with open(node, 'rb') as fp: + contents = fp.read() else: contents = None desc[repos_join(parent, name)] = StateItem(contents=contents) @@ -829,7 +839,7 @@ class State: match = _re_parse_eid_ele.search(line) if match and match.group(2) != 'none': eid = match.group(1) - parent_eid = match.group(3) + parent_eid = match.group(3) path = match.group(4) if path == '.': path = '' @@ -851,7 +861,7 @@ class State: add_to_desc(eids, desc, branch_id) return cls('', desc) - + class StateItem: """Describes an individual item within a working copy. Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/switch_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/switch_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/switch_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/switch_tests.py Fri Jan 14 14:01:45 2022 @@ -1336,25 +1336,23 @@ def mergeinfo_switch_elision(sbox): # Make branches A/B_COPY_1 and A/B_COPY_2 expected_stdout = verify.UnorderedOutput([ - "A " + sbox.ospath('A/B_COPY_1/lambda') + "\n", - "A " + sbox.ospath('A/B_COPY_1/E') + "\n", - "A " + sbox.ospath('A/B_COPY_1/E/alpha') + "\n", - "A " + sbox.ospath('A/B_COPY_1/E/beta') + "\n", - "A " + sbox.ospath('A/B_COPY_1/F') + "\n", - "Checked out revision 1.\n", "A " + B_COPY_1_path + "\n", + "A " + sbox.ospath('A/B_COPY_1/lambda') + "\n", + "A " + sbox.ospath('A/B_COPY_1/E') + "\n", + "A " + sbox.ospath('A/B_COPY_1/E/alpha') + "\n", + "A " + sbox.ospath('A/B_COPY_1/E/beta') + "\n", + "A " + sbox.ospath('A/B_COPY_1/F') + "\n", ]) svntest.actions.run_and_verify_svn(expected_stdout, [], 'copy', sbox.repo_url + "/A/B", B_COPY_1_path) expected_stdout = verify.UnorderedOutput([ - "A " + sbox.ospath('A/B_COPY_2/lambda') + "\n", - "A " + sbox.ospath('A/B_COPY_2/E') + "\n", - "A " + sbox.ospath('A/B_COPY_2/E/alpha') + "\n", - "A " + sbox.ospath('A/B_COPY_2/E/beta') + "\n", - "A " + sbox.ospath('A/B_COPY_2/F') + "\n", - "Checked out revision 1.\n", "A " + B_COPY_2_path + "\n", + "A " + sbox.ospath('A/B_COPY_2/lambda') + "\n", + "A " + sbox.ospath('A/B_COPY_2/E') + "\n", + "A " + sbox.ospath('A/B_COPY_2/E/alpha') + "\n", + "A " + sbox.ospath('A/B_COPY_2/E/beta') + "\n", + "A " + sbox.ospath('A/B_COPY_2/F') + "\n", ]) svntest.actions.run_and_verify_svn(expected_stdout, [], 'copy', sbox.repo_url + "/A/B", B_COPY_2_path) @@ -2029,8 +2027,9 @@ def tolerate_local_mods(sbox): svntest.main.run_svn(None, 'add', L_path) sbox.simple_commit(message='Commit added folder') - # locally modified unversioned file + # locally modified versioned file svntest.main.file_write(LM_path, 'Locally modified file.\n', 'w+') + sbox.simple_add('A/L/local_mod') expected_output = svntest.wc.State(wc_dir, { 'A/L' : Item(status=' ', treeconflict='C'), @@ -2046,7 +2045,8 @@ def tolerate_local_mods(sbox): expected_status.tweak('', 'iota', wc_rev=1) expected_status.tweak('A', switched='S') expected_status.add({ - 'A/L' : Item(status='A ', copied='+', treeconflict='C', wc_rev='-') + 'A/L' : Item(status='A ', copied='+', treeconflict='C', wc_rev='-'), + 'A/L/local_mod' : Item(status='A ', wc_rev='-'), }) # Used to fail with locally modified or unversioned files @@ -2870,7 +2870,7 @@ def switch_moves(sbox): # In Subversion 1.8 this scenario causes an Sqlite row not found error. # It would be nice if we could handle the tree conflict more intelligent, as - # the working copy matches the incomming change. + # the working copy matches the incoming change. svntest.actions.run_and_verify_switch(sbox.wc_dir, sbox.ospath(''), branch_url, None, expected_disk, expected_status) Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/tree_conflict_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/tree_conflict_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/tree_conflict_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/tree_conflict_tests.py Fri Jan 14 14:01:45 2022 @@ -1518,7 +1518,7 @@ def local_missing_dir_endless_loop(sbox) sbox.simple_move('A/B', 'A/B2') sbox.simple_commit() sbox.simple_update() - main.file_append_binary(sbox.ospath("A/B2/lambda"), "This is more content.\n") + main.file_append(sbox.ospath("A/B2/lambda"), "This is more content.\n") sbox.simple_commit() sbox.simple_update() @@ -1541,7 +1541,7 @@ interactive-conflicts = true # If everything works as expected the resolver will recommended a # resolution option and 'svn' will resolve the conflict automatically. # Verify that 'A1/B/lambda' contains the merged content: - contents = open(sbox.ospath('A1/B/lambda'), 'rb').readlines() + contents = open(sbox.ospath('A1/B/lambda'), 'r').readlines() svntest.verify.compare_and_display_lines( "A1/B/lambda has unexpectected contents", sbox.ospath("A1/B/lambda"), [ "This is the file 'lambda'.\n", "This is more content.\n"], contents) Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/update_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/update_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/cmdline/update_tests.py (original) +++ subversion/branches/multi-wc-format/subversion/tests/cmdline/update_tests.py Fri Jan 14 14:01:45 2022 @@ -1650,15 +1650,11 @@ def conflict_markers_matching_eol(sbox): 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' # Checkout a second working copy wc_backup = sbox.add_wc_path('backup') @@ -1677,7 +1673,7 @@ def conflict_markers_matching_eol(sbox): # do the test for each eol-style for eol, eolchar in zip(['CRLF', 'CR', 'native', 'LF'], - [crlf, '\015', '\n', '\012']): + [crlf, '\015', native_nl, '\012']): # rewrite file mu and set the eol-style property. svntest.main.file_write(mu_path, "This is the file 'mu'."+ eolchar, 'wb') svntest.main.run_svn(None, 'propset', 'svn:eol-style', eol, mu_path) @@ -1704,8 +1700,8 @@ def conflict_markers_matching_eol(sbox): svntest.main.run_svn(None, 'update', wc_backup) # Make a local mod to mu - svntest.main.file_append(mu_path, - 'Original appended text for mu' + eolchar) + svntest.main.file_append_binary(mu_path, + 'Original appended text for mu' + eolchar) # Commit the original change and note the 'theirs' revision number svntest.main.run_svn(None, 'commit', '-m', 'test log', wc_dir) @@ -1713,8 +1709,9 @@ def conflict_markers_matching_eol(sbox): theirs_rev = cur_rev # Make a local mod to mu, will conflict with the previous change - svntest.main.file_append(path_backup, - 'Conflicting appended text for mu' + eolchar) + svntest.main.file_append_binary(path_backup, + 'Conflicting appended text for mu' + + eolchar) # Create expected output tree for an update of the wc_backup. expected_backup_output = svntest.wc.State(wc_backup, { @@ -1764,7 +1761,7 @@ def conflict_markers_matching_eol(sbox): expected_backup_output, expected_backup_disk, expected_backup_status, - keep_eol_style=keep_eol_style) + keep_eol_style=True) # cleanup for next run svntest.main.run_svn(None, 'revert', '-R', wc_backup) @@ -1785,15 +1782,7 @@ def update_eolstyle_handling(sbox): 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' # Checkout a second working copy wc_backup = sbox.add_wc_path('backup') @@ -1825,7 +1814,7 @@ def update_eolstyle_handling(sbox): expected_backup_output, expected_backup_disk, expected_backup_status, - keep_eol_style=keep_eol_style) + keep_eol_style=True) # Test 2: now change the eol-style property to another value and commit, # update the still changed mu in the second working copy; there should be @@ -1851,7 +1840,7 @@ def update_eolstyle_handling(sbox): expected_backup_output, expected_backup_disk, expected_backup_status, - keep_eol_style=keep_eol_style) + keep_eol_style=True) # Test 3: now delete the eol-style property and commit, update the still # changed mu in the second working copy; there should be no conflict! @@ -1876,7 +1865,7 @@ def update_eolstyle_handling(sbox): expected_backup_output, expected_backup_disk, expected_backup_status, - keep_eol_style=keep_eol_style) + keep_eol_style=True) # Bug in which "update" put a bogus revision number on a schedule-add file, # causing the wrong version of it to be committed. @@ -3046,13 +3035,12 @@ def mergeinfo_update_elision(sbox): # Make a branch A/B_COPY expected_stdout = verify.UnorderedOutput([ - "A " + sbox.ospath('A/B_COPY/lambda') + "\n", - "A " + sbox.ospath('A/B_COPY/E') + "\n", - "A " + sbox.ospath('A/B_COPY/E/alpha') + "\n", - "A " + sbox.ospath('A/B_COPY/E/beta') + "\n", - "A " + sbox.ospath('A/B_COPY/F') + "\n", - "Checked out revision 1.\n", "A " + B_COPY_path + "\n", + "A " + sbox.ospath('A/B_COPY/lambda') + "\n", + "A " + sbox.ospath('A/B_COPY/E') + "\n", + "A " + sbox.ospath('A/B_COPY/E/alpha') + "\n", + "A " + sbox.ospath('A/B_COPY/E/beta') + "\n", + "A " + sbox.ospath('A/B_COPY/F') + "\n", ]) svntest.actions.run_and_verify_svn(expected_stdout, [], 'copy', sbox.repo_url + "/A/B", B_COPY_path) @@ -3643,10 +3631,6 @@ def update_accept_conflicts(sbox): sbox.build() wc_dir = sbox.wc_dir - # Make a backup copy of the working copy - wc_backup = sbox.add_wc_path('backup') - svntest.actions.duplicate_dir(wc_dir, wc_backup) - # Make a few local mods to files which will be committed iota_path = sbox.ospath('iota') lambda_path = sbox.ospath('A/B/lambda') @@ -3654,13 +3638,25 @@ def update_accept_conflicts(sbox): alpha_path = sbox.ospath('A/B/E/alpha') beta_path = sbox.ospath('A/B/E/beta') pi_path = sbox.ospath('A/D/G/pi') + p_i_path = sbox.ospath('A/D/G/p; i') rho_path = sbox.ospath('A/D/G/rho') + + # Rename pi to "p; i" so we can exercise SVN_EDITOR's handling of paths with + # special characters + sbox.simple_move('A/D/G/pi', 'A/D/G/p; i') + sbox.simple_commit() + sbox.simple_update() + + # Make a backup copy of the working copy + wc_backup = sbox.add_wc_path('backup') + svntest.actions.duplicate_dir(wc_dir, wc_backup) + svntest.main.file_append(lambda_path, 'Their appended text for lambda\n') svntest.main.file_append(iota_path, 'Their appended text for iota\n') svntest.main.file_append(mu_path, 'Their appended text for mu\n') svntest.main.file_append(alpha_path, 'Their appended text for alpha\n') svntest.main.file_append(beta_path, 'Their appended text for beta\n') - svntest.main.file_append(pi_path, 'Their appended text for pi\n') + svntest.main.file_append(p_i_path, 'Their appended text for pi\n') svntest.main.file_append(rho_path, 'Their appended text for rho\n') # Make a few local mods to files which will be conflicted @@ -3669,7 +3665,7 @@ def update_accept_conflicts(sbox): mu_path_backup = os.path.join(wc_backup, 'A', 'mu') alpha_path_backup = os.path.join(wc_backup, 'A', 'B', 'E', 'alpha') beta_path_backup = os.path.join(wc_backup, 'A', 'B', 'E', 'beta') - pi_path_backup = os.path.join(wc_backup, 'A', 'D', 'G', 'pi') + p_i_path_backup = os.path.join(wc_backup, 'A', 'D', 'G', 'p; i') rho_path_backup = os.path.join(wc_backup, 'A', 'D', 'G', 'rho') svntest.main.file_append(iota_path_backup, 'My appended text for iota\n') @@ -3681,7 +3677,7 @@ def update_accept_conflicts(sbox): 'My appended text for alpha\n') svntest.main.file_append(beta_path_backup, 'My appended text for beta\n') - svntest.main.file_append(pi_path_backup, + svntest.main.file_append(p_i_path_backup, 'My appended text for pi\n') svntest.main.file_append(rho_path_backup, 'My appended text for rho\n') @@ -3693,18 +3689,19 @@ def update_accept_conflicts(sbox): 'A/mu' : Item(verb='Sending'), 'A/B/E/alpha': Item(verb='Sending'), 'A/B/E/beta': Item(verb='Sending'), - 'A/D/G/pi' : Item(verb='Sending'), + 'A/D/G/p; i' : Item(verb='Sending'), 'A/D/G/rho' : Item(verb='Sending'), }) - expected_status = svntest.actions.get_virginal_state(wc_dir, 1) - expected_status.tweak('iota', wc_rev=2) - expected_status.tweak('A/B/lambda', wc_rev=2) - expected_status.tweak('A/mu', wc_rev=2) - expected_status.tweak('A/B/E/alpha', wc_rev=2) - expected_status.tweak('A/B/E/beta', wc_rev=2) - expected_status.tweak('A/D/G/pi', wc_rev=2) - expected_status.tweak('A/D/G/rho', wc_rev=2) + expected_status = svntest.actions.get_virginal_state(wc_dir, 2) + expected_status.tweak('iota', wc_rev=3) + expected_status.tweak('A/B/lambda', wc_rev=3) + expected_status.tweak('A/mu', wc_rev=3) + expected_status.tweak('A/B/E/alpha', wc_rev=3) + expected_status.tweak('A/B/E/beta', wc_rev=3) + expected_status.rename({'A/D/G/pi': 'A/D/G/p; i'}) + expected_status.tweak('A/D/G/p; i', wc_rev=3) + expected_status.tweak('A/D/G/rho', wc_rev=3) # Commit. svntest.actions.run_and_verify_commit(wc_dir, expected_output, @@ -3720,14 +3717,14 @@ def update_accept_conflicts(sbox): # Just leave the conflicts alone, since run_and_verify_svn already uses # the --non-interactive option. svntest.actions.run_and_verify_svn(update_output_with_conflicts( - 2, iota_path_backup), + 3, iota_path_backup), [], 'update', iota_path_backup) # lambda: --accept=postpone # Just leave the conflicts alone. svntest.actions.run_and_verify_svn(update_output_with_conflicts( - 2, lambda_path_backup), + 3, lambda_path_backup), [], 'update', '--accept=postpone', lambda_path_backup) @@ -3735,7 +3732,7 @@ def update_accept_conflicts(sbox): # mu: --accept=base # Accept the pre-update base file. svntest.actions.run_and_verify_svn(update_output_with_conflicts_resolved( - 2, mu_path_backup), + 3, mu_path_backup), [], 'update', '--accept=base', mu_path_backup) @@ -3743,7 +3740,7 @@ def update_accept_conflicts(sbox): # alpha: --accept=mine # Accept the user's working file. svntest.actions.run_and_verify_svn(update_output_with_conflicts_resolved( - 2, alpha_path_backup), + 3, alpha_path_backup), [], 'update', '--accept=mine-full', alpha_path_backup) @@ -3751,7 +3748,7 @@ def update_accept_conflicts(sbox): # beta: --accept=theirs # Accept their file. svntest.actions.run_and_verify_svn(update_output_with_conflicts_resolved( - 2, beta_path_backup), + 3, beta_path_backup), [], 'update', '--accept=theirs-full', beta_path_backup) @@ -3761,16 +3758,16 @@ def update_accept_conflicts(sbox): # conflicts in place, so expect a message on stderr, but expect # svn to exit with an exit code of 0. svntest.actions.run_and_verify_svn2(update_output_with_conflicts_resolved( - 2, pi_path_backup), + 3, p_i_path_backup), "system(.*) returned.*", 0, 'update', '--accept=edit', '--force-interactive', - pi_path_backup) + p_i_path_backup) # rho: --accept=launch # Run the external merge tool, it should leave conflict markers in place. svntest.actions.run_and_verify_svn(update_output_with_conflicts( - 2, rho_path_backup), + 3, rho_path_backup), [], 'update', '--accept=launch', '--force-interactive', @@ -3782,55 +3779,57 @@ def update_accept_conflicts(sbox): expected_disk.tweak('iota', contents=("This is the file 'iota'.\n" '<<<<<<< .mine\n' 'My appended text for iota\n' - '||||||| .r1\n' + '||||||| .r2\n' '=======\n' 'Their appended text for iota\n' - '>>>>>>> .r2\n')) + '>>>>>>> .r3\n')) expected_disk.tweak('A/B/lambda', contents=("This is the file 'lambda'.\n" '<<<<<<< .mine\n' 'My appended text for lambda\n' - '||||||| .r1\n' + '||||||| .r2\n' '=======\n' 'Their appended text for lambda\n' - '>>>>>>> .r2\n')) + '>>>>>>> .r3\n')) expected_disk.tweak('A/mu', contents="This is the file 'mu'.\n") expected_disk.tweak('A/B/E/alpha', contents=("This is the file 'alpha'.\n" 'My appended text for alpha\n')) expected_disk.tweak('A/B/E/beta', contents=("This is the file 'beta'.\n" 'Their appended text for beta\n')) - expected_disk.tweak('A/D/G/pi', contents=("This is the file 'pi'.\n" - '<<<<<<< .mine\n' - 'My appended text for pi\n' - '||||||| .r1\n' - '=======\n' - 'Their appended text for pi\n' - '>>>>>>> .r2\n' - 'foo\n')) + expected_disk.rename({'A/D/G/pi': 'A/D/G/p; i'}) + expected_disk.tweak('A/D/G/p; i', contents=("This is the file 'pi'.\n" + '<<<<<<< .mine\n' + 'My appended text for pi\n' + '||||||| .r2\n' + '=======\n' + 'Their appended text for pi\n' + '>>>>>>> .r3\n' + 'foo\n')) expected_disk.tweak('A/D/G/rho', contents=("This is the file 'rho'.\n" '<<<<<<< .mine\n' 'My appended text for rho\n' - '||||||| .r1\n' + '||||||| .r2\n' '=======\n' 'Their appended text for rho\n' - '>>>>>>> .r2\n' + '>>>>>>> .r3\n' 'foo\n')) # Set the expected extra files for the test - extra_files = ['iota.*\.r1', 'iota.*\.r2', 'iota.*\.mine', - 'lambda.*\.r1', 'lambda.*\.r2', 'lambda.*\.mine', - 'rho.*\.r1', 'rho.*\.r2', 'rho.*\.mine'] + extra_files = ['iota.*\.r2', 'iota.*\.r3', 'iota.*\.mine', + 'lambda.*\.r2', 'lambda.*\.r3', 'lambda.*\.mine', + 'rho.*\.r2', 'rho.*\.r3', 'rho.*\.mine'] # Set the expected status for the test - expected_status = svntest.actions.get_virginal_state(wc_backup, 2) + expected_status = svntest.actions.get_virginal_state(wc_backup, 3) + expected_status.rename({'A/D/G/pi': 'A/D/G/p; i'}) expected_status.tweak('iota', 'A/B/lambda', 'A/mu', 'A/B/E/alpha', 'A/B/E/beta', - 'A/D/G/pi', 'A/D/G/rho', wc_rev=2) + 'A/D/G/p; i', 'A/D/G/rho', wc_rev=3) expected_status.tweak('iota', status='C ') expected_status.tweak('A/B/lambda', status='C ') expected_status.tweak('A/mu', status='M ') expected_status.tweak('A/B/E/alpha', status='M ') expected_status.tweak('A/B/E/beta', status=' ') - expected_status.tweak('A/D/G/pi', status='M ') + expected_status.tweak('A/D/G/p; i', status='M ') expected_status.tweak('A/D/G/rho', status='C ') # Set the expected output for the test @@ -6841,21 +6840,65 @@ def update_delete_switched(sbox): svntest.actions.run_and_verify_update(wc_dir, None, None, expected_status, [], False, sbox.ospath('A'), '-r', 0) -@XFail() def update_add_missing_local_add(sbox): "update adds missing local addition" - + sbox.build(read_only=True) - + + ### This used to insert an invalid workqueue item, but the issue vanished + ### when the update editor was changed. Annotate this line for more info. + # Note that updating 'A' to r0 doesn't reproduce this issue... sbox.simple_update('', revision='0') sbox.simple_mkdir('A') sbox.simple_add_text('mumumu', 'A/mu') os.unlink(sbox.ospath('A/mu')) os.rmdir(sbox.ospath('A')) - + sbox.simple_update() +# Verify that deleting an unmodified directory leaves behind any unversioned +# items on disk +def update_keeps_unversioned_items_in_deleted_dir(sbox): + "update keeps unversioned items in deleted dir" + sbox.build() + wc_dir = sbox.wc_dir + + sbox.simple_rm('A/D/G') + sbox.simple_commit() + + sbox.simple_update('', revision='1') + + os.mkdir(sbox.ospath('A/D/G/unversioned-dir')) + svntest.main.file_write(sbox.ospath('A/D/G/unversioned.txt'), + 'unversioned file', 'wb') + + expected_output = svntest.wc.State(wc_dir, { + 'A/D/G' : Item(status='D '), + }) + + expected_disk = svntest.main.greek_state.copy() + # The unversioned items should be left behind on disk + expected_disk.add({ + 'A/D/G/unversioned-dir' : Item(), + 'A/D/G/unversioned.txt' : Item('unversioned file'), + }) + expected_disk.remove('A/D/G/pi') + expected_disk.remove('A/D/G/rho') + expected_disk.remove('A/D/G/tau') + + expected_status = svntest.actions.get_virginal_state(wc_dir, 2) + expected_status.remove('A/D/G') + expected_status.remove('A/D/G/pi') + expected_status.remove('A/D/G/rho') + expected_status.remove('A/D/G/tau') + + svntest.actions.run_and_verify_update(wc_dir, + expected_output, + expected_disk, + expected_status, + [], True) + ####################################################################### # Run the tests @@ -6947,6 +6990,7 @@ test_list = [ None, missing_tmp_update, update_delete_switched, update_add_missing_local_add, + update_keeps_unversioned_items_in_deleted_dir, ] if __name__ == '__main__': Propchange: subversion/branches/multi-wc-format/subversion/tests/libsvn_client/ ------------------------------------------------------------------------------ --- svn:ignore (original) +++ svn:ignore Fri Jan 14 14:01:45 2022 @@ -1,4 +1,15 @@ -.libs *-test *.lo +.libs +mtcc-anchoring +mtcc-file-revs +mtcc-iprops-paths +mtcc-mkdir +mtcc-mkgreek +mtcc-move-and-delete +mtcc-overwrite +mtcc-propset +mtcc-replace_tree +mtcc-swap +mtcc-update-files svn-test-work Modified: subversion/branches/multi-wc-format/subversion/tests/libsvn_client/client-test.c URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/libsvn_client/client-test.c?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/tests/libsvn_client/client-test.c (original) +++ subversion/branches/multi-wc-format/subversion/tests/libsvn_client/client-test.c Fri Jan 14 14:01:45 2022 @@ -31,6 +31,7 @@ #include "../../libsvn_client/client.h" #include "svn_pools.h" #include "svn_client.h" +#include "private/svn_client_private.h" #include "private/svn_client_mtcc.h" #include "svn_repos.h" #include "svn_subst.h" @@ -60,7 +61,7 @@ create_greek_repos(const char **repos_ur svn_fs_txn_t *txn; svn_fs_root_t *txn_root; - /* Create a filesytem and repository. */ + /* Create a filesystem and repository. */ SVN_ERR(svn_test__create_repos( &repos, svn_test_data_path(name, pool), opts, pool)); @@ -371,7 +372,7 @@ test_patch(const svn_test_opts_t *opts, "+It is really the file 'gamma'." }; - /* Create a filesytem and repository containing the Greek tree. */ + /* Create a filesystem and repository containing the Greek tree. */ SVN_ERR(create_greek_repos(&repos_url, "test-patch-repos", opts, pool)); /* Check out the HEAD revision */ @@ -446,7 +447,7 @@ test_wc_add_scenarios(const svn_test_opt const char *ex_dir_path; const char *ex2_dir_path; - /* Create a filesytem and repository containing the Greek tree. */ + /* Create a filesystem and repository containing the Greek tree. */ SVN_ERR(create_greek_repos(&repos_url, "test-wc-add-repos", opts, pool)); committed_rev = 1; @@ -575,7 +576,7 @@ test_copy_crash(const svn_test_opts_t *o const char *dest; const char *repos_url; - /* Create a filesytem and repository containing the Greek tree. */ + /* Create a filesystem and repository containing the Greek tree. */ SVN_ERR(create_greek_repos(&repos_url, "test-copy-crash", opts, pool)); SVN_ERR(svn_client_create_context(&ctx, pool)); @@ -609,7 +610,7 @@ test_16k_add(const svn_test_opts_t *opts apr_pool_t *iterpool = svn_pool_create(pool); int i; - /* Create a filesytem and repository containing the Greek tree. */ + /* Create a filesystem and repository containing the Greek tree. */ SVN_ERR(create_greek_repos(&repos_url, "test-16k-repos", opts, pool)); /* Check out the HEAD revision */ @@ -670,7 +671,7 @@ test_youngest_common_ancestor(const svn_ const char *dest; svn_client__pathrev_t *yc_ancestor; - /* Create a filesytem and repository containing the Greek tree. */ + /* Create a filesystem and repository containing the Greek tree. */ SVN_ERR(create_greek_repos(&repos_url, "test-youngest-common-ancestor", opts, pool)); SVN_ERR(svn_client_create_context(&ctx, pool)); @@ -735,7 +736,10 @@ test_foreign_repos_copy(const svn_test_o const char *repos2_url; const char *wc_path; svn_client_ctx_t *ctx; -/* Create a filesytem and repository containing the Greek tree. */ + svn_ra_session_t *ra_session; + svn_client__pathrev_t *loc; + + /* Create a filesystem and repository containing the Greek tree. */ SVN_ERR(create_greek_repos(&repos_url, "foreign-copy1", opts, pool)); SVN_ERR(create_greek_repos(&repos2_url, "foreign-copy2", opts, pool)); @@ -756,19 +760,26 @@ test_foreign_repos_copy(const svn_test_o SVN_ERR(svn_client_checkout3(NULL, repos_url, wc_path, &peg_rev, &rev, svn_depth_infinity, FALSE, FALSE, ctx, pool)); - SVN_ERR(svn_client__copy_foreign(svn_path_url_add_component2(repos2_url, "A", - pool), - svn_dirent_join(wc_path, "A-copied", pool), - &peg_rev, &rev, svn_depth_infinity, FALSE, FALSE, - ctx, pool)); - - - SVN_ERR(svn_client__copy_foreign(svn_path_url_add_component2(repos2_url, - "iota", - pool), - svn_dirent_join(wc_path, "iota-copied", pool), - &peg_rev, &rev, svn_depth_infinity, FALSE, FALSE, - ctx, pool)); + SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc, + repos2_url, NULL, &peg_rev, &rev, + ctx, pool)); + + loc->url = svn_path_url_add_component2(repos2_url, "A", pool); + SVN_WC__CALL_WITH_WRITE_LOCK( + svn_client__repos_to_wc_copy_by_editor(NULL /*sleep*/, svn_node_dir, + loc->url, loc->rev, + svn_dirent_join(wc_path, "A-copied", pool), + ra_session, ctx, pool), + ctx->wc_ctx, wc_path, FALSE, pool); + + SVN_ERR(svn_ra_reparent(ra_session, repos2_url, pool)); + loc->url = svn_path_url_add_component2(repos2_url, "iota", pool); + SVN_WC__CALL_WITH_WRITE_LOCK( + svn_client__repos_to_wc_copy_by_editor(NULL /*sleep*/, svn_node_file, + loc->url, loc->rev, + svn_dirent_join(wc_path, "iota-copied", pool), + ra_session, ctx, pool), + ctx->wc_ctx, wc_path, FALSE, pool); return SVN_NO_ERROR; } @@ -787,7 +798,7 @@ test_suggest_mergesources(const svn_test peg_rev.kind = svn_opt_revision_unspecified; - /* Create a filesytem and repository containing the Greek tree. */ + /* Create a filesystem and repository containing the Greek tree. */ SVN_ERR(create_greek_repos(&repos_url, "mergesources", opts, pool)); SVN_ERR(svn_client_create_context(&ctx, pool)); @@ -928,7 +939,7 @@ test_remote_only_status(const svn_test_o SVN_ERR(svn_stream_mark(contentstream, &start, pool)); - /* Create a filesytem and repository containing the Greek tree. */ + /* Create a filesystem and repository containing the Greek tree. */ SVN_ERR(create_greek_repos(&repos_url, "test-remote-only-status", opts, pool)); SVN_ERR(svn_client_create_context(&ctx, pool)); @@ -1096,7 +1107,7 @@ test_copy_pin_externals(const svn_test_o { NULL }, }; - /* Create a filesytem and repository containing the Greek tree. */ + /* Create a filesystem and repository containing the Greek tree. */ SVN_ERR(create_greek_repos(&repos_url, "pin-externals", opts, pool)); wc_path = svn_test_data_path("pin-externals-working-copy", pool); @@ -1323,7 +1334,7 @@ test_copy_pin_externals_select_subtree(c { NULL }, }; - /* Create a filesytem and repository containing the Greek tree. */ + /* Create a filesystem and repository containing the Greek tree. */ SVN_ERR(create_greek_repos(&repos_url, "pin-externals-select-subtree", opts, pool));
