You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2022/01/14 14:01:51 UTC

svn commit: r1897034 [31/37] - in /subversion/branches/multi-wc-format: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ contrib/client-side/ contrib/client-side/svn_load_dirs/ contrib/hook-scripts/ contrib/s...

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));