subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hwri...@apache.org
Subject svn commit: r1231318 [29/35] - in /subversion/branches/revprop-packing: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/server-side/mod_dontdothat/ notes/ notes/http-and-webdav/ not...
Date Fri, 13 Jan 2012 21:40:38 GMT
Modified: subversion/branches/revprop-packing/subversion/tests/cmdline/basic_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/tests/cmdline/basic_tests.py?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/tests/cmdline/basic_tests.py (original)
+++ subversion/branches/revprop-packing/subversion/tests/cmdline/basic_tests.py Fri Jan 13 21:40:26 2012
@@ -999,6 +999,7 @@ def verify_dir_deleted(path):
 
   return 1
 
+@Issue(687,4074)
 def basic_delete(sbox):
   "basic delete command"
 
@@ -1182,7 +1183,7 @@ def basic_delete(sbox):
                                      'rm', '--force', foo_path)
   verify_file_deleted("Failed to remove unversioned file foo", foo_path)
 
-  # At one stage deleting an URL dumped core
+  # At one stage deleting a URL dumped core
   iota_URL = sbox.repo_url + '/iota'
 
   svntest.actions.run_and_verify_svn(None,
@@ -1190,6 +1191,12 @@ def basic_delete(sbox):
                                      'rm', '-m', 'delete iota URL',
                                      iota_URL)
 
+  # Issue 4074, deleting a root url SEGV.
+  expected_error = 'svn: E170000: .*not within a repository'
+  svntest.actions.run_and_verify_svn(None, [], expected_error,
+                                     'rm', sbox.repo_url,
+                                     '--message', 'delete root')
+
 #----------------------------------------------------------------------
 
 def basic_checkout_deleted(sbox):
@@ -1614,6 +1621,12 @@ def basic_add_parents(sbox):
                                         None,
                                         wc_dir)
 
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'rm', X_path, '--keep-local')
+
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'add', '--parents', zeta_path)
+
 #----------------------------------------------------------------------
 def uri_syntax(sbox):
   'make sure URI syntaxes are parsed correctly'
@@ -2623,7 +2636,7 @@ def basic_relocate(sbox):
   repo_dir = sbox.repo_dir
   repo_url = sbox.repo_url
   other_repo_dir, other_repo_url = sbox.add_repo_path('other')
-  shutil.copytree(repo_dir, other_repo_dir)
+  svntest.main.copy_repos(repo_dir, other_repo_dir, 1, 0)
 
   def _verify_url(wc_path, url):
     name = os.path.basename(wc_path)
@@ -2815,6 +2828,63 @@ def add_multiple_targets(sbox):
                                      'status', wc_dir)
 
 
+def quiet_commits(sbox):
+  "commits with --quiet"
+
+  sbox.build()
+
+  svntest.main.file_append(sbox.ospath('A/mu'), 'xxx')
+
+  svntest.actions.run_and_verify_svn(None, [], [],
+                                     'commit', sbox.wc_dir,
+                                     '--message', 'commit', '--quiet')
+
+  svntest.actions.run_and_verify_svn(None, [], [],
+                                     'mkdir', sbox.repo_url + '/X',
+                                     '--message', 'mkdir URL', '--quiet')
+
+  svntest.actions.run_and_verify_svn(None, [], [],
+                                     'import', sbox.ospath('A/mu'),
+                                     sbox.repo_url + '/f',
+                                     '--message', 'import', '--quiet')
+
+  svntest.actions.run_and_verify_svn(None, [], [],
+                                     'rm', sbox.repo_url + '/f',
+                                     '--message', 'rm URL', '--quiet')
+
+  svntest.actions.run_and_verify_svn(None, [], [],
+                                     'copy', sbox.repo_url + '/X',
+                                     sbox.repo_url + '/Y',
+                                     '--message', 'cp URL URL', '--quiet')
+
+  svntest.actions.run_and_verify_svn(None, [], [],
+                                     'move', sbox.repo_url + '/Y',
+                                     sbox.repo_url + '/Z',
+                                     '--message', 'mv URL URL', '--quiet')
+
+  # Not fully testing each command, just that they all commit and
+  # produce no output.
+  expected_output = wc.State(sbox.wc_dir, {
+    'X' : Item(status='A '),
+    'Z' : Item(status='A '),
+    })
+  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 7)
+  expected_status.add({
+      'X'   : Item(status='  ', wc_rev=7),
+      'Z'   : Item(status='  ', wc_rev=7),
+      })
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/mu',
+                      contents=expected_disk.desc['A/mu'].contents
+                      + 'xxx')
+  expected_disk.add({
+    'X' : Item(),
+    'Z' : Item()
+    })
+  svntest.actions.run_and_verify_update(sbox.wc_dir,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status)
 
 ########################################################################
 # Run the tests
@@ -2879,6 +2949,7 @@ test_list = [ None,
               ls_url_special_characters,
               ls_multiple_and_non_existent_targets,
               add_multiple_targets,
+              quiet_commits,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/revprop-packing/subversion/tests/cmdline/cat_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/tests/cmdline/cat_tests.py?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/tests/cmdline/cat_tests.py (original)
+++ subversion/branches/revprop-packing/subversion/tests/cmdline/cat_tests.py Fri Jan 13 21:40:26 2012
@@ -159,8 +159,7 @@ def cat_skip_uncattable(sbox):
                                        'cat', rho_path, new_file_path)
 
   expected_err3 = expected_err1 + expected_err2 + \
-      ".*svn: E200009: Could not cat all targets because some targets " + \
-      "don't exist\n"
+      ".*svn: E200009: Could not cat all targets because some targets"
   expected_err_re = re.compile(expected_err3, re.DOTALL)
 
   exit_code, output, error = svntest.main.run_svn(1, 'cat', rho_path, G_path, new_file_path)

Modified: subversion/branches/revprop-packing/subversion/tests/cmdline/commit_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/tests/cmdline/commit_tests.py?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/tests/cmdline/commit_tests.py (original)
+++ subversion/branches/revprop-packing/subversion/tests/cmdline/commit_tests.py Fri Jan 13 21:40:26 2012
@@ -1145,7 +1145,7 @@ def commit_in_dir_scheduled_for_addition
   svntest.actions.run_and_verify_commit(wc_dir,
                                         None,
                                         None,
-                                        "not under version control",
+                                        "not known to exist in the repository",
                                         mu_path)
 
   Q_path = os.path.join(wc_dir, 'Q')
@@ -1160,7 +1160,7 @@ def commit_in_dir_scheduled_for_addition
   svntest.actions.run_and_verify_commit(wc_dir,
                                         None,
                                         None,
-                                        "not under version control",
+                                        "not known to exist in the repository",
                                         bloo_path)
 
 #----------------------------------------------------------------------
@@ -2803,6 +2803,58 @@ def commit_multiple_nested_deletes(sbox)
 
   svntest.main.run_svn(None, 'ci', A, A_B, '-m', 'Q')
 
+@Issue(4042)
+def commit_incomplete(sbox):
+  "commit an incomplete dir"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  sbox.simple_propset('pname', 'pval', 'A/B')
+  svntest.actions.set_incomplete(sbox.ospath('A/B'), 1)
+
+  expected_output = svntest.wc.State(wc_dir, {
+      'A/B' : Item(verb='Sending'),
+      })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/B',  status='! ', wc_rev=2)
+
+  svntest.actions.run_and_verify_commit(wc_dir,
+                                        expected_output,
+                                        expected_status,
+                                        None,
+                                        wc_dir)
+  
+#----------------------------------------------------------------------
+# Reported here:
+#   Message-ID: <4EBF0FC9.300@gmail.com>
+#   Date: Sun, 13 Nov 2011 13:31:05 +1300
+#   From: Fergus Slorach <sugref@gmail.com>
+#   Subject: svn commit --targets behaviour change in 1.7?
+@Issue(4059)
+def commit_add_subadd(sbox):
+  "committing add with explicit subadd targets"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  targets_file = sbox.ospath('targets') # ### better tempdir?
+  targets_file = os.path.abspath(targets_file)
+
+  # prepare targets file
+  targets = "A/D A/D/H A/D/H/chi A/D/H/omega A/D/H/psi".split()
+  open(targets_file, 'w').write("\n".join(targets))
+
+  # r2: rm A/D
+  sbox.simple_rm('A/D')
+  sbox.simple_commit(message='rm')
+
+  # r3: revert r2, with specific invocation
+  os.chdir(wc_dir)
+  svntest.main.run_svn(None, 'up')
+  svntest.main.run_svn(None, 'merge', '-c', '-2', './')
+  svntest.main.run_svn(None, 'commit', '--targets', targets_file, '-mm')
+
 
 ########################################################################
 # Run the tests
@@ -2871,6 +2923,8 @@ test_list = [ None,
               tree_conflicts_block_commit,
               tree_conflicts_resolved,
               commit_multiple_nested_deletes,
+              commit_incomplete,
+              commit_add_subadd,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/revprop-packing/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/tests/cmdline/copy_tests.py?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/branches/revprop-packing/subversion/tests/cmdline/copy_tests.py Fri Jan 13 21:40:26 2012
@@ -3444,11 +3444,12 @@ def copy_peg_rev_url(sbox):
                                      wc_dir)
 
   # Copy using a peg rev
-  # Add peg rev '@HEAD' to sigma_url when copying which tests for issue #3651.
+  # Add an empty peg specifier ('@') to sigma_url when copying, to test for
+  # issue #3651 "svn copy does not eat peg revision within copy target path".
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'cp',
                                      iota_url + '@HEAD', '-r', '1',
-                                     sigma_url + '@HEAD', '-m', 'rev 3')
+                                     sigma_url + '@', '-m', 'rev 3')
 
   # Validate the copy destination's mergeinfo (we expect none).
   svntest.actions.run_and_verify_svn(None, [], [],
@@ -4653,9 +4654,15 @@ def changed_dir_data_should_match_checko
 
   os.chdir(was_cwd)
   os.chdir(wc_dir)
-  svntest.actions.run_and_verify_svn(None, verify_out, [], 'status', '-v')
+  rv, verify_out2, err = main.run_svn (None, 'status', '-v')
   os.chdir(was_cwd)
 
+  # The order of the status output is not absolutely defined, but
+  # otherwise should match
+  svntest.verify.verify_outputs(None,
+                                sorted(verify_out2), None,
+                                sorted(verify_out), None)
+
 def move_added_nodes(sbox):
   """move added nodes"""
 
@@ -5545,6 +5552,122 @@ def commit_deleted_half_of_move(sbox):
   svntest.actions.run_and_verify_svn(None, None, expected_error,
                                      'commit', '-m', 'foo', A_path)
 
+@Issue(4026)
+def wc_wc_copy_incomplete(sbox):
+  "wc-to-wc copy of an incomplete directory"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # We don't know whether copy will do E or F first, so make both
+  # incomplete
+  svntest.actions.set_incomplete(sbox.ospath('A/B/E'), 1)
+  svntest.actions.set_incomplete(sbox.ospath('A/B/F'), 1)
+
+  # Copy fails with no changes to wc
+  svntest.actions.run_and_verify_svn(None, None,
+                                     'svn: E155035: Cannot handle status',
+                                     'copy',
+                                     sbox.ospath('A/B/E'),
+                                     sbox.ospath('A/B/E2'))
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/B/E', 'A/B/F', status='! ')
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+  # Copy fails part way through
+  svntest.actions.run_and_verify_svn(None, None,
+                                     'svn: E155035: Cannot handle status',
+                                     'copy',
+                                     sbox.ospath('A/B'),
+                                     sbox.ospath('A/B2'))
+
+  expected_status.add({
+      'A/B2'        : Item(status='A ', copied='+', wc_rev='-'),
+      'A/B2/E'      : Item(status='! ', wc_rev='-'),
+      'A/B2/F'      : Item(status='! ', wc_rev='-'),
+      'A/B2/lambda' : Item(status='  ', copied='+', wc_rev='-'),
+      })
+  ### Can't get this to work as copied status of E and F in 1.6
+  ### entries tree doesn't match 1.7 status tree
+  #svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+  # Commit preserves incomplete status
+  expected_output = svntest.wc.State(wc_dir, {
+      'A/B2': Item(verb='Adding'),
+      })
+  expected_status.tweak('A/B2', 'A/B2/lambda',
+                        status='  ', copied=None, wc_rev=2)
+  expected_status.tweak('A/B2/E', 'A/B2/F',
+                        status='! ', copied=None, wc_rev=2)
+  ### E and F are status '!' but the test code ignores them?
+  expected_status.remove('A/B2/E', 'A/B2/F')
+  svntest.actions.run_and_verify_commit(wc_dir,
+                                        expected_output,
+                                        expected_status,
+                                        None, wc_dir)
+  expected_status.add({
+      'A/B2/E'       : Item(status='! ', wc_rev=2),
+      'A/B2/F'       : Item(status='! ', wc_rev=2),
+      })
+
+  # Update makes things complete
+  expected_output = svntest.wc.State(wc_dir, {
+      'A/B2/E'       : Item(status='A '),
+      'A/B2/E/alpha' : Item(status='A '),
+      'A/B2/E/beta'  : Item(status='A '),
+      'A/B2/F'       : Item(status='A '),
+      })
+  expected_status.tweak(wc_rev=2, status='  ')
+  expected_status.add({
+      'A/B2/E/alpha' : Item(status='  ', wc_rev=2),
+      'A/B2/E/beta'  : Item(status='  ', wc_rev=2),
+      })
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output,
+                                        None,
+                                        expected_status)
+
+def three_nested_moves(sbox):
+  "three nested moves"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  svntest.actions.run_and_verify_svn(None, None, [], 'mv',
+                                     sbox.ospath('A/B'),
+                                     sbox.ospath('A/B2'))
+  svntest.actions.run_and_verify_svn(None, None, [], 'mv',
+                                     sbox.ospath('A/B2/E'),
+                                     sbox.ospath('A/B2/E2'))
+  svntest.actions.run_and_verify_svn(None, None, [], 'mv',
+                                     sbox.ospath('A/B2/E2/alpha'),
+                                     sbox.ospath('A/B2/E2/alpha2'))
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+      'A/B2'           : Item(status='  ', wc_rev=2),
+      'A/B2/E2'        : Item(status='  ', wc_rev=2),
+      'A/B2/E2/alpha2' : Item(status='  ', wc_rev=2),
+      'A/B2/E2/beta'   : Item(status='  ', wc_rev=2),
+      'A/B2/F'         : Item(status='  ', wc_rev=2),
+      'A/B2/lambda'    : Item(status='  ', wc_rev=2),
+      })
+  expected_status.remove('A/B', 'A/B/E', 'A/B/E/alpha', 'A/B/E/beta',
+                         'A/B/F', 'A/B/lambda')
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/B'            : Item(verb='Deleting'),
+    'A/B2'           : Item(verb='Adding'),
+    'A/B2/E'         : Item(verb='Deleting'),
+    'A/B2/E2'        : Item(verb='Adding'),
+    'A/B2/E2/alpha'  : Item(verb='Deleting'),
+    'A/B2/E2/alpha2' : Item(verb='Adding'),
+    })
+
+  svntest.actions.run_and_verify_commit(wc_dir,
+                                        expected_output,
+                                        expected_status,
+                                        None, wc_dir)
+
 ########################################################################
 # Run the tests
 
@@ -5657,6 +5780,8 @@ test_list = [ None,
               copy_deleted_dir,
               commit_copied_half_of_move,
               commit_deleted_half_of_move,
+              wc_wc_copy_incomplete,
+              three_nested_moves,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/revprop-packing/subversion/tests/cmdline/dav-mirror-autocheck.sh
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/tests/cmdline/dav-mirror-autocheck.sh?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/tests/cmdline/dav-mirror-autocheck.sh (original)
+++ subversion/branches/revprop-packing/subversion/tests/cmdline/dav-mirror-autocheck.sh Fri Jan 13 21:40:26 2012
@@ -323,7 +323,7 @@ fi
 [ -r "$MOD_AUTHZ_SVN" ] \
   || fail "authz_svn_module not found, please use '--enable-shared --enable-dso --with-apxs' with your 'configure' script"
 
-export LD_LIBRARY_PATH="$ABS_BUILDDIR/subversion/libsvn_ra_neon/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_local/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_svn/.libs"
+export LD_LIBRARY_PATH="$ABS_BUILDDIR/subversion/libsvn_ra_neon/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_local/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_svn/.libs:$LD_LIBRARY_PATH"
 
 MASTER_REPOS="${MASTER_REPOS:-"$HTTPD_ROOT/master_repos"}"
 SLAVE_REPOS="${SLAVE_REPOS:-"$HTTPD_ROOT/slave_repos"}"

Modified: subversion/branches/revprop-packing/subversion/tests/cmdline/davautocheck.sh
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/tests/cmdline/davautocheck.sh?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/tests/cmdline/davautocheck.sh (original)
+++ subversion/branches/revprop-packing/subversion/tests/cmdline/davautocheck.sh Fri Jan 13 21:40:26 2012
@@ -195,7 +195,7 @@ fi
 [ -r "$MOD_AUTHZ_SVN" ] \
   || fail "authz_svn_module not found, please use '--enable-shared --enable-dso --with-apxs' with your 'configure' script"
 
-export LD_LIBRARY_PATH="$ABS_BUILDDIR/subversion/libsvn_ra_neon/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_local/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_svn/.libs"
+export LD_LIBRARY_PATH="$ABS_BUILDDIR/subversion/libsvn_ra_neon/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_local/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_svn/.libs:$LD_LIBRARY_PATH"
 
 case "`uname`" in
   Darwin*) LDD='otool -L'

Modified: subversion/branches/revprop-packing/subversion/tests/cmdline/depth_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/tests/cmdline/depth_tests.py?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/tests/cmdline/depth_tests.py (original)
+++ subversion/branches/revprop-packing/subversion/tests/cmdline/depth_tests.py Fri Jan 13 21:40:26 2012
@@ -1076,7 +1076,8 @@ def diff_in_depthy_wc(sbox):
     "___________________________________________________________________\n",
     "Deleted: foo\n",
     "## -1 +0,0 ##\n",
-    "-foo-val\n"]
+    "-foo-val\n",
+    "\\ No newline at end of property\n"]
 
   os.chdir(wc_empty)
 
@@ -2811,6 +2812,35 @@ def sparse_update_with_dash_dash_parents
                                         None, None, None, None, None, False,
                                         '--parents', omega_path)
 
+def update_below_depth_empty(sbox):
+  "update below depth empty shouldn't be applied"
+  sbox.build()
+
+  repo_url = sbox.repo_url
+  A = sbox.ospath('A')
+
+  expected_output = svntest.wc.State(sbox.wc_dir, {
+      'A/C'               : Item(status='D '),
+      'A/B'               : Item(status='D '),
+      'A/mu'              : Item(status='D '),
+      'A/D'               : Item(status='D '),
+    })
+  svntest.actions.run_and_verify_update(sbox.wc_dir, expected_output, None,
+                                        None, None, None, None, None, None,
+                                        False,
+                                        '--set-depth', 'empty', A)
+
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp', repo_url + '/iota',
+                                           repo_url + '/A/B',
+                                     '-m', 'remote copy')
+
+  expected_output = svntest.wc.State(sbox.wc_dir, {
+    })
+
+  # This update should just update the revision of the working copy
+  svntest.actions.run_and_verify_update(sbox.wc_dir, expected_output, None,
+                                        None, None)
 
 #----------------------------------------------------------------------
 # list all tests here, starting with None:
@@ -2858,6 +2888,7 @@ test_list = [ None,
               update_excluded_path_sticky_depths,
               update_depth_empty_root_of_infinite_children,
               sparse_update_with_dash_dash_parents,
+              update_below_depth_empty,
               ]
 
 if __name__ == "__main__":

Modified: subversion/branches/revprop-packing/subversion/tests/cmdline/diff_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/tests/cmdline/diff_tests.py?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/tests/cmdline/diff_tests.py (original)
+++ subversion/branches/revprop-packing/subversion/tests/cmdline/diff_tests.py Fri Jan 13 21:40:26 2012
@@ -57,6 +57,16 @@ def make_diff_header(path, old_tag, new_
     "+++ " + path_as_shown + "\t(" + new_tag + ")\n",
     ]
 
+def make_no_diff_deleted_header(path, old_tag, new_tag):
+  """Generate the expected diff header for a deleted file PATH when in
+  'no-diff-deleted' mode. (In that mode, no further details appear after the
+  header.) Return the header as an array of newline-terminated strings."""
+  path_as_shown = path.replace('\\', '/')
+  return [
+    "Index: " + path_as_shown + " (deleted)\n",
+    "===================================================================\n",
+    ]
+
 def make_git_diff_header(target_path, repos_relpath,
                          old_tag, new_tag, add=False, src_label=None,
                          dst_label=None, delete=False, text_changes=True,
@@ -83,66 +93,101 @@ def make_git_diff_header(target_path, re
   else:
     dst_label = ''
 
+  output = [
+    "Index: " + path_as_shown + "\n",
+    "===================================================================\n"
+  ]
   if add:
-    output = [
-      "Index: " + path_as_shown + "\n",
-      "===================================================================\n",
+    output.extend([
       "diff --git a/" + repos_relpath + " b/" + repos_relpath + "\n",
       "new file mode 10644\n",
-    ]
+    ])
     if text_changes:
       output.extend([
         "--- /dev/null\t(" + old_tag + ")\n",
         "+++ b/" + repos_relpath + dst_label + "\t(" + new_tag + ")\n"
       ])
   elif delete:
-    output = [
-      "Index: " + path_as_shown + "\n",
-      "===================================================================\n",
+    output.extend([
       "diff --git a/" + repos_relpath + " b/" + repos_relpath + "\n",
       "deleted file mode 10644\n",
-    ]
+    ])
     if text_changes:
       output.extend([
         "--- a/" + repos_relpath + src_label + "\t(" + old_tag + ")\n",
         "+++ /dev/null\t(" + new_tag + ")\n"
       ])
   elif cp:
-    output = [
-      "Index: " + path_as_shown + "\n",
-      "===================================================================\n",
+    output.extend([
       "diff --git a/" + copyfrom_path + " b/" + repos_relpath + "\n",
       "copy from " + copyfrom_path + "\n",
       "copy to " + repos_relpath + "\n",
-    ]
+    ])
     if text_changes:
       output.extend([
         "--- a/" + copyfrom_path + src_label + "\t(" + old_tag + ")\n",
         "+++ b/" + repos_relpath + "\t(" + new_tag + ")\n"
       ])
   elif mv:
-    return [
-      "Index: " + path_as_shown + "\n",
-      "===================================================================\n",
+    output.extend([
       "diff --git a/" + copyfrom_path + " b/" + path_as_shown + "\n",
       "rename from " + copyfrom_path + "\n",
       "rename to " + repos_relpath + "\n",
-    ]
+    ])
     if text_changes:
       output.extend([
         "--- a/" + copyfrom_path + src_label + "\t(" + old_tag + ")\n",
         "+++ b/" + repos_relpath + "\t(" + new_tag + ")\n"
       ])
   else:
-    output = [
-      "Index: " + path_as_shown + "\n",
-      "===================================================================\n",
+    output.extend([
       "diff --git a/" + repos_relpath + " b/" + repos_relpath + "\n",
       "--- a/" + repos_relpath + src_label + "\t(" + old_tag + ")\n",
       "+++ b/" + repos_relpath + dst_label + "\t(" + new_tag + ")\n",
-    ]
+    ])
   return output
 
+def make_diff_prop_header(path):
+  """Return a property diff sub-header, as a list of newline-terminated
+     strings."""
+  return [
+    "\n",
+    "Property changes on: " + path.replace('\\', '/') + "\n",
+    "___________________________________________________________________\n"
+  ]
+
+def make_diff_prop_val(plus_minus, pval):
+  "Return diff for prop value PVAL, with leading PLUS_MINUS (+ or -)."
+  if len(pval) > 0 and pval[-1] != '\n':
+    return [plus_minus + pval + "\n","\\ No newline at end of property\n"]
+  return [plus_minus + pval]
+  
+def make_diff_prop_deleted(pname, pval):
+  """Return a property diff for deletion of property PNAME, old value PVAL.
+     PVAL is a single string with no embedded newlines.  Return the result
+     as a list of newline-terminated strings."""
+  return [
+    "Deleted: " + pname + "\n",
+    "## -1 +0,0 ##\n"
+  ] + make_diff_prop_val("-", pval)
+
+def make_diff_prop_added(pname, pval):
+  """Return a property diff for addition of property PNAME, new value PVAL.
+     PVAL is a single string with no embedded newlines.  Return the result
+     as a list of newline-terminated strings."""
+  return [
+    "Added: " + pname + "\n",
+    "## -0,0 +1 ##\n",
+  ] + make_diff_prop_val("+", pval)
+
+def make_diff_prop_modified(pname, pval1, pval2):
+  """Return a property diff for modification of property PNAME, old value
+     PVAL1, new value PVAL2.  PVAL is a single string with no embedded
+     newlines.  Return the result as a list of newline-terminated strings."""
+  return [
+    "Modified: " + pname + "\n",
+    "## -1 +1 ##\n",
+  ] + make_diff_prop_val("-", pval1) + make_diff_prop_val("+", pval2)
 
 ######################################################################
 # Diff output checker
@@ -734,29 +779,20 @@ def diff_only_property_change(sbox):
   sbox.build()
   wc_dir = sbox.wc_dir
 
-  expected_output = [
-    "Index: iota\n",
-    "===================================================================\n",
-    "--- iota\t(revision 1)\n",
-    "+++ iota\t(revision 2)\n",
-    "\n",
-    "Property changes on: iota\n",
-    "___________________________________________________________________\n",
-    "Added: svn:eol-style\n",
-    "## -0,0 +1 ##\n",
-    "+native\n" ]
-
-  expected_reverse_output = list(expected_output)
-  expected_reverse_output[2] = expected_reverse_output[2].replace("1", "2")
-  expected_reverse_output[3] = expected_reverse_output[3].replace("2", "1")
-  expected_reverse_output[7] = expected_reverse_output[7].replace("Added",
-                                                                  "Deleted")
-  expected_reverse_output[8] = "## -1 +0,0 ##\n"
-  expected_reverse_output[9] = "-native\n"
-
-  expected_rev1_output = list(expected_output)
-  expected_rev1_output[3] = expected_rev1_output[3].replace("revision 2",
-                                                            "working copy")
+  expected_output = \
+    make_diff_header("iota", "revision 1", "revision 2") + \
+    make_diff_prop_header("iota") + \
+    make_diff_prop_added("svn:eol-style", "native")
+
+  expected_reverse_output = \
+    make_diff_header("iota", "revision 2", "revision 1") + \
+    make_diff_prop_header("iota") + \
+    make_diff_prop_deleted("svn:eol-style", "native")
+
+  expected_rev1_output = \
+    make_diff_header("iota", "revision 1", "working copy") + \
+    make_diff_prop_header("iota") + \
+    make_diff_prop_added("svn:eol-style", "native")
 
   os.chdir(sbox.wc_dir)
   svntest.actions.run_and_verify_svn(None, None, [],
@@ -1194,6 +1230,7 @@ def diff_deleted_in_head(sbox):
 
 
 #----------------------------------------------------------------------
+@Issue(2873)
 def diff_targets(sbox):
   "select diff targets"
 
@@ -1239,30 +1276,20 @@ def diff_targets(sbox):
                                                             update_path,
                                                             add_path)
 
-  regex = 'svn: E195012: Unable to find repository location for \'.*\''
-  for line in err_output:
-    if re.match(regex, line):
-      break
-  else:
+  if check_update_a_file(diff_output) or check_add_a_file(diff_output):
     raise svntest.Failure
 
   exit_code, diff_output, err_output = svntest.main.run_svn(1,
                                                             'diff', '-r1:2',
                                                             add_path)
-  for line in err_output:
-    if re.match(regex, line):
-      break
-  else:
+
+  if not check_update_a_file(diff_output) or check_add_a_file(diff_output):
     raise svntest.Failure
 
   exit_code, diff_output, err_output = svntest.main.run_svn(
     1, 'diff', '-r1:2', '--old', parent_path, 'alpha', 'theta')
 
-  regex = 'svn: E160013: \'.*\' was not found in the repository'
-  for line in err_output:
-    if re.match(regex, line):
-      break
-  else:
+  if check_update_a_file(diff_output) or check_add_a_file(diff_output):
     raise svntest.Failure
 
   exit_code, diff_output, err_output = svntest.main.run_svn(
@@ -2025,33 +2052,17 @@ def diff_property_changes_to_base(sbox):
   wc_dir = sbox.wc_dir
 
 
-  add_diff = [
-    "\n",
-    "Property changes on: A\n",
-    "___________________________________________________________________\n",
-    "Added: dirprop\n",
-    "## -0,0 +1 ##\n",
-    "+r2value\n",
-    "\n",
-    "Property changes on: iota\n",
-    "___________________________________________________________________\n",
-    "Added: fileprop\n",
-    "## -0,0 +1 ##\n",
-    "+r2value\n"]
-
-  del_diff = [
-    "\n",
-    "Property changes on: A\n",
-    "___________________________________________________________________\n",
-    "Deleted: dirprop\n",
-    "## -1 +0,0 ##\n",
-    "-r2value\n",
-    "\n",
-    "Property changes on: iota\n",
-    "___________________________________________________________________\n",
-    "Deleted: fileprop\n",
-    "## -1 +0,0 ##\n",
-    "-r2value\n"]
+  add_diff = \
+    make_diff_prop_header("A") + \
+    make_diff_prop_added("dirprop", "r2value") + \
+    make_diff_prop_header("iota") + \
+    make_diff_prop_added("fileprop", "r2value")
+
+  del_diff = \
+    make_diff_prop_header("A") + \
+    make_diff_prop_deleted("dirprop", "r2value") + \
+    make_diff_prop_header("iota") + \
+    make_diff_prop_deleted("fileprop", "r2value")
 
 
   expected_output_r1_r2 = list(make_diff_header('A', 'revision 1', 'revision 2')
@@ -2287,35 +2298,15 @@ def diff_prop_change_local_propmod(sbox)
 
   sbox.build()
 
-  expected_output_r2_wc = [
-    "Index: A\n",
-    "===================================================================\n",
-    "--- A\t(revision 2)\n",
-    "+++ A\t(working copy)\n",
-    "\n",
-    "Property changes on: A\n",
-    "___________________________________________________________________\n",
-    "Modified: dirprop\n",
-    "## -1 +1 ##\n",
-    "-r2value\n",
-    "+workingvalue\n",
-    "Added: newdirprop\n",
-    "## -0,0 +1 ##\n",
-    "+newworkingvalue\n",
-    "Index: iota\n",
-    "===================================================================\n",
-    "--- iota\t(revision 2)\n",
-    "+++ iota\t(working copy)\n",
-    "\n",
-    "Property changes on: iota\n",
-    "___________________________________________________________________\n",
-    "Modified: fileprop\n",
-    "## -1 +1 ##\n",
-    "-r2value\n",
-    "+workingvalue\n",
-    "Added: newfileprop\n",
-    "## -0,0 +1 ##\n",
-    "+newworkingvalue\n" ]
+  expected_output_r2_wc = \
+    make_diff_header("A", "revision 2", "working copy") + \
+    make_diff_prop_header("A") + \
+    make_diff_prop_modified("dirprop", "r2value", "workingvalue") + \
+    make_diff_prop_added("newdirprop", "newworkingvalue") + \
+    make_diff_header("iota", "revision 2", "working copy") + \
+    make_diff_prop_header("iota") + \
+    make_diff_prop_modified("fileprop", "r2value", "workingvalue") + \
+    make_diff_prop_added("newfileprop", "newworkingvalue")
 
   os.chdir(sbox.wc_dir)
 
@@ -2378,31 +2369,16 @@ def diff_repos_wc_add_with_props(sbox):
   diff_foo = [
     "@@ -0,0 +1 @@\n",
     "+content\n",
-    "\n",
-    "Property changes on: foo\n",
-    "___________________________________________________________________\n",
-    "Added: propname\n",
-    "## -0,0 +1 ##\n",
-    "+propvalue\n",
-    ]
-  diff_X = [
-    "\n",
-    "Property changes on: X\n",
-    "___________________________________________________________________\n",
-    "Added: propname\n",
-    "## -0,0 +1 ##\n",
-    "+propvalue\n",
-    ]
+    ] + make_diff_prop_header("foo") + \
+    make_diff_prop_added("propname", "propvalue")
+  diff_X = \
+    make_diff_prop_header("X") + \
+    make_diff_prop_added("propname", "propvalue")
   diff_X_bar = [
     "@@ -0,0 +1 @@\n",
     "+content\n",
-    "\n",
-    "Property changes on: X/bar\n",
-    "___________________________________________________________________\n",
-    "Added: propname\n",
-    "## -0,0 +1 ##\n",
-    "+propvalue\n",
-    ]
+    ] + make_diff_prop_header("X/bar") + \
+    make_diff_prop_added("propname", "propvalue")
 
   diff_X_r1_base = make_diff_header("X", "revision 1",
                                          "working copy") + diff_X
@@ -2876,49 +2852,32 @@ def diff_with_depth(sbox):
   sbox.build()
   B_path = os.path.join('A', 'B')
 
-  diff = [
-    "\n",
-    "Property changes on: .\n",
-    "___________________________________________________________________\n",
-    "Added: foo1\n",
-    "## -0,0 +1 ##\n",
-    "+bar1\n",
-    "\n",
-    "Property changes on: iota\n",
-    "___________________________________________________________________\n",
-    "Added: foo2\n",
-    "## -0,0 +1 ##\n",
-    "+bar2\n",
-    "\n",
-    "Property changes on: A\n",
-    "___________________________________________________________________\n",
-    "Added: foo3\n",
-    "## -0,0 +1 ##\n",
-    "+bar3\n",
-    "\n",
-    "Property changes on: A/B\n",
-    "___________________________________________________________________\n",
-    "Added: foo4\n",
-    "## -0,0 +1 ##\n",
-    "+bar4\n"]
+  diff = make_diff_prop_header(".") + \
+         make_diff_prop_added("foo1", "bar1") + \
+         make_diff_prop_header("iota") + \
+         make_diff_prop_added("foo2", "bar2") + \
+         make_diff_prop_header("A") + \
+         make_diff_prop_added("foo3", "bar3") + \
+         make_diff_prop_header("A/B") + \
+         make_diff_prop_added("foo4", "bar4")
 
   dot_header = make_diff_header(".", "revision 1", "working copy")
   iota_header = make_diff_header('iota', "revision 1", "working copy")
   A_header = make_diff_header('A', "revision 1", "working copy")
   B_header = make_diff_header(B_path, "revision 1", "working copy")
 
-  expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:6])
-  expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:6]
-                                                  + iota_header + diff[7:12])
-  expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:6]
+  expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:7])
+  expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:7]
+                                                  + iota_header + diff[8:14])
+  expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:7]
                                                        + iota_header
-                                                       + diff[7:12]
-                                                       +  A_header + diff[8:18])
-  expected_infinity = svntest.verify.UnorderedOutput(dot_header + diff[:6]
+                                                       + diff[8:14]
+                                                       + A_header + diff[15:21])
+  expected_infinity = svntest.verify.UnorderedOutput(dot_header + diff[:7]
                                                        + iota_header
-                                                       + diff[7:12]
-                                                       +  A_header + diff[8:18]
-                                                       + B_header + diff[12:])
+                                                       + diff[8:14]
+                                                       + A_header + diff[15:21]
+                                                       + B_header + diff[22:])
 
   os.chdir(sbox.wc_dir)
 
@@ -2954,18 +2913,18 @@ def diff_with_depth(sbox):
   A_header = make_diff_header('A', "revision 1", "revision 2")
   B_header = make_diff_header(B_path, "revision 1", "revision 2")
 
-  expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:6])
-  expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:6]
-                                                  + iota_header + diff[7:12])
-  expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:6]
+  expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:7])
+  expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:7]
+                                                  + iota_header + diff[8:14])
+  expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:7]
                                                        + iota_header
-                                                       + diff[7:12]
-                                                       +  A_header + diff[8:18])
+                                                       + diff[8:14]
+                                                       + A_header + diff[15:21])
   expected_infinity = svntest.verify.UnorderedOutput(dot_header + diff[:6]
                                                        + iota_header
-                                                       + diff[7:12]
-                                                       +  A_header + diff[8:18]
-                                                       + B_header + diff[12:])
+                                                       + diff[8:14]
+                                                       + A_header + diff[15:21]
+                                                       + B_header + diff[22:])
 
   # Test repos-repos diff.
   svntest.actions.run_and_verify_svn(None, expected_empty, [],
@@ -2977,66 +2936,31 @@ def diff_with_depth(sbox):
   svntest.actions.run_and_verify_svn(None, expected_infinity, [],
                                      'diff', '-c2', '--depth', 'infinity')
 
-  diff_wc_repos = [
-    "Index: A/B\n",
-    "===================================================================\n",
-    "--- A/B\t(revision 2)\n",
-    "+++ A/B\t(working copy)\n",
-    "\n",
-    "Property changes on: A/B\n",
-    "___________________________________________________________________\n",
-    "Modified: foo4\n",
-    "## -1 +1 ##\n",
-    "-bar4\n",
-    "+baz4\n",
-    "Index: A\n",
-    "===================================================================\n",
-    "--- A\t(revision 2)\n",
-    "+++ A\t(working copy)\n",
-    "\n",
-    "Property changes on: A\n",
-    "___________________________________________________________________\n",
-    "Modified: foo3\n",
-    "## -1 +1 ##\n",
-    "-bar3\n",
-    "+baz3\n",
-    "Index: A/mu\n",
-    "===================================================================\n",
-    "--- A/mu\t(revision 1)\n",
-    "+++ A/mu\t(working copy)\n",
+  diff_wc_repos = \
+    make_diff_header("A/B", "revision 2", "working copy") + \
+    make_diff_prop_header("A/B") + \
+    make_diff_prop_modified("foo4", "bar4", "baz4") + \
+    make_diff_header("A", "revision 2", "working copy") + \
+    make_diff_prop_header("A") + \
+    make_diff_prop_modified("foo3", "bar3", "baz3") + \
+    make_diff_header("A/mu", "revision 1", "working copy") + [
     "@@ -1 +1,2 @@\n",
     " This is the file 'mu'.\n",
     "+new text\n",
-    "Index: iota\n",
-    "===================================================================\n",
-    "--- iota\t(revision 2)\n",
-    "+++ iota\t(working copy)\n",
+    ] + make_diff_header("iota", "revision 2", "working copy") + [
     "@@ -1 +1,2 @@\n",
     " This is the file 'iota'.\n",
     "+new text\n",
-    "\n",
-    "Property changes on: iota\n",
-    "___________________________________________________________________\n",
-    "Modified: foo2\n",
-    "## -1 +1 ##\n",
-    "-bar2\n",
-    "+baz2\n",
-    "Index: .\n",
-    "===================================================================\n",
-    "--- .\t(revision 2)\n",
-    "+++ .\t(working copy)\n",
-    "\n",
-    "Property changes on: .\n",
-    "___________________________________________________________________\n",
-    "Modified: foo1\n",
-    "## -1 +1 ##\n",
-    "-bar1\n",
-    "+baz1\n" ]
-
-  expected_empty = svntest.verify.UnorderedOutput(diff_wc_repos[43:])
-  expected_files = svntest.verify.UnorderedOutput(diff_wc_repos[29:])
-  expected_immediates = svntest.verify.UnorderedOutput(diff_wc_repos[11:22]
-                                                       +diff_wc_repos[29:])
+    ] + make_diff_prop_header("iota") + \
+    make_diff_prop_modified("foo2", "bar2", "baz2") + \
+    make_diff_header(".", "revision 2", "working copy") + \
+    make_diff_prop_header(".") + \
+    make_diff_prop_modified("foo1", "bar1", "baz1")
+
+  expected_empty = svntest.verify.UnorderedOutput(diff_wc_repos[49:])
+  expected_files = svntest.verify.UnorderedOutput(diff_wc_repos[33:])
+  expected_immediates = svntest.verify.UnorderedOutput(diff_wc_repos[13:26]
+                                                       +diff_wc_repos[33:])
   expected_infinity = svntest.verify.UnorderedOutput(diff_wc_repos[:])
 
   svntest.actions.run_and_verify_svn(None, None, [],
@@ -3542,10 +3466,8 @@ def diff_prop_missing_context(sbox):
   svntest.main.run_svn(None,
                        "propset", "prop", prop_val, iota_path)
   expected_output = make_diff_header(iota_path, 'revision 2',
-                                     'working copy') + [
-    "\n",
-    "Property changes on: %s\n" % iota_path.replace('\\', '/'),
-    "___________________________________________________________________\n",
+                                     'working copy') + \
+                    make_diff_prop_header(iota_path) + [
     "Modified: prop\n",
     "## -1,7 +1,4 ##\n",
     "-line 1\n",
@@ -3612,10 +3534,8 @@ def diff_prop_multiple_hunks(sbox):
   svntest.main.run_svn(None,
                        "propset", "prop", prop_val, iota_path)
   expected_output = make_diff_header(iota_path, 'revision 2',
-                                     'working copy') + [
-    "\n",
-    "Property changes on: %s\n" % iota_path.replace('\\', '/'),
-    "___________________________________________________________________\n",
+                                     'working copy') + \
+                    make_diff_prop_header(iota_path) + [
     "Modified: prop\n",
     "## -1,6 +1,7 ##\n",
     " line 1\n",
@@ -3697,28 +3617,59 @@ def diff_git_with_props(sbox):
   svntest.main.run_svn(None, 'propset', 'svn:eol-style', 'native', new_path)
   svntest.main.run_svn(None, 'propset', 'svn:keywords', 'Id', iota_path)
 
-  expected_output = make_git_diff_header(new_path, "new", "revision 0",
-                                         "working copy",
-                                         add=True, text_changes=False) + [
-      "\n",
-      "Property changes on: new\n",
-      "___________________________________________________________________\n",
-      "Added: svn:eol-style\n",
-      "## -0,0 +1 ##\n",
-      "+native\n",
-  ] + make_git_diff_header(iota_path, "iota", "revision 1", "working copy",
-                           text_changes=False) + [
-      "\n",
-      "Property changes on: iota\n",
-      "___________________________________________________________________\n",
-      "Added: svn:keywords\n",
-      "## -0,0 +1 ##\n",
-      "+Id\n",
-  ]
+  expected_output = make_git_diff_header(new_path, "new",
+                                         "revision 0", "working copy",
+                                         add=True, text_changes=False) + \
+                    make_diff_prop_header("new") + \
+                    make_diff_prop_added("svn:eol-style", "native") + \
+                    make_git_diff_header(iota_path, "iota",
+                                         "revision 1", "working copy",
+                                         text_changes=False) + \
+                    make_diff_prop_header("iota") + \
+                    make_diff_prop_added("svn:keywords", "Id")
+
+  svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
+                                     '--git', wc_dir)
+
+@XFail()
+@Issue(4010)
+def diff_correct_wc_base_revnum(sbox):
+  "diff WC-WC shows the correct base rev num"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  iota_path = os.path.join(wc_dir, 'iota')
+  svntest.main.file_write(iota_path, "")
+
+  # Commit a local mod, creating rev 2.
+  expected_output = svntest.wc.State(wc_dir, {
+    'iota' : Item(verb='Sending'),
+    })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'iota' : Item(status='  ', wc_rev=2),
+    })
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, None, wc_dir)
+
+  # Child's base is now 2; parent's is still 1.
+  # Make a local mod.
+  svntest.main.run_svn(None, 'propset', 'svn:keywords', 'Id', iota_path)
+
+  expected_output = make_git_diff_header(iota_path, "iota",
+                                         "revision 2", "working copy") + \
+                    make_diff_prop_header("iota") + \
+                    make_diff_prop_added("svn:keywords", "Id")
 
+  # Diff the parent.
   svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
                                      '--git', wc_dir)
 
+  # The same again, but specifying the target explicity. This should
+  # give the same output.
+  svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
+                                     '--git', iota_path)
+
 def diff_git_with_props_on_dir(sbox):
   "diff in git format showing prop changes on dir"
   sbox.build()
@@ -3742,14 +3693,9 @@ def diff_git_with_props_on_dir(sbox):
   os.chdir(wc_dir)
   expected_output = make_git_diff_header(".", "", "revision 1",
                                          "revision 2",
-                                         add=False, text_changes=False) + [
-      "\n",
-      "Property changes on: \n",
-      "___________________________________________________________________\n",
-      "Added: a\n",
-      "## -0,0 +1 ##\n",
-      "+b\n",
-  ]
+                                         add=False, text_changes=False) + \
+                    make_diff_prop_header("") + \
+                    make_diff_prop_added("a", "b")
 
   svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
                                      '-c2', '--git')
@@ -3873,6 +3819,7 @@ test_list = [ None,
               diff_git_with_props_on_dir,
               diff_abs_localpath_from_wc_folder,
               no_spurious_conflict,
+              diff_correct_wc_base_revnum,
               ]
 
 if __name__ == '__main__':

Modified: subversion/branches/revprop-packing/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/tests/cmdline/externals_tests.py?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/branches/revprop-packing/subversion/tests/cmdline/externals_tests.py Fri Jan 13 21:40:26 2012
@@ -225,7 +225,7 @@ def change_external_expect_error(path, n
   but expect to get an error message that matches EXPECTED_ERR."""
 
   svntest.actions.set_prop('svn:externals', new_val, path,
-                           expected_err=expected_err)
+                           expected_re_string=expected_err)
 
 
 def probe_paths_exist(paths):
@@ -706,6 +706,13 @@ def disallow_dot_or_dotdot_directory_ref
   if not external_urls: external_urls = list(external_url_for.values())
   externals_value_8 = external_urls.pop() + " /foo \n"
   if not external_urls: external_urls = list(external_url_for.values())
+  if svntest.main.is_os_windows():
+    externals_value_9 = external_urls.pop() + " D:/foo\n"
+    if not external_urls: external_urls = list(external_url_for.values())
+    externals_value_10 = external_urls.pop() + " D:\\foo\n"
+    if not external_urls: external_urls = list(external_url_for.values())
+    externals_value_11 = external_urls.pop() + " D:foo\n"
+    if not external_urls: external_urls = list(external_url_for.values())
 
   set_externals_for_path_expect_error(B_path, externals_value_1)
   set_externals_for_path_expect_error(G_path, externals_value_2)
@@ -715,6 +722,10 @@ def disallow_dot_or_dotdot_directory_ref
   set_externals_for_path_expect_error(B_path, externals_value_6)
   set_externals_for_path_expect_error(G_path, externals_value_7)
   set_externals_for_path_expect_error(H_path, externals_value_8)
+  if svntest.main.is_os_windows():
+    set_externals_for_path_expect_error(B_path, externals_value_9)
+    set_externals_for_path_expect_error(B_path, externals_value_10)
+    set_externals_for_path_expect_error(B_path, externals_value_11)
 
 
 #----------------------------------------------------------------------
@@ -1886,7 +1897,7 @@ def file_externals_different_repos(sbox)
   r1_url = sbox.repo_url
 
   r2_dir, r2_url = sbox.add_repo_path('2')
-  shutil.copytree(sbox.repo_dir, r2_dir)
+  svntest.main.copy_repos(sbox.repo_dir, r2_dir, 1, 0)
 
 
   sbox.simple_propset('svn:externals',
@@ -1921,6 +1932,777 @@ def file_externals_different_repos(sbox)
                                         expected_output, None, None,
                                         'svn: warning: W200007: Unsupported.*')
 
+def file_external_in_unversioned(sbox):
+  "file external in unversioned dir"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  sbox.simple_propset('svn:externals', '^/A/mu X/mu', 'A')
+
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/X/mu' : Item(status='A '),
+  })
+  svntest.actions.run_and_verify_update(wc_dir, expected_output, None, None)
+
+  # At one point this failed with SVN_DEBUG wcng consistency checks enabled
+  svntest.actions.run_and_verify_svn(None, None, [], 'cleanup', wc_dir)
+
+
+from svntest import verify, actions, main
+
+@Issue(3589, 4000)
+def copy_file_externals(sbox):
+  "a WC->WC copy should exclude file externals"
+
+  #  svntest.factory.make(sbox,"""
+  #  svn mkdir X
+  #  ### manual edit: add '\n ^/A/mu xmu' to externals definition:
+  #  svn ps svn:externals "^/iota xiota" X
+  #  """)
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  X = os.path.join(wc_dir, 'X')
+
+  # svn mkdir X
+  expected_stdout = ['A         ' + X + '\n']
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'mkdir', X)
+
+  # svn ps svn:externals "^/iota xiota" X
+  expected_stdout = ["property 'svn:externals' set on '" + X + "'\n"]
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'ps',
+    'svn:externals', '''
+    ^/iota xiota
+    ^/A/mu xmu
+    ''', X)
+
+  #  svntest.factory.make(sbox, '''
+  #  svn ci
+  #  svn up
+  #  # have a commit on one of the files
+  #  echo mod >> X/xmu
+  #  svn ci X/xmu
+  #  svn up
+  #  # now perform the WC->WC copy
+  #  svn cp X X_copy
+  #  ### manual edit: add a verify_disk(check_props=True) here
+  #  svn ci
+  #  ### manual edit: add check_props=True to below update
+  #  svn up
+  #  ''')
+
+  X = os.path.join(wc_dir, 'X')
+  X_copy = os.path.join(wc_dir, 'X_copy')
+  X_xmu = os.path.join(wc_dir, 'X', 'xmu')
+
+  # svn ci
+  expected_output = svntest.wc.State(wc_dir, {
+    'X'                 : Item(verb='Adding'),
+  })
+
+  expected_status = actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'X'                 : Item(status='  ', wc_rev='2'),
+  })
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/xmu'             : Item(status='A '),
+    'X/xiota'           : Item(status='A '),
+  })
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'X'                 : Item(),
+    'X/xiota'           : Item(contents="This is the file 'iota'.\n"),
+    'X/xmu'             : Item(contents="This is the file 'mu'.\n"),
+  })
+
+  expected_status.add({
+    'X/xiota'           : Item(status='  ', wc_rev='2', switched='X'),
+    'X/xmu'             : Item(status='  ', wc_rev='2', switched='X'),
+  })
+  expected_status.tweak(wc_rev='2')
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # have a commit on one of the files
+  # echo mod >> X/xmu
+  main.file_append(X_xmu, 'mod\n')
+
+  # svn ci X/xmu
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/xmu'             : Item(verb='Sending'),
+  })
+
+  expected_status.tweak('X/xmu', wc_rev='3')
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, X_xmu)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/mu'              : Item(status='U '),
+  })
+
+  expected_disk.tweak('A/mu', 'X/xmu',
+    contents="This is the file 'mu'.\nmod\n")
+
+  expected_status.tweak(wc_rev='3')
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # now perform the WC->WC copy
+  # svn cp X X_copy
+  expected_stdout = ['A         ' + X_copy + '\n']
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'cp', X,
+    X_copy)
+
+  # svn ci
+  expected_output = svntest.wc.State(wc_dir, {
+    'X_copy'            : Item(verb='Adding'),
+  })
+
+  expected_status.add({
+    'X_copy'            : Item(status='  ', wc_rev='4'),
+  })
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # verify disk state, also verifying props
+  expected_disk.add({
+    'X_copy'            : Item(),
+  })
+  expected_disk.tweak('X', 'X_copy',
+    props={'svn:externals' : '\n    ^/iota xiota\n    ^/A/mu xmu\n    \n'})
+
+  actions.verify_disk(wc_dir, expected_disk, True)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'X_copy/xmu'        : Item(status='A '),
+    'X_copy/xiota'      : Item(status='A '),
+  })
+
+  expected_disk.add({
+    'X_copy/xmu'        : Item(contents="This is the file 'mu'.\nmod\n"),
+    'X_copy/xiota'      : Item(contents="This is the file 'iota'.\n"),
+  })
+
+  expected_status.add({
+    'X_copy/xmu'        : Item(status='  ', wc_rev='4', switched='X'),
+    'X_copy/xiota'      : Item(status='  ', wc_rev='4', switched='X'),
+  })
+  expected_status.tweak(wc_rev='4')
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, True, wc_dir)
+
+def include_externals(sbox):
+  "commit --include-externals"
+  # svntest.factory.make(sbox, """
+  #   mkdir Z
+  #   echo 'This is the file zeta.' > Z/zeta
+  #   svn add Z
+  #   svn mkdir --parents Xpegged X/Y
+  #   svn ci
+  #   svn up
+  #   svn ps svn:externals "^/Z xZ" A/D/H
+  #   svn ps svn:externals "^/iota@1 Xpegged/xiota" wc_dir
+  #   # ^^^ manually set externals to:
+  #   #  ^/iota@1 Xpegged/xiota
+  #   #  -r1 ^/A/B/E Xpegged/xE
+  #   #  ^/A/mu X/xmu
+  #   #  ^/A/B/lambda X/Y/xlambda
+  #   #  ^/A/D/G X/xG
+  #   #  ^/A/D/H X/Y/xH
+  #   """)
+  # exit(0)
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  A_D_H = os.path.join(wc_dir, 'A', 'D', 'H')
+  X = os.path.join(wc_dir, 'X')
+  X_Y = os.path.join(wc_dir, 'X', 'Y')
+  Xpegged = os.path.join(wc_dir, 'Xpegged')
+  Z = os.path.join(wc_dir, 'Z')
+  Z_zeta = os.path.join(wc_dir, 'Z', 'zeta')
+
+  # mkdir Z
+  os.makedirs(Z)
+
+  # echo 'This is the file zeta.' > Z/zeta
+  main.file_write(Z_zeta, 'This is the file zeta.\n')
+
+  # svn add Z
+  expected_stdout = verify.UnorderedOutput([
+    'A         ' + Z + '\n',
+    'A         ' + Z_zeta + '\n',
+  ])
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'add', Z)
+
+  # svn mkdir --parents Xpegged X/Y
+  expected_stdout = verify.UnorderedOutput([
+    'A         ' + Xpegged + '\n',
+    'A         ' + X + '\n',
+    'A         ' + X_Y + '\n',
+  ])
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'mkdir',
+    '--parents', Xpegged, X_Y)
+
+  # svn ci
+  expected_output = svntest.wc.State(wc_dir, {
+    'Z'                 : Item(verb='Adding'),
+    'Z/zeta'            : Item(verb='Adding'),
+    'X'                 : Item(verb='Adding'),
+    'X/Y'               : Item(verb='Adding'),
+    'Xpegged'           : Item(verb='Adding'),
+  })
+
+  expected_status = actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'Z'                 : Item(status='  ', wc_rev='2'),
+    'Z/zeta'            : Item(status='  ', wc_rev='2'),
+    'X'                 : Item(status='  ', wc_rev='2'),
+    'X/Y'               : Item(status='  ', wc_rev='2'),
+    'Xpegged'           : Item(status='  ', wc_rev='2'),
+  })
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {})
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'Z'                 : Item(),
+    'Z/zeta'            : Item(contents="This is the file zeta.\n"),
+    'Xpegged'           : Item(),
+    'X'                 : Item(),
+    'X/Y'               : Item(),
+  })
+
+  expected_status.tweak(wc_rev='2')
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # svn ps svn:externals "^/Z xZ" A/D/H
+  expected_stdout = ["property 'svn:externals' set on '" + A_D_H + "'\n"]
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'ps',
+    'svn:externals', '^/Z xZ', A_D_H)
+
+  # svn ps svn:externals "^/iota@1 Xpegged/xiota" wc_dir
+  expected_stdout = ["property 'svn:externals' set on '" + wc_dir + "'\n"]
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'ps',
+    'svn:externals',
+    '''
+      ^/iota@1 Xpegged/xiota
+      -r1 ^/A/B/E Xpegged/xE
+      ^/A/mu X/xmu
+      ^/A/B/lambda X/Y/xlambda
+      ^/A/D/G X/xG
+      ^/A/D/H X/Y/xH
+    ''', wc_dir)
+
+  # svntest.factory.make(sbox, prev_disk=expected_disk,
+  #                      prev_status=expected_status,
+  #                      commands = """
+  #   svn ci
+  #   svn up
+  #   echo mod >> Xpegged/xE/alpha
+  #   echo mod >> X/xmu
+  #   echo mod >> X/Y/xlambda
+  #   echo mod >> X/xG/pi
+  #   echo mod >> X/Y/xH/chi
+  #   echo mod >> X/Y/xH/xZ/zeta
+  #   svn status
+  #   # Expect no externals to be committed
+  #   svn ci
+  #   # Expect no externals to be committed, because pegged
+  #   svn ci --include-externals Xpegged
+  #   # Expect no externals to be committed, because of depth
+  #   svn ci --depth=immediates --include-externals
+  #   # Expect only unpegged externals to be committed (those in X/)
+  #   svn ci --include-externals
+  #   # ### Below, manually add:
+  #   # expected_status.tweak('A/D/H/xZ', 'Xpegged/xE', 'X/Y/xH', 'X/xG',
+  #   #                       wc_rev=None)
+  #   svn up
+  #   # new mods to check more cases
+  #   echo mod >> X/xmu
+  #   echo mod >> X/Y/xlambda
+  #   echo mod >> X/xG/pi
+  #   echo mod >> X/Y/xH/chi
+  #   echo mod >> X/Y/xH/xZ/zeta
+  #   svn status
+  #   # Expect no externals to be committed, because of depth
+  #   svn ci --include-externals --depth=empty X
+  #   # Expect only file external xmu to be committed, because of depth
+  #   svn ci --include-externals --depth=files X
+  #   svn status
+  #   # ### Below, manually add:
+  #   # expected_status.tweak('A/D/H/xZ', 'Xpegged/xE', 'X/Y/xH', 'X/xG',
+  #   #                       wc_rev=None)
+  #   svn up
+  #   echo mod >> X/xG/pi
+  #   svn status
+  #   # Expect explicit targets to be committed
+  #   svn ci X/Y/xlambda X/xG
+  #   svn status
+  #   """)
+
+  X = os.path.join(wc_dir, 'X')
+  X_xG = os.path.join(wc_dir, 'X', 'xG')
+  X_xG_pi = os.path.join(wc_dir, 'X', 'xG', 'pi')
+  X_xmu = os.path.join(wc_dir, 'X', 'xmu')
+  X_Y_xH_chi = os.path.join(wc_dir, 'X', 'Y', 'xH', 'chi')
+  X_Y_xH_xZ_zeta = os.path.join(wc_dir, 'X', 'Y', 'xH', 'xZ', 'zeta')
+  X_Y_xlambda = os.path.join(wc_dir, 'X', 'Y', 'xlambda')
+  Xpegged = os.path.join(wc_dir, 'Xpegged')
+  Xpegged_xE_alpha = os.path.join(wc_dir, 'Xpegged', 'xE', 'alpha')
+
+  # svn ci
+  expected_output = svntest.wc.State(wc_dir, {
+    ''                  : Item(verb='Sending'),
+    'A/D/H'             : Item(verb='Sending'),
+  })
+
+  expected_status.tweak('', 'A/D/H', wc_rev='3')
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/xmu'             : Item(status='A '),
+    'X/xG/tau'          : Item(status='A '),
+    'X/xG/rho'          : Item(status='A '),
+    'X/xG/pi'           : Item(status='A '),
+    'X/Y/xH'            : Item(status=' U'),
+    'X/Y/xH/psi'        : Item(status='A '),
+    'X/Y/xH/xZ/zeta'    : Item(status='A '),
+    'X/Y/xH/chi'        : Item(status='A '),
+    'X/Y/xH/omega'      : Item(status='A '),
+    'X/Y/xlambda'       : Item(status='A '),
+    'A/D/H/xZ/zeta'     : Item(status='A '),
+    'Xpegged/xiota'     : Item(status='A '),
+    'Xpegged/xE/alpha'  : Item(status='A '),
+    'Xpegged/xE/beta'   : Item(status='A '),
+  })
+
+  expected_disk.add({
+    'Xpegged/xE'        : Item(),
+    'Xpegged/xE/beta'   : Item(contents="This is the file 'beta'.\n"),
+    'Xpegged/xE/alpha'  : Item(contents="This is the file 'alpha'.\n"),
+    'Xpegged/xiota'     : Item(contents="This is the file 'iota'.\n"),
+    'A/D/H/xZ'          : Item(),
+    'A/D/H/xZ/zeta'     : Item(contents="This is the file zeta.\n"),
+    'X/Y/xlambda'       : Item(contents="This is the file 'lambda'.\n"),
+    'X/Y/xH'            : Item(),
+    'X/Y/xH/chi'        : Item(contents="This is the file 'chi'.\n"),
+    'X/Y/xH/xZ'         : Item(),
+    'X/Y/xH/xZ/zeta'    : Item(contents="This is the file zeta.\n"),
+    'X/Y/xH/psi'        : Item(contents="This is the file 'psi'.\n"),
+    'X/Y/xH/omega'      : Item(contents="This is the file 'omega'.\n"),
+    'X/xmu'             : Item(contents="This is the file 'mu'.\n"),
+    'X/xG'              : Item(),
+    'X/xG/tau'          : Item(contents="This is the file 'tau'.\n"),
+    'X/xG/rho'          : Item(contents="This is the file 'rho'.\n"),
+    'X/xG/pi'           : Item(contents="This is the file 'pi'.\n"),
+  })
+
+  expected_status.tweak(wc_rev='3')
+  expected_status.add({
+    'A/D/H/xZ'          : Item(status='X '),
+    'Xpegged/xiota'     : Item(status='  ', wc_rev='1', switched='X'),
+    'Xpegged/xE'        : Item(status='X '),
+    'X/Y/xH'            : Item(status='X '),
+    'X/Y/xlambda'       : Item(status='  ', wc_rev='3', switched='X'),
+    'X/xmu'             : Item(status='  ', wc_rev='3', switched='X'),
+    'X/xG'              : Item(status='X '),
+  })
+  expected_status.tweak('Xpegged/xiota', wc_rev='1')
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # echo mod >> Xpegged/xE/alpha
+  main.file_append(Xpegged_xE_alpha, 'mod\n')
+
+  # echo mod >> X/xmu
+  main.file_append(X_xmu, 'mod\n')
+
+  # echo mod >> X/Y/xlambda
+  main.file_append(X_Y_xlambda, 'mod\n')
+
+  # echo mod >> X/xG/pi
+  main.file_append(X_xG_pi, 'mod\n')
+
+  # echo mod >> X/Y/xH/chi
+  main.file_append(X_Y_xH_chi, 'mod\n')
+
+  # echo mod >> X/Y/xH/xZ/zeta
+  main.file_append(X_Y_xH_xZ_zeta, 'mod\n')
+
+  # svn status
+  expected_status.tweak('X/Y/xlambda', 'X/xmu', status='M ')
+
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+  # Expect no externals to be committed
+  # svn ci
+  expected_output = svntest.wc.State(wc_dir, {})
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # Expect no externals to be committed, because pegged
+  # svn ci --include-externals Xpegged
+  expected_output = svntest.wc.State(wc_dir, {})
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, '--include-externals', Xpegged)
+
+  # Expect no externals to be committed, because of depth
+  # svn ci --depth=immediates --include-externals
+  expected_output = svntest.wc.State(wc_dir, {})
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, '--depth=immediates', '--include-externals', wc_dir)
+
+  # Expect only unpegged externals to be committed (those in X/)
+  # svn ci --include-externals
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/xmu'             : Item(verb='Sending'),
+    'X/Y/xlambda'       : Item(verb='Sending'),
+    'X/Y/xH/xZ/zeta'    : Item(verb='Sending'),
+    'X/Y/xH/chi'        : Item(verb='Sending'),
+    'X/xG/pi'           : Item(verb='Sending'),
+  })
+
+  expected_status.tweak(status='  ')
+  expected_status.tweak('X/Y/xlambda', 'X/xmu', wc_rev='4')
+  expected_status.tweak('X/Y/xH', 'X/xG', 'A/D/H/xZ', 'Xpegged/xE',
+    status='X ')
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, '--include-externals', wc_dir)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/mu'              : Item(status='U '),
+    'A/D/H/chi'         : Item(status='U '),
+    'A/D/H/xZ/zeta'     : Item(status='U '),
+    'A/D/G/pi'          : Item(status='U '),
+    'A/B/lambda'        : Item(status='U '),
+    'Z/zeta'            : Item(status='U '),
+  })
+
+  expected_disk.tweak('Xpegged/xE/alpha',
+    contents="This is the file 'alpha'.\nmod\n")
+  expected_disk.tweak('A/D/H/chi', 'X/Y/xH/chi',
+    contents="This is the file 'chi'.\nmod\n")
+  expected_disk.tweak('A/D/H/xZ/zeta', 'X/Y/xH/xZ/zeta', 'Z/zeta',
+    contents='This is the file zeta.\nmod\n')
+  expected_disk.tweak('A/D/G/pi', 'X/xG/pi',
+    contents="This is the file 'pi'.\nmod\n")
+  expected_disk.tweak('A/mu', 'X/xmu',
+    contents="This is the file 'mu'.\nmod\n")
+  expected_disk.tweak('A/B/lambda', 'X/Y/xlambda',
+    contents="This is the file 'lambda'.\nmod\n")
+
+  expected_status.tweak(wc_rev='4')
+  expected_status.tweak('Xpegged/xiota', wc_rev='1')
+  expected_status.tweak('A/D/H/xZ', 'Xpegged/xE', 'X/Y/xH', 'X/xG',
+                        wc_rev=None)
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # new mods to check more cases
+  # echo mod >> X/xmu
+  main.file_append(X_xmu, 'mod\n')
+
+  # echo mod >> X/Y/xlambda
+  main.file_append(X_Y_xlambda, 'mod\n')
+
+  # echo mod >> X/xG/pi
+  main.file_append(X_xG_pi, 'mod\n')
+
+  # echo mod >> X/Y/xH/chi
+  main.file_append(X_Y_xH_chi, 'mod\n')
+
+  # echo mod >> X/Y/xH/xZ/zeta
+  main.file_append(X_Y_xH_xZ_zeta, 'mod\n')
+
+  # svn status
+  expected_status.tweak('X/Y/xlambda', 'X/xmu', status='M ')
+
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+  # Expect no externals to be committed, because of depth
+  # svn ci --include-externals --depth=empty X
+  expected_output = svntest.wc.State(wc_dir, {})
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, '--include-externals', '--depth=empty', X)
+
+  # Expect only file external xmu to be committed, because of depth
+  # svn ci --include-externals --depth=files X
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/xmu'             : Item(verb='Sending'),
+  })
+
+  expected_status.tweak(status='  ')
+  expected_status.tweak('X/xmu', wc_rev='5')
+  expected_status.tweak('X/Y/xlambda', status='M ')
+  expected_status.tweak('X/Y/xH', 'X/xG', 'A/D/H/xZ', 'Xpegged/xE',
+    status='X ')
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, '--include-externals', '--depth=files', X)
+
+  # svn status
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/mu'              : Item(status='U '),
+  })
+
+  expected_disk.tweak('A/mu', 'X/xmu',
+    contents="This is the file 'mu'.\nmod\nmod\n")
+  expected_disk.tweak('X/Y/xlambda',
+    contents="This is the file 'lambda'.\nmod\nmod\n")
+  expected_disk.tweak('X/Y/xH/chi',
+    contents="This is the file 'chi'.\nmod\nmod\n")
+  expected_disk.tweak('X/Y/xH/xZ/zeta',
+    contents='This is the file zeta.\nmod\nmod\n')
+  expected_disk.tweak('X/xG/pi',
+    contents="This is the file 'pi'.\nmod\nmod\n")
+
+  expected_status.tweak(wc_rev='5')
+  expected_status.tweak('Xpegged/xiota', wc_rev='1')
+  expected_status.tweak('A/D/H/xZ', 'Xpegged/xE', 'X/Y/xH', 'X/xG',
+                        wc_rev=None)
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # echo mod >> X/xG/pi
+  main.file_append(X_xG_pi, 'mod\n')
+
+  # svn status
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+  # Expect explicit targets to be committed
+  # svn ci X/Y/xlambda X/xG
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/Y/xlambda'       : Item(verb='Sending'),
+    'X/xG/pi'           : Item(verb='Sending'),
+  })
+
+  expected_status.tweak(status='  ')
+  expected_status.tweak('X/Y/xlambda', wc_rev='6')
+  expected_status.tweak('X/Y/xH', 'X/xG', 'A/D/H/xZ', 'Xpegged/xE',
+    status='X ')
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, X_Y_xlambda, X_xG)
+
+  # svn status
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+
+@XFail()
+def include_immediate_dir_externals(sbox):
+  "commit --include-externals --depth=immediates"
+  # See also comment inside svn_client_commit6().
+
+  #   svntest.factory.make(sbox,"""
+  #     svn mkdir X
+  #     svn ci
+  #     svn up
+  #     svn ps svn:externals "^/A/B/E X/XE" wc_dir
+  #     svn ci
+  #     svn up
+  # 
+  #     svn ps some change X/XE
+  #     echo mod >> X/XE/alpha
+  # 
+  #     svn st X/XE
+  #     # Expect only the propset on X/XE to be committed.
+  #     # Should be like 'svn commit --include-externals --depth=empty X/XE'.
+  #     svn commit --include-externals --depth=immediates X
+  #     """)
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  X = os.path.join(wc_dir, 'X')
+  X_XE = os.path.join(wc_dir, 'X', 'XE')
+  X_XE_alpha = os.path.join(wc_dir, 'X', 'XE', 'alpha')
+
+  # svn mkdir X
+  expected_stdout = ['A         ' + X + '\n']
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'mkdir', X)
+
+  # svn ci
+  expected_output = svntest.wc.State(wc_dir, {
+    'X'                 : Item(verb='Adding'),
+  })
+
+  expected_status = actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'X'                 : Item(status='  ', wc_rev='2'),
+  })
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {})
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'X'                 : Item(),
+  })
+
+  expected_status.tweak(wc_rev='2')
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # svn ps svn:externals "^/A/B/E X/XE" wc_dir
+  expected_stdout = ["property 'svn:externals' set on '" + wc_dir + "'\n"]
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'ps',
+    'svn:externals', '^/A/B/E X/XE', wc_dir)
+
+  # svn ci
+  expected_output = svntest.wc.State(wc_dir, {
+    ''                  : Item(verb='Sending'),
+  })
+
+  expected_status.tweak('', wc_rev='3')
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/XE/alpha'        : Item(status='A '),
+    'X/XE/beta'         : Item(status='A '),
+  })
+
+  expected_disk.add({
+    'X/XE'              : Item(),
+    'X/XE/alpha'        : Item(contents="This is the file 'alpha'.\n"),
+    'X/XE/beta'         : Item(contents="This is the file 'beta'.\n"),
+  })
+
+  expected_status.tweak(wc_rev='3')
+  expected_status.add({
+    'X/XE'              : Item(status='X '),
+  })
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # svn ps some change X/XE
+  expected_stdout = ["property 'some' set on '" + X_XE + "'\n"]
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'ps', 'some',
+    'change', X_XE)
+
+  # echo mod >> X/XE/alpha
+  main.file_append(X_XE_alpha, 'mod\n')
+
+  # svn st X/XE
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+  # Expect only the propset on X/XE to be committed.
+  # Should be like 'svn commit --include-externals --depth=empty X/XE'.
+  # svn commit --include-externals --depth=immediates X
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/XE'              : Item(verb='Sending'),
+  })
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, '--include-externals', '--depth=immediates', X)
+
+
+@Issue(4085)
+@XFail()
+def shadowing(sbox):
+  "external shadows an existing dir"
+
+  sbox.build(read_only=True)
+  wc_dir = sbox.wc_dir
+
+  # Setup external: /A/B/F as 'C' child of /A
+  externals_prop = "^/A/B/F C\n"
+
+  raised = False
+  try:
+    change_external(sbox.ospath('A'), externals_prop, commit=False)
+  except:
+    raised = True
+  if not raised:
+    raise svntest.Failure("Creating conflicting child 'C' of 'A' didn't error")
+
+# Test for issue #4093 'remapping a file external can segfault due to
+# "deleted" props'.
+@Issue(4093)
+def remap_file_external_with_prop_del(sbox):
+  "file external remap segfaults due to deleted props"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  A_path  = os.path.join(wc_dir, "A")
+  mu_path = os.path.join(wc_dir, "A", "mu")
+
+  # Add a property to A/mu
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ps', 'propname', 'propval', mu_path)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'commit', '-m', 'New property on a file',
+                                     wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+
+  # Add a new file external A/external pointing to ^/A/mu
+  externals_prop = "^/A/mu external\n"
+  change_external(A_path, externals_prop)
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+
+  # Change A/external to point to ^/iota
+  externals_prop = "^/iota external\n"
+  change_external(A_path, externals_prop)
+
+  # Now update to bring the new external down.
+  # This previously segfaulted as described in
+  # http://subversion.tigris.org/issues/show_bug.cgi?id=4093#desc1
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
 
 ########################################################################
 # Run the tests
@@ -1961,6 +2743,12 @@ test_list = [ None,
               incoming_file_external_on_file,
               exclude_externals,
               file_externals_different_repos,
+              file_external_in_unversioned,
+              copy_file_externals,
+              include_externals,
+              include_immediate_dir_externals,
+              shadowing,
+              remap_file_external_with_prop_del,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/revprop-packing/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout (original)
+++ subversion/branches/revprop-packing/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout Fri Jan 13 21:40:26 2012
@@ -38,6 +38,10 @@ usage: 1. log [PATH][@REV]
     svn log http://www.example.com/repo/project foo.c bar.c
     svn log http://www.example.com/repo/project@50 foo.c bar.c
 
+    This command shows the log entry for the revision the branch
+    ^/branches/foo was created in:
+      svn log --stop-on-copy --limit 1 -r0:HEAD ^/branches/foo
+
 Valid options:
   -r [--revision] ARG      : ARG (some commands also take ARG1:ARG2 range)
                              A revision argument can be one of:
@@ -157,9 +161,10 @@ Valid options:
   --ignore-ancestry        : ignore ancestry when calculating merges
   --force                  : force operation to run
   --accept ARG             : specify automatic conflict resolution action
-                             ('postpone', 'base', 'mine-conflict',
+                             ('postpone', 'working', 'base', 'mine-conflict',
                              'theirs-conflict', 'mine-full', 'theirs-full',
                              'edit', 'launch')
+                             (shorthand: 'p', 'mc', 'tc', 'mf', 'tf', 'e', 'l')
 
 Global options:
   --username ARG           : specify a username ARG

Modified: subversion/branches/revprop-packing/subversion/tests/cmdline/input_validation_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/tests/cmdline/input_validation_tests.py?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/tests/cmdline/input_validation_tests.py (original)
+++ subversion/branches/revprop-packing/subversion/tests/cmdline/input_validation_tests.py Fri Jan 13 21:40:26 2012
@@ -151,18 +151,23 @@ def invalid_log_targets(sbox):
 def invalid_merge_args(sbox):
   "invalid arguments for 'merge'"
   sbox.build(read_only=True)
-  run_and_verify_svn_in_wc(sbox, "svn: E195002: A working copy merge source needs "
-                           "an explicit revision", 'merge', 'iota', '^/')
-  for (src, target) in [('iota@HEAD', '^/'), ('iota@BASE', 'file://')]:
-    run_and_verify_svn_in_wc(sbox, "svn: E205000: Merge sources must both be either "
-                             "paths or URLs", 'merge', src, target)
-  run_and_verify_svn_in_wc(sbox, "svn: E155010: Path '.*' does not exist",
-                           'merge', 'iota@BASE', 'iota@HEAD', 'nonexistent')
+  for args in [('iota', 'A/mu@HEAD'),
+               ('iota@BASE', 'A/mu@HEAD')]:
+    run_and_verify_svn_in_wc(sbox, "svn: E195002: .* working copy .* revision",
+                             'merge', *args)
+  for args in [(sbox.repo_url, 'A@1', 'A'),
+               ('^/A', 'A@HEAD', 'A'),
+               ('A@HEAD', '^/A', 'A'),
+               ('A@HEAD', '^/A')]:
+    run_and_verify_svn_in_wc(sbox, "svn: E205000: Merge sources must both "
+                             "be either paths or URLs", 'merge', *args)
+  run_and_verify_svn_in_wc(sbox, "svn: E155010: .* was not found",
+                           'merge', '^/@0', '^/@1', 'nonexistent')
   run_and_verify_svn_in_wc(sbox, "svn: E205000: Too many arguments given",
                           'merge', '-c42', '^/A/B', '^/A/C', 'iota')
   run_and_verify_svn_in_wc(sbox, "svn: E205000: Cannot specify a revision range with" +
                            " two URLs", 'merge', '-c42', '^/mu', '^/')
-  run_and_verify_svn_in_wc(sbox, "svn: E155010: Path '.*' does not exist",
+  run_and_verify_svn_in_wc(sbox, "svn: E155010: .* was not found",
                            'merge', '-c42', '^/mu', 'nonexistent')
 
 def invalid_wcpath_upgrade(sbox):

Modified: subversion/branches/revprop-packing/subversion/tests/cmdline/lock_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/tests/cmdline/lock_tests.py?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/tests/cmdline/lock_tests.py (original)
+++ subversion/branches/revprop-packing/subversion/tests/cmdline/lock_tests.py Fri Jan 13 21:40:26 2012
@@ -1335,7 +1335,7 @@ def unlock_wrong_token(sbox):
   svntest.actions.run_and_verify_svn(None, ".*locked by user", [], 'lock',
                                      file_path)
 
-  # Steal the lock as the same author, but using an URL to keep the old token
+  # Steal the lock as the same author, but using a URL to keep the old token
   # in the WC.
   svntest.actions.run_and_verify_svn(None, ".*locked by user", [], 'lock',
                                     "--force", file_url)



Mime
View raw message