You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by cm...@apache.org on 2013/05/10 16:58:56 UTC

svn commit: r1481041 [34/38] - in /subversion/branches/master-passphrase: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/client-side/svncopy/ contrib/hook-scripts/ contrib/server-side/fsfsfixer/ contrib/server-side/fsfsf...

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/basic_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/basic_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/basic_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/basic_tests.py Fri May 10 14:58:47 2013
@@ -3016,6 +3016,38 @@ def delete_conflicts_one_of_many(sbox):
   verify_file_deleted("failed to remove conflict file",
                       sbox.ospath('A/D/G/rho.mine'))
 
+@Issue(3231)
+@XFail()
+def peg_rev_on_non_existent_wc_path(sbox):
+  """peg rev resolution on non-existent wc paths"""
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # setup some history
+  sbox.simple_move('A', 'A2')
+  sbox.simple_move('A2/mu', 'A2/mu2')
+  open(sbox.ospath('A2/mu2'), 'w').write('r2\n')
+  sbox.simple_commit(message='r2')
+  #
+  sbox.simple_move('A2/mu2', 'A2/mu3')
+  sbox.simple_move('A2', 'A3')
+  open(sbox.ospath('A3/mu3'), 'w').write('r3\n')
+  sbox.simple_commit(message='r3')
+  #
+  sbox.simple_move('A3/mu3', 'A3/mu4')
+  open(sbox.ospath('A3/mu4'), 'w').write('r4\n')
+  sbox.simple_move('A3', 'A4')
+  sbox.simple_commit(message='r4')
+
+  # test something.
+  sbox.simple_update()
+  # This currently fails with ENOENT on A/mu3.
+  svntest.actions.run_and_verify_svn(None, ['r2\n'], [],
+                                     'cat', '-r2', sbox.ospath('A3/mu3') + '@3')
+  os.chdir(sbox.ospath('A4'))
+  svntest.actions.run_and_verify_svn(None, ['r2\n'], [],
+                                     'cat', '-r2', sbox.ospath('mu3') + '@3')
 
 ########################################################################
 # Run the tests
@@ -3084,6 +3116,7 @@ test_list = [ None,
               quiet_commits,
               rm_missing_with_case_clashing_ondisk_item,
               delete_conflicts_one_of_many,
+              peg_rev_on_non_existent_wc_path,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/blame_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/blame_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/blame_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/blame_tests.py Fri May 10 14:58:47 2013
@@ -150,7 +150,7 @@ def blame_binary(sbox):
   svntest.main.run_svn(None, 'propdel', 'svn:mime-type', iota)
   svntest.main.run_svn(None, 'ci',
                        '-m', '', iota)
-  
+
   # Blame fails when asking about an old revision where the mime-type is binary
   exit_code, output, errput = svntest.main.run_svn(2, 'blame', iota + '@3')
   if (len(errput) != 1) or (errput[0].find('Skipping') == -1):

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/cat_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/cat_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/cat_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/cat_tests.py Fri May 10 14:58:47 2013
@@ -163,6 +163,8 @@ def cat_skip_uncattable(sbox):
   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)
+  error = [line for line in error
+           if not re.compile(svntest.main.stack_trace_regexp).match(line)]
 
   # Verify output
   if output[0] != expected_out:

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/commit_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/commit_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/commit_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/commit_tests.py Fri May 10 14:58:47 2013
@@ -2892,7 +2892,7 @@ def commit_danglers(sbox):
   A_copied = sbox.ospath('A_copied')
   mu_copied = sbox.ospath('A_copied/mu')
 
-  svntest.main.file_write(mu_copied, "xxxx")  
+  svntest.main.file_write(mu_copied, "xxxx")
 
   # We already test for this problem for some time
   expected_error = "svn: E200009: '.*A_copied' .*exist.*yet.* '.*mu'.*part"
@@ -2936,16 +2936,16 @@ def last_changed_of_copied_subdir(sbox):
   E_copied = sbox.ospath('A/B_copied/E')
   alpha_copied = sbox.ospath('A/B_copied/E/alpha')
 
-  svntest.main.file_write(alpha_copied, "xxxx") 
-  
+  svntest.main.file_write(alpha_copied, "xxxx")
+
   svntest.main.run_svn(None, 'commit', wc_dir, '-mm')
 
   expected = {'Revision'          : '2',
               'Last Changed Rev'  : '2',
              }
   svntest.actions.run_and_verify_info([expected], E_copied)
-  
-  
+
+
 ########################################################################
 # Run the tests
 

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/copy_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/copy_tests.py Fri May 10 14:58:47 2013
@@ -4749,7 +4749,7 @@ def mixed_rev_copy_del(sbox):
                                         '-r1',
                                         sbox.ospath('A/B/E/alpha'),
                                         sbox.ospath('A/B/E/beta'))
-  
+
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
   # Copy A/B/E to A/B/E_copy
@@ -5217,7 +5217,7 @@ def case_only_rename(sbox):
   # Create expected status.
   expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
   expected_status.add({
-  
+
     'iota'              : Item(status='D ', wc_rev=1, moved_to='IoTa'),
     'IoTa'              : Item(status='A ', copied='+', wc_rev='-', moved_from='iota'),
     'A/B'               : Item(status='D ', wc_rev='1', moved_to='A/b'),

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/davautocheck.sh
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/davautocheck.sh?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/davautocheck.sh (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/davautocheck.sh Fri May 10 14:58:47 2013
@@ -441,6 +441,9 @@ MaxRequestsPerChild 0
 <IfModule worker.c>
   ThreadsPerChild   8
 </IfModule>
+<IfModule event.c>
+  ThreadsPerChild   8
+</IfModule>
 MaxClients          32
 HostNameLookups     Off
 LogFormat           "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" format

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/depth_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/depth_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/depth_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/depth_tests.py Fri May 10 14:58:47 2013
@@ -2867,9 +2867,9 @@ def revert_depth_files(sbox):
   "depth immediate+files should revert deleted files"
 
   sbox.build(read_only = True)
-  
+
   expected_output = "Reverted '" + re.escape(sbox.ospath('A/mu')) + "'"
-  
+
   # Apply an unrelated delete one level to deep
   sbox.simple_rm('A/D/gamma')
 

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/diff_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/diff_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/diff_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/diff_tests.py Fri May 10 14:58:47 2013
@@ -1899,7 +1899,7 @@ def diff_keywords(sbox):
 
 
 def diff_force(sbox):
-  "show diffs for binary files with --force"
+  "show diffs for binary files"
 
   sbox.build()
   wc_dir = sbox.wc_dir
@@ -1943,34 +1943,20 @@ def diff_force(sbox):
   svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                         expected_status, None, wc_dir)
 
-  # Check that we get diff when the first, the second and both files are
-  # marked as binary.
+  # Check that we get diff when the first, the second and both files
+  # are marked as binary.  First we'll use --force.  Then we'll use
+  # the configuration option 'diff-ignore-content-type'.
 
   re_nodisplay = re.compile('^Cannot display:')
 
-  exit_code, stdout, stderr = svntest.main.run_svn(None,
-                                                   'diff', '-r1:2', iota_path,
-                                                   '--force')
-
-  for line in stdout:
-    if (re_nodisplay.match(line)):
-      raise svntest.Failure
-
-  exit_code, stdout, stderr = svntest.main.run_svn(None,
-                                                   'diff', '-r2:1', iota_path,
-                                                   '--force')
-
-  for line in stdout:
-    if (re_nodisplay.match(line)):
-      raise svntest.Failure
-
-  exit_code, stdout, stderr = svntest.main.run_svn(None,
-                                                   'diff', '-r2:3', iota_path,
-                                                   '--force')
-
-  for line in stdout:
-    if (re_nodisplay.match(line)):
-      raise svntest.Failure
+  for opt in ['--force',
+              '--config-option=config:miscellany:diff-ignore-content-type=yes']:
+    for range in ['-r1:2', '-r2:1', '-r2:3']:
+      exit_code, stdout, stderr = svntest.main.run_svn(None, 'diff', range,
+                                                       iota_path, opt)
+      for line in stdout:
+        if (re_nodisplay.match(line)):
+          raise svntest.Failure
 
 #----------------------------------------------------------------------
 # Regression test for issue #2333: Renaming a directory should produce
@@ -3388,7 +3374,7 @@ def diff_git_format_wc_wc(sbox):
   expected_output = make_git_diff_header(
                          alpha_copied_path, "A/B/E/alpha_copied",
                          "revision 0", "working copy",
-                         copyfrom_path="A/B/E/alpha", 
+                         copyfrom_path="A/B/E/alpha",
                          copyfrom_rev='1', cp=True,
                          text_changes=True) + [
     "@@ -1 +1,2 @@\n",
@@ -3983,7 +3969,7 @@ def diff_two_working_copies(sbox):
                       "@@ -1 +0,0 @@\n",
                       "-This is the file 'psi'.\n",
                     ]
-                    
+
   # Files in diff may be in any order.
   expected_output = svntest.verify.UnorderedOutput(expected_output)
   svntest.actions.run_and_verify_svn(None, expected_output, [],

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/export_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/export_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/export_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/export_tests.py Fri May 10 14:58:47 2013
@@ -918,6 +918,52 @@ def export_file_overwrite_with_force(sbo
                                      iota_url, tmpdir)
   svntest.actions.verify_disk(tmpdir, expected_disk)
 
+def export_custom_keywords(sbox):
+  """export with custom keywords"""
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # 248=SVN_KEYWORD_MAX_LEN-7 where 7 is '$', 'Q', 'q', ':', ' ', ' ', '$'
+  alpha_content = ('[$Qq: %s $ $Pp: %s $]\n'
+                   % (sbox.repo_url[:248],
+                      (sbox.repo_url + '/A/B/E/alpha')[:248]))
+
+  sbox.simple_append('A/B/E/alpha', '[$Qq$ $Pp$]\n', truncate=True)
+  sbox.simple_propset('svn:keywords', 'Qq=%R Pp=%u', 'A/B/E/alpha')
+  sbox.simple_commit()
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/B/E/alpha', contents=alpha_content)
+  svntest.actions.verify_disk(sbox.wc_dir, expected_disk)
+
+  # Export a tree
+  export_target = sbox.add_wc_path('export')
+  expected_output = svntest.wc.State(export_target, {
+    ''             : Item(status='A '),
+    'alpha'       : Item(status='A '),
+    'beta'        : Item(status='A '),
+  })
+  expected_disk = svntest.wc.State('', {
+      'alpha': Item(contents=alpha_content),
+      'beta' : Item(contents="This is the file 'beta'.\n"),
+      })
+  svntest.actions.run_and_verify_export(sbox.repo_url + '/A/B/E',
+                                        export_target,
+                                        expected_output,
+                                        expected_disk)
+
+  # Export a file
+  export_file = os.path.join(export_target, 'alpha')
+  os.remove(export_file)
+  expected_output = ['A    %s\n' % export_file, 'Export complete.\n']
+  svntest.actions.run_and_verify_svn(None, expected_output, [],
+                                     'export', '--force',
+                                     sbox.repo_url + '/A/B/E/alpha',
+                                     export_target)
+
+  if open(export_file).read() != ''.join(alpha_content):
+    raise svntest.Failure("wrong keyword expansion")
+
 ########################################################################
 # Run the tests
 
@@ -951,6 +997,7 @@ test_list = [ None,
               export_externals_with_native_eol,
               export_to_current_dir,
               export_file_overwrite_with_force,
+              export_custom_keywords,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/externals_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/externals_tests.py Fri May 10 14:58:47 2013
@@ -2556,7 +2556,7 @@ def commit_include_externals(sbox):
 
 
   # Assume everything r4, except what is pegged
-  expected_status.tweak(wc_rev='4')  
+  expected_status.tweak(wc_rev='4')
   expected_status.tweak('Xpegged/xiota', 'Xpegged/xE', 'Xpegged/xE/alpha',
                         'Xpegged/xE/beta', wc_rev=1)
 
@@ -2781,7 +2781,7 @@ def include_immediate_dir_externals(sbox
   #
   #   >svn st
   #   X       X\XE
-  #   
+  #
   #   Performing status on external item at 'X\XE':
   #    M      C:\SVN\src-trunk\...\externals_tests-37\X\XE
   #   M       C:\SVN\src-trunk\...\externals_tests-37\X\XE\alpha
@@ -3048,15 +3048,15 @@ def duplicate_targets(sbox):
   actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'pg',
     'svn:externals', wc_dir)
 
-@Issue(4225)  
+@Issue(4225)
 def list_include_externals(sbox):
   "list with --include-externals"
-  
+
   externals_test_setup(sbox)
 
   wc_dir         = sbox.wc_dir
   repo_url       = sbox.repo_url
-  
+
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'checkout',
                                      repo_url, wc_dir)
@@ -3073,7 +3073,7 @@ def list_include_externals(sbox):
     return string
 
   expected_stdout = verify.UnorderedOutput([
-    "E/" + "\n", 
+    "E/" + "\n",
     "F/" + "\n",
     "lambda" + "\n",
     list_external_string("gamma", B_url ) + "\n",
@@ -3081,7 +3081,7 @@ def list_include_externals(sbox):
 
   exit_code, stdout, stderr = svntest.actions.run_and_verify_svn2(
     "OUTPUT", expected_stdout, [], 0, 'ls', '--include-externals', B_path)
-  
+
   exit_code, stdout, stderr = svntest.actions.run_and_verify_svn2(
     "OUTPUT", expected_stdout, [], 0, 'ls', '--include-externals', B_url)
 
@@ -3094,10 +3094,10 @@ def list_include_externals(sbox):
     "chi" + "\n",
     "omega" + "\n",
     "psi" + "\n"])
-  
+
   exit_code, stdout, stderr = svntest.actions.run_and_verify_svn2(
     "OUTPUT", expected_stdout, [], 0, 'ls', '--include-externals', C_path)
-  
+
   exit_code, stdout, stderr = svntest.actions.run_and_verify_svn2(
     "OUTPUT", expected_stdout, [], 0, 'ls', '--include-externals', C_url)
 

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/import_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/import_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/import_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/import_tests.py Fri May 10 14:58:47 2013
@@ -554,7 +554,7 @@ def import_inherited_ignores(sbox):
   svntest.actions.run_and_verify_svn(None, [], [], 'import',
                                      '--config-dir', config_dir,
                                      os.path.join(import_tree_dir,
-                                                  'DIR6', 'file6.foo'), 
+                                                  'DIR6', 'file6.foo'),
                                      sbox.repo_url + '/A/B/E/file6.foo',
                                      '-m', 'This import should fail!')
 
@@ -563,7 +563,7 @@ def import_inherited_ignores(sbox):
   svntest.actions.run_and_verify_svn(None, None, [], 'import', '--no-ignore',
                                      '--config-dir', config_dir,
                                      os.path.join(import_tree_dir,
-                                                  'DIR6', 'file6.foo'), 
+                                                  'DIR6', 'file6.foo'),
                                      sbox.repo_url + '/A/B/E/file6.foo',
                                      '-m', 'import')
   expected_output = svntest.verify.UnorderedOutput(

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/info_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/info_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/info_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/info_tests.py Fri May 10 14:58:47 2013
@@ -544,7 +544,7 @@ def relpath_escaping(sbox):
               'URL' : '.*/path.*with.*space.*',
               'Relative URL' : '.*/path.*with.*space.*',
              }
-             
+
   svntest.actions.run_and_verify_info([expected], sbox.ospath(name))
 
   info = svntest.actions.run_and_parse_info(sbox.ospath(name), sbox.ospath(name2))

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/iprop_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/iprop_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/iprop_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/iprop_tests.py Fri May 10 14:58:47 2013
@@ -99,7 +99,7 @@ def iprops_basic_working(sbox):
     D_path, expected_iprops, expected_explicit_props)
 
   ### Propget Directory Targets
-  
+
   # Propget directory target with only explicit props.
   expected_iprops = {}
   expected_explicit_props = {'RootProp2' : 'Root-Prop-Val2'}
@@ -315,7 +315,7 @@ def iprops_switched_subtrees(sbox):
 
   svntest.main.run_svn(None, 'copy', sbox.repo_url + '/A',
                        sbox.repo_url + '/branch2', '-m', 'Make branch2')
-  
+
   # Create a root property and two branch properties
   svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
   sbox.simple_propset('Root-Prop-1', 'Root-Prop-Val1', '.')
@@ -430,7 +430,7 @@ def iprops_pegged_wc_targets(sbox):
   sbox.simple_propset('RootProp1', 'Root-Prop-Val-1-set-in-r2', '.')
   sbox.simple_propset('RootProp2', 'Root-Prop-Val-2-set-in-r2', '.')
   sbox.simple_propset('D-Prop', 'D-Prop-Val-set-in-r2', 'A/D')
-  svntest.main.file_write(alpha_path, "Edit in r2.\n")  
+  svntest.main.file_write(alpha_path, "Edit in r2.\n")
   svntest.main.run_svn(None, 'commit', '-m', 'Add some properties',
                        wc_dir)
 

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/lock_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/lock_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/lock_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/lock_tests.py Fri May 10 14:58:47 2013
@@ -1779,14 +1779,14 @@ def locks_stick_over_switch(sbox):
   switched_status.tweak('iota', writelocked='K')
   switched_status.tweak('A', switched='S')
 
-  svntest.actions.run_and_verify_switch(wc_dir, sbox.ospath('A'), 
+  svntest.actions.run_and_verify_switch(wc_dir, sbox.ospath('A'),
                                         repo_url + '/AA',
                                         expected_output, None, switched_status)
 
   # And now switch back to verify that the locks reappear
   expected_output = svntest.wc.State(wc_dir, {
   })
-  svntest.actions.run_and_verify_switch(wc_dir, sbox.ospath('A'), 
+  svntest.actions.run_and_verify_switch(wc_dir, sbox.ospath('A'),
                                         repo_url + '/A',
                                         expected_output, None, expected_status)
 

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/log_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/log_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/log_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/log_tests.py Fri May 10 14:58:47 2013
@@ -2220,7 +2220,7 @@ def log_diff_moved(sbox):
   sbox.simple_move('A/mu2', 'A/mu3')
   svntest.main.file_append(sbox.ospath('A/mu3'), "now mu3\n")
   sbox.simple_commit()
-  
+
   mu_at_1 = sbox.repo_url + '/A/mu@1'
   mu3_at_3 = sbox.repo_url + '/A/mu3@3'
 
@@ -2296,13 +2296,13 @@ def log_search(sbox):
   log_chain = parse_log_output(output)
   check_log_chain(log_chain, [7, 6, 3])
 
-  # search is case-insensitive
+  # search is case-sensitive
   exit_code, output, err = svntest.actions.run_and_verify_svn(
                              None, None, [], 'log', '--search',
                              'FOR REVISION [367]')
 
   log_chain = parse_log_output(output)
-  check_log_chain(log_chain, [7, 6, 3])
+  check_log_chain(log_chain, [])
 
   # multi-pattern search
   exit_code, output, err = svntest.actions.run_and_verify_svn(
@@ -2365,6 +2365,133 @@ def merge_sensitive_log_with_search(sbox
   }
   check_merge_results(log_chain, expected_merges)
 
+#----------------------------------------------------------------------
+# Test for issue #4355 'svn_client_log5 broken with multiple revisions
+# which span a rename'.
+@Issue(4355)
+@SkipUnless(server_has_mergeinfo)
+def log_multiple_revs_spanning_rename(sbox):
+  "log for multiple revs which span a rename"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  msg_file=os.path.join(sbox.repo_dir, 'log-msg')
+  msg_file=os.path.abspath(msg_file)
+  mu_path1 = os.path.join(wc_dir, 'A', 'mu')
+  mu_path2 = os.path.join(wc_dir, 'trunk', 'mu')
+  trunk_path = os.path.join(wc_dir, 'trunk')
+
+  # r2 - Change a file.
+  msg=""" Log message for revision 2
+  but with multiple lines
+  to test the code"""
+  svntest.main.file_write(msg_file, msg)
+  svntest.main.file_append(mu_path1, "2")
+  svntest.main.run_svn(None, 'ci', '-F', msg_file, wc_dir)
+
+  # r3 - Rename that file's parent.
+  svntest.main.run_svn(None, 'up', wc_dir)
+  sbox.simple_move('A', 'trunk')
+  svntest.main.run_svn(None, 'ci', '-m', "Log message for revision 3",
+                       wc_dir)
+
+  # r4 - Change the file again.
+  msg=""" Log message for revision 4
+  but with multiple lines
+  to test the code"""
+  svntest.main.file_write(msg_file, msg)
+  svntest.main.file_append(mu_path2, "4")
+  svntest.main.run_svn(None, 'ci', '-F', msg_file, wc_dir)
+  svntest.main.run_svn(None, 'up', wc_dir)
+
+  # Check that log can handle a revision range that spans a rename.
+  exit_code, output, err = svntest.actions.run_and_verify_svn(
+    None, None, [], 'log', '-r2:4', sbox.repo_url + '/trunk/mu')
+  log_chain = parse_log_output(output)
+  check_log_chain(log_chain, [2,3,4])
+
+  # Check that log can handle discrete revisions that don't span a rename.
+  exit_code, output, err = svntest.actions.run_and_verify_svn(
+    None, None, [], 'log', '-c3,4', sbox.repo_url + '/trunk/mu')
+  log_chain = parse_log_output(output)
+  check_log_chain(log_chain, [3,4])
+
+  # Check that log can handle discrete revisions that span a rename.
+  #
+  # Previously this failed with:
+  #
+  #   >svn log ^/trunk -c2,3,1
+  #   ------------------------------------------------------------------------
+  #   r2 | jrandom | 2013-04-18 19:58:47 -0400 (Thu, 18 Apr 2013) | 3 lines
+  #
+  #    Log message for revision 2
+  #     but with multiple lines
+  #     to test the code
+  #   ------------------------------------------------------------------------
+  #   r3 | jrandom | 2013-04-18 19:58:47 -0400 (Thu, 18 Apr 2013) | 1 line
+  #
+  #   Log message for revision 3
+  #   ..\..\..\subversion\svn\log-cmd.c:868,
+  #   ..\..\..\subversion\libsvn_client\log.c:641,
+  #   ..\..\..\subversion\libsvn_repos\log.c:1931,
+  #   ..\..\..\subversion\libsvn_repos\log.c:1358,
+  #   ..\..\..\subversion\libsvn_fs\fs-loader.c:979,
+  #   ..\..\..\subversion\libsvn_fs_fs\tree.c:3205:
+  #     (apr_err=SVN_ERR_FS_NOT_FOUND)
+  #   svn: E160013: File not found: revision 1, path '/trunk'
+  exit_code, output, err = svntest.actions.run_and_verify_svn(
+    None, None, [], 'log', '-c2,3,1', sbox.repo_url + '/trunk/mu')
+  log_chain = parse_log_output(output)
+  check_log_chain(log_chain, [2,3,1])
+
+  # Should work with a WC target too.
+  exit_code, output, err = svntest.actions.run_and_verify_svn(
+    None, None, [], 'log', '-c2,3,1', mu_path2)
+  log_chain = parse_log_output(output)
+  check_log_chain(log_chain, [2,3,1])
+
+  # Discreet revision *ranges* which span a rename should work too.
+  exit_code, output, err = svntest.actions.run_and_verify_svn(
+    None, None, [], 'log', '-r1', '-r4:2', sbox.repo_url + '/trunk')
+  log_chain = parse_log_output(output)
+  check_log_chain(log_chain, [1,4,3,2])
+
+  # As above, but revision ranges from younger to older.  Previously this
+  # failed with:
+  #
+  #  >svn log ^/trunk -r1:1 -r2:4
+  #  ------------------------------------------------------------------------
+  #  r1 | jrandom | 2013-04-18 19:58:46 -0400 (Thu, 18 Apr 2013) | 1 line
+  #
+  #  Log message for revision 1.
+  #  ..\..\..\subversion\svn\log-cmd.c:868,
+  #  ..\..\..\subversion\libsvn_client\log.c:678,
+  #  ..\..\..\subversion\libsvn_repos\log.c:1931,
+  #  ..\..\..\subversion\libsvn_repos\log.c:1358,
+  #  ..\..\..\subversion\libsvn_fs\fs-loader.c:979,
+  #  ..\..\..\subversion\libsvn_fs_fs\tree.c:3205:
+  #    (apr_err=SVN_ERR_FS_NOT_FOUND)
+  #  svn: E160013: File not found: revision 4, path '/A'
+  exit_code, output, err = svntest.actions.run_and_verify_svn(
+    None, None, [], 'log', '-r1', '-r2:4', sbox.repo_url + '/trunk')
+  log_chain = parse_log_output(output)
+  check_log_chain(log_chain, [1,2,3,4])
+
+  # Discrete revs with WC-only opt revs shouldn't cause any problems.
+  exit_code, output, err = svntest.actions.run_and_verify_svn(
+    None, None, [], 'log', '-r1', '-rPREV', trunk_path)
+  log_chain = parse_log_output(output)
+  check_log_chain(log_chain, [1,3])
+
+  exit_code, output, err = svntest.actions.run_and_verify_svn(
+    None, None, [], 'log', '-r1', '-rCOMMITTED', trunk_path)
+  log_chain = parse_log_output(output)
+  check_log_chain(log_chain, [1,4])
+
+  exit_code, output, err = svntest.actions.run_and_verify_svn(
+    None, None, [], 'log', '-r1', '-rBASE', trunk_path)
+  log_chain = parse_log_output(output)
+  check_log_chain(log_chain, [1,4])
 
 ########################################################################
 # Run the tests
@@ -2411,6 +2538,7 @@ test_list = [ None,
               log_diff_moved,
               log_search,
               merge_sensitive_log_with_search,
+              log_multiple_revs_spanning_rename,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/merge_authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/merge_authz_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/merge_authz_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/merge_authz_tests.py Fri May 10 14:58:47 2013
@@ -737,133 +737,6 @@ def reintegrate_fails_if_no_root_access(
                                        None, True, True,
                                        '--reintegrate', A_path)
 
-#----------------------------------------------------------------------
-# Test for issue #4319 'faulty merge notifications when target subtree
-# unreadable'.
-@SkipUnless(svntest.main.server_has_mergeinfo)
-@Skip(svntest.main.is_ra_type_file)
-@Issue(4319)
-@XFail()
-def merge_notifications_and_authz_skips(sbox):
-  "merge notifications when target subtree unreadable"
-
-  sbox.build()
-  wc_dir = sbox.wc_dir
-
-  deep_source_tree = sbox.ospath('A/C/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z')
-  deep_source_file = sbox.ospath('A/C/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/nu')
-  branch_root = sbox.ospath('branch')
-
-  # r2 - branch ^/A to ^/branch
-  sbox.simple_copy('A', 'branch')
-  sbox.simple_commit()
-  sbox.simple_update()
-
-  # r3 - Add a deep subtree
-  svntest.actions.run_and_verify_svn(None, None, [], 'mkdir',
-                                     deep_source_tree, '--parents')
-  svntest.main.file_write(deep_source_file, "This is the file 'nu'.\n")
-  svntest.actions.run_and_verify_svn(None, None, [], 'add', deep_source_file)
-  sbox.simple_commit()
-
-  # 
-  # Create a restrictive authz where part of the merge source and part
-  # of the target are inaccesible.
-  sbox.simple_update(revision=0)
-  write_restrictive_svnserve_conf(sbox.repo_dir)
-  write_authz_file(sbox, {"/" : svntest.main.wc_author +"=rw",
-                          # Make a subtree in the merge target inaccessible.
-                          "/branch/C" : svntest.main.wc_author + "=",
-                          })
-  sbox.simple_update()
-
-  expected_output = wc.State(branch_root, {
-    })
-  expected_mergeinfo_output = wc.State(branch_root, {
-    ''  : Item(status=' U'),
-    })
-  expected_elision_output = wc.State(branch_root, {
-    })
-  expected_status = wc.State(branch_root, {
-    ''          : Item(status=' M', wc_rev=3),
-    'D/H/chi'   : Item(status='  ', wc_rev=3),
-    'D/H/omega' : Item(status='  ', wc_rev=3),
-    'D/H/psi'   : Item(status='  ', wc_rev=3),
-    'D/H'       : Item(status='  ', wc_rev=3),
-    'D/gamma'   : Item(status='  ', wc_rev=3),
-    'D'         : Item(status='  ', wc_rev=3),
-    'D/G'       : Item(status='  ', wc_rev=3),
-    'D/G/pi'    : Item(status='  ', wc_rev=3),
-    'D/G/rho'   : Item(status='  ', wc_rev=3),
-    'D/G/tau'   : Item(status='  ', wc_rev=3),
-    'B/lambda'  : Item(status='  ', wc_rev=3),
-    'B/E'       : Item(status='  ', wc_rev=3),
-    'B/E/alpha' : Item(status='  ', wc_rev=3),
-    'B/E/beta'  : Item(status='  ', wc_rev=3),
-    'B/F'       : Item(status='  ', wc_rev=3),
-    'B'         : Item(status='  ', wc_rev=3),
-    'mu'        : Item(status='  ', wc_rev=3),
-    })
-  expected_disk = wc.State('', {
-    ''          : Item(props={SVN_PROP_MERGEINFO : '/A:2-3*'}),
-    'D/H/omega' : Item("This is the file 'omega'.\n"),
-    'D/H/chi'   : Item("This is the file 'chi'.\n"),
-    'D/H/psi'   : Item("This is the file 'psi'.\n"),
-    'D/H'       : Item(),
-    'D/gamma'   : Item("This is the file 'gamma'.\n"),
-    '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"),
-    'B/lambda'  : Item("This is the file 'lambda'.\n"),
-    'B/E'       : Item(),
-    'B/E/alpha' : Item("This is the file 'alpha'.\n"),
-    'B/E/beta'  : Item("This is the file 'beta'.\n"),
-    'B/F'       : Item(),
-    'B'         : Item(),
-    'mu'        : Item("This is the file 'mu'.\n"),
-    })
-  expected_skip = wc.State(branch_root,
-                           {'C' : Item(verb='Skipped missing target')})
-  # This fails because notifications for all the added subtrees under
-  # branch/C occur:
-  #
-  #   >svn merge ^^/A branch -r1:3
-  #   Skipped missing target: 'branch\C'
-  #      A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z\nu
-  #      A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
-  #      A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y
-  #      A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X
-  #      A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U\V\W
-  #      A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U\V
-  #      A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U
-  #      A branch\C\J\K\L\M\N\O\P\Q\R\S\T
-  #      A branch\C\J\K\L\M\N\O\P\Q\R\S
-  #      A branch\C\J\K\L\M\N\O\P\Q\R
-  #      A branch\C\J\K\L\M\N\O\P\Q
-  #      A branch\C\J\K\L\M\N\O\P
-  #      A branch\C\J\K\L\M\N\O
-  #      A branch\C\J\K\L\M\N
-  #      A branch\C\J\K\L\M
-  #      A branch\C\J\K\L
-  #      A branch\C\J\K
-  #      A branch\C\J
-  #   --- Recording mergeinfo for merge of r2 through r3 into 'branch':
-  #    U   branch
-  #   Summary of conflicts:
-  #     Skipped paths: 1
-  svntest.actions.run_and_verify_merge(branch_root, None, None,
-                                       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, 0)
-
 ########################################################################
 # Run the tests
 
@@ -873,7 +746,6 @@ test_list = [ None,
               mergeinfo_and_skipped_paths,
               merge_fails_if_subtree_is_deleted_on_src,
               reintegrate_fails_if_no_root_access,
-              merge_notifications_and_authz_skips,
              ]
 serial_only = True
 

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/merge_automatic_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/merge_automatic_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/merge_automatic_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/merge_automatic_tests.py Fri May 10 14:58:47 2013
@@ -757,7 +757,6 @@ def cherry3_fwd(sbox):
 #----------------------------------------------------------------------
 # Automatic merges ignore subtree mergeinfo during reintegrate.
 @SkipUnless(server_has_mergeinfo)
-@XFail()
 @Issue(4258)
 def subtree_to_and_fro(sbox):
   "reintegrate considers source subtree mergeinfo"
@@ -799,10 +798,10 @@ def subtree_to_and_fro(sbox):
   svntest.actions.run_and_verify_svn(None, None, [], 'ci', wc_dir,
                                      '-m', 'Edit a file on our trunk')
 
-  # Now reintegrate ^/A_COPY back to A.  To the automatic merge code the
-  # subtree merge to A_COPY/D just looks like any other branch edit, it is
-  # not considered a merge.  So the changes which exist on A/D and were
-  # merged to A_COPY/D, are merged *back* to A, resulting in a conflict:
+  # Now reintegrate ^/A_COPY back to A.  Prior to issue #4258's fix, the
+  # the subtree merge to A_COPY/D just looks like any other branch edit and
+  # was not considered a merge.  So the changes which exist on A/D and were
+  # merged to A_COPY/D, were merged *back* to A, resulting in a conflict:
   #
   #   C:\...\working_copies\merge_automatic_tests-18>svn merge ^^/A_COPY A
   #   DBG: merge.c:11461: base on source: ^/A@1
@@ -826,8 +825,8 @@ def subtree_to_and_fro(sbox):
     None, [], svntest.verify.AnyOutput,
     'merge', sbox.repo_url + '/A_COPY', A_path)
 
-  # The 'old' merge produced a warning that reintegrate could not be used.
-  # Not claiming this is perfect, but it's better(?) than a conflict:
+  # Better to produce the same warning that explicitly using the
+  # --reintegrate option would produce:
   svntest.verify.verify_outputs("Automatic Reintegrate failed, but not "
                                 "in the way expected",
                                 err, None,
@@ -838,9 +837,9 @@ def subtree_to_and_fro(sbox):
                                 "|(  A_COPY\n)"
                                 "|(    Missing ranges: /A:5\n)"
                                 "|(\n)"
-                                "|(.*apr_err.*)", # In case of debug build
+                                "|" + svntest.main.stack_trace_regexp,
                                 None,
-                                True) # Match *all* lines of stdout  
+                                True) # Match *all* lines of stdout
 
 #----------------------------------------------------------------------
 # Automatic merges ignore subtree mergeinfo gaps older than the last rev
@@ -889,7 +888,7 @@ def merge_to_reverse_cherry_subtree_to_m
   # Try an automatic sync merge from ^/A to A_COPY.  Revision 5 should be
   # merged to A_COPY/B as its subtree mergeinfo reveals that rev is missing,
   # like so:
-  # 
+  #
   #   >svn merge ^/A A_COPY
   #   --- Merging r5 into 'A_COPY\B':
   #   U    A_COPY\B\E\beta
@@ -1129,7 +1128,6 @@ def auto_merge_handles_replacements_in_m
 # source is fully synced'
 @SkipUnless(server_has_mergeinfo)
 @Issue(4329)
-@XFail()
 def effective_sync_results_in_reintegrate(sbox):
   "an effectively synced branch gets reintegrated"
 
@@ -1168,7 +1166,7 @@ def effective_sync_results_in_reintegrat
   # This should work because since the resolution of
   # http://subversion.tigris.org/issues/show_bug.cgi?id=3577
   # if B is *effectively* synced with A, then B can be reintegrated
-  # to A.  
+  # to A.
   sbox.simple_update()
   expected_output = [
     "--- Merging differences between repository URLs into '" +
@@ -1184,10 +1182,10 @@ def effective_sync_results_in_reintegrat
   # Revert the merge and try it again, this time without the --reintegrate
   # option.  The merge should still work with the same results.
   #
-  # Currently this fails because the reintegrate code path is not followed,
+  # Previously this failed because the reintegrate code path is not followed,
   # rather the automatic merge attempts a sync style merge of the yca (^/A@1)
   # through the HEAD of the branch (^/branch@7).  This results in a spurious
-  # conflict on A/mu as the edit made in r3 is reapplied..
+  # conflict on A/mu as the edit made in r3 is reapplied.
   #
   # >svn merge ^/branch A
   # --- Merging r2 through r6 into 'A':

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/merge_reintegrate_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/merge_reintegrate_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/merge_reintegrate_tests.py Fri May 10 14:58:47 2013
@@ -63,7 +63,7 @@ def run_reintegrate_expect_error(src_url
      unless stdout and stderr both match and the exit code is non-zero.
      Every line of stderr must match the regex EXPECTED_STDERR.
   """
-  expected_stderr += "|(.*apr_err.*)"  # In case of debug build
+  expected_stderr += "|" + svntest.main.stack_trace_regexp
 
   # The actions.run_and_verify_* methods are happy if one line of the error
   # matches the regex, but we want to check that every line matches.
@@ -1844,8 +1844,11 @@ def reintegrate_with_self_referential_me
                                        None, 1, 0)
 
 #----------------------------------------------------------------------
-# Test for issue #3577 '1.7 subtree mergeinfo recording breaks reintegrate'.
-@Issue(3577)
+# Test for issue #3577 '1.7 subtree mergeinfo recording breaks reintegrate'
+# and issue #4329 'automatic merge uses reintegrate type merge if source is
+# fully synced'.
+@Issue(3577,4329)
+@SkipUnless(server_has_mergeinfo)
 def reintegrate_with_subtree_merges(sbox):
   "reintegrate with prior subtree merges to source"
 
@@ -1857,6 +1860,7 @@ def reintegrate_with_subtree_merges(sbox
 
   # Some paths we'll care about
   A_path        = sbox.ospath('A')
+  psi_path      = sbox.ospath('A/D/H/psi')
   mu_COPY_path  = sbox.ospath('A_COPY/mu')
   A_COPY_path   = sbox.ospath('A_COPY')
   B_COPY_path   = sbox.ospath('A_COPY/B')
@@ -1974,6 +1978,28 @@ def reintegrate_with_subtree_merges(sbox
                              expected_A_skip,
                              None, 1, 1)
 
+  # Test issue #4329.  Revert previous merge and commit a new edit to
+  # A/D/H/psi. Attempt the same merge without the --reintegrate option.
+  # It should succeed because the automatic merge code should detect that
+  # a reintegrate-style merge is required, that merge should succeed and
+  # there should be not conflict on A/D/H/psi.
+  svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R', wc_dir)
+  svntest.main.file_write(psi_path, "Non-conflicting trunk edit.\n")
+  svntest.main.run_svn(None, 'commit', '-m',
+                       'An edit on trunk prior to reintegrate.', wc_dir)
+  sbox.simple_update()
+  expected_A_status.tweak(wc_rev=9)
+  expected_A_disk.tweak('', props={SVN_PROP_MERGEINFO: '/A_COPY:2-9'})
+  expected_A_disk.tweak('D/H/psi', contents='Non-conflicting trunk edit.\n')
+  svntest.actions.run_and_verify_merge(A_path, None, None,
+                                       sbox.repo_url + '/A_COPY', None,
+                                       expected_output,
+                                       expected_mergeinfo_output,
+                                       expected_elision_output,
+                                       expected_A_disk, expected_A_status,
+                                       expected_A_skip, None, None, None,
+                                       None, None, True, False, A_path)
+
 #----------------------------------------------------------------------
 # Test for issue #3654 'added subtrees with mergeinfo break reintegrate'.
 @Issue(3654)

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/merge_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/merge_tests.py Fri May 10 14:58:47 2013
@@ -54,6 +54,7 @@ from svntest.verify import RegexListOutp
 def expected_merge_output(rev_ranges, additional_lines=[], foreign=False,
                           elides=False, two_url=False, target=None,
                           text_conflicts=0, prop_conflicts=0, tree_conflicts=0,
+                          text_resolved=0, prop_resolved=0, tree_resolved=0,
                           skipped_paths=0):
   """Generate an (inefficient) regex representing the expected merge
   output and mergeinfo notifications from REV_RANGES and ADDITIONAL_LINES.
@@ -113,8 +114,11 @@ def expected_merge_output(rev_ranges, ad
     additional_lines = [line.replace("\\", "\\\\") for line in additional_lines]
   lines += additional_lines
 
-  lines += svntest.main.summary_of_conflicts(text_conflicts, prop_conflicts,
-                                             tree_conflicts, skipped_paths)
+  lines += svntest.main.summary_of_conflicts(
+             text_conflicts, prop_conflicts, tree_conflicts,
+             text_resolved, prop_resolved, tree_resolved,
+             skipped_paths,
+             as_regex=True)
 
   return "|".join(lines)
 
@@ -1830,7 +1834,7 @@ def merge_into_missing(sbox):
   })
   expected_mergeinfo_output = wc.State(F_path, {
     })
-  
+
   svntest.actions.run_and_verify_merge(F_path, '1', '2', F_url, None,
                                        expected_output,
                                        expected_mergeinfo_output,
@@ -4477,8 +4481,9 @@ def obey_reporter_api_semantics_while_do
 #----------------------------------------------------------------------
 def set_up_branch(sbox, branch_only = False, nbr_of_branches = 1):
   '''Starting with standard greek tree, copy 'A' NBR_OF_BRANCHES times
-  to A_COPY, A_COPY_2, A_COPY_3, and so on.  Then make four modifications
-  (setting file contents to "New content") under A:
+  to A_COPY, A_COPY_2, A_COPY_3, and so on.  Then, unless BRANCH_ONLY is
+  true, make four modifications (setting file contents to "New content")
+  under A:
     r(2 + NBR_OF_BRANCHES) - A/D/H/psi
     r(3 + NBR_OF_BRANCHES) - A/D/G/rho
     r(4 + NBR_OF_BRANCHES) - A/B/E/beta
@@ -6501,7 +6506,18 @@ def foreign_repos_does_not_update_mergei
 def avoid_reflected_revs(sbox):
   "avoid repeated merges for cyclic merging"
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2897. ##
+  # See <http://subversion.tigris.org/issues/show_bug.cgi?id=2897>.
+  #
+  # This test cherry-picks some changes (all of them, in fact) from the
+  # parent branch 'A' to the child branch 'A_COPY', and then tries to
+  # reintegrate 'A_COPY' to 'A' (explicitly specifying a revision range
+  # on the source branch).  It expects the changes that are unique to the
+  # branch 'A_COPY' to be merged to 'A'.
+  #
+  #   A     --1----[3]---[5]----------?
+  #            \     \_____\___      /
+  #             \           \  \    /
+  #   A_COPY     2-[---4-----6--7--8]-
 
   # Create a WC with a single branch
   sbox.build()
@@ -12542,7 +12558,9 @@ def svn_copy(s_rev, path1, path2):
                                      '-r', s_rev, path1, path2)
 
 def svn_merge(rev_range, source, target, lines=None, elides=[],
-              text_conflicts=0, prop_conflicts=0, tree_conflicts=0, args=[]):
+              text_conflicts=0, prop_conflicts=0, tree_conflicts=0,
+              text_resolved=0, prop_resolved=0, tree_resolved=0,
+              args=[]):
   """Merge a single change from path SOURCE to path TARGET and verify the
   output and that there is no error.  (The changes made are not verified.)
 
@@ -12579,7 +12597,10 @@ def svn_merge(rev_range, source, target,
                                   elides=elides,
                                   text_conflicts=text_conflicts,
                                   prop_conflicts=prop_conflicts,
-                                  tree_conflicts=tree_conflicts)
+                                  tree_conflicts=tree_conflicts,
+                                  text_resolved=text_resolved,
+                                  prop_resolved=prop_resolved,
+                                  tree_resolved=tree_resolved)
   svntest.actions.run_and_verify_svn(None, exp_out, [],
                                      'merge', rev_arg, source, target, *args)
 
@@ -13131,8 +13152,9 @@ def merge_two_edits_to_same_prop(sbox):
 
   # Merge the first change, then the second, to trunk.
   svn_merge(rev3, A_COPY_path, A_path, [
-      " G   %s\n" % mu_path,
-      ],
+      " C   %s\n" % mu_path,
+      "Resolved .* '%s'\n" % mu_path,
+      ], prop_resolved=1,
       args=['--allow-mixed-revisions',
             '--accept=working'])
   svn_merge(rev4, A_COPY_path, A_path, [
@@ -15243,7 +15265,8 @@ def merge_automatic_conflict_resolution(
                                      'revert', '--recursive', wc_dir)
 
   # Test --accept mine-conflict and mine-full
-  expected_output = wc.State(A_COPY_path, {'D/H/psi' : Item(status='U ')})
+  ### TODO: Also test that the output has a 'Resolved' line for this path.
+  expected_output = wc.State(A_COPY_path, {'D/H/psi' : Item(status='C ')})
   expected_disk.tweak('D/H/psi', contents="BASE.\n")
   expected_status.tweak('D/H/psi', status='  ')
   svntest.actions.run_and_verify_merge(A_COPY_path, '2', '3',
@@ -15278,7 +15301,8 @@ def merge_automatic_conflict_resolution(
                                      'revert', '--recursive', wc_dir)
 
   # Test --accept theirs-conflict and theirs-full
-  expected_output = wc.State(A_COPY_path, {'D/H/psi' : Item(status='U ')})
+  ### TODO: Also test that the output has a 'Resolved' line for this path.
+  expected_output = wc.State(A_COPY_path, {'D/H/psi' : Item(status='C ')})
   expected_disk.tweak('D/H/psi', contents="New content")
   expected_status.tweak('D/H/psi', status='M ')
   svntest.actions.run_and_verify_merge(A_COPY_path, '2', '3',
@@ -15312,7 +15336,8 @@ def merge_automatic_conflict_resolution(
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'revert', '--recursive', wc_dir)
   # Test --accept base
-  expected_output = wc.State(A_COPY_path, {'D/H/psi' : Item(status='U ')})
+  ### TODO: Also test that the output has a 'Resolved' line for this path.
+  expected_output = wc.State(A_COPY_path, {'D/H/psi' : Item(status='C ')})
   expected_elision_output = wc.State(A_COPY_path, {
     })
   expected_disk.tweak('D/H/psi', contents="This is the file 'psi'.\n")
@@ -16255,7 +16280,7 @@ def merge_with_os_deleted_subtrees(sbox)
   err_re = "svn: E195016: Merge tracking not allowed with missing subtrees; " + \
            "try restoring these items first:"                        + \
            "|(\n)"                                                   + \
-           "|(.*apr_err.*\n)" # In case of debug build
+           "|" + svntest.main.stack_trace_regexp
 
   # Case 1: Infinite depth merge into infinite depth WC target.
   # Every missing subtree under the target should be reported as missing.
@@ -16768,6 +16793,8 @@ def merge_adds_subtree_with_mergeinfo(sb
   "merge adds subtree with mergeinfo"
 
   sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
   wc_dir = sbox.wc_dir
   wc_disk, wc_status = set_up_branch(sbox, False, 2)
 
@@ -16896,6 +16923,8 @@ def reverse_merge_adds_subtree(sbox):
   "reverse merge adds subtree"
 
   sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
   wc_dir = sbox.wc_dir
   wc_disk, wc_status = set_up_branch(sbox)
 
@@ -17031,6 +17060,8 @@ def merged_deletion_causes_tree_conflict
   "merged deletion causes spurious tree conflict"
 
   sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
   wc_dir = sbox.wc_dir
 
   A_path        = sbox.ospath('A')
@@ -17103,6 +17134,8 @@ def record_only_merge_adds_new_subtree_m
   "record only merge adds new subtree mergeinfo"
 
   sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
   wc_dir = sbox.wc_dir
   wc_disk, wc_status = set_up_branch(sbox)
 
@@ -17394,11 +17427,12 @@ def unnecessary_noninheritable_mergeinfo
 #    svn merge -cr1295005 ^/subversion/trunk@1295000 ../src
 #    svn merge -cr1295004 ^/subversion/trunk/@r1295004 ../src
 @Issue(4132)
-@XFail()
 def svnmucc_abuse_1(sbox):
   "svnmucc: merge a replacement"
 
   sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
   wc_dir = sbox.wc_dir
 
   ## Using A/ as our trunk, since one cannot replace the root.
@@ -17429,22 +17463,32 @@ def svnmucc_abuse_1(sbox):
 
   ## Attempt to merge that.
   # This used to assert:
-  #   --- Recording mergeinfo for merge of r5 into 'svn-test-work/working_copies/merge_tests-125/A_COPY':
+  #   --- Recording mergeinfo for merge of r5 into \
+  #     'svn-test-work/working_copies/merge_tests-125/A_COPY':
   #   subversion/libsvn_subr/mergeinfo.c:1172: (apr_err=235000)
-  #   svn: E235000: In file 'subversion/libsvn_subr/mergeinfo.c' line 1172: assertion failed (IS_VALID_FORWARD_RANGE(first))
+  #   svn: E235000: In file 'subversion/libsvn_subr/mergeinfo.c' \
+  #     line 1172: assertion failed (IS_VALID_FORWARD_RANGE(first))
+  #
+  # Then, prior to the fix asserted this way:
+  #
+  #   >svn merge -c5 ^/A@r5 A_COPY
+  #   subversion\libsvn_client\merge.c:4871: (apr_err=235000)
+  #   svn: E235000: In file 'subversion\libsvn_client\merge.c'
+  #     line 4871: assertion failed (*gap_start < *gap_end)
   sbox.simple_update()
   svntest.main.run_svn(None, 'merge', '-c', 'r5', '^/A@r5',
-                             sbox.ospath('A_COPY'))
+                       sbox.ospath('A_COPY'))
 
 #----------------------------------------------------------------------
 # Test for issue #4138 'replacement in merge source not notified correctly'.
 @SkipUnless(server_has_mergeinfo)
-@XFail()
 @Issue(4138)
 def merge_source_with_replacement(sbox):
   "replacement in merge source not notified correctly"
 
   sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
   wc_dir = sbox.wc_dir
 
   # Some paths we'll care about.
@@ -17455,8 +17499,8 @@ def merge_source_with_replacement(sbox):
   psi_COPY_path   = sbox.ospath('A_COPY/D/H/psi')
   rho_COPY_path   = sbox.ospath('A_COPY/D/G/rho')
   omega_COPY_path = sbox.ospath('A_COPY/D/H/omega')
-  
-  # branch A@1 to A_COPY in r2, then make a few edits under A in r3-6:  
+
+  # branch A@1 to A_COPY in r2, then make a few edits under A in r3-6:
   wc_disk, wc_status = set_up_branch(sbox)
 
   # r7 Delete A, replace it with A@5, effectively reverting the change
@@ -17472,9 +17516,22 @@ def merge_source_with_replacement(sbox):
   svntest.main.run_svn(None, 'ci', '-m', 'file edit', wc_dir)
 
   # Update and sync merge ^/A to A_COPY.
+  #
+  #         text  text  text  text              text
+  #         edit  edit  edit  edit              edit
+  #         psi   rho   beta  omega             omega
+  #  A@r1---r3----r4----r5----r6---X       r7---r8--------->
+  #    |                 |                 ^          |
+  #    |                 v                 |          |
+  #    |                 +---replacement---+          |
+  #   copy                                            |
+  #    |                                          sync-merge
+  #    |                                              |
+  #    v                                              v
+  #    r2---A_COPY----------------------------------------->
   svntest.main.run_svn(None, 'up', wc_dir)
-  # This currently fails because the merge notifications make it look like
-  # r6 from ^/A was merged and recorded:
+  # This test previously failed because the merge notifications make it look
+  # like r6 from ^/A was merged and recorded:
   #
   #   >svn merge ^^/A A_COPY
   #   --- Merging r2 through r5 into 'A_COPY':
@@ -17487,13 +17544,14 @@ def merge_source_with_replacement(sbox):
   #   U    A_COPY\D\H\omega
   #   --- Recording mergeinfo for merge of r6 through r8 into 'A_COPY':
   #   G   A_COPY
-  expected_output = expected_merge_output([[2,5],[7,8]],
-                          ['U    ' + beta_COPY_path  + '\n',
-                           'U    ' + rho_COPY_path   + '\n',
-                           'U    ' + omega_COPY_path + '\n',
-                           'U    ' + psi_COPY_path   + '\n',
-                           ' U   ' + A_COPY_path     + '\n',
-                           ' G   ' + A_COPY_path     + '\n',])
+  expected_output = expected_merge_output(
+    [[2,5],[7,8]],
+    ['U    ' + beta_COPY_path  + '\n',
+     'U    ' + rho_COPY_path   + '\n',
+     'U    ' + omega_COPY_path + '\n',
+     'U    ' + psi_COPY_path   + '\n',
+     ' U   ' + A_COPY_path     + '\n',
+     ' G   ' + A_COPY_path     + '\n',])
   svntest.actions.run_and_verify_svn(None, expected_output, [],
                                      'merge', sbox.repo_url + '/A',
                                      A_COPY_path)
@@ -17505,6 +17563,23 @@ def merge_source_with_replacement(sbox):
                                      [], 'pg', SVN_PROP_MERGEINFO,
                                      '-R', A_COPY_path)
 
+  # Commit the above merge and then reverse merge it.  Again r6 is not
+  # being merged and should not be part of the notifications.
+  sbox.simple_commit()
+  sbox.simple_update()
+  expected_output = expected_merge_output(
+    [[5,2],[8,7]],
+    ['U    ' + beta_COPY_path  + '\n',
+     'U    ' + rho_COPY_path   + '\n',
+     'U    ' + omega_COPY_path + '\n',
+     'U    ' + psi_COPY_path   + '\n',
+     ' U   ' + A_COPY_path     + '\n',
+     ' G   ' + A_COPY_path     + '\n',],
+    elides=True)
+  svntest.actions.run_and_verify_svn(None, expected_output, [],
+                                     'merge', sbox.repo_url + '/A',
+                                     A_COPY_path, '-r8:1')
+
 #----------------------------------------------------------------------
 # Test for issue #4144 'Reverse merge with replace in source applies
 # diffs in forward order'.
@@ -17514,6 +17589,8 @@ def reverse_merge_with_rename(sbox):
   "reverse merge applies revs in reverse order"
 
   sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
   wc_dir = sbox.wc_dir
 
   # Some paths we'll care about.
@@ -17525,7 +17602,7 @@ def reverse_merge_with_rename(sbox):
   rho_COPY_path   = sbox.ospath('A_COPY/D/G/rho')
   omega_COPY_path = sbox.ospath('A_COPY/D/H/omega')
 
-  # branch A@1 to A_COPY in r2, then make a few edits under A in r3-6:  
+  # branch A@1 to A_COPY in r2, then make a few edits under A in r3-6:
   wc_disk, wc_status = set_up_branch(sbox)
 
   # r7 - Rename ^/A to ^/trunk.
@@ -17596,15 +17673,17 @@ def reverse_merge_with_rename(sbox):
 def merge_adds_then_deletes_subtree(sbox):
   "merge adds then deletes subtree"
 
+  sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
+  wc_dir = sbox.wc_dir
+
   # Some paths we'll care about.
   A_path         = sbox.ospath('A')
   nu_path        = sbox.ospath('A/C/nu')
   C_branch_path  = sbox.ospath('branch/C')
   nu_branch_path = sbox.ospath('branch/C/nu')
 
-  sbox.build()
-  wc_dir = sbox.wc_dir
-
   # Make a branch.
   svntest.actions.run_and_verify_svn(None, None, [], 'copy',
                                      sbox.repo_url + '/A',
@@ -17666,6 +17745,11 @@ def merge_adds_then_deletes_subtree(sbox
 def merge_with_added_subtrees_with_mergeinfo(sbox):
   "merge with added subtrees with mergeinfo"
 
+  sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
+  wc_dir = sbox.wc_dir
+
   # Some paths we'll care about.
   A_path      = sbox.ospath('A')
   Y_path      = sbox.ospath('A/C/X/Y')
@@ -17676,9 +17760,6 @@ def merge_with_added_subtrees_with_merge
   W_COPY_path = sbox.ospath('A_COPY/C/X/Y/Z/W')
   A_COPY2_path = sbox.ospath('A_COPY_2')
 
-  sbox.build()
-  wc_dir = sbox.wc_dir
-
   # Make two branches of ^/A and then make a few edits under A in r4-7:
   wc_disk, wc_status = set_up_branch(sbox, nbr_of_branches=2)
 
@@ -17736,7 +17817,7 @@ def merge_with_added_subtrees_with_merge
   #    vvvvvvvvvvvvvvvvvvvv
   #    U   A_COPY_2\C\X\Y\Z
   #    ^^^^^^^^^^^^^^^^^^^^
-  #   
+  #
   #   >svn pl -vR A_COPY_2
   #   Properties on 'A_COPY_2':
   #     svn:mergeinfo
@@ -17838,6 +17919,11 @@ def merge_with_added_subtrees_with_merge
 def merge_with_externals_with_mergeinfo(sbox):
   "merge with externals with mergeinfo"
 
+  sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
+  wc_dir = sbox.wc_dir
+
   # Some paths we'll care about.
   A_path = sbox.ospath('A')
   A_COPY_path = sbox.ospath('A_COPY')
@@ -17845,9 +17931,6 @@ def merge_with_externals_with_mergeinfo(
   mu_COPY_path = sbox.ospath('A_COPY/mu')
   mu_path = sbox.ospath('A/mu')
 
-  sbox.build()
-  wc_dir = sbox.wc_dir
-
   # Make a branch of ^/A and then make a few edits under A in r3-6:
   wc_disk, wc_status = set_up_branch(sbox)
 
@@ -18019,6 +18102,8 @@ def merge_target_selection(sbox):
   "merge target selection handling"
 
   sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
 
   # r2
   sbox.simple_mkdir('dir')
@@ -18114,6 +18199,8 @@ def merge_properties_on_adds(sbox):
   "merged directory properties are added"
 
   sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
 
   sbox.simple_copy('A/D/G', 'G')
 
@@ -18172,7 +18259,7 @@ def merge_properties_on_adds(sbox):
   # For fun, also check the status: 'svn status' suppresses the M from AM.
 
   # G = sbox.ospath('G')
-  # 
+  #
   # expected_status = wc.State('G', {
   #   ''           : Item(status=' M', wc_rev='2'),
   #   'pi'         : Item(status='  ', wc_rev='2'),
@@ -18246,7 +18333,8 @@ class RangeList(list):
 def expected_merge_output2(tgt_ospath,
                            recorded_ranges,
                            merged_ranges=None,
-                           prop_conflicts=0):
+                           prop_conflicts=0,
+                           prop_resolved=0):
   """Return an ExpectedOutput instance corresponding to the expected
      output of a merge into TGT_OSPATH, with one 'recording
      mergeinfo...' notification per specified revision range in
@@ -18268,7 +18356,7 @@ def expected_merge_output2(tgt_ospath,
     # List of mergeinfo-strings => list of rangelists
     merged_ranges = [RangeList(r) for r in merged_ranges]
 
-  status_letters_re = prop_conflicts and ' [UC]' or ' U'
+  status_letters_re = (prop_conflicts or prop_resolved) and ' [UC]' or ' U'
   status_letters_mi = ' [UG]'
   lines = []
   for i, rr in enumerate(recorded_ranges):
@@ -18287,14 +18375,19 @@ def expected_merge_output2(tgt_ospath,
     lines += [status_letters_mi + '   ' + re.escape(tgt_ospath) + '\n']
 
   # Summary of conflicts
-  lines += svntest.main.summary_of_conflicts(prop_conflicts=prop_conflicts)
-
-  return RegexListOutput(lines)
+  lines += svntest.main.summary_of_conflicts(prop_conflicts=prop_conflicts,
+                                             prop_resolved=prop_resolved,
+                                             as_regex=True)
+
+  # The 'match_all=False' is because we also expect some
+  # 'Resolved conflicted state of ...' lines.
+  return RegexListOutput(lines, match_all=False)
 
 def expected_out_and_err(tgt_ospath,
                            recorded_ranges,
                            merged_ranges=None,
                            prop_conflicts=0,
+                           prop_resolved=0,
                            expect_error=True):
   """Return a tuple (expected_out, expected_err) giving the expected
      output and expected error output for a merge into TGT_OSPATH. See
@@ -18304,7 +18397,8 @@ def expected_out_and_err(tgt_ospath,
      raised.
   """
   expected_out = expected_merge_output2(tgt_ospath, recorded_ranges,
-                                        merged_ranges, prop_conflicts)
+                                        merged_ranges,
+                                        prop_conflicts, prop_resolved)
   if expect_error:
     expected_err = RegexListOutput([
                      '^svn: E155015: .* conflicts were produced .* into$',
@@ -18348,6 +18442,8 @@ def conflict_aborted_mergeinfo_described
   "conflicted split merge can be repeated"
 
   sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
 
   trunk = 'A'
   branch = 'A2'
@@ -18538,6 +18634,8 @@ def multiple_editor_drive_merge_notifica
   "each editor drive gets its own notification"
 
   sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
 
   iota_branch_path = sbox.ospath('iota-copy')
   C_branch_path = sbox.ospath('branch')
@@ -18626,6 +18724,8 @@ def multiple_editor_drive_merge_notifica
 def single_editor_drive_merge_notifications(sbox):
   "single editor drive merge notifications"
   sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
   wc_dir = sbox.wc_dir
 
   A_copy_path = sbox.ospath('A_COPY')
@@ -18704,11 +18804,207 @@ def single_editor_drive_merge_notificati
      D_copy_path + "':\n",
      " U   " + D_copy_path + "\n",
      "--- Eliding mergeinfo from '" + D_copy_path + "':\n",
-     " U   " + D_copy_path + "\n"])     
+     " U   " + D_copy_path + "\n"])
   svntest.actions.run_and_verify_svn(None, expected_output, [], 'merge',
                                      '-r9:2', sbox.repo_url + '/A',
                                      A_copy_path)
 
+@SkipUnless(server_has_mergeinfo)
+@Issue(4316)  # 'Merge errors out after resolving conflicts'
+# Very similar to conflict_aborted_mergeinfo_described_partial_merge()
+# (test number 135), except here we tell the merge to resolve the
+# conflicts that are generated part way through a multi-revision-range
+# merge, and we expect it to continue with the rest of the merge.
+def conflicted_split_merge_with_resolve(sbox):
+  "conflicted split merge with resolve"
+
+  sbox.build()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
+
+  trunk = 'A'
+  branch = 'A2'
+  file = 'mu'
+  dir = 'B'
+  trunk_file = 'A/mu'
+  trunk_dir = 'A/B'
+
+  # r2: initial state
+  for rev in range(4, 11):
+    sbox.simple_propset('prop-' + str(rev), 'Old pval ' + str(rev),
+                        trunk_file, trunk_dir)
+  sbox.simple_commit()
+
+  # r3: branch
+  sbox.simple_update()
+  sbox.simple_copy(trunk, branch)
+  sbox.simple_commit()
+
+  zero_rev = 3
+
+  def edit_file_or_dir(path, rev, val):
+    """Make a local edit to the file at PATH."""
+    sbox.simple_propset('prop-' + str(rev), val + ' pval ' + str(rev), path)
+
+  # r4 through r10: simple edits
+  for rev in range(4, 11):
+    edit_file_or_dir(trunk_file, rev, 'Edited')
+    edit_file_or_dir(trunk_dir, rev, 'Edited')
+    sbox.simple_commit()
+
+  # r14: merge some changes to the branch so that later merges will be split
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge', '-c5,9',
+                                     '^/' + trunk, sbox.ospath(branch),
+                                     '--accept', 'theirs-conflict')
+  sbox.simple_commit()
+  sbox.simple_update()
+
+  def revert_branch():
+    svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R',
+                                       sbox.ospath(branch))
+
+  def try_merge(relpath, conflict_rev, rev_args,
+                expected_out_err, expected_mi):
+    """Revert RELPATH in the branch; make a change that will conflict
+       with CONFLICT_REV if not None; merge RELPATH in the trunk
+       to RELPATH in the branch using revision arguments REV_ARGS (list of
+       '-r...' or '-c...' strings).
+
+       EXPECTED_OUT_ERR_MI is a tuple: (expected_out, expected_err,
+       expected_mi).  EXPECTED_OUT and EXPECTED_ERR are instances of
+       ExpectedOutput.
+
+       Expect to find mergeinfo EXPECTED_MI if not None.  EXPECTED_MI is
+       a single mergeinfo-string.
+    """
+    src_path = trunk + '/' + relpath
+    tgt_path = branch + '/' + relpath
+    tgt_ospath = sbox.ospath(tgt_path)
+
+    expected_out, expected_err = expected_out_err
+
+    revert_branch()
+
+    # Arrange for the merge to conflict at CONFLICT_REV.
+    if conflict_rev:
+      edit_file_or_dir(tgt_path, conflict_rev, 'Conflict')
+
+    src_url = '^/' + src_path + '@11'
+    svntest.actions.run_and_verify_svn(
+                      None, expected_out, expected_err,
+                      'merge', src_url, tgt_ospath, '--accept', 'mine-full',
+                      *rev_args)
+
+    if expected_mi is not None:
+      expected_mergeinfo = ['/' + src_path + ':' + expected_mi + '\n']
+      check_mergeinfo(expected_mergeinfo, tgt_ospath)
+
+  # In a mergeinfo-aware merge, each specified revision range is split
+  # internally into sub-ranges, to avoid any already-merged revisions.
+  #
+  # From white-box inspection, we see there are code paths that treat
+  # the last specified range and the last sub-range specially.  The
+  # first specified range or sub-range is not treated specially in terms
+  # of the code paths, although it might be in terms of data flow.
+  #
+  # We test merges that raise a conflict in the first and last sub-range
+  # of the first and last specified range.
+
+  for target in [file, dir]:
+
+    tgt_ospath = sbox.ospath(branch + '/' + target)
+
+    # First test: Merge "everything" to the branch.
+    #
+    # This merge is split into three sub-ranges: r3-4, r6-8, r10-head.
+    # We have arranged that the merge will raise a conflict in the first
+    # sub-range.  Since we are postponing conflict resolution, the merge
+    # should stop after the first sub-range, allowing us to resolve and
+    # repeat the merge at which point the next sub-range(s) can be merged.
+    # The mergeinfo on the target then should only reflect that the first
+    # sub-range (r3-4) has been merged.
+    expect = expected_out_and_err(tgt_ospath,
+                                  '3-4,6-11',
+                                  ['3-4', '6-8,10-11'],
+                                  prop_resolved=1, expect_error=False)
+    try_merge(target, 4, [], expect, '3-11')
+
+    # Try a multiple-range merge that raises a conflict in the
+    # first sub-range in the first specified range;
+    expect = expected_out_and_err(tgt_ospath,
+                                  '4,6,8-10',
+                                  ['4', '6', '8,10'],
+                                  prop_resolved=1, expect_error=False)
+    try_merge(target, 4, ['-c4-6,8-10'], expect, '4-6,8-10')
+    # last sub-range in the first specified range;
+    expect = expected_out_and_err(tgt_ospath,
+                                  '4-6,8-10', ['4,6', '8,10'],
+                                  prop_resolved=1, expect_error=False)
+    try_merge(target, 6, ['-c4-6,8-10'], expect, '4-6,8-10')
+    # first sub-range in the last specified range;
+    expect = expected_out_and_err(tgt_ospath,
+                                  '4-6,8,10',
+                                  ['4,6', '8', '10'],
+                                  prop_resolved=1, expect_error=False)
+    try_merge(target, 8, ['-c4-6,8-10'], expect, '4-6,8-10')
+    # last sub-range in the last specified range.
+    # (Expect no error, because 'svn merge' does not throw an error if
+    # there is no more merging to do when a conflict occurs.)
+    expect = expected_out_and_err(tgt_ospath,
+                                  '4-6,8-10', ['4,6', '8,10'],
+                                  prop_resolved=1, expect_error=False)
+    try_merge(target, 10, ['-c4-6,8-10'], expect, '4-6,8-10')
+
+    # Try similar merges but involving ranges in reverse order.
+    expect = expected_out_and_err(tgt_ospath,
+                                  '8', ['8'],
+                                  prop_resolved=1, expect_error=False)
+    try_merge(target, 8,  ['-c8-10,4-6'], expect, '4-6,8-10')
+    expect = expected_out_and_err(tgt_ospath,
+                                  '8-10', ['8,10'],
+                                  prop_resolved=1, expect_error=False)
+    try_merge(target, 10, ['-c8-10,4-6'], expect, '4-6,8-10')
+    expect = expected_out_and_err(tgt_ospath,
+                                  '8-10,4', ['8,10', '4'],
+                                  prop_resolved=1, expect_error=False)
+    try_merge(target, 4,  ['-c8-10,4-6'], expect, '4-6,8-10')
+    expect = expected_out_and_err(tgt_ospath,
+                                  '8-10,4-6', ['8,10', '4,6'],
+                                  prop_resolved=1, expect_error=False)
+    try_merge(target, 6,  ['-c8-10,4-6'], expect, '4-6,8-10')
+
+    # Try some reverse merges, with ranges in forward and reverse order.
+    #
+    # Reverse merges start with all source changes merged except 5 and 9.
+    revert_branch()
+    simple_merge(trunk + '/' + target, sbox.ospath(branch + '/' + target),
+                 ['-c-5,-9,4,6-8,10'])
+    sbox.simple_commit()
+    sbox.simple_update()
+
+    expect = expected_out_and_err(tgt_ospath,
+                                  '6-4,10-8', ['-6,-4', '-10,-8'],
+                                  expect_error=False)
+    try_merge(target, None, ['-r6:3', '-r10:7'], expect, '7')
+    expect = expected_out_and_err(tgt_ospath,
+                                  '-6,-4,10-8',
+                                  ['-6', '-4', '-10,-8'],
+                                  prop_resolved=1, expect_error=False)
+    try_merge(target, 6,  ['-r6:3', '-r10:7'], expect, '7')
+    expect = expected_out_and_err(tgt_ospath,
+                                  '6-4,10-8', ['-6,-4', '-10,-8'],
+                                  prop_resolved=1, expect_error=False)
+    try_merge(target, 4,  ['-r6:3', '-r10:7'], expect, '7')
+    expect = expected_out_and_err(tgt_ospath,
+                                  '6-4,-10,-8',
+                                  ['-6,-4', '-10', '-8'],
+                                  prop_resolved=1, expect_error=False)
+    try_merge(target, 10, ['-r6:3', '-r10:7'], expect, '7')
+    expect = expected_out_and_err(tgt_ospath,
+                                  '6-4,10-8', ['-6,-4', '-10,-8'],
+                                  prop_resolved=1, expect_error=False)
+    try_merge(target, 8,  ['-r6:3', '-r10:7'], expect, '7')
+
 ########################################################################
 # Run the tests
 
@@ -18852,6 +19148,7 @@ test_list = [ None,
               conflict_aborted_mergeinfo_described_partial_merge,
               multiple_editor_drive_merge_notifications,
               single_editor_drive_merge_notifications,
+              conflicted_split_merge_with_resolve,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/merge_tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/merge_tree_conflict_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/merge_tree_conflict_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/merge_tree_conflict_tests.py Fri May 10 14:58:47 2013
@@ -1329,7 +1329,7 @@ def tree_conflicts_merge_edit_onto_missi
   })
 
   # Currently this test fails because some parts of the merge
-  # start succeeding. 
+  # start succeeding.
   svntest.deeptrees.deep_trees_run_tests_scheme_for_merge(sbox,
     [ DeepTreesTestCase(
                "local_tree_missing_incoming_leaf_edit",

Modified: subversion/branches/master-passphrase/subversion/tests/cmdline/mergeinfo_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/cmdline/mergeinfo_tests.py?rev=1481041&r1=1481040&r2=1481041&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/cmdline/mergeinfo_tests.py (original)
+++ subversion/branches/master-passphrase/subversion/tests/cmdline/mergeinfo_tests.py Fri May 10 14:58:47 2013
@@ -384,6 +384,14 @@ def recursive_mergeinfo(sbox):
                                            sbox.repo_url + '/A2',
                                            sbox.repo_url + '/A_COPY',
                                            '--show-revs', 'eligible', '-R')
+  # Do the same as above, but test that we can request the revisions
+  # in reverse order.
+  svntest.actions.run_and_verify_mergeinfo(adjust_error_for_server_version(""),
+                                           ['8*', '4*', '3'],
+                                           sbox.repo_url + '/A2',
+                                           sbox.repo_url + '/A_COPY',
+                                           '--show-revs', 'eligible', '-R',
+                                           '-r', '9:0')
 
   # Asking for merged revisions from A2 to A_COPY should show:
   #
@@ -406,6 +414,15 @@ def recursive_mergeinfo(sbox):
                                            A_COPY_path,
                                            '--show-revs', 'merged',
                                            '--depth', 'infinity')
+  # Do the same as above, but test that we can request the revisions
+  # in reverse order.
+  svntest.actions.run_and_verify_mergeinfo(adjust_error_for_server_version(""),
+                                           ['8*', '6', '5', '4*'],
+                                           A2_path,
+                                           A_COPY_path,
+                                           '--show-revs', 'merged',
+                                           '--depth', 'infinity',
+                                           '-r', '9:0')
 
   # A couple tests of problems found with initial issue #3242 fixes.
   # We should be able to check for the merged revs from a URL to a URL