You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/08/11 18:43:31 UTC

svn commit: r984468 [22/25] - in /subversion/branches/ignore-mergeinfo: ./ build/ build/generator/ build/generator/templates/ notes/ notes/tree-conflicts/ notes/wc-ng/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subvers...

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_authz_tests.py?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_authz_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_authz_tests.py Wed Aug 11 16:43:22 2010
@@ -442,7 +442,6 @@ def mergeinfo_and_skipped_paths(sbox):
     })
   expected_skip = wc.State(A_COPY_2_H_path, {})
   saved_cwd = os.getcwd()
-  #raise svntest.Failure("PTB")
   svntest.actions.run_and_verify_merge(A_COPY_2_H_path, '7', '9',
                                        sbox.repo_url + '/A/D/H', None,
                                        expected_output,
@@ -641,7 +640,7 @@ def reintegrate_fails_if_no_root_access(
     'mu'           : Item(status='U '),
     })
   expected_mergeinfo_output = wc.State(A_path, {
-    '' : Item(status=' G'),
+    '' : Item(status=' U'),
     })
   expected_elision_output = wc.State(A_path, {
     })

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_reintegrate_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_reintegrate_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_reintegrate_tests.py Wed Aug 11 16:43:22 2010
@@ -171,7 +171,7 @@ def basic_reintegrate(sbox):
     'mu'           : Item(status='U '),
     })
   expected_mergeinfo_output = wc.State(A_path, {
-    '' : Item(status=' G'),
+    '' : Item(status=' U'),
     })
   expected_elision_output = wc.State(A_path, {
     })
@@ -229,7 +229,7 @@ def basic_reintegrate(sbox):
     'mu'           : Item(status='U '),
     })
   expected_mergeinfo_output = wc.State(A_MOVED_path, {
-    '' : Item(status=' G'),
+    '' : Item(status=' U'),
     })
   expected_elision_output = wc.State(A_MOVED_path, {
     })
@@ -452,8 +452,8 @@ def reintegrate_with_rename(sbox):
     'D/G/tauprime' : Item(status='A '),
     })
   expected_mergeinfo_output = wc.State(A_path, {
-    ''             : Item(status=' G'),
-    'D/G/tauprime' : Item(status=' G'),
+    ''             : Item(status=' U'),
+    'D/G/tauprime' : Item(status=' U'),
     })
   expected_elision_output = wc.State(A_path, {
     })
@@ -1114,9 +1114,9 @@ def reintegrate_with_subtree_mergeinfo(s
     'D'         : Item(status=' U'),
     })
   expected_mergeinfo_output = wc.State(A_path, {
-    ''   : Item(status=' G'),
+    ''   : Item(status=' U'),
     'mu' : Item(status=' G'),
-    'D'  : Item(status=' G'),
+    'D'  : Item(status=' U'),
     })
   expected_elision_output = wc.State(A_path, {
     })
@@ -1350,9 +1350,9 @@ def reintegrate_with_subtree_mergeinfo(s
     'D/gamma_moved' : Item(status=' U'),
     })
   expected_mergeinfo_output = wc.State(A_path, {
-    ''              : Item(status=' G'),
+    ''              : Item(status=' U'),
     'mu'            : Item(status=' G'),
-    'D'             : Item(status=' G'),
+    'D'             : Item(status=' U'),
     'D/gamma_moved' : Item(status=' G'),
     })
   expected_elision_output = wc.State(A_path, {
@@ -1397,8 +1397,21 @@ def reintegrate_with_subtree_mergeinfo(s
     'D/G/pi'        : Item("This is the file 'pi'.\n"),
     'D/G/rho'       : Item("New content"),
     'D/G/tau'       : Item("This is the file 'tau'.\n"),
+    # Why do we expect mergeinfo of '/A_COPY/D/G/tauprime:2-9' on
+    # A/D/G/tauprime?  Because this --reintegrate merge is effectively a
+    # two URL merge of %URL%/A@9 %URL%/A_COPY@9 to 'A'.  Since %URL%/A@9 and
+    # %URL%/A_COPY@9 have a common ancestor in %URL%/A@1 we expect this 2-URL
+    # merge to record mergeinfo and a component of that mergeinfo describes
+    # the merge of %URL%/A_COPY@2 to %URL%/A_COPY@9.  We see that above on
+    # A.  But we also get it on A's subtrees with explicit mergeinfo, namely
+    # A/D/G/tauprime.  Now I know what you are thinking, "'A_COPY/D/G/tauprime'
+    # doesn't even exist until r9!", and you are quite right.  But this
+    # inheritance of bogus mergeinfo is a known problem, see
+    # http://subversion.tigris.org/issues/show_bug.cgi?id=3157#desc8,
+    # and is not what this test is about, so we won't fail because of it.
     'D/gamma_moved' : Item(
-      "Even newer content", props={SVN_PROP_MERGEINFO :
+      "Even newer content", props={SVN_PROP_MERGEINFO : 
+                                   '/A/D/gamma_moved:2-15\n'
                                    '/A_COPY/D/gamma_moved:2-19\n'
                                    '/A_COPY_3/D/gamma:9'}),
     'D/H'           : Item(),
@@ -1514,7 +1527,7 @@ def multiple_reintegrates_from_the_same_
     'B/E/beta' : Item(status='U '),
     })
   expected_mergeinfo_output = wc.State(A_path, {
-    '' : Item(status=' G'),
+    '' : Item(status=' U'),
     })
   expected_elision_output = wc.State(A_path, {
     })
@@ -1983,7 +1996,7 @@ def added_subtrees_with_mergeinfo_break_
     'C/nu'     : Item(status=' U'),
     })
   expected_mergeinfo_output = wc.State(A_path, {
-    ''     : Item(status=' G'),
+    ''     : Item(status=' U'),
     'C/nu' : Item(status=' G'),
     })
   expected_elision_output = wc.State(A_path, {
@@ -2149,36 +2162,15 @@ def two_URL_merge_removes_valid_mergefin
   # of mergeinfo showing that the history of A_COPY is now part of A_COPY_2,
   # i.e. '/A_COPY:2-11'
   #
-  # This test is currently marked as XFail because this is not what happens.
-  # Well, actually, all the above *does* happen, but as discussed in
-  # http://svn.haxx.se/dev/archive-2010-05/0292.shtml, the merge removes some
-  # of the valid mergeinfo on A_COPY_2 that describes the sync merge made in
-  # r9:
-  #
-  #   >svn pl -vR A_COPY_2
-  #   Properties on 'A_COPY_2':
-  #     svn:mergeinfo
-  #       /A:9-10
-  #       /A_COPY:2-11
-  #
-  #   >svn diff --depth empty A_COPY_2
-  #
-  #   Property changes on: A_COPY_2
-  #   ___________________________________________________________________
-  #   Modified: svn:mergeinfo
-  #      Reverse-merged /A:r3-8
-  #      Merged /A_COPY:r2-11
-  #
-  # '/A:r3-8' represents valid, operative changes merged from A to A_COPY_2!
-  # If this merge was committed, subsequent merges would try to reapply the
-  # diff, possibly leading to spurious conflicts.
+  # Before issue #3648 was fixed this test failed because the valid mergeinfo
+  # '/A:r3-8' on A_COPY_2 was removed by the merge.
   svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
   expected_output = wc.State(A_COPY_2_path, {
     ''         : Item(status=' G'),
     'B/lambda' : Item(status='U '),
     })
   expected_mergeinfo_output = wc.State(A_COPY_2_path, {
-    '' : Item(status=' G'),
+    '' : Item(status=' U'),
     })
   expected_elision_output = wc.State(A_COPY_2_path, {
     })
@@ -2262,7 +2254,7 @@ test_list = [ None,
                          server_has_mergeinfo),
               reintegrate_with_self_referential_mergeinfo,
               added_subtrees_with_mergeinfo_break_reintegrate,
-              XFail(two_URL_merge_removes_valid_mergefino_from_target),
+              two_URL_merge_removes_valid_mergefino_from_target,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tests.py?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tests.py Wed Aug 11 16:43:22 2010
@@ -1325,8 +1325,12 @@ def merge_in_new_file_and_diff(sbox):
 
   # Finally, run diff.
   expected_output = [
+    "Index: " + url_branch_path + "\n",
+    "===================================================================\n",
+    "--- "+ url_branch_path + "\t(revision 2)\n",
+    "+++ "+ url_branch_path + "\t(working copy)\n",
     "\n",
-    "Property changes on: " + branch_path + "\n",
+    "Property changes on: " + url_branch_path + "\n",
     "___________________________________________________________________\n",
     "Added: " + SVN_PROP_MERGEINFO + "\n",
     "   Merged /A/B/E:r2-3\n",
@@ -6784,6 +6788,8 @@ def merge_loses_mergeinfo(sbox):
     '' : Item(status=' U'),
     })
   expected_disk = wc.State('', {'J': Item()})
+  if svntest.main.wc_is_singledb(wc_dir):
+    expected_disk.remove('J')
   expected_status = wc.State(A_C_wc_dir,
                              { ''    : Item(wc_rev=4, status=' M'),
                                'J'   : Item(wc_rev=4, status='D ')
@@ -6805,6 +6811,8 @@ def merge_loses_mergeinfo(sbox):
     'J'       : Item(),
     ''        : Item(props={SVN_PROP_MERGEINFO : '/A/B:3'}),
     })
+  if svntest.main.wc_is_singledb(wc_dir):
+    expected_disk.remove('J')
   expected_status = wc.State(A_C_wc_dir,
                              { ''    : Item(wc_rev=4, status=' M'),
                                'K'   : Item(status='A ',
@@ -13771,6 +13779,8 @@ def no_self_referential_filtering_on_add
     'D/H/psi'   : Item("New content"),
     'D/H/omega' : Item("New content"),
     })
+  if svntest.main.wc_is_singledb(wc_dir):
+    expected_A_COPY_2_disk.remove('C')
   expected_A_COPY_2_skip = wc.State(A_COPY_2_path, { })
   svntest.actions.run_and_verify_merge(A_COPY_2_path, None, None,
                                        sbox.repo_url + '/A', None,
@@ -15243,6 +15253,8 @@ def committed_case_only_move_and_revert(
     })
   expected_disk.tweak('', props={SVN_PROP_MERGEINFO : '/A:3,5'})
   expected_disk.add({'c' : Item()})
+  if svntest.main.wc_is_singledb(wc_dir):
+    expected_disk.remove('C')
   expected_status.tweak('MU', status='  ', wc_rev=4, copied=None)
   expected_status.remove('mu')
   expected_status.tweak('C', status='D ')
@@ -15617,6 +15629,131 @@ def record_only_merge_creates_self_refer
                                        None, None, None, None, None, 1, 1,
                                        '--record-only')
 
+#----------------------------------------------------------------------
+# Test for issue #3657 'phantom svn:eol-style changes cause spurious merge
+# text conflicts'.
+def copy_causes_phantom_eol_conflict(sbox):
+  "other prop changes cause phantom eol conflict"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # Some paths we'll care about
+  mu_path                = os.path.join(wc_dir, "A", "mu")
+  A_path                 = os.path.join(wc_dir, "A")
+  A_branch_path          = os.path.join(wc_dir, "A-branch")
+  A_branch_backport_path = os.path.join(wc_dir, "A-branch-backport")
+  mu_path                = os.path.join(wc_dir, "A", "mu")
+  mu2_path               = os.path.join(wc_dir, "A", "mu2")
+  mu_backport_path       = os.path.join(wc_dir, "A-branch-backport", "mu")
+  
+  # r2 - Set the 'native' svn:eol-style on A/mu:
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ps', 'svn:eol-style', 'native',
+                                     mu_path)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ci', '-m', 'Set native eol-style',
+                                     wc_dir)
+    
+  # r3 - Branch 'A' to 'A-branch':
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'copy', A_path, A_branch_path)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ci', '-m', 'Create a branch of A',
+                                     wc_dir)
+
+  # r4 - Make a text mod and prop mod to 'A/mu':
+  svntest.main.file_write(mu_path, "The new mu!\n")
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ps', 'prop-name', 'prop-val', mu_path)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ci', '-m', 'Edit a file', wc_dir)
+
+  # Now merge r4 from 'A' to 'A-branch'.
+  #
+  # Previously this failed over ra_neon and ra_serf on Windows:
+  #
+  #   >svn merge ^^/A A-branch -c4
+  #   Conflict discovered in 'A-branch/mu'.
+  #   Select: (p) postpone, (df) diff-full, (e) edit,
+  #           (mc) mine-conflict, (tc) theirs-conflict,
+  #           (s) show all options: p
+  #   --- Merging r4 into 'A-branch':
+  #   CU   A-branch\mu
+  #   --- Recording mergeinfo for merge of r4 into 'A-branch':
+  #    U   A-branch
+  #   Summary of conflicts:
+  #     Text conflicts: 1
+  #
+  # The conflict was on the whole file as it appeared there was an eol-style
+  # change to native, when in fact no such change was present in r7.
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  expected_output = wc.State(A_branch_path, {
+    'mu' : Item(status='UU'),
+    })
+  expected_mergeinfo_output = wc.State(A_branch_path, {
+    ''   : Item(status=' U'),
+    })
+  expected_elision_output = wc.State(A_branch_path, {})
+  expected_status = wc.State(A_branch_path, {
+    ''          : Item(status=' M'),
+    'B'         : Item(status='  '),
+    'mu'        : Item(status='MM'),
+    'B/E'       : Item(status='  '),
+    'B/E/alpha' : Item(status='  '),
+    'B/E/beta'  : Item(status='  '),
+    'B/lambda'  : Item(status='  '),
+    'B/F'       : Item(status='  '),
+    'C'         : Item(status='  '),
+    'D'         : Item(status='  '),
+    'D/G'       : Item(status='  '),
+    'D/G/pi'    : Item(status='  '),
+    'D/G/rho'   : Item(status='  '),
+    'D/G/tau'   : Item(status='  '),
+    'D/gamma'   : Item(status='  '),
+    'D/H'       : Item(status='  '),
+    'D/H/chi'   : Item(status='  '),
+    'D/H/psi'   : Item(status='  '),
+    'D/H/omega' : Item(status='  '),
+    })
+  expected_status.tweak(wc_rev=4)
+  expected_disk = wc.State('', {
+    ''          : Item(props={SVN_PROP_MERGEINFO :
+                              '/A:4'}),
+    'B'         : Item(),
+    'mu'        : Item("The new mu!\n",
+                       props={'prop-name' : 'prop-val',
+                              'svn:eol-style' : 'native'}),
+    'B/E'       : Item(),
+    'B/E/alpha' : Item("This is the file 'alpha'.\n"),
+    'B/E/beta'  : Item("This is the file 'beta'.\n"),
+    'B/lambda'  : Item("This is the file 'lambda'.\n"),
+    'B/F'       : Item(),
+    'C'         : Item(),
+    'D'         : Item(),
+    'D/G'       : Item(),
+    'D/G/pi'    : Item("This is the file 'pi'.\n"),
+    'D/G/rho'   : Item("This is the file 'rho'.\n"),
+    'D/G/tau'   : Item("This is the file 'tau'.\n"),
+    'D/gamma'   : Item("This is the file 'gamma'.\n"),
+    'D/H'       : Item(),
+    'D/H/chi'   : Item("This is the file 'chi'.\n"),
+    'D/H/psi'   : Item("This is the file 'psi'.\n"),
+    'D/H/omega' : Item("This is the file 'omega'.\n"),
+    })
+  expected_skip = wc.State(A_branch_path, {})
+  svntest.actions.run_and_verify_merge(A_branch_path, 3, 4,
+                                       sbox.repo_url + '/A',
+                                       None,
+                                       expected_output,
+                                       expected_mergeinfo_output,
+                                       expected_elision_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, None, None, None, None, 1, 1)
+  
 ########################################################################
 # Run the tests
 
@@ -15803,6 +15940,7 @@ test_list = [ None,
               foreign_repos_del_and_props,
               immediate_depth_merge_creates_minimal_subtree_mergeinfo,
               record_only_merge_creates_self_referential_mergeinfo,
+              copy_causes_phantom_eol_conflict,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tree_conflict_tests.py?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tree_conflict_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tree_conflict_tests.py Wed Aug 11 16:43:22 2010
@@ -1703,7 +1703,6 @@ def merge_replace_causes_tree_conflict(s
     "--- Recording mergeinfo for merge between repository URLs into '" \
     + A + "':\n",
     ' U   ' + A + '\n',
-    ' G   ' + A + '\n',
     'Summary of conflicts:\n',
     '  Tree conflicts: 4\n',
   ])

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/patch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/patch_tests.py?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/patch_tests.py Wed Aug 11 16:43:22 2010
@@ -935,9 +935,10 @@ def patch_add_new_dir(sbox):
   patch_file_path = make_patch_path(sbox)
 
   # The first diff is adding 'new' with two missing dirs. The second is
-  # adding 'new' with one missing dir to a 'A' that is locally deleted
-  # (should be skipped). The third is adding 'new' with a directory that
-  # is unversioned (should be skipped as well).
+  # adding 'new' with one missing dir to a 'A/B/E' that is locally deleted
+  # (should be skipped). The third is adding 'new' to 'A/C' that is locally
+  # deleted (should be skipped too). The fourth is adding 'new' with a
+  # directory that is unversioned (should be skipped as well).
   unidiff_patch = [
     "Index: new\n",
     "===================================================================\n",
@@ -947,8 +948,14 @@ def patch_add_new_dir(sbox):
     "+new\n",
     "Index: new\n",
     "===================================================================\n",
-    "--- A/C/Y/new\t(revision 0)\n",
-    "+++ A/C/Y/new\t(revision 0)\n",
+    "--- A/B/E/Y/new\t(revision 0)\n",
+    "+++ A/B/E/Y/new\t(revision 0)\n",
+    "@@ -0,0 +1 @@\n",
+    "+new\n",
+    "Index: new\n",
+    "===================================================================\n",
+    "--- A/C/new\t(revision 0)\n",
+    "+++ A/C/new\t(revision 0)\n",
     "@@ -0,0 +1 @@\n",
     "+new\n",
     "Index: new\n",
@@ -960,37 +967,55 @@ def patch_add_new_dir(sbox):
   ]
 
   C_path = os.path.join(wc_dir, 'A', 'C')
+  E_path = os.path.join(wc_dir, 'A', 'B', 'E')
   svntest.actions.run_and_verify_svn("Deleting C failed", None, [],
                                      'rm', C_path)
+  svntest.actions.run_and_verify_svn("Deleting E failed", None, [],
+                                     'rm', E_path)
   svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
 
-  A_C_Y_new_path = os.path.join(wc_dir, 'A', 'C', 'Y', 'new')
+  A_B_E_Y_new_path = os.path.join(wc_dir, 'A', 'B', 'E', 'Y', 'new')
+  A_C_new_path = os.path.join(wc_dir, 'A', 'C', 'new')
   A_Z_new_path = os.path.join(wc_dir, 'A', 'Z', 'new')
   expected_output = [
     'A         %s\n' % os.path.join(wc_dir, 'X'),
     'A         %s\n' % os.path.join(wc_dir, 'X', 'Y'),
     'A         %s\n' % os.path.join(wc_dir, 'X', 'Y', 'new'),
-    'Skipped missing target: \'%s\'\n' % A_C_Y_new_path,
+    'Skipped missing target: \'%s\'\n' % A_B_E_Y_new_path,
+    'Skipped missing target: \'%s\'\n' % A_C_new_path,
     'Skipped missing target: \'%s\'\n' % A_Z_new_path,
     'Summary of conflicts:\n',
-    '  Skipped paths: 2\n',
+    '  Skipped paths: 3\n',
   ]
 
   # Create the unversioned obstructing directory
   os.mkdir(os.path.dirname(A_Z_new_path))
 
   expected_disk = svntest.main.greek_state.copy()
-  expected_disk.add({'X/Y/new': Item(contents='new\n')})
-  expected_disk.add({'A/Z': Item()})
+  expected_disk.add({
+           'X/Y/new'   : Item(contents='new\n'),
+           'A/Z'       : Item()
+  })
+  expected_disk.remove('A/B/E/alpha')
+  expected_disk.remove('A/B/E/beta')
+  if svntest.main.wc_is_singledb(wc_dir):
+    expected_disk.remove('A/B/E')
+    expected_disk.remove('A/C')
 
   expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
-  expected_status.add({'X' : Item(status='A ', wc_rev=0)})
-  expected_status.add({'X/Y' : Item(status='A ', wc_rev=0)})
-  expected_status.add({'X/Y/new' : Item(status='A ', wc_rev=0)})
-  expected_status.add({'A/C' : Item(status='D ', wc_rev=1)})
-
-  expected_skip = wc.State('', {A_C_Y_new_path : Item(),
-                                A_Z_new_path : Item() })
+  expected_status.add({
+           'X'         : Item(status='A ', wc_rev=0),
+           'X/Y'       : Item(status='A ', wc_rev=0),
+           'X/Y/new'   : Item(status='A ', wc_rev=0),
+           'A/B/E'     : Item(status='D ', wc_rev=1),
+           'A/B/E/alpha': Item(status='D ', wc_rev=1),
+           'A/B/E/beta': Item(status='D ', wc_rev=1),
+           'A/C'       : Item(status='D ', wc_rev=1),
+  })
+
+  expected_skip = wc.State('', {A_Z_new_path : Item(),
+                                A_B_E_Y_new_path : Item(),
+                                A_C_new_path : Item()})
 
   svntest.actions.run_and_verify_patch(wc_dir,
                                        os.path.abspath(patch_file_path),
@@ -1081,6 +1106,10 @@ def patch_remove_empty_dirs(sbox):
   expected_disk.remove('A/B/lambda')
   expected_disk.remove('A/B/E/alpha')
   expected_disk.remove('A/B/E/beta')
+  if svntest.main.wc_is_singledb(wc_dir):
+    expected_disk.remove('A/B/E')
+    expected_disk.remove('A/B/F')
+    expected_disk.remove('A/B')
 
   expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
   expected_status.add({'A/D/H/chi' : Item(status='! ', wc_rev=1)})
@@ -2162,6 +2191,790 @@ def patch_no_eol_at_eof(sbox):
                                        1, # check-props
                                        1) # dry-run
 
+def patch_with_properties(sbox):
+  "patch with properties"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  patch_file_path = make_patch_path(sbox)
+  iota_path = os.path.join(wc_dir, 'iota')
+
+  modified_prop_contents = "This is the property 'modified'.\n"
+  deleted_prop_contents = "This is the property 'deleted'.\n"
+
+  # Set iota prop contents
+  svntest.main.run_svn(None, 'propset', 'modified', modified_prop_contents,
+                       iota_path)
+  svntest.main.run_svn(None, 'propset', 'deleted', deleted_prop_contents,
+                       iota_path)
+  expected_output = svntest.wc.State(wc_dir, {
+      'iota'    : Item(verb='Sending'),
+      })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('iota', wc_rev=2)
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, None, wc_dir)
+  # Apply patch
+
+  unidiff_patch = [
+    "Index: iota\n",
+    "===================================================================\n",
+    "--- iota\t(revision 1)\n",
+    "+++ iota\t(working copy)\n",
+    "Property changes on: iota\n",
+    "-------------------------------------------------------------------\n",
+    "Modified: modified\n",
+    "## -1 +1 ##\n",
+    "-This is the property 'modified'.\n",
+    "+The property 'modified' has changed.\n",
+    "Added: added\n",
+    "## -0,0 +1 ##\n",
+    "+This is the property 'added'.\n",
+    "Deleted: deleted\n",
+    "## -1 +0,0 ##\n",
+    "-This is the property 'deleted'.\n",
+  ]
+
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  modified_prop_contents = "The property 'modified' has changed.\n"
+  added_prop_contents = "This is the property 'added'.\n"
+
+  expected_output = [
+    ' U        %s\n' % os.path.join(wc_dir, 'iota'),
+  ]
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('iota', props={'modified' : modified_prop_contents,
+                                     'added' : added_prop_contents})
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('iota', status=' M', wc_rev='2')
+
+  expected_skip = wc.State('', { })
+
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       1) # dry-run
+
+def patch_same_twice(sbox):
+  "apply the same patch twice"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  patch_file_path = make_patch_path(sbox)
+  mu_path = os.path.join(wc_dir, 'A', 'mu')
+  beta_path = os.path.join(wc_dir, 'A', 'B', 'E', 'beta')
+
+  mu_contents = [
+    "Dear internet user,\n",
+    "\n",
+    "We wish to congratulate you over your email success in our computer\n",
+    "Balloting. This is a Millennium Scientific Electronic Computer Draw\n",
+    "in which email addresses were used. All participants were selected\n",
+    "through a computer ballot system drawn from over 100,000 company\n",
+    "and 50,000,000 individual email addresses from all over the world.\n",
+    "\n",
+    "Your email address drew and have won the sum of  750,000 Euros\n",
+    "( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    "file with\n",
+    "    REFERENCE NUMBER: ESP/WIN/008/05/10/MA;\n",
+    "    WINNING NUMBER : 14-17-24-34-37-45-16\n",
+    "    BATCH NUMBERS :\n",
+    "    EULO/1007/444/606/08;\n",
+    "    SERIAL NUMBER: 45327\n",
+    "and PROMOTION DATE: 13th June. 2009\n",
+    "\n",
+    "To claim your winning prize, you are to contact the appointed\n",
+    "agent below as soon as possible for the immediate release of your\n",
+    "winnings with the below details.\n",
+    "\n",
+    "Again, we wish to congratulate you over your email success in our\n"
+    "computer Balloting.\n"
+  ]
+
+  # Set mu contents
+  svntest.main.file_write(mu_path, ''.join(mu_contents))
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/mu'       : Item(verb='Sending'),
+    })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/mu', wc_rev=2)
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, None, wc_dir)
+
+  # Apply patch
+
+  unidiff_patch = [
+    "Index: A/D/gamma\n",
+    "===================================================================\n",
+    "--- A/D/gamma\t(revision 1)\n",
+    "+++ A/D/gamma\t(working copy)\n",
+    "@@ -1 +1 @@\n",
+    "-This is the file 'gamma'.\n",
+    "+It is the file 'gamma'.\n",
+    "Index: iota\n",
+    "===================================================================\n",
+    "--- iota\t(revision 1)\n",
+    "+++ iota\t(working copy)\n",
+    "@@ -1 +1,2 @@\n",
+    " This is the file 'iota'.\n",
+    "+Some more bytes\n",
+    "\n",
+    "Index: new\n",
+    "===================================================================\n",
+    "--- new	(revision 0)\n",
+    "+++ new	(revision 0)\n",
+    "@@ -0,0 +1 @@\n",
+    "+new\n",
+    "\n",
+    "--- A/mu.orig	2009-06-24 15:23:55.000000000 +0100\n",
+    "+++ A/mu	2009-06-24 15:21:23.000000000 +0100\n",
+    "@@ -6,6 +6,9 @@\n",
+    " through a computer ballot system drawn from over 100,000 company\n",
+    " and 50,000,000 individual email addresses from all over the world.\n",
+    " \n",
+    "+It is a promotional program aimed at encouraging internet users;\n",
+    "+therefore you do not need to buy ticket to enter for it.\n",
+    "+\n",
+    " Your email address drew and have won the sum of  750,000 Euros\n",
+    " ( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    " file with\n",
+    "@@ -14,11 +17,8 @@\n",
+    "     BATCH NUMBERS :\n",
+    "     EULO/1007/444/606/08;\n",
+    "     SERIAL NUMBER: 45327\n",
+    "-and PROMOTION DATE: 13th June. 2009\n",
+    "+and PROMOTION DATE: 14th June. 2009\n",
+    " \n",
+    " To claim your winning prize, you are to contact the appointed\n",
+    " agent below as soon as possible for the immediate release of your\n",
+    " winnings with the below details.\n",
+    "-\n",
+    "-Again, we wish to congratulate you over your email success in our\n",
+    "-computer Balloting.\n",
+    "Index: A/B/E/beta\n",
+    "===================================================================\n",
+    "--- A/B/E/beta	(revision 1)\n",
+    "+++ A/B/E/beta	(working copy)\n",
+    "@@ -1 +0,0 @@\n",
+    "-This is the file 'beta'.\n",
+  ]
+
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  gamma_contents = "It is the file 'gamma'.\n"
+  iota_contents = "This is the file 'iota'.\nSome more bytes\n"
+  new_contents = "new\n"
+  mu_contents = [
+    "Dear internet user,\n",
+    "\n",
+    "We wish to congratulate you over your email success in our computer\n",
+    "Balloting. This is a Millennium Scientific Electronic Computer Draw\n",
+    "in which email addresses were used. All participants were selected\n",
+    "through a computer ballot system drawn from over 100,000 company\n",
+    "and 50,000,000 individual email addresses from all over the world.\n",
+    "\n",
+    "It is a promotional program aimed at encouraging internet users;\n",
+    "therefore you do not need to buy ticket to enter for it.\n",
+    "\n",
+    "Your email address drew and have won the sum of  750,000 Euros\n",
+    "( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    "file with\n",
+    "    REFERENCE NUMBER: ESP/WIN/008/05/10/MA;\n",
+    "    WINNING NUMBER : 14-17-24-34-37-45-16\n",
+    "    BATCH NUMBERS :\n",
+    "    EULO/1007/444/606/08;\n",
+    "    SERIAL NUMBER: 45327\n",
+    "and PROMOTION DATE: 14th June. 2009\n",
+    "\n",
+    "To claim your winning prize, you are to contact the appointed\n",
+    "agent below as soon as possible for the immediate release of your\n",
+    "winnings with the below details.\n",
+  ]
+
+  expected_output = [
+    'U         %s\n' % os.path.join(wc_dir, 'A', 'D', 'gamma'),
+    'U         %s\n' % os.path.join(wc_dir, 'iota'),
+    'A         %s\n' % os.path.join(wc_dir, 'new'),
+    'U         %s\n' % os.path.join(wc_dir, 'A', 'mu'),
+    'D         %s\n' % beta_path,
+  ]
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/D/gamma', contents=gamma_contents)
+  expected_disk.tweak('iota', contents=iota_contents)
+  expected_disk.add({'new' : Item(contents=new_contents)})
+  expected_disk.tweak('A/mu', contents=''.join(mu_contents))
+  expected_disk.remove('A/B/E/beta')
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/D/gamma', status='M ')
+  expected_status.tweak('iota', status='M ')
+  expected_status.add({'new' : Item(status='A ', wc_rev=0)})
+  expected_status.tweak('A/mu', status='M ', wc_rev=2)
+  expected_status.tweak('A/B/E/beta', status='D ')
+
+  expected_skip = wc.State('', { })
+
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       1) # dry-run
+  # apply the patch again
+  expected_output = [
+    'G         %s\n' % os.path.join(wc_dir, 'A', 'D', 'gamma'),
+    '>         hunk @@ -1,1 +1,1 @@ already applied\n',
+    'G         %s\n' % os.path.join(wc_dir, 'iota'),
+    '>         hunk @@ -1,1 +1,2 @@ already applied\n',
+    'G         %s\n' % os.path.join(wc_dir, 'new'),
+    '>         hunk @@ -0,0 +1,1 @@ already applied\n',
+    'G         %s\n' % os.path.join(wc_dir, 'A', 'mu'),
+    '>         hunk @@ -6,6 +6,9 @@ already applied\n',
+    '>         hunk @@ -14,11 +17,8 @@ already applied\n',
+    'Skipped \'%s\'\n' % beta_path,
+    'Summary of conflicts:\n',
+    '  Skipped paths: 1\n',
+  ]
+
+  expected_skip = wc.State('', {beta_path : Item()})
+
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       1) # dry-run
+
+def patch_dir_properties(sbox):
+  "patch with dir properties"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  patch_file_path = make_patch_path(sbox)
+  B_path = os.path.join(wc_dir, 'A', 'B')
+
+  modified_prop_contents = "This is the property 'modified'.\n"
+  deleted_prop_contents = "This is the property 'deleted'.\n"
+
+  # Set the properties
+  svntest.main.run_svn(None, 'propset', 'modified', modified_prop_contents,
+                       wc_dir)
+  svntest.main.run_svn(None, 'propset', 'deleted', deleted_prop_contents,
+                       B_path)
+  expected_output = svntest.wc.State(wc_dir, {
+      '.'    : Item(verb='Sending'),
+      'A/B'    : Item(verb='Sending'),
+      })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('', wc_rev=2)
+  expected_status.tweak('A/B', wc_rev=2)
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, None, wc_dir)
+  # Apply patch
+
+  unidiff_patch = [
+    "Index: .\n",
+    "===================================================================\n",
+    "--- .\t(revision 1)\n",
+    "+++ .\t(working copy)\n",
+    "\n",
+    "Property changes on: .\n",
+    "-------------------------------------------------------------------\n",
+    "Modified: modified\n",
+    "## -1 +1 ##\n",
+    "-This is the property 'modified'.\n",
+    "+The property 'modified' has changed.\n",
+    "Added: svn:ignore\n",
+    "## -0,0 +1,3 ##\n",
+    "+*.o\n",
+    "+.libs\n",
+    "+*.lo\n",
+    "Index: A/B\n",
+    "===================================================================\n",
+    "--- A/B\t(revision 1)\n",
+    "+++ A/B\t(working copy)\n",
+    "\n",
+    "Property changes on: A/B\n",
+    "-------------------------------------------------------------------\n",
+    "Deleted: deleted\n",
+    "## -1 +0,0 ##\n",
+    "-This is the property 'deleted'.\n",
+    "Added: svn:executable\n",
+    "## -0,0 +1 ##\n",
+    "+*\n",
+  ]
+
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  modified_prop_contents = "The property 'modified' has changed.\n"
+  ignore_prop_contents = "*.o\n.libs\n*.lo\n"
+
+  ### The output for properties set on illegal targets (i.e. svn:excutable
+  ### on a dir) is still subject to change. We might just want to bail out 
+  ### directly instead of catching the error and use the notify mechanism.
+  expected_output = [
+    ' U        %s\n' % wc_dir,
+    ' U        %s\n' % os.path.join(wc_dir, 'A', 'B'),
+    'Skipped missing target \'svn:executable\' on (\'%s\')' % B_path,
+    'Summary of conflicts:\n',
+    '  Skipped paths: 1\n',
+  ]
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    '' : Item(props={'modified' : modified_prop_contents,
+                     'svn:ignore' : ignore_prop_contents})
+    })
+  expected_disk.tweak('A/B', props={})
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('', status=' M')
+  expected_status.tweak('A/B', status=' M')
+
+  expected_skip = wc.State('', { })
+
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       1) # dry-run
+
+def patch_add_path_with_props(sbox):
+  "patch that adds paths with props"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  patch_file_path = make_patch_path(sbox)
+  iota_path = os.path.join(wc_dir, 'iota')
+
+  # Apply patch that adds a file and a dir.
+
+  unidiff_patch = [
+    "Index: new\n",
+    "===================================================================\n",
+    "--- new\t(revision 0)\n",
+    "+++ new\t(working copy)\n",
+    "@@ -0,0 +1 @@\n",
+    "+This is the file 'new'\n",
+    "\n",
+    "Property changes on: new\n",
+    "-------------------------------------------------------------------\n",
+    "Added: added\n",
+    "## -0,0 +1 ##\n",
+    "+This is the property 'added'.\n",
+    "Index: X\n",
+    "===================================================================\n",
+    "--- X\t(revision 0)\n",
+    "+++ X\t(working copy)\n",
+    "\n",
+    "Property changes on: X\n",
+    "-------------------------------------------------------------------\n",
+    "Added: added\n",
+    "## -0,0 +1 ##\n",
+    "+This is the property 'added'.\n",
+  ]
+
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  added_prop_contents = "This is the property 'added'.\n"
+
+  expected_output = [
+    'A         %s\n' % os.path.join(wc_dir, 'new'),
+    'A         %s\n' % os.path.join(wc_dir, 'X'),
+  ]
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({'new': Item(contents="This is the file 'new'\n", 
+                                 props={'added' : added_prop_contents})})
+  expected_disk.add({'X': Item(props={'added' : added_prop_contents})})
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({'new': Item(status='A ', wc_rev='0')})
+  expected_status.add({'X': Item(status='A ', wc_rev='0')})
+
+  expected_skip = wc.State('', { })
+
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       1) # dry-run
+
+def patch_prop_offset(sbox):
+  "property patch with offset searching"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  patch_file_path = make_patch_path(sbox)
+  iota_path = os.path.join(wc_dir, 'iota')
+
+  prop1_content = ''.join([
+    "Dear internet user,\n",
+    # The missing line here will cause the first hunk to match early
+    "We wish to congratulate you over your email success in our computer\n",
+    "Balloting. This is a Millennium Scientific Electronic Computer Draw\n",
+    "in which email addresses were used. All participants were selected\n",
+    "through a computer ballot system drawn from over 100,000 company\n",
+    "and 50,000,000 individual email addresses from all over the world.\n",
+    "\n",
+    "Your email address drew and have won the sum of  750,000 Euros\n",
+    "( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    "file with\n",
+    "    REFERENCE NUMBER: ESP/WIN/008/05/10/MA;\n",
+    "These extra lines will cause the second hunk to match late\n",
+    "These extra lines will cause the second hunk to match late\n",
+    "These extra lines will cause the second hunk to match late\n",
+    "These extra lines will cause the second hunk to match late\n",
+    "These extra lines will cause the second hunk to match late\n",
+    "    WINNING NUMBER : 14-17-24-34-37-45-16\n",
+    "    BATCH NUMBERS :\n",
+    "    EULO/1007/444/606/08;\n",
+    "    SERIAL NUMBER: 45327\n",
+    "and PROMOTION DATE: 13th June. 2009\n",
+    "\n",
+    "To claim your winning prize, you are to contact the appointed\n",
+    "agent below as soon as possible for the immediate release of your\n",
+    "winnings with the below details.\n",
+    "\n",
+    "Again, we wish to congratulate you over your email success in our\n"
+    "computer Balloting.\n",
+  ])
+
+  # prop2's content will make both a late and early match possible.
+  # The hunk to be applied is replicated here for reference:
+  # ## -5,6 +5,7 ##
+  #  property
+  #  property
+  #  property
+  # +x
+  #  property
+  #  property
+  #  property
+  #
+  # This hunk wants to be applied at line 5, but that isn't
+  # possible because line 8 ("zzz") does not match "property".
+  # The early match happens at line 2 (offset 3 = 5 - 2).
+  # The late match happens at line 9 (offset 4 = 9 - 5).
+  # Subversion will pick the early match in this case because it
+  # is closer to line 5.
+  prop2_content = ''.join([
+    "property\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "zzz\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "property\n"
+  ])
+
+  # Set iota prop contents
+  svntest.main.run_svn(None, 'propset', 'prop1', prop1_content,
+                       iota_path)
+  svntest.main.run_svn(None, 'propset', 'prop2', prop2_content,
+                       iota_path)
+  expected_output = svntest.wc.State(wc_dir, {
+    'iota'       : Item(verb='Sending'),
+    })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('iota', wc_rev=2)
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, None, wc_dir)
+
+  # Apply patch
+
+  unidiff_patch = [
+    "Index: iota\n",
+    "===================================================================\n",
+    "--- iota	(revision XYZ)\n",
+    "+++ iota	(working copy)\n",
+    "\n",
+    "Property changes on: iota\n",
+    "-------------------------------------------------------------------\n",
+    "Modified: prop1\n",
+    "## -6,6 +6,9 ##\n",
+    " through a computer ballot system drawn from over 100,000 company\n",
+    " and 50,000,000 individual email addresses from all over the world.\n",
+    " \n",
+    "+It is a promotional program aimed at encouraging internet users;\n",
+    "+therefore you do not need to buy ticket to enter for it.\n",
+    "+\n",
+    " Your email address drew and have won the sum of  750,000 Euros\n",
+    " ( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    " file with\n",
+    "## -14,11 +17,8 ##\n",
+    "     BATCH NUMBERS :\n",
+    "     EULO/1007/444/606/08;\n",
+    "     SERIAL NUMBER: 45327\n",
+    "-and PROMOTION DATE: 13th June. 2009\n",
+    "+and PROMOTION DATE: 14th June. 2009\n",
+    " \n",
+    " To claim your winning prize, you are to contact the appointed\n",
+    " agent below as soon as possible for the immediate release of your\n",
+    " winnings with the below details.\n",
+    "-\n",
+    "-Again, we wish to congratulate you over your email success in our\n",
+    "-computer Balloting.\n",
+    "Modified: prop2\n",
+    "## -5,6 +5,7 ##\n",
+    " property\n",
+    " property\n",
+    " property\n",
+    "+x\n",
+    " property\n",
+    " property\n",
+    " property\n",
+  ]
+
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  prop1_content = ''.join([
+    "Dear internet user,\n",
+    "We wish to congratulate you over your email success in our computer\n",
+    "Balloting. This is a Millennium Scientific Electronic Computer Draw\n",
+    "in which email addresses were used. All participants were selected\n",
+    "through a computer ballot system drawn from over 100,000 company\n",
+    "and 50,000,000 individual email addresses from all over the world.\n",
+    "\n",
+    "It is a promotional program aimed at encouraging internet users;\n",
+    "therefore you do not need to buy ticket to enter for it.\n",
+    "\n",
+    "Your email address drew and have won the sum of  750,000 Euros\n",
+    "( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    "file with\n",
+    "    REFERENCE NUMBER: ESP/WIN/008/05/10/MA;\n",
+    "These extra lines will cause the second hunk to match late\n",
+    "These extra lines will cause the second hunk to match late\n",
+    "These extra lines will cause the second hunk to match late\n",
+    "These extra lines will cause the second hunk to match late\n",
+    "These extra lines will cause the second hunk to match late\n",
+    "    WINNING NUMBER : 14-17-24-34-37-45-16\n",
+    "    BATCH NUMBERS :\n",
+    "    EULO/1007/444/606/08;\n",
+    "    SERIAL NUMBER: 45327\n",
+    "and PROMOTION DATE: 14th June. 2009\n",
+    "\n",
+    "To claim your winning prize, you are to contact the appointed\n",
+    "agent below as soon as possible for the immediate release of your\n",
+    "winnings with the below details.\n",
+  ])
+
+  prop2_content = ''.join([
+    "property\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "x\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "zzz\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "property\n",
+    "property\n",
+  ])
+
+  os.chdir(wc_dir)
+
+  expected_output = [
+    ' U        iota\n',
+    '>         applied hunk ## -6,6 +6,9 ## with offset -1 (prop1)\n',
+    '>         applied hunk ## -14,11 +17,8 ## with offset 4 (prop1)\n',
+    '>         applied hunk ## -5,6 +5,7 ## with offset -3 (prop2)\n',
+  ]
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('iota', props = {'prop1' : prop1_content,
+                                       'prop2' : prop2_content})
+
+  expected_status = svntest.actions.get_virginal_state('.', 1)
+  expected_status.tweak('iota', status=' M', wc_rev=2)
+
+  expected_skip = wc.State('', { })
+
+  svntest.actions.run_and_verify_patch('.', os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       1) # dry-run
+
+def patch_prop_with_fuzz(sbox):
+  "property patch with fuzz"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  patch_file_path = make_patch_path(sbox)
+
+  mu_path = os.path.join(wc_dir, 'A', 'mu')
+
+  # We have replaced a couple of lines to cause fuzz. Those lines contains
+  # the word fuzz
+  prop_contents = ''.join([
+    "Line replaced for fuzz = 1\n",
+    "\n",
+    "We wish to congratulate you over your email success in our computer\n",
+    "Balloting. This is a Millennium Scientific Electronic Computer Draw\n",
+    "in which email addresses were used. All participants were selected\n",
+    "through a computer ballot system drawn from over 100,000 company\n",
+    "and 50,000,000 individual email addresses from all over the world.\n",
+    "Line replaced for fuzz = 2 with only the second context line changed\n",
+    "Your email address drew and have won the sum of  750,000 Euros\n",
+    "( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    "file with\n",
+    "    REFERENCE NUMBER: ESP/WIN/008/05/10/MA;\n",
+    "    WINNING NUMBER : 14-17-24-34-37-45-16\n",
+    "    BATCH NUMBERS :\n",
+    "    EULO/1007/444/606/08;\n",
+    "    SERIAL NUMBER: 45327\n",
+    "and PROMOTION DATE: 13th June. 2009\n",
+    "\n",
+    "This line is inserted to cause an offset of +1\n",
+    "To claim your winning prize, you are to contact the appointed\n",
+    "agent below as soon as possible for the immediate release of your\n",
+    "winnings with the below details.\n",
+    "\n",
+    "Line replaced for fuzz = 2\n",
+    "Line replaced for fuzz = 2\n",
+  ])
+
+  # Set mu prop contents
+  svntest.main.run_svn(None, 'propset', 'prop', prop_contents,
+                       mu_path)
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/mu'       : Item(verb='Sending'),
+    })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/mu', wc_rev=2)
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                      expected_status, None, wc_dir)
+
+  unidiff_patch = [
+    "Index: mu\n",
+    "===================================================================\n",
+    "--- A/mu\t(revision 0)\n",
+    "+++ A/mu\t(revision 0)\n",
+    "\n",
+    "Property changes on: mu\n",
+    "Modified: prop\n",
+    "## -1,6 +1,7 ##\n",
+    " Dear internet user,\n",
+    " \n",
+    " We wish to congratulate you over your email success in our computer\n",
+    "+A new line here\n",
+    " Balloting. This is a Millennium Scientific Electronic Computer Draw\n",
+    " in which email addresses were used. All participants were selected\n",
+    " through a computer ballot system drawn from over 100,000 company\n",
+    "## -7,7 +8,9 ##\n",
+    " and 50,000,000 individual email addresses from all over the world.\n",
+    " \n",
+    " Your email address drew and have won the sum of  750,000 Euros\n",
+    "+Another new line\n",
+    " ( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    "+A third new line\n",
+    " file with\n",
+    "    REFERENCE NUMBER: ESP/WIN/008/05/10/MA;\n",
+    "    WINNING NUMBER : 14-17-24-34-37-45-16\n",
+    "## -19,6 +20,7 ##\n",
+    " To claim your winning prize, you are to contact the appointed\n",
+    " agent below as soon as possible for the immediate release of your\n",
+    " winnings with the below details.\n",
+    "+A fourth new line\n",
+    " \n",
+    " Again, we wish to congratulate you over your email success in our\n"
+    " computer Balloting. [No trailing newline here]"
+  ]
+
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  prop_contents = ''.join([
+    "Line replaced for fuzz = 1\n",
+    "\n",
+    "We wish to congratulate you over your email success in our computer\n",
+    "A new line here\n",
+    "Balloting. This is a Millennium Scientific Electronic Computer Draw\n",
+    "in which email addresses were used. All participants were selected\n",
+    "through a computer ballot system drawn from over 100,000 company\n",
+    "and 50,000,000 individual email addresses from all over the world.\n",
+    "Line replaced for fuzz = 2 with only the second context line changed\n",
+    "Your email address drew and have won the sum of  750,000 Euros\n",
+    "Another new line\n",
+    "( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    "A third new line\n",
+    "file with\n",
+    "    REFERENCE NUMBER: ESP/WIN/008/05/10/MA;\n",
+    "    WINNING NUMBER : 14-17-24-34-37-45-16\n",
+    "    BATCH NUMBERS :\n",
+    "    EULO/1007/444/606/08;\n",
+    "    SERIAL NUMBER: 45327\n",
+    "and PROMOTION DATE: 13th June. 2009\n",
+    "\n",
+    "This line is inserted to cause an offset of +1\n",
+    "To claim your winning prize, you are to contact the appointed\n",
+    "agent below as soon as possible for the immediate release of your\n",
+    "winnings with the below details.\n",
+    "A fourth new line\n",
+    "\n",
+    "Line replaced for fuzz = 2\n",
+    "Line replaced for fuzz = 2\n",
+  ])
+
+  expected_output = [
+    ' U        %s\n' % os.path.join(wc_dir, 'A', 'mu'),
+    '>         applied hunk ## -1,6 +1,7 ## with fuzz 1 (prop)\n',
+    '>         applied hunk ## -7,7 +8,9 ## with fuzz 2 (prop)\n',
+    '>         applied hunk ## -19,6 +20,7 ## with offset 1 and fuzz 2 (prop)\n',
+  ]
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/mu', props = {'prop' : prop_contents})
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/mu', status=' M', wc_rev=2)
+
+  expected_skip = wc.State('', { })
+
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       1) # dry-run
+
 ########################################################################
 #Run the tests
 
@@ -2185,6 +2998,12 @@ test_list = [ None,
               patch_with_ignore_whitespace,
               patch_replace_locally_deleted_file,
               patch_no_eol_at_eof,
+              patch_with_properties,
+              patch_same_twice,
+              XFail(patch_dir_properties),
+              XFail(patch_add_path_with_props),
+              patch_prop_offset,
+              patch_prop_with_fuzz,
             ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/prop_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/prop_tests.py?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/prop_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/prop_tests.py Wed Aug 11 16:43:22 2010
@@ -1944,20 +1944,32 @@ def obstructed_subdirs(sbox):
                              expected_disk.old_tree())
 
   expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
-  expected_status.tweak('A/C', status='! ', wc_rev='?')
+  if svntest.main.wc_is_singledb(wc_dir):
+    expected_status.tweak('A/C', status='! ', wc_rev='1')
+  else:
+    expected_status.tweak('A/C', status='! ', wc_rev='?')
+
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
   # Drop an empty file there to obstruct the now-deleted subdir
   open(C_path, 'w')
 
-  expected_disk.add({'A/C': Item(contents='')})
+  # Single-DB doesn't lose properties
+  if svntest.main.wc_is_singledb(wc_dir):
+    expected_disk.add({'A/C': Item(contents='', props={'red': 'blue'})})
+    expected_status.tweak('A/C', status='~ ', wc_rev='1')
+  else:
+    expected_disk.add({'A/C': Item(contents='')})
+
+    # NOTE: r943346 fixes a problem with reporter processing, which
+    #   is necessary for this status to complete properly.
+    expected_status.tweak('A/C', status='~ ', wc_rev='?')
+
   actual_disk_tree = svntest.tree.build_tree_from_wc(wc_dir, load_props=True)
   svntest.tree.compare_trees("disk", actual_disk_tree,
                              expected_disk.old_tree())
 
-  # NOTE: r943346 fixes a problem with reporter processing, which
-  #   is necessary for this status to complete properly.
-  expected_status.tweak('A/C', status='~ ', wc_rev='?')
+  
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
 

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/resolved_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/resolved_tests.py?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/resolved_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/resolved_tests.py Wed Aug 11 16:43:22 2010
@@ -112,6 +112,8 @@ def resolved_on_wc_root(sbox):
                        'A/B/lambda',
                        'A/B/E/alpha', 'A/B/E/beta',
                        'A/D/gamma')
+  if svntest.main.wc_is_singledb(sbox.wc_dir):
+    expected_disk.remove('A/B/E', 'A/B/F', 'A/B')
 
   expected_status = svntest.actions.get_virginal_state(wc, 2)
   expected_status.tweak('iota', 'A/B', 'A/D/gamma',

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/revert_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/revert_tests.py?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/revert_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/revert_tests.py Wed Aug 11 16:43:22 2010
@@ -740,20 +740,35 @@ def status_of_missing_dir_after_revert(s
   svntest.actions.run_and_verify_svn(None, expected_output, [], "revert",
                                      A_D_G_path)
 
-  expected_output = svntest.verify.UnorderedOutput(
-    ["D       " + os.path.join(A_D_G_path, "pi") + "\n",
+  deletes = [
+     "D       " + os.path.join(A_D_G_path, "pi") + "\n",
      "D       " + os.path.join(A_D_G_path, "rho") + "\n",
-     "D       " + os.path.join(A_D_G_path, "tau") + "\n"])
+     "D       " + os.path.join(A_D_G_path, "tau") + "\n"
+  ]
+  expected_output = svntest.verify.UnorderedOutput(deletes)
   svntest.actions.run_and_verify_svn(None, expected_output, [],
                                      "status", wc_dir)
 
   svntest.main.safe_rmtree(A_D_G_path)
 
-  expected_output = svntest.verify.UnorderedOutput(
-    ["!       " + A_D_G_path + "\n"])
+  expected_output = ["!       " + A_D_G_path + "\n"]
+
+  if svntest.main.wc_is_singledb(wc_dir):
+    expected_output.extend(deletes)
+
+  expected_output = svntest.verify.UnorderedOutput(expected_output)
+
   svntest.actions.run_and_verify_svn(None, expected_output, [], "status",
                                      wc_dir)
 
+  # When using single-db, we can get back to the virginal state.
+  if svntest.main.wc_is_singledb(wc_dir):
+    svntest.actions.run_and_verify_svn(None, None, [], "revert",
+                                       "-R", A_D_G_path)
+
+    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+    svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
 #----------------------------------------------------------------------
 # Test for issue #2804 with replaced directory
 def status_of_missing_dir_after_revert_replaced_with_history_dir(sbox):

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/schedule_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/schedule_tests.py?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/schedule_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/schedule_tests.py Wed Aug 11 16:43:22 2010
@@ -35,6 +35,7 @@ import svntest
 Skip = svntest.testcase.Skip
 SkipUnless = svntest.testcase.SkipUnless
 XFail = svntest.testcase.XFail
+Wimp = svntest.testcase.Wimp
 Item = svntest.wc.StateItem
 
 
@@ -575,8 +576,7 @@ def add_recursive_already_versioned(sbox
 
   wc_dir = sbox.wc_dir
 
-  if svntest.actions.make_repo_and_wc(sbox):
-    return 1
+  svntest.actions.make_repo_and_wc(sbox)
 
   # Create some files, then schedule them for addition
   delta_path = sbox.ospath('delta')
@@ -646,6 +646,54 @@ def delete_non_existent(sbox):
   svntest.actions.run_and_verify_svn(None, None, svntest.verify.AnyOutput,
                                      'rm', '--force', 'non-existent')
 
+
+#----------------------------------------------------------------------
+# Problem encountered by cmpilato when he inadvertantly upset an
+# 'svn rm --keep-local' and had to retry it.
+def delete_redelete_fudgery(sbox):
+  "retry of manually upset --keep-local deletion"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  B_path = os.path.join(wc_dir, 'A', 'B')
+
+  # Delete 'A/B' using --keep-local, then remove at the OS level.
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'rm', '--keep-local', B_path)
+  svntest.main.safe_rmtree(B_path)
+
+  # Update the tree.
+  #
+  ### When WC-NG is running in single-DB mode (one .svn directory and
+  ### database for the whole working copy), I suspect that this update
+  ### will change.  Today it re-adds the directory which we just
+  ### scheduled for deletion because the only record of that
+  ### scheduling is stored -- you guessed it -- the directory's .svn/
+  ### area... which we just deleted from disk.
+  ###
+  ### In single-DB-WC-NG-land, though, deleting the directory from
+  ### disk should have no bearing whatsoever on the scheduling
+  ### information stored now in the working copy root's one DB.  That
+  ### could change the whole flow of this test, possible leading us to
+  ### remove it as altogether irrelevant.  --cmpilato
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+
+  # Now try to run
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'rm', '--keep-local', B_path)
+
+def propset_on_deleted_should_fail(sbox):
+  "calling svn propset on a deleted node should fail"
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  iota = os.path.join(wc_dir, 'iota')
+
+  svntest.actions.run_and_verify_svn(None, None, [], 'rm', iota)
+
+  svntest.actions.run_and_verify_svn(None, None, "svn: Can't set propert.*",
+                                     'ps', 'prop', 'val', iota)
+
+
 ########################################################################
 # Run the tests
 
@@ -658,13 +706,15 @@ test_list = [ None,
               SkipUnless(revert_add_executable, svntest.main.is_posix_os),
               revert_delete_files,
               revert_delete_dirs,
-              XFail(unschedule_missing_added),
+              Wimp('Needs single-db', unschedule_missing_added),
               delete_missing,
               revert_inside_newly_added_dir,
               status_add_deleted_directory,
               add_recursive_already_versioned,
               fail_add_directory,
               delete_non_existent,
+              delete_redelete_fudgery,
+              propset_on_deleted_should_fail,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/stat_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/stat_tests.py?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/stat_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/stat_tests.py Wed Aug 11 16:43:22 2010
@@ -39,6 +39,7 @@ Skip = svntest.testcase.Skip
 SkipUnless = svntest.testcase.SkipUnless
 XFail = svntest.testcase.XFail
 Item = svntest.wc.StateItem
+UnorderedOutput = svntest.verify.UnorderedOutput
 
 
 
@@ -175,39 +176,70 @@ def status_type_change(sbox):
   os.rename('A', 'iota')
   os.rename('was_iota', 'A')
 
-  exit_code, output, err = svntest.actions.run_and_verify_svn(None, None, [],
-                                                              'status')
-  if len(output) != 2:
-    raise svntest.Failure
-  for line in output:
-    if not re.match("~ +(iota|A)", line):
-      raise svntest.Failure
+  expected_output = [
+        '~       A\n',
+        '~       iota\n',
+    ]
+
+  svntest.actions.run_and_verify_svn(None, UnorderedOutput(expected_output),
+                                     [], 'status')
 
   # Now change the file that is obstructing the versioned dir into an
   # unversioned dir.
   os.remove('A')
   os.mkdir('A')
 
-  exit_code, output, err = svntest.actions.run_and_verify_svn(None, None, [],
-                                                              'status')
-  if len(output) != 2:
-    raise svntest.Failure
-  for line in output:
-    if not re.match("~ +(iota|A)", line):
-      raise svntest.Failure
+  if svntest.main.wc_is_singledb('.'):
+    # A is a directory again, so it is no longer missing, but it's
+    # descendants are
+    expected_output = [
+        '!       A/mu\n',
+        '!       A/B\n',
+        '!       A/B/lambda\n',
+        '!       A/B/E\n',
+        '!       A/B/E/alpha\n',
+        '!       A/B/E/beta\n',
+        '!       A/B/F\n',
+        '!       A/C\n',
+        '!       A/D\n',
+        '!       A/D/gamma\n',
+        '!       A/D/G\n',
+        '!       A/D/G/rho\n',
+        '!       A/D/G/pi\n',
+        '!       A/D/G/tau\n',
+        '!       A/D/H\n',
+        '!       A/D/H/chi\n',
+        '!       A/D/H/omega\n',
+        '!       A/D/H/psi\n',
+        '~       iota\n',
+    ]
+    # Fix separator for Windows
+    expected_output = [s.replace('/', os.path.sep) for s in expected_output]
+  else:
+    # A misses its administrative area, so it is missing
+    expected_output = [
+        '~       A\n',
+        '~       iota\n',
+    ]
+
+  svntest.actions.run_and_verify_svn(None, UnorderedOutput(expected_output),
+                                     [], 'status')
 
   # Now change the versioned dir that is obstructing the file into an
   # unversioned dir.
   svntest.main.safe_rmtree('iota')
   os.mkdir('iota')
 
-  exit_code, output, err = svntest.actions.run_and_verify_svn(None, None, [],
-                                                              'status')
-  if len(output) != 2:
-    raise svntest.Failure
-  for line in output:
-    if not re.match("~ +(iota|A)", line):
-      raise svntest.Failure
+  if not svntest.main.wc_is_singledb('.'):
+    # A misses its administrative area, so it is still missing and
+    # iota is still obstructed
+    expected_output = [
+        '~       A\n',
+        '~       iota\n',
+    ]
+
+  svntest.actions.run_and_verify_svn(None, UnorderedOutput(expected_output),
+                                     [], 'status')
 
 #----------------------------------------------------------------------
 
@@ -366,7 +398,7 @@ def status_nonrecursive_update_different
 
   os.chdir('A')
   svntest.actions.run_and_verify_svn(None,
-                                     expected_output,
+                                     UnorderedOutput(expected_output),
                                      [],
                                      'status', '-v', '-N', '-u', 'C')
 
@@ -378,7 +410,7 @@ def status_nonrecursive_update_different
 
   os.chdir('C')
   svntest.actions.run_and_verify_svn(None,
-                                     expected_output,
+                                     UnorderedOutput(expected_output),
                                      [],
                                      'status', '-v', '-N', '-u', '.')
 
@@ -803,8 +835,11 @@ def missing_dir_in_anchor(sbox):
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
   # At one point this caused a "foo not locked" error
+  is_singledb = svntest.main.wc_is_singledb(foo_path)
   svntest.main.safe_rmtree(foo_path)
   expected_status.tweak('foo', status='! ', wc_rev='?')
+  if is_singledb:
+    expected_status.tweak('foo', entry_status='A ', entry_rev='0')
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
 
@@ -907,25 +942,55 @@ def status_missing_dir(sbox):
   # ok, blow away the A/D/G directory
   svntest.main.safe_rmtree(a_d_g)
 
-  expected = svntest.verify.UnorderedOutput(["!       " + a_d_g + "\n"])
-  svntest.actions.run_and_verify_svn(None, expected, [], "status", wc_dir)
+  if svntest.main.wc_is_singledb(wc_dir):
+    expected = [
+                 '!       A/D/G\n',
+                 '!       A/D/G/rho\n',
+                 '!       A/D/G/pi\n',
+                 '!       A/D/G/tau\n',
+               ]
+    expected = [ s.replace('A/D/G', a_d_g).replace('/', os.path.sep)
+                 for s in expected ]
+  else:
+    expected = ["!       " + a_d_g + "\n"]
 
-  expected = svntest.verify.UnorderedOutput(
-         ["        *            " + os.path.join(a_d_g, "pi") + "\n",
+  svntest.actions.run_and_verify_svn(None, UnorderedOutput(expected), [],
+                                     "status", wc_dir)
+
+  if svntest.main.wc_is_singledb(wc_dir):
+    expected = [
+          "!                1   " + a_d_g + "\n",
+          "!                1   " + os.path.join(a_d_g, "rho") + "\n",
+          "!                1   " + os.path.join(a_d_g, "pi") + "\n",
+          "!                1   " + os.path.join(a_d_g, "tau") + "\n",
+          "Status against revision:      1\n" ]
+  else:
+    expected = [
+          "        *            " + os.path.join(a_d_g, "pi") + "\n",
           "        *            " + os.path.join(a_d_g, "rho") + "\n",
           "        *            " + os.path.join(a_d_g, "tau") + "\n",
           "!       *       ?    " + a_d_g + "\n",
           "        *        1   " + os.path.join(wc_dir, "A", "D") + "\n",
-          "Status against revision:      1\n" ])
+          "Status against revision:      1\n" ]
 
   # now run status -u, we should be able to do this without crashing
-  svntest.actions.run_and_verify_svn(None, expected, [],
+  svntest.actions.run_and_verify_svn(None, UnorderedOutput(expected), [],
                                      "status", "-u", wc_dir)
 
   # Finally run an explicit status request directly on the missing directory.
-  svntest.actions.run_and_verify_svn(None,
-                                     ["!       " + a_d_g + "\n"],
-                                     [], "status", a_d_g)
+  if svntest.main.wc_is_singledb(wc_dir):
+    expected = [
+                  "!       A/D/G\n",
+                  "!       A/D/G/rho\n",
+                  "!       A/D/G/pi\n",
+                  "!       A/D/G/tau\n",
+               ]
+    expected = [ s.replace('A/D/G', a_d_g).replace('/', os.path.sep)
+                 for s in expected ]
+  else:
+    expected = ["!       " + a_d_g + "\n"]
+  svntest.actions.run_and_verify_svn(None, UnorderedOutput(expected), [],
+                                     "status", a_d_g)
 
 def status_add_plus_conflict(sbox):
   "status on conflicted added file"
@@ -1488,6 +1553,8 @@ def status_dash_u_deleted_directories(sb
                                      "status", "-u", "B")
 
   # again, but now from inside B, should give the same output
+  if not os.path.exists('B'):
+    os.mkdir('B')
   os.chdir("B")
   expected = svntest.verify.UnorderedOutput(
          ["D                1   %s\n" % ".",
@@ -1545,7 +1612,35 @@ def status_dash_u_type_change(sbox):
   svntest.main.safe_rmtree('A')
   os.mkdir('A')
 
-  expected = svntest.verify.UnorderedOutput(
+  if svntest.main.wc_is_singledb('.'):
+    output =[
+               "!                1   A/mu\n",
+               "!                1   A/B\n",
+               "!                1   A/B/lambda\n",
+               "!                1   A/B/E\n",
+               "!                1   A/B/E/alpha\n",
+               "!                1   A/B/E/beta\n",
+               "!                1   A/B/F\n",
+               "!                1   A/C\n",
+               "!                1   A/D\n",
+               "!                1   A/D/gamma\n",
+               "!                1   A/D/G\n",
+               "!                1   A/D/G/rho\n",
+               "!                1   A/D/G/pi\n",
+               "!                1   A/D/G/tau\n",
+               "!                1   A/D/H\n",
+               "!                1   A/D/H/chi\n",
+               "!                1   A/D/H/omega\n",
+               "!                1   A/D/H/psi\n",
+               "~                1   iota\n",
+               "Status against revision:      1\n"
+            ]
+
+    expected = svntest.verify.UnorderedOutput(
+                        [s.replace('/', os.path.sep)
+                            for s in  output])
+  else:
+    expected = svntest.verify.UnorderedOutput(
          ["~                1   iota\n",
           "~               ?    A\n",
           "Status against revision:      1\n" ])

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnadmin_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnadmin_tests.py?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnadmin_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnadmin_tests.py Wed Aug 11 16:43:22 2010
@@ -1162,28 +1162,7 @@ def dont_drop_valid_mergeinfo_during_inc
 
   # Check the resulting mergeinfo.  We expect the exact same results
   # as Part 3.
-  #
-  # Currently this fails because our current logic mapping mergeinfo revs
-  # in the load stream to their new values based on the offset of the
-  # target repository is quite flawed.  Right now this is the resulting
-  # mergeinfo:
-  #
-  #    Properties on 'svnadmin_tests-21\Projects\Project-X\branches\B1\B
-  #      svn:mergeinfo
-  #        /Projects/Project-X/branches/B2/B/E:11-12
-  #        /Projects/Project-X/trunk/B/E:5-6,8-9
-  #    Properties on 'svnadmin_tests-21\Projects\Project-X\branches\B1':
-  #      svn:mergeinfo
-  #        /Projects/Project-X/branches/B2:11-18
-  #                                           ^^
-  #                                 The *only* correct rev here!
-  #        /Projects/Project-X/trunk:6,9
-  #    Properties on 'svnadmin_tests-21\Projects\Project-X\branches\B2':
-  #      svn:mergeinfo
-  #        /Projects/Project-X/trunk:9
-  #
-  # See http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc16 for
-  # more info.
+  # See http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc16.
   svntest.actions.run_and_verify_svn(None, expected_output, [],
                                      'propget', 'svn:mergeinfo', '-R',
                                      sbox.repo_url)
@@ -1276,7 +1255,7 @@ test_list = [ None,
               create_in_repo_subdir,
               SkipUnless(verify_with_invalid_revprops,
                          svntest.main.is_fs_type_fsfs),
-              XFail(dont_drop_valid_mergeinfo_during_incremental_loads),
+              dont_drop_valid_mergeinfo_during_incremental_loads,
               SkipUnless(hotcopy_symlink, svntest.main.is_posix_os),
              ]
 

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnlook_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnlook_tests.py?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnlook_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnlook_tests.py Wed Aug 11 16:43:22 2010
@@ -267,11 +267,22 @@ def test_print_property_diffs(sbox):
   if len(output) != len(expected_output):
     raise svntest.Failure
 
+  canonical_iota_path = iota_path.replace(os.path.sep, '/')
+
   # replace wcdir/iota with iota in expected_output
   for i in range(len(expected_output)):
-    expected_output[i] = expected_output[i].replace(iota_path, 'iota')
+    expected_output[i] = expected_output[i].replace(canonical_iota_path, 
+                                                    'iota')
+
+  # Check that the header filenames match.
+  if expected_output[2].split()[1] != output[2].split()[1]:
+    raise svntest.Failure
+  if expected_output[3].split()[1] != output[3].split()[1]:
+    raise svntest.Failure
 
-  svntest.verify.compare_and_display_lines('', '', expected_output, output)
+  svntest.verify.compare_and_display_lines('', '', 
+                                           expected_output[4:],
+                                           output[4:])
 
 #----------------------------------------------------------------------
 # Check that svnlook info repairs allows inconsistent line endings in logs.
@@ -520,11 +531,22 @@ def diff_ignore_eolstyle(sbox):
                          '--ignore-eol-style', repo_dir, '/A/mu')
     rev += 1
 
+    canonical_mu_path = mu_path.replace(os.path.sep, '/')
+
     # replace wcdir/A/mu with A/mu in expected_output
     for i in range(len(expected_output)):
-      expected_output[i] = expected_output[i].replace(mu_path, 'A/mu')
+      expected_output[i] = expected_output[i].replace(canonical_mu_path, 
+                                                      'A/mu')
+
+    # Check that the header filenames match.
+    if expected_output[2].split()[1] != output[2].split()[1]:
+      raise svntest.Failure
+    if expected_output[3].split()[1] != output[3].split()[1]:
+      raise svntest.Failure
 
-    svntest.verify.compare_and_display_lines('', '', expected_output, output)
+    svntest.verify.compare_and_display_lines('', '', 
+                                             expected_output[4:],
+                                             output[4:])
 
 
 #----------------------------------------------------------------------

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests.py?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests.py Wed Aug 11 16:43:22 2010
@@ -775,6 +775,11 @@ def commit_a_copy_of_root(sbox):
   #Testcase for issue 3438.
   run_test(sbox, "repo_with_copy_of_root_dir.dump")
 
+# issue #3641
+def descend_into_replace(sbox):
+  "descending into replaced dir looks in src"
+  run_test(sbox, "descend_into_replace.dump", subdir='/trunk/H',
+           exp_dump_file_name = "descend_into_replace.expected.dump")
 
 ########################################################################
 # Run the tests
@@ -788,8 +793,8 @@ test_list = [ None,
               modified_in_place,
               tag_empty_trunk,
               tag_trunk_with_dir,
-              tag_trunk_with_file2,
               tag_trunk_with_file,
+              tag_trunk_with_file2,
               tag_with_modified_file,
               dir_prop_change,
               file_dir_file,
@@ -815,6 +820,7 @@ test_list = [ None,
               copy_bad_line_endings,
               delete_svn_props,
               commit_a_copy_of_root,
+              descend_into_replace,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-and-modify.dump
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-and-modify.dump?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-and-modify.dump (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-and-modify.dump Wed Aug 11 16:43:22 2010
@@ -16,10 +16,6 @@ Revision-number: 1
 Prop-content-length: 112
 Content-length: 112
 
-K 7
-svn:log
-V 11
-add foo.txt
 K 10
 svn:author
 V 6
@@ -28,6 +24,10 @@ K 8
 svn:date
 V 27
 2005-11-07T23:37:17.705159Z
+K 7
+svn:log
+V 11
+add foo.txt
 PROPS-END
 
 Node-path: foo.txt
@@ -46,11 +46,6 @@ Revision-number: 2
 Prop-content-length: 135
 Content-length: 135
 
-K 7
-svn:log
-V 34
-copy and change at the same time.
-
 K 10
 svn:author
 V 6
@@ -59,6 +54,11 @@ K 8
 svn:date
 V 27
 2005-11-07T23:37:44.549695Z
+K 7
+svn:log
+V 34
+copy and change at the same time.
+
 PROPS-END
 
 Node-path: bar.txt

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-bad-line-endings.dump
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-bad-line-endings.dump?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-bad-line-endings.dump (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-bad-line-endings.dump Wed Aug 11 16:43:22 2010
@@ -16,11 +16,6 @@ Revision-number: 1
 Prop-content-length: 151
 Content-length: 151
 
-K 7
-svn:log
-V 49
-added svn:ignore using CRLF to
 terminate lines
-
 K 10
 svn:author
 V 7
@@ -29,6 +24,11 @@ K 8
 svn:date
 V 27
 2009-03-27T19:33:51.178381Z
+K 7
+svn:log
+V 49
+added svn:ignore using CRLF to
 terminate lines
+
 PROPS-END
 
 Node-path: 

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-bad-line-endings.expected.dump
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-bad-line-endings.expected.dump?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-bad-line-endings.expected.dump (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-bad-line-endings.expected.dump Wed Aug 11 16:43:22 2010
@@ -16,12 +16,6 @@ Revision-number: 1
 Prop-content-length: 150
 Content-length: 150
 
-K 7
-svn:log
-V 48
-added svn:ignore using CRLF to
- terminate lines
-
 K 10
 svn:author
 V 7
@@ -30,6 +24,12 @@ K 8
 svn:date
 V 27
 2009-03-27T19:33:51.178381Z
+K 7
+svn:log
+V 48
+added svn:ignore using CRLF to
+ terminate lines
+
 PROPS-END
 
 Node-path: 

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-from-previous-version-and-modify.dump
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-from-previous-version-and-modify.dump?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-from-previous-version-and-modify.dump (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-from-previous-version-and-modify.dump Wed Aug 11 16:43:22 2010
@@ -16,10 +16,6 @@ Revision-number: 1
 Prop-content-length: 103
 Content-length: 103
 
-K 7
-svn:log
-V 3
-ttb
 K 10
 svn:author
 V 6
@@ -28,6 +24,10 @@ K 8
 svn:date
 V 27
 2005-11-15T21:10:58.608841Z
+K 7
+svn:log
+V 3
+ttb
 PROPS-END
 
 Node-path: branches
@@ -61,11 +61,6 @@ Revision-number: 2
 Prop-content-length: 116
 Content-length: 116
 
-K 7
-svn:log
-V 15
-first version!
-
 K 10
 svn:author
 V 6
@@ -74,6 +69,11 @@ K 8
 svn:date
 V 27
 2005-11-15T21:11:19.415517Z
+K 7
+svn:log
+V 15
+first version!
+
 PROPS-END
 
 Node-path: trunk/file.txt
@@ -93,11 +93,6 @@ Revision-number: 3
 Prop-content-length: 117
 Content-length: 117
 
-K 7
-svn:log
-V 16
-second version!
-
 K 10
 svn:author
 V 6
@@ -106,6 +101,11 @@ K 8
 svn:date
 V 27
 2005-11-15T21:11:29.391885Z
+K 7
+svn:log
+V 16
+second version!
+
 PROPS-END
 
 Node-path: trunk/file.txt
@@ -123,11 +123,6 @@ Revision-number: 4
 Prop-content-length: 122
 Content-length: 122
 
-K 7
-svn:log
-V 21
-a copy, but modified
-
 K 10
 svn:author
 V 6
@@ -136,6 +131,11 @@ K 8
 svn:date
 V 27
 2005-11-15T21:11:50.278301Z
+K 7
+svn:log
+V 21
+a copy, but modified
+
 PROPS-END
 
 Node-path: trunk/copy-of-file.txt

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-from-previous-version.dump
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-from-previous-version.dump?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-from-previous-version.dump (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-from-previous-version.dump Wed Aug 11 16:43:22 2010
@@ -16,11 +16,6 @@ Revision-number: 1
 Prop-content-length: 104
 Content-length: 104
 
-K 7
-svn:log
-V 4
-ttb
-
 K 10
 svn:author
 V 6
@@ -29,6 +24,11 @@ K 8
 svn:date
 V 27
 2005-11-15T20:53:08.484681Z
+K 7
+svn:log
+V 4
+ttb
+
 PROPS-END
 
 Node-path: branches
@@ -62,11 +62,6 @@ Revision-number: 2
 Prop-content-length: 119
 Content-length: 119
 
-K 7
-svn:log
-V 18
-Add first version
-
 K 10
 svn:author
 V 6
@@ -75,6 +70,11 @@ K 8
 svn:date
 V 27
 2005-11-15T20:53:34.716301Z
+K 7
+svn:log
+V 18
+Add first version
+
 PROPS-END
 
 Node-path: trunk/file.txt
@@ -94,11 +94,6 @@ Revision-number: 3
 Prop-content-length: 120
 Content-length: 120
 
-K 7
-svn:log
-V 19
-Add second version
-
 K 10
 svn:author
 V 6
@@ -107,6 +102,11 @@ K 8
 svn:date
 V 27
 2005-11-15T20:53:48.805239Z
+K 7
+svn:log
+V 19
+Add second version
+
 PROPS-END
 
 Node-path: trunk/file.txt
@@ -124,11 +124,6 @@ Revision-number: 4
 Prop-content-length: 149
 Content-length: 149
 
-K 7
-svn:log
-V 48
-Add a new file to create an uninvolved revision
-
 K 10
 svn:author
 V 6
@@ -137,6 +132,11 @@ K 8
 svn:date
 V 27
 2005-11-15T20:56:25.247172Z
+K 7
+svn:log
+V 48
+Add a new file to create an uninvolved revision
+
 PROPS-END
 
 Node-path: trunk/foo.txt
@@ -155,11 +155,6 @@ Revision-number: 5
 Prop-content-length: 131
 Content-length: 131
 
-K 7
-svn:log
-V 30
-copy from a previous revision
-
 K 10
 svn:author
 V 6
@@ -168,6 +163,11 @@ K 8
 svn:date
 V 27
 2005-11-15T20:56:46.198327Z
+K 7
+svn:log
+V 30
+copy from a previous revision
+
 PROPS-END
 
 Node-path: trunk/copy-of-file.txt

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-parent-modify-prop.dump
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-parent-modify-prop.dump?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-parent-modify-prop.dump (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/copy-parent-modify-prop.dump Wed Aug 11 16:43:22 2010
@@ -16,10 +16,6 @@ Revision-number: 1
 Prop-content-length: 113
 Content-length: 113
 
-K 7
-svn:log
-V 16
-add dir and file
 K 10
 svn:author
 V 2
@@ -28,6 +24,10 @@ K 8
 svn:date
 V 27
 2006-04-19T12:50:29.623828Z
+K 7
+svn:log
+V 16
+add dir and file
 PROPS-END
 
 Node-path: dir
@@ -55,10 +55,6 @@ Revision-number: 2
 Prop-content-length: 126
 Content-length: 126
 
-K 7
-svn:log
-V 29
-copy dir and modify prop of f
 K 10
 svn:author
 V 2
@@ -67,6 +63,10 @@ K 8
 svn:date
 V 27
 2006-04-19T12:51:15.837786Z
+K 7
+svn:log
+V 29
+copy dir and modify prop of f
 PROPS-END
 
 Node-path: dir2

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/delete-svn-props.dump
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/delete-svn-props.dump?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/delete-svn-props.dump (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnsync_tests_data/delete-svn-props.dump Wed Aug 11 16:43:22 2010
@@ -16,10 +16,6 @@ Revision-number: 1
 Prop-content-length: 137
 Content-length: 137
 
-K 7
-svn:log
-V 37
-adding file with prop 'svn:eol-style'
 K 10
 svn:author
 V 5
@@ -28,6 +24,10 @@ K 8
 svn:date
 V 27
 2009-06-05T14:23:41.185914Z
+K 7
+svn:log
+V 37
+adding file with prop 'svn:eol-style'
 PROPS-END
 
 Node-path: file
@@ -51,10 +51,6 @@ Revision-number: 2
 Prop-content-length: 139
 Content-length: 139
 
-K 7
-svn:log
-V 39
-removing prop 'svn:eol-style' from file
 K 10
 svn:author
 V 5
@@ -63,6 +59,10 @@ K 8
 svn:date
 V 27
 2009-06-05T14:23:42.140849Z
+K 7
+svn:log
+V 39
+removing prop 'svn:eol-style' from file
 PROPS-END
 
 Node-path: file