Modified: subversion/branches/addremove/subversion/tests/cmdline/lock_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/lock_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/lock_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/lock_tests.py Sat 
May 23 14:16:56 2020
@@ -1001,7 +1001,7 @@ def lock_and_exebit1(sbox):
   if (not gamma_stat & mode_r
       or gamma_stat & mode_w
       or not gamma_stat & mode_x):
-    logger.warn("Commiting a file with 'svn:needs-lock, svn:executable'")
+    logger.warn("Committing a file with 'svn:needs-lock, svn:executable'")
     logger.warn("after unlocking modified file's permissions")
     raise svntest.Failure
 
@@ -1065,7 +1065,7 @@ def lock_and_exebit2(sbox):
   if (not gamma_stat & mode_r
       or gamma_stat & mode_w
       or not gamma_stat & mode_x):
-    logger.warn("Commiting a file with 'svn:needs-lock, svn:executable'")
+    logger.warn("Committing a file with 'svn:needs-lock, svn:executable'")
     logger.warn("did not set the file to read-only, executable")
     raise svntest.Failure
 
@@ -1454,7 +1454,7 @@ def lock_path_not_in_head(sbox):
   svntest.actions.run_and_verify_svn(None, [], 'up', '-r1', wc_dir)
   expected_lock_fail_err_re = "svn: warning: W160042: " \
   "(Path .* doesn't exist in HEAD revision)"
-  # Issue #3524 These lock attemtps were triggering an assert over ra_serf:
+  # Issue #3524 These lock attempts were triggering an assert over ra_serf:
   #
   # working_copies\lock_tests-37>svn lock A\D
   # ..\..\..\subversion\libsvn_client\ra.c:275: (apr_err=235000)
@@ -1571,7 +1571,8 @@ def cp_isnt_ro(sbox):
   mu2_path = sbox.ospath('A/mu2')
   mu3_path = sbox.ospath('A/mu3')
   kappa_path = sbox.ospath('kappa')
-  open(kappa_path, 'w').write("This is the file 'kappa'.\n")
+  with open(kappa_path, 'w') as f:
+    f.write("This is the file 'kappa'.\n")
 
   ## added file
   sbox.simple_add('kappa')
@@ -1834,7 +1835,7 @@ def commit_stolen_lock(sbox):
 # When removing directories, the locks of contained files were not
 # correctly removed from the working copy database, thus they later
 # magically reappeared when new files or directories with the same
-# pathes were added.
+# paths were added.
 @Issue(4364)
 def drop_locks_on_parent_deletion(sbox):
   "drop locks when the parent is deleted"
@@ -1855,7 +1856,7 @@ def drop_locks_on_parent_deletion(sbox):
                                         [],
                                         expected_status)
 
-  # now re-add entities to the deleted pathes.
+  # now re-add entities to the deleted paths.
   sbox.simple_mkdir('A/B')
   sbox.simple_add_text('new file replacing old file', 'A/B/lambda')
   sbox.simple_add_text('file replacing former dir', 'A/B/F')
@@ -2251,7 +2252,6 @@ def dav_lock_refresh(sbox):
   if r.status != httplib.OK:
     raise svntest.Failure('Lock refresh failed: %d %s' % (r.status, r.reason))
 
-@SkipUnless(svntest.main.is_ra_type_dav)
 def delete_locked_file_with_percent(sbox):
   "lock and delete a file called 'a %( ) .txt'"
 

Modified: subversion/branches/addremove/subversion/tests/cmdline/log_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/log_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/log_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/log_tests.py Sat May 
23 14:16:56 2020
@@ -1592,7 +1592,7 @@ def merge_sensitive_log_added_mergeinfo_
   # a merge results in added explicit mergeinfo on a path, but that
   # path previously inherited mergeinfo (rather than had no explicit
   # or inherited mergeinfo).  See issue #3235, specifically
-  # http://subversion.tigris.org/issues/show_bug.cgi?id=3235#desc8.
+  # https://issues.apache.org/jira/browse/SVN-3235#desc8.
 
   sbox.build()
   wc_dir = sbox.wc_dir
@@ -1752,7 +1752,7 @@ def merge_sensitive_log_added_mergeinfo_
 def merge_sensitive_log_propmod_merge_inheriting_path(sbox):
   "log -g and simple propmod to merge-inheriting path"
 
-  # Issue #3285 (http://subversion.tigris.org/issues/show_bug.cgi?id=3285)
+  # Issue #3285 (https://issues.apache.org/jira/browse/SVN-3285)
 
   sbox.build()
   wc_dir = sbox.wc_dir
@@ -2094,7 +2094,7 @@ def merge_sensitive_log_copied_path_inhe
   svntest.main.run_svn(None, 'move', old_gamma_path, new_gamma_path)
   sbox.simple_commit(message='Move file')
 
-  # 'svn log -g --stop-on-copy ^/A/C/gamma' hould return *only* r5
+  # 'svn log -g --stop-on-copy ^/A/C/gamma' should return *only* r5
   # Previously this test failed because the change in gamma's inherited
   # mergeinfo between r4 and r5, due to the move, was understood as a merge:
   #
@@ -2166,13 +2166,13 @@ def log_diff(sbox):
                + [ "@@ -1 +1,2 @@\n",
                    " This is the file 'beta'.\n",
                    "+9\n",
-                   "\ No newline at end of file\n",
+                   "\\ No newline at end of file\n",
                  ]
            ]
   r8diff = [ make_diff_header('A2/D/G/rho', 'nonexistent', 'revision 8')
               + [ "@@ -0,0 +1 @@\n",
                   "+88\n",
-                  "\ No newline at end of file\n",
+                  "\\ No newline at end of file\n",
                 ]
            ]
   log_chain = parse_log_output(output, with_diffs=True)
@@ -2779,6 +2779,42 @@ def log_on_deleted_deep(sbox):
                                      '',
                                      '-q', '-c', '1-2')
 
+@XFail()
+@Issue(4711)
+def log_with_merge_history_and_search(sbox):
+  "log --use-merge-history --search"
+  
+  sbox.build()
+
+  # r2: create branch
+  sbox.simple_repo_copy('A', 'A2') # r2
+
+  # r3: mod in trunk
+  sbox.simple_append('A/mu', 'line 2')
+  sbox.simple_commit(message='r3: mod')
+  sbox.simple_update()
+
+  # r4: merge
+  svntest.main.run_svn(None, 'merge', sbox.repo_url + '/A', sbox.ospath('A2'))
+  sbox.simple_commit(message='r4: merge')
+  sbox.simple_update()
+
+  # Helper function
+  def count(haystack, needle):
+    """Return the number of times the string NEEDLE occurs in the string
+    HAYSTACK."""
+    return len(haystack.split(needle)) - 1
+
+  # Check the output is valid
+  # ### Since the test is currently XFail, we only smoke test the output.
+  # ### When fixing this test to PASS, extend this validation.
+  _, output, _ = svntest.main.run_svn(None, 'log', '--xml', '-g',
+                                      '--search', "this will have no matches",
+                                      sbox.ospath('A2'))
+
+  output = '\n'.join(output)
+  if count(output, "<logentry") != count(output, "</logentry"):
+    raise svntest.Failure("Apparently invalid XML in " + repr(output))
 
 ########################################################################
 # Run the tests
@@ -2830,6 +2866,7 @@ test_list = [ None,
               merge_sensitive_log_xml_reverse_merges,
               log_revision_move_copy,
               log_on_deleted_deep,
+              log_with_merge_history_and_search,
              ]
 
 if __name__ == '__main__':

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/merge_authz_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/merge_authz_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/merge_authz_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/merge_authz_tests.py 
Sat May 23 14:16:56 2020
@@ -97,7 +97,7 @@ def mergeinfo_and_skipped_paths(sbox):
   wc_disk, wc_status = set_up_branch(sbox, False, 3)
 
   # Create a restrictive authz where part of the merge source and part
-  # of the target are inaccesible.
+  # of the target are inaccessible.
   write_restrictive_svnserve_conf(sbox.repo_dir)
   write_authz_file(sbox, {"/"               : svntest.main.wc_author +"=rw",
                           # Make a directory in the merge source inaccessible.
@@ -342,7 +342,7 @@ def mergeinfo_and_skipped_paths(sbox):
   # this.
   #
   # Merge -c5 -c8 to the restricted WC's A_COPY_2/D/H.  r5 gets merged first
-  # but is a no-op, r8 get's merged next and is operative so the mergeinfo
+  # but is a no-op, r8 gets merged next and is operative so the mergeinfo
   # should be updated on the merge target to reflect both merges.
   expected_output = wc.State(A_COPY_2_H_path, {
     'omega' : Item(status='U '),
@@ -486,7 +486,7 @@ def mergeinfo_and_skipped_paths(sbox):
 def merge_fails_if_subtree_is_deleted_on_src(sbox):
   "merge fails if subtree is deleted on src"
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2876. ##
+  ## See https://issues.apache.org/jira/browse/SVN-2876. ##
 
   # Create a WC
   sbox.build()
@@ -613,7 +613,7 @@ def reintegrate_fails_if_no_root_access(
   # should be able to reintegrate, regardless of what authorization
   # they have to parents of the source and target.
   #
-  # See http://subversion.tigris.org/issues/show_bug.cgi?id=3242#desc78
+  # See https://issues.apache.org/jira/browse/SVN-3242#desc78
 
   # Some paths we'll care about
   wc_dir = sbox.wc_dir

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/merge_automatic_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/merge_automatic_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- 
subversion/branches/addremove/subversion/tests/cmdline/merge_automatic_tests.py 
(original)
+++ 
subversion/branches/addremove/subversion/tests/cmdline/merge_automatic_tests.py 
Sat May 23 14:16:56 2020
@@ -1163,7 +1163,7 @@ def effective_sync_results_in_reintegrat
 
   # Now try an explicit --reintegrate merge from ^/branch to A.
   # This should work because since the resolution of
-  # http://subversion.tigris.org/issues/show_bug.cgi?id=3577
+  # https://issues.apache.org/jira/browse/SVN-3577
   # if B is *effectively* synced with A, then B can be reintegrated
   # to A.
   sbox.simple_update()

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/merge_reintegrate_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- 
subversion/branches/addremove/subversion/tests/cmdline/merge_reintegrate_tests.py
 (original)
+++ 
subversion/branches/addremove/subversion/tests/cmdline/merge_reintegrate_tests.py
 Sat May 23 14:16:56 2020
@@ -1363,7 +1363,7 @@ def reintegrate_with_subtree_mergeinfo(s
   # how can any prop changes be merged to it?  The answer is that
   # the merge code does some quiet housekeeping, merging gamma_moved's
   # inherited mergeinfo into its incoming mergeinfo, see
-  # http://subversion.tigris.org/issues/show_bug.cgi?id=4309
+  # https://issues.apache.org/jira/browse/SVN-4309
   # This test is not covering issue #4309 so we let the current
   # behavior pass.
   # r17 - B) Synch merge from A to A_COPY

Modified: subversion/branches/addremove/subversion/tests/cmdline/merge_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/merge_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/merge_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/merge_tests.py Sat 
May 23 14:16:56 2020
@@ -697,7 +697,7 @@ def simple_property_merges(sbox):
 def merge_similar_unrelated_trees(sbox):
   "merging similar trees ancestrally unrelated"
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=1249. ##
+  ## See https://issues.apache.org/jira/browse/SVN-1249. ##
 
   sbox.build()
   wc_dir = sbox.wc_dir
@@ -3939,7 +3939,7 @@ def avoid_repeated_merge_on_subtree_with
                                        check_props=True)
 
   # Test for part of Issue #2821, see
-  # http://subversion.tigris.org/issues/show_bug.cgi?id=2821#desc22
+  # https://issues.apache.org/jira/browse/SVN-2821#desc22
   #
   # Revert all local changes.
   svntest.actions.run_and_verify_svn(None, [], 'revert', '-R', wc_dir)
@@ -4794,7 +4794,7 @@ def mergeinfo_inheritance_and_discontinu
   # Merge r2:6 into A_COPY/D
   #
   # A_COPY/D should inherit the mergeinfo '/A:4' from A_COPY
-  # combine it with the discontinous merges performed directly on
+  # combine it with the discontinuous merges performed directly on
   # it (A/D/ 2:3 and A/D 4:6) resulting in '/A/D:3-6'.
   expected_output = wc.State(D_COPY_path, {
     'H/psi'   : Item(status='U '),
@@ -4966,11 +4966,11 @@ def merge_to_switched_path(sbox):
   A_COPY_D_G_rho_path = sbox.ospath('A_COPY/D/G/rho')
 
   expected = svntest.verify.UnorderedOutput(
-         ["A    " + os.path.join(G_COPY_path, "pi") + "\n",
-          "A    " + os.path.join(G_COPY_path, "rho") + "\n",
-          "A    " + os.path.join(G_COPY_path, "tau") + "\n",
-          "Checked out revision 6.\n",
-          "A         " + G_COPY_path + "\n"])
+         ["A         " + G_COPY_path + "\n",
+          "A         " + os.path.join(G_COPY_path, "pi") + "\n",
+          "A         " + os.path.join(G_COPY_path, "rho") + "\n",
+          "A         " + os.path.join(G_COPY_path, "tau") + "\n",
+          ])
 
   # r7 - Copy A/D/G to A/D/G_COPY and commit.
   svntest.actions.run_and_verify_svn(expected, [], 'copy',
@@ -6007,7 +6007,7 @@ def foreign_repos_does_not_update_mergei
 def avoid_reflected_revs(sbox):
   "avoid repeated merges for cyclic merging"
 
-  # See <http://subversion.tigris.org/issues/show_bug.cgi?id=2897>.
+  # See <https://issues.apache.org/jira/browse/SVN-2897>.
   #
   # This test cherry-picks some changes (all of them, in fact) from the
   # parent branch 'A' to the child branch 'A_COPY', and then tries to
@@ -8294,7 +8294,7 @@ def cherry_picking(sbox):
 def propchange_of_subdir_raises_conflict(sbox):
   "merge of propchange on subdir raises conflict"
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2969. ##
+  ## See https://issues.apache.org/jira/browse/SVN-2969. ##
 
   # Create a WC with a single branch
   sbox.build()
@@ -8515,7 +8515,7 @@ def reverse_merge_prop_add_on_child(sbox
 def merge_target_with_non_inheritable_mergeinfo(sbox):
   "merge target with non inheritable mergeinfo"
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2970. ##
+  ## See https://issues.apache.org/jira/browse/SVN-2970. ##
 
   # Create a WC with a single branch
   sbox.build()
@@ -8547,7 +8547,7 @@ def merge_target_with_non_inheritable_me
   expected_output = wc.State(A_COPY_B_path, {
     'lambda' : Item(status='U '),
     })
-  # Issue #3642 http://subversion.tigris.org/issues/show_bug.cgi?id=3642
+  # Issue #3642 https://issues.apache.org/jira/browse/SVN-3642
   #
   # We don't expect A_COPY/B/F to have mergeinfo recorded on it because
   # not only is it unaffected by the merge at depth immediates, it could
@@ -8820,7 +8820,7 @@ def merge_from_renamed_branch_fails_whil
   #Merge r4 from A/RENAMED_C to A/C
   #Merge r2:5 from A/RENAMED_C to A/C <-- This fails tracked via #3032.
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=3032. ##
+  ## See https://issues.apache.org/jira/browse/SVN-3032. ##
 
   # Create a WC with a single branch
   sbox.build()
@@ -9250,7 +9250,7 @@ def new_subtrees_should_not_break_merge(
   # so we expect only subtree merges on A_COPY/D, A_COPY_D_H, and
   # A_COPY/D/H/nu.  The fact that A/D/H/nu doesn't exist at r6 should not cause
   # the merge to fail -- see
-  # http://subversion.tigris.org/issues/show_bug.cgi?id=3067#desc7.
+  # https://issues.apache.org/jira/browse/SVN-3067#desc7.
   expected_output = wc.State(A_COPY_path, {
     'D/H/omega': Item(status='U '),
     })
@@ -10495,7 +10495,7 @@ def reverse_merge_away_all_mergeinfo(sbo
 # Another test for issue #3067: 'subtrees with intersecting mergeinfo,
 # that don't exist at the start of a merge range shouldn't break the
 # merge'.  Specifically see
-# http://subversion.tigris.org/issues/show_bug.cgi?id=3067#desc5
+# https://issues.apache.org/jira/browse/SVN-3067#desc5
 @SkipUnless(server_has_mergeinfo)
 @Issues(3138,3067,4217)
 def dont_merge_revs_into_subtree_that_predate_it(sbox):
@@ -10614,7 +10614,7 @@ def dont_merge_revs_into_subtree_that_pr
   # Cherry harvest all eligible revisions from 'A/D/H' to 'H_COPY'.
   #
   # This is where we see the problem described in
-  # http://subversion.tigris.org/issues/show_bug.cgi?id=3067#desc5.
+  # https://issues.apache.org/jira/browse/SVN-3067#desc5.
   #
   # Use run_and_verify_svn() because run_and_verify_merge*() require
   # explicit revision ranges.
@@ -11786,7 +11786,7 @@ def subtree_source_missing_in_requested_
 # Another test for issue #3067: 'subtrees that don't exist at the start
 # or end of a merge range shouldn't break the merge'
 #
-# See http://subversion.tigris.org/issues/show_bug.cgi?id=3067#desc34
+# See https://issues.apache.org/jira/browse/SVN-3067#desc34
 @Issue(3067)
 @SkipUnless(server_has_mergeinfo)
 def subtrees_with_empty_mergeinfo(sbox):
@@ -12848,6 +12848,39 @@ def natural_history_filtering(sbox):
   #      the revisions on 'trunk' which occurred after 'branch2' was copied as
   #      these are not part of 'branch2's natural history.
 
+  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",
+    ]
+
   sbox.build()
   wc_dir = sbox.wc_dir
 
@@ -12861,68 +12894,16 @@ def natural_history_filtering(sbox):
 
   # r7: Make a second 'branch': Copy A to A_COPY_2
   expected = svntest.verify.UnorderedOutput(
-    ["A    " + os.path.join(A_COPY_2_path, "B") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "B", "lambda") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "B", "E") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "B", "E", "alpha") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "B", "E", "beta") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "B", "F") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "mu") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "C") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "D") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "D", "gamma") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "D", "G") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "D", "G", "pi") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "D", "G", "rho") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "D", "G", "tau") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "D", "H") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "D", "H", "chi") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "D", "H", "omega") + "\n",
-     "A    " + os.path.join(A_COPY_2_path, "D", "H", "psi") + "\n",
-     "Checked out revision 6.\n",
-     "A         " + A_COPY_2_path + "\n"])
-  wc_status.add({
-    "A_COPY_2" + "/B"         : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/B/lambda"  : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/B/E"       : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/B/E/alpha" : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/B/E/beta"  : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/B/F"       : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/mu"        : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/C"         : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/D"         : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/D/gamma"   : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/D/G"       : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/D/G/pi"    : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/D/G/rho"   : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/D/G/tau"   : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/D/H"       : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/D/H/chi"   : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/D/H/omega" : Item(status='  ', wc_rev=7),
-    "A_COPY_2" + "/D/H/psi"   : Item(status='  ', wc_rev=7),
-    "A_COPY_2"                : Item(status='  ', wc_rev=7),
-    })
-  wc_disk.add({
-    "A_COPY_2"                : Item(),
-    "A_COPY_2" + '/B'         : Item(),
-    "A_COPY_2" + '/B/lambda'  : Item("This is the file 'lambda'.\n"),
-    "A_COPY_2" + '/B/E'       : Item(),
-    "A_COPY_2" + '/B/E/alpha' : Item("This is the file 'alpha'.\n"),
-    "A_COPY_2" + '/B/E/beta'  : Item("New content"),
-    "A_COPY_2" + '/B/F'       : Item(),
-    "A_COPY_2" + '/mu'        : Item("This is the file 'mu'.\n"),
-    "A_COPY_2" + '/C'         : Item(),
-    "A_COPY_2" + '/D'         : Item(),
-    "A_COPY_2" + '/D/gamma'   : Item("This is the file 'gamma'.\n"),
-    "A_COPY_2" + '/D/G'       : Item(),
-    "A_COPY_2" + '/D/G/pi'    : Item("This is the file 'pi'.\n"),
-    "A_COPY_2" + '/D/G/rho'   : Item("New content"),
-    "A_COPY_2" + '/D/G/tau'   : Item("This is the file 'tau'.\n"),
-    "A_COPY_2" + '/D/H'       : Item(),
-    "A_COPY_2" + '/D/H/chi'   : Item("New content"),
-    "A_COPY_2" + '/D/H/omega' : Item("This is the file 'omega'.\n"),
-    "A_COPY_2" + '/D/H/psi'   : Item("New content"),
-    })
+    [ "A         " + sbox.ospath(path_join("A_COPY_2", p)) + "\n"
+      for p in A_paths ])
+  wc_status.add(
+    { path_join("A_COPY_2", p) : Item(status='  ', wc_rev=7)
+      for p in A_paths })
+  wc_disk.add(
+    { path_join("A_COPY_2", p) :
+        Item("New content") if p in ['B/E/beta', 'D/G/rho', 'D/H/chi', 
'D/H/psi']
+                            else greek_file_item(p)
+      for p in A_paths })
   svntest.actions.run_and_verify_svn(expected, [], 'copy',
                                      sbox.repo_url + "/A",
                                      A_COPY_2_path)
@@ -13305,7 +13286,7 @@ def no_self_referential_filtering_on_add
   # how can any prop changes be merged to it?  The answer is that
   # the merge code does some quiet housekeeping, merging C_MOVED's
   # inherited mergeinfo into its incoming mergeinfo, see
-  # http://subversion.tigris.org/issues/show_bug.cgi?id=4309
+  # https://issues.apache.org/jira/browse/SVN-4309
   # This test is not covering issue #4309 so we let the current
   # behavior pass.
   expected_mergeinfo_output = wc.State(A_COPY_2_path, {
@@ -13374,13 +13355,13 @@ def no_self_referential_filtering_on_add
 
 #----------------------------------------------------------------------
 # Test for issue #3324
-# http://subversion.tigris.org/issues/show_bug.cgi?id=3324
+# https://issues.apache.org/jira/browse/SVN-3324
 @Issue(3324)
 @SkipUnless(server_has_mergeinfo)
 def merge_range_prior_to_rename_source_existence(sbox):
   "merge prior to rename src existence still dels src"
 
-  # Replicate a merge bug found while synching up a feature branch on the
+  # Replicate a merge bug found while syncing up a feature branch on the
   # Subversion repository with trunk.  See r874121 of
   # http://svn.apache.org/repos/asf/subversion/branches/ignore-mergeinfo, in 
which
   # a move was merged to the target, but the delete half of the move
@@ -13881,7 +13862,7 @@ def dont_merge_gaps_in_history(sbox):
 
 #----------------------------------------------------------------------
 # Test for issue #3432 'Merge can record mergeinfo from natural history
-# gaps'.  See http://subversion.tigris.org/issues/show_bug.cgi?id=3432
+# gaps'.  See https://issues.apache.org/jira/browse/SVN-3432
 @Issue(3432)
 @SkipUnless(server_has_mergeinfo)
 def handle_gaps_in_implicit_mergeinfo(sbox):
@@ -15122,7 +15103,7 @@ def foreign_repos_del_and_props(sbox):
 
 #----------------------------------------------------------------------
 # Test for issue #3642 'immediate depth merges don't create proper subtree
-# mergeinfo'. See http://subversion.tigris.org/issues/show_bug.cgi?id=3642
+# mergeinfo'. See https://issues.apache.org/jira/browse/SVN-3642
 @Issue(3642)
 def immediate_depth_merge_creates_minimal_subtree_mergeinfo(sbox):
   "no spurious mergeinfo from immediate depth merges"
@@ -15817,7 +15798,7 @@ def subtree_merges_inherit_invalid_worki
 
 #----------------------------------------------------------------------
 # Test for issue #3686 'executable flag not correctly set on merge'
-# See http://subversion.tigris.org/issues/show_bug.cgi?id=3686
+# See https://issues.apache.org/jira/browse/SVN-3686
 @Issue(3686)
 @SkipUnless(server_has_mergeinfo)
 @SkipUnless(svntest.main.is_posix_os)

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/merge_tree_conflict_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/merge_tree_conflict_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- 
subversion/branches/addremove/subversion/tests/cmdline/merge_tree_conflict_tests.py
 (original)
+++ 
subversion/branches/addremove/subversion/tests/cmdline/merge_tree_conflict_tests.py
 Sat May 23 14:16:56 2020
@@ -540,7 +540,7 @@ def merge_add_over_versioned_file_confli
 def mergeinfo_recording_in_skipped_merge(sbox):
   "mergeinfo recording in skipped merge"
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2829. ##
+  ## See https://issues.apache.org/jira/browse/SVN-2829. ##
 
   # Create a WC with a single branch
   sbox.build()
@@ -705,7 +705,7 @@ def del_differing_file(sbox):
 def tree_conflicts_and_obstructions(sbox):
   "tree conflicts and obstructions"
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=3146. ##
+  ## See https://issues.apache.org/jira/browse/SVN-3146. ##
 
   sbox.build()
   wc_dir = sbox.wc_dir

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/mergeinfo_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/mergeinfo_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/mergeinfo_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/mergeinfo_tests.py 
Sat May 23 14:16:56 2020
@@ -196,7 +196,7 @@ def mergeinfo_on_unknown_url(sbox):
 
 # Test for issue #3126 'svn mergeinfo shows too few or too many
 # eligible revisions'.  Specifically
-# http://subversion.tigris.org/issues/show_bug.cgi?id=3126#desc5.
+# https://issues.apache.org/jira/browse/SVN-3126#desc5.
 @SkipUnless(server_has_mergeinfo)
 @Issue(3126)
 def non_inheritable_mergeinfo(sbox):

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/mod_authz_svn_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/mod_authz_svn_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- 
subversion/branches/addremove/subversion/tests/cmdline/mod_authz_svn_tests.py 
(original)
+++ 
subversion/branches/addremove/subversion/tests/cmdline/mod_authz_svn_tests.py 
Sat May 23 14:16:56 2020
@@ -167,7 +167,7 @@ def anon(sbox):
 
   write_authz_file(sbox)
 
-  anon_tests = ( 
+  anon_tests = (
                  { 'path': '', 'status': 301 },
                  { 'path': '/', 'status': 200 },
                  { 'path': '/repos', 'status': 301 },

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/mod_dav_svn_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/mod_dav_svn_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/mod_dav_svn_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/mod_dav_svn_tests.py 
Sat May 23 14:16:56 2020
@@ -102,7 +102,7 @@ def compare_xml_elem(a, b):
   # iteration.
   def sortcmp(x, y):
     return compare_xml_elem(x, y)[0]
- 
+
   a_children = sorted(list(a), key=functools.cmp_to_key(sortcmp))
   b_children = sorted(list(b), key=functools.cmp_to_key(sortcmp))
 
@@ -640,6 +640,53 @@ def propfind_propname(sbox):
   actual_response = r.read()
   verify_xml_response(expected_response, actual_response)
 
+@SkipUnless(svntest.main.is_ra_type_dav)
+def last_modified_header(sbox):
+  "verify 'Last-Modified' header on 'external' GETs"
+
+  sbox.build(create_wc=False, read_only=True)
+
+  headers = {
+    'Authorization': 'Basic ' + 
base64.b64encode(b'jconstant:rayjandom').decode(),
+  }
+
+  h = svntest.main.create_http_connection(sbox.repo_url)
+
+  # GET /repos/iota
+  # Expect to see a Last-Modified header.
+  h.request('GET', sbox.repo_url + '/iota', None, headers)
+  r = h.getresponse()
+  if r.status != httplib.OK:
+    raise svntest.Failure('Request failed: %d %s' % (r.status, r.reason))
+  svntest.verify.compare_and_display_lines(None, 'Last-Modified',
+                                           svntest.verify.RegexOutput('.+'),
+                                           r.getheader('Last-Modified'))
+  r.read()
+
+  # HEAD /repos/iota
+  # Expect to see a Last-Modified header.
+  h.request('HEAD', sbox.repo_url + '/iota', None, headers)
+  r = h.getresponse()
+  if r.status != httplib.OK:
+    raise svntest.Failure('Request failed: %d %s' % (r.status, r.reason))
+  svntest.verify.compare_and_display_lines(None, 'Last-Modified',
+                                           svntest.verify.RegexOutput('.+'),
+                                           r.getheader('Last-Modified'))
+  r.read()
+
+  # GET /repos/!svn/rvr/1/iota
+  # There should not be a Last-Modified header (it's costly and not useful,
+  # see r1724790)
+  h.request('GET', sbox.repo_url + '/!svn/rvr/1/iota', None, headers)
+  r = h.getresponse()
+  if r.status != httplib.OK:
+    raise svntest.Failure('Request failed: %d %s' % (r.status, r.reason))
+  last_modified = r.getheader('Last-Modified')
+  if last_modified:
+    raise svntest.Failure('Unexpected Last-Modified header: %s' % 
last_modified)
+  r.read()
+
+
 ########################################################################
 # Run the tests
 
@@ -652,6 +699,7 @@ test_list = [ None,
               propfind_404,
               propfind_allprop,
               propfind_propname,
+              last_modified_header,
              ]
 serial_only = True
 

Propchange: 
subversion/branches/addremove/subversion/tests/cmdline/mod_dav_svn_tests.py
------------------------------------------------------------------------------
    svn:executable = *

Modified: subversion/branches/addremove/subversion/tests/cmdline/move_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/move_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/move_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/move_tests.py Sat 
May 23 14:16:56 2020
@@ -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"
@@ -1261,7 +1261,7 @@ def nested_replaces(sbox):
     '   D /A/B/C/Y',
   ]))
   expected_output = svntest.verify.UnorderedRegexListOutput(escaped
-                    + [ '^-', '^r2', '^-', '^Changed paths:', ])
+                    + [ '^--*', '^r2.*', '^--*', '^Changed paths:', ])
   svntest.actions.run_and_verify_svn(expected_output, [],
                                      'log', '-qvr2', repo_url)
 
@@ -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/addremove/subversion/tests/cmdline/patch_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/patch_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/patch_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/patch_tests.py Sat 
May 23 14:16:56 2020
@@ -4246,7 +4246,7 @@ def patch_git_with_index_line(sbox):
     "+++ b/src/tools/ConsoleRunner/hi.txt\n",
     "@@ -0,0 +1 @@\n",
     "+hihihihihihi\n",
-    "\ No newline at end of file\n",
+    "\\ No newline at end of file\n",
   ]
 
   svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
@@ -4413,7 +4413,7 @@ def patch_replace_dir_with_file_and_vv(s
     "+++ A/D\t(working copy)\n",
     "@@ -0,0 +1 @@\n",
     "+New file\n",
-    "\ No newline at end of file\n",
+    "\\ No newline at end of file\n",
 
   # Add iota as directory
     "Index: iota\n",
@@ -4426,7 +4426,7 @@ def patch_replace_dir_with_file_and_vv(s
     "Added: k\n",
     "## -0,0 +1 ##\n",
     "+v\n",
-    "\ No newline at end of property\n",
+    "\\ No newline at end of property\n",
   ]))
 
   expected_output = wc.State(wc_dir, {
@@ -6541,7 +6541,7 @@ def patch_prop_madness(sbox):
                                        "Property: del_n\n"
                                        "## -1,1 +0,0 ##\n"
                                        "-no-eol\n"
-                                       "\ No newline at end of property\n"
+                                       "\\ No newline at end of property\n"
                                        % (sbox.path('iota'),
                                           sbox.path('iota'))),
   })
@@ -7791,6 +7791,225 @@ def patch_merge(sbox):
                                        expected_disk, None,
                                        expected_skip)
 
+def patch_mergeinfo_in_regular_prop_format(sbox):
+  "patch mergeinfo in regular prop format"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  strip_count = wc_dir.count(os.path.sep)+1
+
+  sbox.simple_copy('A/B/E', 'E')
+  sbox.simple_append('A/B/E/alpha', 'extra\nlines\n')
+  sbox.simple_commit()
+
+  sbox.simple_propset('a', 'A', 'E') # 'a' < 'svn:mergeinfo'
+  sbox.simple_propset('z', 'Z', 'E') # 'z' > 'svn:mergeinfo'
+
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'merge', '^/A/B/E', sbox.ospath('E'))
+  # Rename 'svn:mergeinfo' to 'svn_mergeinfo' so that 'diff' doesn't
+  # pretty-print it; then rename it back before we run it through 'patch'.
+  # (Alternatively, we could disable pretty-printing when we implement a
+  # command-line switch to do so.)
+  mergeinfo_value = sbox.simple_propget('svn:mergeinfo', 'E')
+  sbox.simple_propdel('svn:mergeinfo', 'E')
+  sbox.simple_propset('svn_mergeinfo', mergeinfo_value, 'E')
+
+  _, diff, _ = svntest.actions.run_and_verify_svn(None, [],
+                                                  'diff', wc_dir)
+  diff = re.sub('svn_mergeinfo', 'svn:mergeinfo', ''.join(diff))
+
+  sbox.simple_revert('E', 'E/alpha')
+
+  patch = sbox.get_tempname('recurse.patch')
+  svntest.main.file_write(patch, diff, mode='wb')
+
+  expected_output = wc.State(wc_dir, {
+    'E'                 : Item(status=' U'),
+    'E/alpha'           : Item(status='U '),
+  })
+  expected_skip = wc.State(wc_dir, {})
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'E'                 : Item(status=' M', wc_rev='2'),
+    'E/alpha'           : Item(status='M ', wc_rev='2'),
+    'E/beta'            : Item(status='  ', wc_rev='2'),
+  })
+  expected_status.tweak('A/B/E/alpha', wc_rev=2)
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/B/E/alpha', contents="This is the file 
'alpha'.\nextra\nlines\n")
+  expected_disk.add({
+    'E'                 : Item(props={'a': 'A',
+                                      # here is the correctly patched mergeinfo
+                                      'svn:mergeinfo': '/A/B/E:2',
+                                      'z': 'Z'}),
+    'E/beta'            : Item(contents="This is the file 'beta'.\n"),
+    'E/alpha'           : Item(contents="This is the file 
'alpha'.\nextra\nlines\n"),
+  })
+
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], True, True,
+                                       '--strip', strip_count)
+
+@XFail()
+def patch_empty_prop(sbox):
+  "patch empty prop"
+  sbox.build(empty=True)
+  was_cwd = os.getcwd()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
+  wc_dir = ''
+
+  # start with a file with an empty prop
+  sbox.simple_add_text('', 'f')
+  sbox.simple_propset('p', '', 'f')
+  sbox.simple_commit()
+
+  # a patch that modifies the prop to a non-empty value
+  unidiff_patch = [
+    "--- f\n",
+    "+++ f\n",
+    "\n",
+    "Property changes on: f\n",
+    "___________________________________________________________________\n",
+    "Modified: p\n",
+    "## -0,0 +1 ##\n",
+    "+v\n",
+  ]
+
+  trailing_eol = False
+  if trailing_eol:
+    value = "v\n"
+  else:
+    value = "v"
+    unidiff_patch += ['\ No newline at end of property\n']
+
+  patch_file_path = sbox.get_tempname('my.patch')
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch), 'wb')
+
+  expected_output = [
+    ' U        %s\n' % sbox.ospath('f'),
+  ]
+
+  expected_disk = svntest.wc.State(wc_dir, {})
+  expected_disk.add({'f': Item(props={'p' : value})})
+  expected_status = svntest.wc.State(wc_dir, {})
+  expected_status.add({'f': Item(status=' M')})
+  expected_skip = wc.State('', { })
+
+  svntest.actions.run_and_verify_patch(wc_dir, patch_file_path,
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       False, # dry-run
+                                       )
+
+  svntest.actions.check_prop('p', wc_dir, [value.encode()])
+
+  os.chdir(was_cwd)
+
+# Test that 'patch' can apply a patch that modifies properties on the root
+# of a WC and/or the root of a repository. This test uses the format of
+# diff output produced by 'svn diff --git' in svn <= 1.10.0: paths are given
+# as 'a/' and 'b/' and 'Property changes on: ' (with no following '.').
+#
+# See dev@ email thread 2018-07-09 from Dmitry Pavlenko,
+# '[PATCH] can't "svn patch" working copy root if the patch is in --git 
format',
+# 
https://lists.apache.org/thread.html/d1d9811ca36fac8cabb9339634840099e22811beac505be2ea59f19f@%3Cdev.subversion.apache.org%3E
+@XFail()
+def patch_git_wcroot(sbox):
+  "patch working copy root"
+  sbox.build(empty=True)
+  wc_dir = sbox.wc_dir
+
+  git_patch = [ "Index: .\n",
+                
"===================================================================\n",
+                "diff --git a/ b/\n",
+                "--- a/        (revision 0)\n",
+                "+++ b/        (working copy)\n",
+                "Property changes on: \n",
+                
"___________________________________________________________________\n",
+                "Added: p\n",
+                "## -0,0 +1 ##\n",
+                "+v\n",
+                "\\ No newline at end of property\n",
+  ]
+  value = 'v'
+
+  patch_file_path = sbox.get_tempname('my.patch')
+  svntest.main.file_write(patch_file_path, ''.join(git_patch), 'wb')
+
+  expected_output = wc.State(wc_dir, {
+    '.'                 : Item(status=' U'),
+  })
+  expected_disk = svntest.wc.State('', {})
+  expected_disk.add({'': Item(props={'p' : value })})
+  expected_status = svntest.wc.State(wc_dir, {})
+  expected_status.add({'': Item(status=' M', wc_rev='0')})
+  expected_skip = wc.State('', { })
+
+  svntest.actions.run_and_verify_patch(wc_dir, patch_file_path,
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       True, # check-props
+                                       False, # dry-run
+                                       )
+
+  svntest.actions.check_prop('p', wc_dir, [value.encode()])
+
+# Test that 'patch' can apply a patch that modifies properties on the root
+# of a WC and/or the root of a repository. This test performs a round-trip
+# through 'diff --git' and 'patch' rather than assuming any particular
+# variant of the patch format.
+#
+# See dev@ email thread 2018-07-09 from Dmitry Pavlenko,
+# '[PATCH] can't "svn patch" working copy root if the patch is in --git 
format',
+# 
https://lists.apache.org/thread.html/d1d9811ca36fac8cabb9339634840099e22811beac505be2ea59f19f@%3Cdev.subversion.apache.org%3E
+@XFail()
+def patch_git_wcroot2(sbox):
+  "patch working copy root"
+  sbox.build(empty=True)
+  wc_dir = sbox.wc_dir
+
+  value = 'v'
+  sbox.simple_propset('p', value, '')
+  exit_code, git_patch, err_output = svntest.main.run_svn(None, 'diff',
+                                                          '--git', wc_dir)
+
+  patch_file_path = sbox.get_tempname('my.patch')
+  svntest.main.file_write(patch_file_path, ''.join(git_patch), 'wb')
+
+  sbox.simple_revert('')
+
+  expected_output = wc.State(wc_dir, {
+    '.'                 : Item(status=' U'),
+  })
+  expected_disk = svntest.wc.State('', {})
+  expected_disk.add({'': Item(props={'p' : value })})
+  expected_status = svntest.wc.State(wc_dir, {})
+  expected_status.add({'': Item(status=' M', wc_rev='0')})
+  expected_skip = wc.State('', { })
+
+  svntest.actions.run_and_verify_patch(wc_dir, patch_file_path,
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       True, # check-props
+                                       False, # dry-run
+                                       )
+
+  svntest.actions.check_prop('p', wc_dir, [value.encode()])
+
 ########################################################################
 #Run the tests
 
@@ -7874,6 +8093,10 @@ test_list = [ None,
               missing_trailing_context,
               patch_missed_trail,
               patch_merge,
+              patch_mergeinfo_in_regular_prop_format,
+              patch_empty_prop,
+              patch_git_wcroot,
+              patch_git_wcroot2,
             ]
 
 if __name__ == '__main__':

Modified: subversion/branches/addremove/subversion/tests/cmdline/prop_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/prop_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/prop_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/prop_tests.py Sat 
May 23 14:16:56 2020
@@ -1768,7 +1768,7 @@ def rm_of_replaced_file(sbox):
                                                    'proplist', '-v',
                                                    mu_path + '@base')
   expected_output = svntest.verify.UnorderedRegexListOutput([
-      'Properties on',
+      'Properties on.*',
       '  yellow',
       '    submarine',
       '  orange',

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/relocate_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/relocate_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/relocate_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/relocate_tests.py 
Sat May 23 14:16:56 2020
@@ -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/addremove/subversion/tests/cmdline/revert_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/revert_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/revert_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/revert_tests.py Sat 
May 23 14:16:56 2020
@@ -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)
@@ -1550,20 +1500,18 @@ def revert_with_unversioned_targets(sbox
   psi_contents = "modified psi\n"
 
   # touch delta
-  open(delta_path, 'w').write(delta_contents)
+  with open(delta_path, 'w') as f:
+    f.write(delta_contents)
 
   # modify chi psi
-  open(chi_path, 'w').write(chi_contents)
-  open(psi_path, 'w').write(psi_contents)
+  with open(chi_path, 'w') as f:
+    f.write(chi_contents)
+  with open(psi_path, 'w') as f:
+    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)
@@ -1582,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):
@@ -1638,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
@@ -1680,6 +1655,7 @@ test_list = [ None,
               revert_nonexistent,
               revert_obstructing_wc,
               revert_moved_dir_partial,
+              revert_remove_added,
              ]
 
 if __name__ == '__main__':

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/special_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/special_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/special_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/special_tests.py Sat 
May 23 14:16:56 2020
@@ -535,7 +535,7 @@ def diff_symlink_to_dir(sbox):
     "+++ link\t(working copy)\n",
     "@@ -0,0 +1 @@\n",
     "+link A/D\n",
-    "\ No newline at end of file\n",
+    "\\ No newline at end of file\n",
     "\n",
     "Property changes on: link\n",
     "___________________________________________________________________\n",
@@ -730,7 +730,8 @@ def unrelated_changed_special_status(sbo
 
   os.chdir(os.path.join(sbox.wc_dir, 'A/D/H'))
 
-  open('chi', 'a').write('random local mod')
+  with open('chi', 'a') as f:
+    f.write('random local mod')
   os.unlink('psi')
   os.symlink('omega', 'psi') # omega is versioned!
   svntest.main.run_svn(None, 'changelist', 'chi cl', 'chi')

Modified: subversion/branches/addremove/subversion/tests/cmdline/stat_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/stat_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/stat_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/stat_tests.py Sat 
May 23 14:16:56 2020
@@ -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,
@@ -1949,7 +1949,8 @@ def modified_modulo_translation(sbox):
   sbox.simple_commit()
 
   # CRLF it.
-  open(sbox.ospath('iota'), 'wb').write("This is the file 'iota'.\r\n")
+  with open(sbox.ospath('iota'), 'wb') as f:
+    f.write("This is the file 'iota'.\r\n")
 
   # Run status.  Expect some output.
   # TODO: decide how such files should show in the output; whether they

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/svnadmin_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnadmin_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svnadmin_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svnadmin_tests.py 
Sat May 23 14:16:56 2020
@@ -53,6 +53,24 @@ Wimp = svntest.testcase.Wimp_deco
 SkipDumpLoadCrossCheck = svntest.testcase.SkipDumpLoadCrossCheck_deco
 Item = svntest.wc.StateItem
 
+def read_rep_cache(repo_dir):
+  """Return the rep-cache contents as a dict {hash: (rev, index, ...)}.
+  """
+  db_path = os.path.join(repo_dir, 'db', 'rep-cache.db')
+  db1 = svntest.sqlite3.connect(db_path)
+  schema1 = db1.execute("pragma user_version").fetchone()[0]
+  # Can't test newer rep-cache schemas with an old built-in SQLite; see the
+  # documentation of STMT_CREATE_SCHEMA_V2 in 
../../libsvn_fs_fs/rep-cache-db.sql
+  if schema1 >= 2 and svntest.sqlite3.sqlite_version_info < (3, 8, 2):
+    raise svntest.Failure("Can't read rep-cache schema %d using old "
+                          "Python-SQLite version %s < (3,8,2)" %
+                           (schema1,
+                            svntest.sqlite3.sqlite_version_info))
+
+  content = { row[0]: row[1:] for row in
+              db1.execute("select * from rep_cache") }
+  return content
+
 def check_hotcopy_bdb(src, dst):
   "Verify that the SRC BDB repository has been correctly copied to DST."
   ### TODO: This function should be extended to verify all hotcopied files,
@@ -129,6 +147,15 @@ def check_hotcopy_fsfs_fsx(src, dst):
         if src_file == 'rep-cache.db':
           db1 = svntest.sqlite3.connect(src_path)
           db2 = svntest.sqlite3.connect(dst_path)
+          schema1 = db1.execute("pragma user_version").fetchone()[0]
+          schema2 = db2.execute("pragma user_version").fetchone()[0]
+          if schema1 != schema2:
+            raise svntest.Failure("rep-cache schema differs: '%s' vs. '%s'"
+                                  % (schema1, schema2))
+          # Can't test newer rep-cache schemas with an old built-in SQLite.
+          if schema1 >= 2 and svntest.sqlite3.sqlite_version_info < (3, 8, 2):
+            continue
+
           rows1 = []
           rows2 = []
           for row in db1.execute("select * from rep_cache order by hash"):
@@ -247,7 +274,8 @@ def patch_format(repo_dir, shard_size):
 
   new_contents = b"\n".join(processed_lines)
   os.chmod(format_path, svntest.main.S_ALL_RW)
-  open(format_path, 'wb').write(new_contents)
+  with open(format_path, 'wb') as f:
+    f.write(new_contents)
 
 def is_sharded(repo_dir):
   """Return whether the FSFS repository REPO_DIR is sharded."""
@@ -746,7 +774,7 @@ def verify_windows_paths_in_repos(sbox):
                  "* Verified revision 0.\n",
                  "* Verified revision 1.\n",
                  "* Verified revision 2.\n"], output)
-  elif svntest.main.fs_has_rep_sharing():
+  elif svntest.main.fs_has_rep_sharing() and not svntest.main.is_fs_type_bdb():
     svntest.verify.compare_and_display_lines(
       "Error while running 'svnadmin verify'.",
       'STDOUT', ["* Verifying repository metadata ...\n",
@@ -768,9 +796,13 @@ def verify_windows_paths_in_repos(sbox):
 def fsfs_file(repo_dir, kind, rev):
   if svntest.main.options.server_minor_version >= 5:
     if svntest.main.options.fsfs_sharding is None:
+      if svntest.main.is_fs_type_fsx():
+        rev = 'r' + rev
       return os.path.join(repo_dir, 'db', kind, '0', rev)
     else:
       shard = int(rev) // svntest.main.options.fsfs_sharding
+      if svntest.main.is_fs_type_fsx():
+        rev = 'r' + rev
       path = os.path.join(repo_dir, 'db', kind, str(shard), rev)
 
       if svntest.main.options.fsfs_packing is None or kind == 'revprops':
@@ -790,6 +822,10 @@ def fsfs_file(repo_dir, kind, rev):
 def verify_incremental_fsfs(sbox):
   """svnadmin verify detects corruption dump can't"""
 
+  if svntest.main.options.fsfs_version is not None and \
+     svntest.main.options.fsfs_version not in [4, 6]:
+    raise svntest.Skip("Unsupported prepackaged repository version")
+
   # setup a repo with a directory 'c:hi'
   # use physical addressing as this is hard to provoke with logical addressing
   sbox.build(create_wc = False,
@@ -807,7 +843,7 @@ def verify_incremental_fsfs(sbox):
   # the listing itself is valid.
   r2 = fsfs_file(sbox.repo_dir, 'revs', '2')
   if r2.endswith('pack'):
-    raise svntest.Skip('Test doesn\'t handle packed revisions')
+    raise svntest.Skip("Test doesn't handle packed revisions")
 
   fp = open(r2, 'wb')
   fp.write(b"""id: 0-2.0.r2/0
@@ -1030,7 +1066,7 @@ def fsfs_recover_old_db_current(sbox):
 def load_with_parent_dir(sbox):
   "'svnadmin load --parent-dir' reparents mergeinfo"
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2983. ##
+  ## See https://issues.apache.org/jira/browse/SVN-2983. ##
   sbox.build(empty=True)
 
   dumpfile_location = os.path.join(os.path.dirname(sys.argv[0]),
@@ -1121,7 +1157,7 @@ def set_uuid(sbox):
 def reflect_dropped_renumbered_revs(sbox):
   "reflect dropped renumbered revs in svn:mergeinfo"
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=3020. ##
+  ## See https://issues.apache.org/jira/browse/SVN-3020. ##
 
   sbox.build(empty=True)
 
@@ -1313,7 +1349,7 @@ def verify_with_invalid_revprops(sbox):
 #   2) Dump 'SOURCE-REPOS' in a series of incremental dumps and load
 #      each of them to 'TARGET-REPOS'.
 #
-# See http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc13
+# See https://issues.apache.org/jira/browse/SVN-3020#desc13
 @Issue(3020)
 def dont_drop_valid_mergeinfo_during_incremental_loads(sbox):
   "don't filter mergeinfo revs from incremental dump"
@@ -1499,7 +1535,7 @@ def dont_drop_valid_mergeinfo_during_inc
 
   # Check the resulting mergeinfo.  We expect the exact same results
   # as Part 3.
-  # See http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc16.
+  # See https://issues.apache.org/jira/browse/SVN-3020#desc16.
   svntest.actions.run_and_verify_svn(expected_output, [],
                                      'propget', 'svn:mergeinfo', '-R',
                                      sbox.repo_url)
@@ -1510,7 +1546,7 @@ def dont_drop_valid_mergeinfo_during_inc
 def hotcopy_symlink(sbox):
   "'svnadmin hotcopy' replicates symlink"
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2591. ##
+  ## See https://issues.apache.org/jira/browse/SVN-2591. ##
 
   # Create a repository.
   sbox.build(create_wc=False, empty=True)
@@ -1616,9 +1652,9 @@ text
   sbox.build(empty=True)
 
   # Try to load the dumpstream, expecting a failure (because of mixed EOLs).
-  exp_err = svntest.verify.RegexListOutput(['svnadmin: E125005',
-                                            'svnadmin: E125005',
-                                            'svnadmin: E125017'],
+  exp_err = svntest.verify.RegexListOutput(['svnadmin: E125005:.*',
+                                            'svnadmin: E125005:.*',
+                                            'svnadmin: E125017:.*'],
                                            match_all=False)
   load_and_verify_dumpstream(sbox, [], exp_err, dumpfile_revisions,
                              False, dump_str, '--ignore-uuid')
@@ -1654,6 +1690,10 @@ text
 def verify_non_utf8_paths(sbox):
   "svnadmin verify with non-UTF-8 paths"
 
+  if svntest.main.options.fsfs_version is not None and \
+     svntest.main.options.fsfs_version not in [4, 6]:
+    raise svntest.Skip("Unsupported prepackaged repository version")
+
   dumpfile = clean_dumpfile()
 
   # Corruption only possible in physically addressed revisions created
@@ -1682,14 +1722,11 @@ def verify_non_utf8_paths(sbox):
     elif line == b"text: 1 340 44 32 a6be7b4cf075fd39e6a99eb69a31232b\n":
       # phys, deltified directories: fix up the representation checksum
       fp_new.write(b"text: 1 340 44 32 f2e93e73272cac0f18fccf16f224eb93\n")
-    elif line == b"text: 1 6 31 31 90f306aa9bfd72f456072076a2bd94f7\n":
-      # log addressing: fix up the representation checksum
-      fp_new.write(b"text: 1 6 31 31 db2d4a0bad5dff0aea9a288dec02f1fb\n")
     elif line == b"cpath: /A\n":
       # 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)
@@ -1746,10 +1783,10 @@ def test_lslocks_and_rmlocks(sbox):
   def expected_output_list(path):
     return [
       "Path: " + path,
-      "UUID Token: opaquelocktoken",
+      "UUID Token: opaquelocktoken:.*",
       "Owner: jrandom",
-      "Created:",
-      "Expires:",
+      "Created:.*",
+      "Expires:.*",
       "Comment \(1 line\):",
       "Locking files",
       "\n", # empty line
@@ -1800,7 +1837,7 @@ def test_lslocks_and_rmlocks(sbox):
 def load_ranges(sbox):
   "'svnadmin load --revision X:Y'"
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=3734. ##
+  ## See https://issues.apache.org/jira/browse/SVN-3734. ##
   sbox.build(empty=True)
 
   dumpfile_location = os.path.join(os.path.dirname(sys.argv[0]),
@@ -2151,7 +2188,7 @@ def verify_keep_going(sbox):
                                                         sbox.repo_dir)
 
   if (svntest.main.is_fs_log_addressing()):
-    exp_out = svntest.verify.RegexListOutput([".*Verifying metadata at 
revision 0"])
+    exp_out = svntest.verify.RegexListOutput([".*Verifying metadata at 
revision 0.*"])
   else:
     exp_out = svntest.verify.RegexListOutput([".*Verified revision 0.",
                                               ".*Verified revision 1."])
@@ -2520,7 +2557,7 @@ def verify_denormalized_names(sbox):
     ".*Verified revision 7."]
 
   # The BDB backend doesn't do global metadata verification.
-  if (svntest.main.fs_has_rep_sharing()):
+  if (svntest.main.fs_has_rep_sharing() and not svntest.main.is_fs_type_bdb()):
     expected_output_regex_list.insert(0, ".*Verifying repository metadata.*")
 
   if svntest.main.options.fsfs_sharding is not None:
@@ -2842,10 +2879,7 @@ def verify_quickly(sbox):
   "verify quickly using metadata"
 
   sbox.build(create_wc = False)
-  if svntest.main.is_fs_type_fsfs():
-    rev_file = open(fsfs_file(sbox.repo_dir, 'revs', '1'), 'r+b')
-  else:
-    rev_file = open(fsfs_file(sbox.repo_dir, 'revs', 'r1'), 'r+b')
+  rev_file = open(fsfs_file(sbox.repo_dir, 'revs', '1'), 'r+b')
 
   # set new contents
   rev_file.seek(8)
@@ -3143,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.
 
@@ -3186,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',
@@ -3351,6 +3385,7 @@ def dump_no_op_change(sbox):
                                      sbox2.repo_url + '/bar')
 
 @XFail(svntest.main.is_fs_type_bdb)
+@XFail(svntest.main.is_fs_type_fsx)
 @Issue(4623)
 def dump_no_op_prop_change(sbox):
   "svnadmin dump with no-op property change"
@@ -3443,7 +3478,8 @@ def load_from_file(sbox):
   sbox.build(empty=True)
 
   file = sbox.get_tempname()
-  open(file, 'wb').writelines(clean_dumpfile())
+  with open(file, 'wb') as f:
+    f.writelines(clean_dumpfile())
   svntest.actions.run_and_verify_svnadmin2(None, [],
                                            0, 'load', '--file', file,
                                            '--ignore-uuid', sbox.repo_dir)
@@ -3747,7 +3783,7 @@ def dump_exclude_all_rev_changes(sbox):
   # Check log. Revision properties ('svn:log' etc.) should be empty for r2.
   expected_output = svntest.verify.RegexListOutput([
     '-+\\n',
-    'r3\ |\ jrandom\ |\ .*\ |\ 1\ line\\n',
+    'r3 | jrandom | .* | 1 line\\n',
     re.escape('Changed paths:'),
     re.escape('   A /r3a'),
     re.escape('   A /r3b'),
@@ -3759,7 +3795,7 @@ def dump_exclude_all_rev_changes(sbox):
     '',
     '',
     '-+\\n',
-    'r1\ |\ jrandom\ |\ .*\ |\ 1\ line\\n',
+    'r1 | jrandom | .* | 1 line\\n',
     re.escape('Changed paths:'),
     re.escape('   A /r1a'),
     re.escape('   A /r1b'),
@@ -3786,6 +3822,243 @@ def dump_invalid_filtering_option(sbox):
                                           '--include', '/A/B/E',
                                           sbox.repo_dir)
 
+@Issue(4725)
+def load_issue4725(sbox):
+  """load that triggers issue 4725"""
+
+  sbox.build(empty=True)
+
+  sbox.simple_mkdir('subversion')
+  sbox.simple_commit()
+  sbox.simple_mkdir('subversion/trunk')
+  sbox.simple_mkdir('subversion/branches')
+  sbox.simple_commit()
+  sbox.simple_mkdir('subversion/trunk/src')
+  sbox.simple_commit()
+
+  _, dump, _ = svntest.actions.run_and_verify_svnadmin(None, [],
+                                                       'dump', '-q',
+                                                       sbox.repo_dir)
+
+  sbox2 = sbox.clone_dependent()
+  sbox2.build(create_wc=False, empty=True)
+  load_and_verify_dumpstream(sbox2, None, [], None, False, dump, '-M100')
+
+@Issue(4767)
+def dump_no_canonicalize_svndate(sbox):
+  "svnadmin dump shouldn't canonicalize svn:date"
+
+  sbox.build(create_wc=False, empty=True)
+  svntest.actions.enable_revprop_changes(sbox.repo_dir)
+
+  # set svn:date in a non-canonical format (not six decimal places)
+  propval = "2015-01-01T00:00:00.0Z"
+  svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [],
+                                     "propset", "--revprop", "-r0", "svn:date",
+                                     propval,
+                                     sbox.repo_url)
+
+  dump_lines = svntest.actions.run_and_verify_dump(sbox.repo_dir)
+  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
+     true/false.
+  """
+  # Remember the initial rep cache content.
+  rep_cache_r1 = read_rep_cache(sbox.repo_dir)
+  #print '\n'.join([h + ": " + repr(ref) for h, ref in rep_cache_r1.items()])
+
+  # Commit one new rep and check the rep-cache is extended.
+  sbox.simple_append('iota', 'New line.\n')
+  sbox.simple_commit()
+  rep_cache_r2 = read_rep_cache(sbox.repo_dir)
+  if not (len(rep_cache_r2) == len(rep_cache_r1) + 1):
+    raise svntest.Failure
+
+  fsfs_conf = svntest.main.get_fsfs_conf_file_path(sbox.repo_dir)
+  svntest.main.file_append(fsfs_conf,
+                           # Add a newline in case the existing file doesn't
+                           # end with one.
+                           "\n"
+                           "[rep-sharing]\n"
+                           "enable-rep-sharing = %s\n"
+                           % (('true' if enable_rep_sharing else 'false'),))
+
+  # Break r2 in such a way that 'recover' will discard it
+  head_rev_path = fsfs_file(sbox.repo_dir, 'revs', '2')
+  os.remove(head_rev_path)
+  current_path = os.path.join(sbox.repo_dir, 'db', 'current')
+  svntest.main.file_write(current_path, '1\n')
+
+  # Recover back to r1.
+  svntest.actions.run_and_verify_svnadmin(None, [],
+                                          "recover", sbox.repo_dir)
+  svntest.actions.run_and_verify_svnlook(['1\n'], [], 'youngest',
+                                         sbox.repo_dir)
+
+  # Check the rep-cache is pruned.
+  rep_cache_recovered = read_rep_cache(sbox.repo_dir)
+  if not (rep_cache_recovered == rep_cache_r1):
+    raise svntest.Failure
+
+@Issue(4077)
+@SkipUnless(svntest.main.is_fs_type_fsfs)
+@SkipUnless(svntest.main.python_sqlite_can_read_without_rowid)
+def recover_prunes_rep_cache_when_enabled(sbox):
+  "recover prunes rep cache when enabled"
+  sbox.build()
+
+  check_recover_prunes_rep_cache(sbox, enable_rep_sharing=True)
+
+@Issue(4077)
+@SkipUnless(svntest.main.is_fs_type_fsfs)
+@SkipUnless(svntest.main.python_sqlite_can_read_without_rowid)
+def recover_prunes_rep_cache_when_disabled(sbox):
+  "recover prunes rep cache when disabled"
+  sbox.build()
+
+  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
 
@@ -3858,7 +4131,14 @@ test_list = [ None,
               dump_exclude_by_pattern,
               dump_include_by_pattern,
               dump_exclude_all_rev_changes,
-              dump_invalid_filtering_option
+              dump_invalid_filtering_option,
+              load_issue4725,
+              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__':


Reply via email to