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

svn commit: r984234 [19/20] - in /subversion/branches/ignore-mergeinfo: ./ build/ build/ac-macros/ build/generator/ notes/ notes/api-errata/ notes/obliterate/ notes/obliterate/fspec-cc1/ notes/rename-tracking/ notes/svnpatch/ notes/tree-conflicts/ note...

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/switch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/switch_tests.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/switch_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/switch_tests.py Tue Aug 10 22:07:24 2010
@@ -29,6 +29,7 @@ import shutil, re, os
 
 # Our testing module
 import svntest
+from svntest import verify, actions, main
 
 # (abbreviation)
 Skip = svntest.testcase.Skip
@@ -38,6 +39,7 @@ Item = svntest.wc.StateItem
 
 from svntest.main import SVN_PROP_MERGEINFO, server_has_mergeinfo
 
+
 ### Bummer.  It would be really nice to have easy access to the URL
 ### member of our entries files so that switches could be testing by
 ### examining the modified ancestry.  But status doesn't show this
@@ -543,16 +545,26 @@ def relocate_deleted_missing_copied(sbox
   # Remove A/B/F to create a missing entry
   svntest.main.safe_rmtree(os.path.join(wc_dir, 'A', 'B', 'F'))
 
-  # Copy A/D/H to A/D/H2
-  H_path = os.path.join(wc_dir, 'A', 'D', 'H')
-  H2_path = os.path.join(wc_dir, 'A', 'D', 'H2')
+  # Copy A/D to A/D2
+  D_path = os.path.join(wc_dir, 'A', 'D')
+  D2_path = os.path.join(wc_dir, 'A', 'D2')
   svntest.actions.run_and_verify_svn(None, None, [], 'copy',
-                                     H_path, H2_path)
-  expected_status.add({
-    'A/D/H2'       : Item(status='A ', wc_rev='-', copied='+'),
-    'A/D/H2/chi'   : Item(status='  ', wc_rev='-', copied='+'),
-    'A/D/H2/omega' : Item(status='  ', wc_rev='-', copied='+'),
-    'A/D/H2/psi'   : Item(status='  ', wc_rev='-', copied='+'),
+                                     D_path, D2_path)
+  # Delete within the copy
+  D2G_path = os.path.join(wc_dir, 'A', 'D2', 'G')
+  svntest.actions.run_and_verify_svn(None, None, [], 'rm', D2G_path)
+
+  expected_status.add({
+    'A/D2'         : Item(status='A ', wc_rev='-', copied='+'),
+    'A/D2/gamma'   : Item(status='  ', wc_rev='-', copied='+'),
+    'A/D2/G'       : Item(status='D ', wc_rev='?'),
+    'A/D2/G/pi'    : Item(status='D ', wc_rev='?'),
+    'A/D2/G/rho'   : Item(status='D ', wc_rev='?'),
+    'A/D2/G/tau'   : Item(status='D ', wc_rev='?'),
+    'A/D2/H'       : Item(status='  ', wc_rev='-', copied='+'),
+    'A/D2/H/chi'   : Item(status='  ', wc_rev='-', copied='+'),
+    'A/D2/H/omega' : Item(status='  ', wc_rev='-', copied='+'),
+    'A/D2/H/psi'   : Item(status='  ', wc_rev='-', copied='+'),
     })
   expected_status.tweak('A/B/F', status='! ', wc_rev='?')
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
@@ -574,17 +586,23 @@ def relocate_deleted_missing_copied(sbox
   expected_disk = svntest.main.greek_state.copy()
   expected_disk.remove('A/mu')
   expected_disk.add({
-    'A/D/H2'       : Item(),
-    'A/D/H2/chi'   : Item("This is the file 'chi'.\n"),
-    'A/D/H2/omega' : Item("This is the file 'omega'.\n"),
-    'A/D/H2/psi'   : Item("This is the file 'psi'.\n"),
+    'A/D2'       : Item(),
+    'A/D2/gamma'   : Item("This is the file 'gamma'.\n"),
+    'A/D2/G'       : Item(),
+    'A/D2/H'       : Item(),
+    'A/D2/H/chi'   : Item("This is the file 'chi'.\n"),
+    'A/D2/H/omega' : Item("This is the file 'omega'.\n"),
+    'A/D2/H/psi'   : Item("This is the file 'psi'.\n"),
     })
   expected_status.add({
     'A/B/F'       : Item(status='  ', wc_rev='2'),
     })
   expected_status.tweak(wc_rev=2)
-  expected_status.tweak('A/D/H2', 'A/D/H2/chi', 'A/D/H2/omega', 'A/D/H2/psi',
+  expected_status.tweak('A/D2', 'A/D2/gamma',
+                        'A/D2/H', 'A/D2/H/chi', 'A/D2/H/omega', 'A/D2/H/psi',
                         wc_rev='-')
+  expected_status.tweak('A/D2/G', 'A/D2/G/pi', 'A/D2/G/rho', 'A/D2/G/tau',
+                        wc_rev='?')
   svntest.actions.run_and_verify_update(wc_dir,
                                         expected_output,
                                         expected_disk,
@@ -592,10 +610,13 @@ def relocate_deleted_missing_copied(sbox
 
   # Commit to verify that copyfrom URLs have been relocated
   expected_output = svntest.wc.State(wc_dir, {
-    'A/D/H2'       : Item(verb='Adding'),
+    'A/D2'       : Item(verb='Adding'),
+    'A/D2/G'     : Item(verb='Deleting'),
     })
-  expected_status.tweak('A/D/H2', 'A/D/H2/chi', 'A/D/H2/omega', 'A/D/H2/psi',
+  expected_status.tweak('A/D2', 'A/D2/gamma',
+                        'A/D2/H', 'A/D2/H/chi', 'A/D2/H/omega', 'A/D2/H/psi',
                         status='  ', wc_rev='3', copied=None)
+  expected_status.remove('A/D2/G', 'A/D2/G/pi', 'A/D2/G/rho', 'A/D2/G/tau')
   svntest.actions.run_and_verify_commit(wc_dir,
                                         expected_output, expected_status,
                                         None, wc_dir)
@@ -820,42 +841,84 @@ def bad_intermediate_urls(sbox):
 
 def obstructed_switch(sbox):
   "obstructed switch"
+  #svntest.factory.make(sbox, """svn cp -m msgcopy url/A/B/E url/A/B/Esave
+  #                              svn rm A/B/E/alpha
+  #                              svn commit
+  #                              echo "hello" >> A/B/E/alpha
+  #                              svn switch url/A/B/Esave A/B/E
+  #                              svn status
+  #                              svn info A/B/E/alpha""")
   sbox.build()
   wc_dir = sbox.wc_dir
+  url = sbox.repo_url
 
-  E_url      = sbox.repo_url + '/A/B/E'
-  E_url2     = sbox.repo_url + '/A/B/Esave'
-  svntest.actions.run_and_verify_svn(None,
-                                     ['\n', 'Committed revision 2.\n'], [],
-                                     'cp', '-m', 'msgcopy', E_url, E_url2)
+  A_B_E = os.path.join(wc_dir, 'A', 'B', 'E')
+  A_B_E_alpha = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha')
+  url_A_B_E = url + '/A/B/E'
+  url_A_B_Esave = url + '/A/B/Esave'
 
-  E_path     = os.path.join(wc_dir, 'A', 'B', 'E')
-  alpha_path = os.path.join(E_path, 'alpha')
-  svntest.actions.run_and_verify_svn(None, None, [], 'rm', alpha_path)
-  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  # svn cp -m msgcopy url/A/B/E url/A/B/Esave
+  expected_stdout = verify.UnorderedOutput([
+    '\n',
+    'Committed revision 2.\n',
+  ])
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'cp', '-m',
+    'msgcopy', url_A_B_E, url_A_B_Esave)
+
+  # svn rm A/B/E/alpha
+  expected_stdout = ['D         ' + A_B_E_alpha + '\n']
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'rm',
+    A_B_E_alpha)
+
+  # svn commit
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/B/E/alpha'       : Item(verb='Deleting'),
+  })
+
+  expected_status = actions.get_virginal_state(wc_dir, 1)
   expected_status.remove('A/B/E/alpha')
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # echo "hello" >> A/B/E/alpha
+  main.file_append(A_B_E_alpha, 'hello')
+
+  # svn switch url/A/B/Esave A/B/E
   expected_output = svntest.wc.State(wc_dir, {
-    'A/B/E/alpha' : Item(verb='Deleting'),
-    })
-  svntest.actions.run_and_verify_commit(wc_dir,
-                                        expected_output, expected_status,
-                                        None, wc_dir)
+    'A/B/E/alpha'       : Item(status='  ', treeconflict='C'),
+  })
 
-  svntest.main.file_append(alpha_path, "hello")
-  exit_code, out, err = svntest.main.run_svn(1, 'sw', E_url2, E_path)
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/B/E/alpha', contents='hello')
 
-  for line in err:
-    if line.find("file of the same name already exists") != -1:
-      break
-  else:
-    raise svntest.Failure
+  expected_status.add({
+    'A/B/E/alpha'       : Item(status='? ', treeconflict='C'),
+  })
+  expected_status.tweak('A/B/E', wc_rev='3', switched='S')
+  expected_status.tweak('A/B/E/beta', wc_rev='3')
 
-  os.remove(alpha_path)
-  svntest.actions.run_and_verify_svn(None, None, [], 'sw', E_url2, E_path)
-  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
-  expected_status.tweak('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', wc_rev=3)
-  expected_status.tweak('A/B/E', switched='S')
-  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+  actions.run_and_verify_switch(wc_dir, A_B_E, url_A_B_Esave,
+    expected_output, expected_disk, expected_status, None, None, None, None,
+    None, False)
+
+  # svn status
+  expected_status.add({
+    'A/B/Esave'         : Item(status='  '),
+    'A/B/Esave/beta'    : Item(status='  '),
+    'A/B/Esave/alpha'   : Item(status='  '),
+  })
+
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+  # svn info A/B/E/alpha
+  expected_stdout = verify.RegexOutput(
+                      ".*local unversioned, incoming add upon switch",
+                      match_all=False)
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'info',
+    A_B_E_alpha)
 
 
 #----------------------------------------------------------------------
@@ -1214,191 +1277,230 @@ def forced_switch(sbox):
 
 def forced_switch_failures(sbox):
   "forced switch detects tree conflicts"
-  sbox.build()
+  #  svntest.factory.make(sbox,
+  #    """
+  #    # Add a directory to obstruct a file.
+  #    mkdir A/B/F/pi
+  #
+  #    # Add a file to obstruct a directory.
+  #    echo "The file 'H'" > A/C/H
+  #
+  #    # Test three cases where forced switch should cause a tree conflict
+  #
+  #    # 1) A forced switch that tries to add a file when an unversioned
+  #    #    directory of the same name already exists.  (Currently fails)
+  #    svn switch --force url/A/D A/C
+  #
+  #    # 2) A forced switch that tries to add a dir when a file of the same
+  #    #    name already exists. (Tree conflict)
+  #    svn switch --force url/A/D/G A/B/F
+  #    svn info A/B/F/pi
+  #
+  #    # 3) A forced update that tries to add a directory when a versioned
+  #    #    directory of the same name already exists.
+  #
+  #    # Make dir A/D/H/I in repos.
+  #    svn mkdir -m "Log message" url/A/D/H/I
+  #
+  #    # Make A/D/G/I and co A/D/H/I into it.
+  #    mkdir A/D/G/I
+  #    svn co url/A/D/H/I A/D/G/I
+  #
+  #    # Try the forced switch.  A/D/G/I obstructs the dir A/D/G/I coming
+  #    # from the repos, causing an error.
+  #    svn switch --force url/A/D/H A/D/G
+  #
+  #    # Delete all three obstructions and finish the update.
+  #    rm -rf A/D/G/I
+  #    rm A/B/F/pi
+  #    rm A/C/H
+  #
+  #    # A/B/F is switched to A/D/G
+  #    # A/C is switched to A/D
+  #    # A/D/G is switched to A/D/H
+  #    svn up
+  #    """)
+  #  exit(0)
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  url = sbox.repo_url
+
+  A_B_F = os.path.join(wc_dir, 'A', 'B', 'F')
+  A_B_F_pi = os.path.join(wc_dir, 'A', 'B', 'F', 'pi')
+  A_C = os.path.join(wc_dir, 'A', 'C')
+  A_C_H = os.path.join(wc_dir, 'A', 'C', 'H')
+  A_D_G = os.path.join(wc_dir, 'A', 'D', 'G')
+  A_D_G_I = os.path.join(wc_dir, 'A', 'D', 'G', 'I')
+  url_A_D = url + '/A/D'
+  url_A_D_G = url + '/A/D/G'
+  url_A_D_H = url + '/A/D/H'
+  url_A_D_H_I = url + '/A/D/H/I'
 
   # Add a directory to obstruct a file.
-  pi_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'pi')
-  os.mkdir(pi_path)
+  # mkdir A/B/F/pi
+  os.makedirs(A_B_F_pi)
 
   # Add a file to obstruct a directory.
-  H_path = os.path.join(sbox.wc_dir, 'A', 'C', 'H')
-  svntest.main.file_write(H_path, "The file 'H'\n")
+  # echo "The file 'H'" > A/C/H
+  main.file_write(A_C_H, "The file 'H'\n")
 
   # Test three cases where forced switch should cause a tree conflict
-
   # 1) A forced switch that tries to add a file when an unversioned
   #    directory of the same name already exists.  (Currently fails)
+  # svn switch --force url/A/D A/C
+  expected_error = ('Failed to add directory.*' + re.escape(A_C_H) +
+                    '.*a non-directory object.*already exists')
+
+  actions.run_and_verify_switch(wc_dir, A_C, url_A_D, None, None, None,
+    expected_error, None, None, None, None, False, '--force')
+
+  # 2) A forced switch that tries to add a dir when a file of the same
+  #    name already exists.
+  # svn switch --force url/A/D/G A/B/F
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/B/F/rho'         : Item(status='A '),
+    'A/B/F/pi'          : Item(status='  ', treeconflict='C'),
+    'A/B/F/tau'         : Item(status='A '),
+  })
+
   expected_disk = svntest.main.greek_state.copy()
   expected_disk.add({
-    'A/C'               : Item(),
-    'A/C/gamma'         : Item("This is the file 'gamma'.\n"),
-    'A/C/H'             : Item("The file 'H'\n"),
+    'A/C/gamma'         : Item(contents="This is the file 'gamma'.\n"),
     'A/C/G'             : Item(),
-    'A/C/G/rho'         : Item("This is the file 'rho'.\n"),
-    'A/C/G/pi'          : Item("This is the file 'pi'.\n"),
-    'A/C/G/tau'         : Item("This is the file 'tau'.\n"),
-    })
-  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+    'A/C/G/pi'          : Item(contents="This is the file 'pi'.\n"),
+    'A/C/G/rho'         : Item(contents="This is the file 'rho'.\n"),
+    'A/C/G/tau'         : Item(contents="This is the file 'tau'.\n"),
+    'A/C/H'             : Item(contents="The file 'H'\n"),
+    'A/B/F/pi'          : Item(),
+    'A/B/F/rho'         : Item(contents="This is the file 'rho'.\n"),
+    'A/B/F/tau'         : Item(contents="This is the file 'tau'.\n"),
+  })
+
+  expected_status = actions.get_virginal_state(wc_dir, 1)
   expected_status.add({
-    'A/C'               : Item(status='! ', wc_rev='1', switched='S'),
+    'A/B/F/tau'         : Item(status='  ', wc_rev='1'),
+    'A/B/F/pi'          : Item(status='? ', treeconflict='C'),
+    'A/B/F/rho'         : Item(status='  ', wc_rev='1'),
     'A/C/G'             : Item(status='  ', wc_rev='1'),
-    'A/C/G/pi'          : Item(status='  ', wc_rev='1'),
     'A/C/G/rho'         : Item(status='  ', wc_rev='1'),
+    'A/C/G/pi'          : Item(status='  ', wc_rev='1'),
     'A/C/G/tau'         : Item(status='  ', wc_rev='1'),
     'A/C/gamma'         : Item(status='  ', wc_rev='1'),
-    })
-  svntest.actions.run_and_verify_switch(sbox.wc_dir,
-                                        os.path.join(sbox.wc_dir, 'A', 'C'),
-                                        sbox.repo_url + "/A/D",
-                                        None, None, None,
-                                        ".*Failed to add directory .*" + \
-                                        ": a non-directory object of the" + \
-                                        " same name already exists\n",
-                                        None, None, None, None, 0, '--force')
+  })
+  expected_status.tweak('A/B/F', switched='S')
+  expected_status.tweak('A/C', status='! ', switched='S')
+
+  actions.run_and_verify_switch(wc_dir, A_B_F, url_A_D_G, expected_output,
+    expected_disk, expected_status, None, None, None, None, None, False,
+    '--force')
+
+  # svn info A/B/F/pi
+  expected_stdout = verify.ExpectedOutput(
+    'Tree conflict: local unversioned, incoming add upon switch\n',
+    match_all=False)
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'info',
+    A_B_F_pi)
 
-  # 2) A forced switch that tries to add a dir when a file of the same
-  #    name already exists.  (Currently fails)
-  expected_disk.add({
-    'A/B/F/pi'          : Item(),
-    })
-  expected_status.add({
-    'A/B/F'             : Item(status='! ', wc_rev='1', switched='S'),
-    })
-  svntest.actions.run_and_verify_switch(sbox.wc_dir,
-                                        os.path.join(sbox.wc_dir,
-                                                     'A', 'B', 'F'),
-                                        sbox.repo_url + "/A/D/G",
-                                        None, None, None,
-                                        ".*Failed to add file .*" + \
-                                        ": a non-file object of the " + \
-                                        "same name already exists\n",
-                                        None, None, None, None, 0, '--force')
 
   # 3) A forced update that tries to add a directory when a versioned
   #    directory of the same name already exists.
-
   # Make dir A/D/H/I in repos.
-  I_url = sbox.repo_url + "/A/D/H/I"
-  exit_code, so, se = svntest.actions.run_and_verify_svn(
-    "Unexpected error during mkdir",
-    ['\n', 'Committed revision 2.\n'], [],
-    "mkdir", I_url, "-m", "Log Message")
+  # svn mkdir -m "Log message" url/A/D/H/I
+  expected_stdout = verify.UnorderedOutput([
+    '\n',
+    'Committed revision 2.\n',
+  ])
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'mkdir',
+    '-m', 'Log message', url_A_D_H_I)
 
   # Make A/D/G/I and co A/D/H/I into it.
-  I_path = os.path.join(sbox.wc_dir, 'A', 'D', 'G', 'I')
-  os.mkdir(I_path)
-  exit_code, so, se = svntest.actions.run_and_verify_svn(
-    "Unexpected error during co",
-    ['Checked out revision 2.\n'], [],
-    "co", I_url, I_path)
+  # mkdir A/D/G/I
+  os.makedirs(A_D_G_I)
+
+  # svn co url/A/D/H/I A/D/G/I
+  expected_output = svntest.wc.State(wc_dir, {})
+
+  expected_disk.add({
+    'A/D/G/I'           : Item(),
+  })
+
+  exit_code, so, se = svntest.actions.run_and_verify_svn( 
+    "Unexpected error during co", 
+    ['Checked out revision 2.\n'], [], 
+    "co", url_A_D_H_I, A_D_G_I)
 
   # Try the forced switch.  A/D/G/I obstructs the dir A/D/G/I coming
   # from the repos, causing an error.
-  G_path = os.path.join(sbox.wc_dir, 'A', 'D', 'G')
-  svntest.actions.run_and_verify_switch(sbox.wc_dir,
-                                        G_path,
-                                        sbox.repo_url + "/A/D/H",
-                                        None, None, None,
-                                        "Failed to add directory '.*I'."
-                                        "*already exists",
-                                        None, None, None, None, False,
-                                        '--force')
+  # svn switch --force url/A/D/H A/D/G
+  expected_error = ('Failed to add directory.*' + re.escape(A_D_G_I) +
+                    '.*a separate working copy.*already exists')
+
+  actions.run_and_verify_switch(wc_dir, A_D_G, url_A_D_H, None, None, None,
+    expected_error, None, None, None, None, False, '--force')
 
   # Delete all three obstructions and finish the update.
-  svntest.main.safe_rmtree(I_path)
-  svntest.main.safe_rmtree(pi_path)
-  os.remove(H_path)
+  # rm -rf A/D/G/I
+  main.safe_rmtree(A_D_G_I)
 
-  # For our expected disk start with the standard greek tree.
-  expected_disk = svntest.main.greek_state.copy()
+  # rm A/B/F/pi
+  main.safe_rmtree(A_B_F_pi)
+
+  # rm A/C/H
+  os.remove(A_C_H)
 
-  ### There has to be a simpler way to do this...but it will do for now.
   # A/B/F is switched to A/D/G
-  new_A_B_F = svntest.wc.State('', {
-    "A/B/F"       : Item(),
-    "A/B/F/rho"   : Item("This is the file 'rho'.\n"),
-    "A/B/F/pi"    : Item("This is the file 'pi'.\n"),
-    "A/B/F/tau"   : Item("This is the file 'tau'.\n"),
-    })
   # A/C is switched to A/D
-  new_A_C = svntest.wc.State('', {
-    "A/C"         : Item(),
-    "A/C/gamma"   : Item("This is the file 'gamma'.\n"),
-    "A/C/G"       : Item(),
-    "A/C/G/pi"    : Item("This is the file 'pi'.\n"),
-    "A/C/G/rho"   : Item("This is the file 'rho'.\n"),
-    "A/C/G/tau"   : Item("This is the file 'tau'.\n"),
-    "A/C/H"       : Item(),
-    "A/C/H/chi"   : Item("This is the file 'chi'.\n"),
-    "A/C/H/I"     : Item(),
-    "A/C/H/omega" : Item("This is the file 'omega'.\n"),
-    "A/C/H/psi"   : Item("This is the file 'psi'.\n"),
-    })
   # A/D/G is switched to A/D/H
-  new_A_D_G = svntest.wc.State('', {
-    "A/D/G"       : Item(),
-    "A/D/G/chi"   : Item("This is the file 'chi'.\n"),
-    "A/D/G/omega" : Item("This is the file 'omega'.\n"),
-    "A/D/G/I"     : Item(),
-    "A/D/G/psi"   : Item("This is the file 'psi'.\n"),
-    "A/D/H"       : Item(),
-    "A/D/H/chi"   : Item("This is the file 'chi'.\n"),
-    "A/D/H/omega" : Item("This is the file 'omega'.\n"),
-    "A/D/H/I"     : Item(),
-    "A/D/H/psi"   : Item("This is the file 'psi'.\n"),
-    "iota"        : Item("This is the file 'iota'.\n"),
-    })
-  # Remove the three switched subtrees and replace with their new contents.
-  expected_disk.remove('A/B/F', 'A/C',
-                       'A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
-  expected_disk.add_state('', new_A_B_F)
-  expected_disk.add_state('', new_A_C)
-  expected_disk.add_state('', new_A_D_G)
-
-  expected_status = svntest.wc.State(sbox.wc_dir, {
-    ""            : Item(),
-    "A"           : Item(),
-    "A/B"         : Item(),
-    "A/B/lambda"  : Item(),
-    "A/B/E"       : Item(),
-    "A/B/E/alpha" : Item(),
-    "A/B/E/beta"  : Item(),
-    "A/B/F"       : Item(switched='S'),
-    "A/B/F/rho"   : Item(),
-    "A/B/F/pi"    : Item(),
-    "A/B/F/tau"   : Item(),
-    "A/mu"        : Item(),
-    "A/C"         : Item(switched='S'),
-    "A/C/gamma"   : Item(),
-    "A/C/G"       : Item(),
-    "A/C/G/pi"    : Item(),
-    "A/C/G/rho"   : Item(),
-    "A/C/G/tau"   : Item(),
-    "A/C/H"       : Item(),
-    "A/C/H/chi"   : Item(),
-    "A/C/H/I"     : Item(),
-    "A/C/H/omega" : Item(),
-    "A/C/H/psi"   : Item(),
-    "A/D"         : Item(),
-    "A/D/gamma"   : Item(),
-    "A/D/G"       : Item(switched='S'),
-    "A/D/G/chi"   : Item(),
-    "A/D/G/omega" : Item(),
-    "A/D/G/I"     : Item(),
-    "A/D/G/psi"   : Item(),
-    "A/D/H"       : Item(),
-    "A/D/H/chi"   : Item(),
-    "A/D/H/omega" : Item(),
-    "A/D/H/I"     : Item(),
-    "A/D/H/psi"   : Item(),
-    "iota"        : Item(),
-    })
-  expected_status.tweak(status='  ', wc_rev=2)
-  svntest.actions.run_and_verify_update(sbox.wc_dir,
-                                        None,
-                                        expected_disk,
-                                        expected_status,
-                                        None, None, None, None, None, False)
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/C/H'             : Item(status='A '),
+    'A/C/H/omega'       : Item(status='A '),
+    'A/C/H/chi'         : Item(status='A '),
+    'A/C/H/I'           : Item(status='A '),
+    'A/C/H/psi'         : Item(status='A '),
+    'A/D/G/omega'       : Item(status='A '),
+    'A/D/G/I'           : Item(status='A '),
+    'A/D/G/psi'         : Item(status='A '),
+    'A/D/H/I'           : Item(status='A '),
+    'A/B/F/pi'          : Item(status='A '),
+  })
+
+  expected_disk.remove('A/D/G/tau', 'A/D/G/rho', 'A/D/G/pi')
+  expected_disk.add({
+    'A/D/H/I'           : Item(),
+    'A/D/G/omega'       : Item(contents="This is the file 'omega'.\n"),
+    'A/D/G/psi'         : Item(contents="This is the file 'psi'.\n"),
+    'A/D/G/chi'         : Item(contents="This is the file 'chi'.\n"),
+    'A/C/H/I'           : Item(),
+    'A/C/H/omega'       : Item(contents="This is the file 'omega'.\n"),
+    'A/C/H/psi'         : Item(contents="This is the file 'psi'.\n"),
+    'A/C/H/chi'         : Item(contents="This is the file 'chi'.\n"),
+  })
+  expected_disk.tweak('A/C/H', contents=None)
+  expected_disk.tweak('A/B/F/pi', contents="This is the file 'pi'.\n")
+
+  expected_status.remove('A/D/G/tau', 'A/D/G/rho', 'A/D/G/pi')
+  expected_status.add({
+    'A/D/G/omega'       : Item(status='  ', wc_rev='2'),
+    'A/D/G/I'           : Item(status='  ', wc_rev='2'),
+    'A/D/G/psi'         : Item(status='  ', wc_rev='2'),
+    'A/D/G/chi'         : Item(status='  ', wc_rev='2'),
+    'A/D/H/I'           : Item(status='  ', wc_rev='2'),
+    'A/C/H'             : Item(status='  ', wc_rev='2'),
+    'A/C/H/psi'         : Item(status='  ', wc_rev='2'),
+    'A/C/H/omega'       : Item(status='  ', wc_rev='2'),
+    'A/C/H/chi'         : Item(status='  ', wc_rev='2'),
+    'A/C/H/I'           : Item(status='  ', wc_rev='2'),
+  })
+  expected_status.tweak(wc_rev='2', status='  ')
+  expected_status.tweak('A/B/F/pi', treeconflict=None)
+  expected_status.tweak('A/D/G', switched='S')
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
 
 def switch_with_obstructing_local_adds(sbox):
   "switch tolerates WC adds"
@@ -1436,11 +1538,11 @@ def switch_with_obstructing_local_adds(s
 
   # Setup expected results of switch.
   expected_output = svntest.wc.State(sbox.wc_dir, {
-    "A/B/F/gamma"   : Item(status='E '),
+    "A/B/F/gamma"   : Item(status='  ', treeconflict='C'),
     "A/B/F/G"       : Item(status='E '),
-    "A/B/F/G/pi"    : Item(status='C '),
+    "A/B/F/G/pi"    : Item(status='  ', treeconflict='C'),
     "A/B/F/G/rho"   : Item(status='A '),
-    "A/B/F/G/tau"   : Item(status='E '),
+    "A/B/F/G/tau"   : Item(status='  ', treeconflict='C'),
     "A/B/F/H"       : Item(status='A '),
     "A/B/F/H/chi"   : Item(status='A '),
     "A/B/F/H/omega" : Item(status='A '),
@@ -1451,12 +1553,7 @@ def switch_with_obstructing_local_adds(s
   expected_disk.add({
     "A/B/F/gamma"     : Item("This is the file 'gamma'.\n"),
     "A/B/F/G"         : Item(),
-    "A/B/F/G/pi"      : Item("\n".join(["<<<<<<< .mine",
-                                        "This is the OBSTRUCTING file 'pi'.",
-                                        "=======",
-                                        "This is the file 'pi'.",
-                                        ">>>>>>> .r1",
-                                        ""])),
+    "A/B/F/G/pi"      : Item("This is the OBSTRUCTING file 'pi'.\n"),
     "A/B/F/G/rho"     : Item("This is the file 'rho'.\n"),
     "A/B/F/G/tau"     : Item("This is the file 'tau'.\n"),
     "A/B/F/G/upsilon" : Item("This is the unversioned file 'upsilon'.\n"),
@@ -1469,11 +1566,12 @@ def switch_with_obstructing_local_adds(s
   expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
   expected_status.tweak('A/B/F', switched='S')
   expected_status.add({
-    "A/B/F/gamma"     : Item(status='  ', wc_rev=1),
+    "A/B/F/gamma"     : Item(status='R ', treeconflict='C', wc_rev='1'),
+
     "A/B/F/G"         : Item(status='  ', wc_rev=1),
-    "A/B/F/G/pi"      : Item(status='C ', wc_rev=1),
+    "A/B/F/G/pi"      : Item(status='R ', treeconflict='C', wc_rev='1'),
     "A/B/F/G/rho"     : Item(status='  ', wc_rev=1),
-    "A/B/F/G/tau"     : Item(status='  ', wc_rev=1),
+    "A/B/F/G/tau"     : Item(status='R ', treeconflict='C', wc_rev='1'),
     "A/B/F/G/upsilon" : Item(status='A ', wc_rev=0),
     "A/B/F/H"         : Item(status='  ', wc_rev=1),
     "A/B/F/H/chi"     : Item(status='  ', wc_rev=1),

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/tree_conflict_tests.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/tree_conflict_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/tree_conflict_tests.py Tue Aug 10 22:07:24 2010
@@ -46,7 +46,7 @@ AnyOutput = svntest.verify.AnyOutput
 
 # If verbose mode is enabled, print the LINE and a newline.
 def verbose_print(line):
-  if main.verbose_mode:
+  if main.options.verbose:
     print(line)
 
 # If verbose mode is enabled, print the (assumed newline-terminated) LINES.
@@ -107,6 +107,7 @@ def incoming_paths(root_dir, parent_dir)
     'F1' : os.path.join(root_dir,   "F1"),
     'F'  : os.path.join(parent_dir, "F"),
     'F2' : os.path.join(parent_dir, "F2-in"),
+    'F3' : os.path.join(root_dir,   "F3"),
     'D1' : os.path.join(root_dir,   "D1"),
     'D'  : os.path.join(parent_dir, "D"),
     'D2' : os.path.join(parent_dir, "D2-in"),
@@ -120,6 +121,7 @@ def localmod_paths(root_dir, parent_dir)
     'F1' : os.path.join(root_dir,   "F1"),
     'F'  : os.path.join(parent_dir, "F"),
     'F2' : os.path.join(parent_dir, "F2-local"),
+    'F3' : os.path.join(root_dir,   "F3"),
     'D1' : os.path.join(root_dir,   "D1"),
     'D'  : os.path.join(parent_dir, "D"),
     'D2' : os.path.join(parent_dir, "D2-local"),
@@ -127,8 +129,9 @@ def localmod_paths(root_dir, parent_dir)
 
 # Perform the action MODACTION on the WC items given by PATHS. The
 # available actions can be seen within this function.
-def modify(modaction, paths):
+def modify(modaction, paths, is_init=True):
   F1 = paths['F1']  # existing file to copy from
+  F3 = paths['F3']  # existing file to copy from
   F  = paths['F']   # target file
   F2 = paths['F2']  # non-existing file to copy/move to
   D1 = paths['D1']  # existing dir to copy from
@@ -161,7 +164,10 @@ def modify(modaction, paths):
     main.run_svn(None, 'add', D)
     main.run_svn(None, 'pset', 'dprop2', 'A prop of added dir D.', D)
   elif modaction == 'fC':  # file Copy (from F1)
-    main.run_svn(None, 'copy', F1, F)
+    if is_init:
+      main.run_svn(None, 'copy', F1, F)
+    else:
+      main.run_svn(None, 'copy', F3, F)
   elif modaction == 'dC':  # dir Copy (from D1)
     main.run_svn(None, 'copy', D1, D)
   elif modaction == 'fM':  # file Move (to F2)
@@ -199,6 +205,7 @@ def modify(modaction, paths):
 
 # File names:
 #   F1 = any existing file
+#   F3 = any existing file
 #   F  = the file-path being acted on
 #   F2 = any non-existent file-path
 #   D1 = any existing dir
@@ -316,8 +323,10 @@ def set_up_repos(wc_dir, br_dir, scenari
   # create the file F1 and dir D1 which the tests regard as pre-existing
   paths = incoming_paths(wc_dir, wc_dir)  # second arg is bogus but unimportant
   F1 = paths['F1']  # existing file to copy from
+  F3 = paths['F3']  # existing file to copy from
   main.file_write(F1, "This is initially file F1.\n")
-  main.run_svn(None, 'add', F1)
+  main.file_write(F3, "This is initially file F3.\n")
+  main.run_svn(None, 'add', F1, F3)
   D1 = paths['D1']  # existing dir to copy from
   main.run_svn(None, 'mkdir', D1)
 
@@ -411,7 +420,7 @@ def ensure_tree_conflict(sbox, operation
 
       verbose_print("--- Making local mods")
       for modaction in loc_action:
-        modify(modaction, localmod_paths(".", target_path))
+        modify(modaction, localmod_paths(".", target_path), is_init=False)
       if commit_local_mods:
         run_and_verify_svn(None, AnyOutput, [],
                            'commit', target_path,
@@ -1191,6 +1200,42 @@ def up_add_onto_add_revert(sbox):
                         wc2_dir)
 
 
+#----------------------------------------------------------------------
+# Regression test for issue #3525 and #3533
+#
+def lock_update_only(sbox):
+  "lock status update shouldn't flag tree conflict"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # Make a second copy of the working copy
+  wc_b = sbox.add_wc_path('_b')
+  svntest.actions.duplicate_dir(wc_dir, wc_b)
+
+  fname = 'iota'
+  file_path = os.path.join(sbox.wc_dir, fname)
+  file_path_b = os.path.join(wc_b, fname)
+
+  # Lock a file as wc_author, and schedule the file for deletion.
+  svntest.actions.run_and_verify_svn(None, ".*locked by user", [], 'lock',
+                                     '-m', '', file_path)
+  svntest.main.run_svn(None, 'delete', file_path)
+
+  # In our other working copy, steal that lock.
+  svntest.actions.run_and_verify_svn(None, ".*locked by user", [], 'lock',
+                                     '-m', '', '--force', file_path)
+  
+  # Now update the first working copy.  It should appear as a no-op.
+  expected_disk = main.greek_state.copy()
+  expected_disk.remove('iota')
+  expected_status = get_virginal_state(wc_dir, 1)
+  expected_status.tweak('iota', status='D ')
+  run_and_verify_update(wc_dir,
+                        None, expected_disk, expected_status,
+                        None, None, None, None, None, 1,
+                        wc_dir)
+
 
 #######################################################################
 # Run the tests
@@ -1221,6 +1266,7 @@ test_list = [ None,
               XFail(force_del_tc_is_target),
               XFail(query_absent_tree_conflicted_dir),
               XFail(up_add_onto_add_revert),
+              XFail(lock_update_only),
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/update_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/update_tests.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/update_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/update_tests.py Tue Aug 10 22:07:24 2010
@@ -29,7 +29,7 @@ import sys, re, os, subprocess
 
 # Our testing module
 import svntest
-from svntest import wc
+from svntest import wc, actions, verify
 from merge_tests import expected_merge_output
 from merge_tests import set_up_branch
 
@@ -396,7 +396,11 @@ def update_ignores_added(sbox):
 
   # Create expected status tree for the update.
   expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
-  expected_status.tweak('A/D/gamma', wc_rev=1, status='R ')
+
+  # Before WC-NG we couldn't bump the wc_rev for gamma from 1 to 2 because it could
+  # be replaced with history and we couldn't store all the revision information.
+  # WC-NG just bumps the revision as it can easily store different revisions.
+  expected_status.tweak('A/D/gamma', wc_rev=2, status='R ')
   expected_status.add({
     'A/B/zeta' : Item(status='A ', wc_rev=0),
     })
@@ -2143,13 +2147,32 @@ def forced_update_failures(sbox):
 
   # A forced update that tries to add a file when an unversioned directory
   # of the same name already exists should fail.
-  F_Path = os.path.join(wc_backup, 'A', 'B', 'F')
-  svntest.actions.run_and_verify_update(F_Path, None, None, None,
-                                        ".*Failed to add file.*" + \
-                                        "a non-file object of the " + \
-                                        "same name already exists",
-                                        None, None, None, None, 0, F_Path,
-                                        '--force')
+  #svntest.factory.make(sbox, """svn up --force $WC_DIR.backup/A/B/F""")
+  #exit(0)
+  backup_A_B_F = os.path.join(wc_backup, 'A', 'B', 'F')
+
+  # svn up --force $WC_DIR.backup/A/B/F
+  expected_output = svntest.wc.State(wc_backup, {
+    'A/B/F/nu'          : Item(status='  ', treeconflict='C'),
+  })
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'A/B/F/nu'          : Item(),
+    'A/C/I'             :
+    Item(contents="This is the file 'I'...shouldn't I be a dir?\n"),
+  })
+
+  expected_status = actions.get_virginal_state(wc_backup, 1)
+  expected_status.add({
+    'A/B/F/nu'          : Item(status='? ', treeconflict='C'),
+  })
+  expected_status.tweak('A/B/F', wc_rev='2')
+
+  actions.run_and_verify_update(wc_backup, expected_output,
+    expected_disk, expected_status, None, None, None, None, None, False,
+    '--force', backup_A_B_F)
+
 
   # A forced update that tries to add a directory when an unversioned file
   # of the same name already exists should fail.
@@ -2799,44 +2822,17 @@ def update_with_obstructing_additions(sb
     })
 
   expected_status.tweak('', 'iota', status='  ', wc_rev=4)
-  expected_status.tweak('omicron', status='A ', copied='+', wc_rev='-',
+  expected_status.tweak('omicron', status='R ', copied='+', wc_rev='-',
                         treeconflict='C')
 
-  ### ugh. this update will leave the working copy in a BROKEN state.
-  ### the incoming add is flagged as a tree conflict against our local-copy.
-  ### the file will be "skipped" during the update, and the file will be
-  ### dropped on the floor. 'omicron' is then left in the same "local-copy"
-  ### scheduling state (schedule-add). however, this is incorrect because
-  ### the directory says it is r4 which *includes* an 'omicron', yet we
-  ### have discarded all knowledge of it. the update *should* place the
-  ### incoming 'omicron' into the "revert base" and mark our local copy as
-  ### a schedule-replace.
-  ###
-  ### see: http://svn.haxx.se/dev/archive-2009-04/0760.shtml
   svntest.actions.run_and_verify_update(wc_dir, expected_output,
                                         expected_disk, expected_status,
                                         None, None, None, None, None, False,
                                         wc_dir, '-N')
 
   # Resolve the tree conflict.
-  svntest.main.run_svn(None, 'resolve', '--accept', 'working', omicron_path)
+  svntest.main.run_svn(None, 'resolved', omicron_path)
 
-  ### in wc-1, I believe we see the local-copy as a different revision
-  ### than the parent directory (entry->revision is overloaded; normally,
-  ### it is supposed to represent the BASE revision; we drop a copyfrom
-  ### rev in there, making it appear different from the parent), so we
-  ### send the mixed-rev in the update report (UNVERIFIED; this is
-  ### speculation on cause; the effect is known, as follows). given the
-  ### mixed-rev report, the server will send down another add, reporting
-  ### another conflict.
-  ###
-  ### in wc-ng, a local-copy does not have a revision (it hasn't been
-  ### committed yet!). further, all BASE information has been lost, so
-  ### there is no knowledge of a BASE 'omicron', which is not-present or
-  ### at an old revision, or whatever. thus, wc-ng sees "r4" for the
-  ### directory and thinks there are no sub-items to report as different.
-  ### the server returns with "you're up to date" rather than sending
-  ### another add. thus, no conflict occurs on 'omicron'.
   expected_output = wc.State(wc_dir, { })
 
   expected_status.tweak('omicron', treeconflict=None)
@@ -4231,20 +4227,34 @@ def restarted_update_should_delete_dir_p
                                         expected_status, None, other_wc)
 
   # Back in the first working copy, create an obstructing path and
-  # update. The update will be interrupted, resulting in an incomplete
-  # dir which still has the property.
+  # update. The update will flag a tree conflict.
   svntest.main.file_write(zeta_path, 'Obstructing file\n')
-  error_re = 'Failed to add file.*file of the same name already exists'
 
-  svntest.actions.run_and_verify_update(wc_dir, None, None, None,
-                                        error_re)
+  #svntest.factory.make(sbox, 'svn up')
+  #exit(0)
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'A'                 : Item(status=' U'),
+    'A/zeta'            : Item(status='  ', treeconflict='C'),
+  })
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'A/zeta'            : Item(contents="Obstructing file\n"),
+  })
+
+  expected_status = actions.get_virginal_state(wc_dir, 3)
+  expected_status.add({
+    'A/zeta'            : Item(status='? ', treeconflict='C'),
+  })
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
 
   # Now, delete the obstructing path and rerun the update.
-  # A's property should disappear.
   os.unlink(zeta_path)
 
   expected_output = svntest.wc.State(wc_dir, {
-    'A'      : Item(status=' U'),
     'A/zeta' : Item(status='A '),
     })
 
@@ -4823,8 +4833,6 @@ def tree_conflicts_on_update_3(sbox):
 #----------------------------------------------------------------------
 # Test for issue #3354 'update fails when file with local mods is moved
 # and modified'
-#
-# Marked as XFail until issue #3354 is resolved.
 def update_moves_and_modifies_an_edited_file(sbox):
   "update moves and modifies a file with edits"
 

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/upgrade_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/upgrade_tests.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/upgrade_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/upgrade_tests.py Tue Aug 10 22:07:24 2010
@@ -52,12 +52,16 @@ def get_current_format():
   return int(re.search("\n#define SVN_WC__VERSION (\d+)\n", format_file).group(1))
 
 
-def replace_sbox_with_tarfile(sbox, tar_filename):
+def replace_sbox_with_tarfile(sbox, tar_filename,
+                              dir=None):
   try:
     svntest.main.safe_rmtree(sbox.wc_dir)
   except OSError, e:
     pass
 
+  if not dir:
+    dir = tar_filename.split('.')[0]
+
   tarpath = os.path.join(os.path.dirname(sys.argv[0]), 'upgrade_tests_data',
                          tar_filename)
   t = tarfile.open(tarpath, 'r:bz2')
@@ -65,8 +69,7 @@ def replace_sbox_with_tarfile(sbox, tar_
   for member in t.getmembers():
     t.extract(member, extract_dir)
 
-  shutil.move(os.path.join(extract_dir, tar_filename.split('.')[0]),
-              sbox.wc_dir)
+  shutil.move(os.path.join(extract_dir, dir), sbox.wc_dir)
 
 
 def check_format(sbox, expected_format):
@@ -341,6 +344,112 @@ def basic_upgrade_1_0(sbox):
   svntest.actions.run_and_verify_info(expected_infos,
                                       os.path.join(sbox.wc_dir, 'DELETED'))
 
+# Helper function for the x3 tests.
+def do_x3_upgrade(sbox):
+  # Attempt to use the working copy, this should give an error
+  expected_stderr = wc_is_too_old_regex
+  svntest.actions.run_and_verify_svn(None, None, expected_stderr,
+                                     'info', sbox.wc_dir)
+
+
+  # Now upgrade the working copy
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'upgrade', sbox.wc_dir)
+
+  # Actually check the format number of the upgraded working copy
+  check_format(sbox, get_current_format())
+
+  # Now check the contents of the working copy
+  expected_status = svntest.wc.State(sbox.wc_dir,
+    {
+      ''                  : Item(status='  ', wc_rev='2'),
+      'A'                 : Item(status='  ', wc_rev='2'),
+      'A/D'               : Item(status='  ', wc_rev='2'),
+      'A/D/H'             : Item(status='  ', wc_rev='2'),
+      'A/D/H/omega'       : Item(status='  ', wc_rev='2'),
+      'A/D/H/psi'         : Item(status='D ', wc_rev='2'),
+      'A/D/H/new'         : Item(status='A ', copied='+', wc_rev='-'),
+      'A/D/H/chi'         : Item(status='R ', copied='+', wc_rev='-'),
+      'A/D/gamma'         : Item(status='D ', wc_rev='2'),
+      'A/D/G'             : Item(status='  ', wc_rev='2'),
+      'A/B_new'           : Item(status='A ', copied='+', wc_rev='-'),
+      'A/B_new/B'         : Item(status='A ', copied='+', wc_rev='-'),
+      'A/B_new/B/E'       : Item(status=' M', copied='+', wc_rev='-'),
+      'A/B_new/B/E/alpha' : Item(status='  ', copied='+', wc_rev='-'),
+      'A/B_new/B/E/beta'  : Item(status='R ', copied='+', wc_rev='-'),
+      'A/B_new/B/new'     : Item(status='A ', copied='+', wc_rev='-'),
+      'A/B_new/B/lambda'  : Item(status='R ', copied='+', wc_rev='-'),
+      'A/B_new/B/F'       : Item(status='  ', copied='+', wc_rev='-'),
+      'A/B_new/E'         : Item(status=' M', copied='+', wc_rev='-'),
+      'A/B_new/E/alpha'   : Item(status=' M', copied='+', wc_rev='-'),
+      'A/B_new/E/beta'    : Item(status='RM', copied='+', wc_rev='-'),
+      'A/B_new/lambda'    : Item(status='R ', copied='+', wc_rev='-'),
+      'A/B_new/new'       : Item(status='A ', copied='+', wc_rev='-'),
+      'A/B_new/F'         : Item(status='  ', copied='+', wc_rev='-'),
+      'A/B'               : Item(status='  ', wc_rev='2'),
+      'A/B/E'             : Item(status='  ', wc_rev='2'),
+      'A/B/E/beta'        : Item(status='RM', copied='+', wc_rev='-'),
+      'A/B/E/alpha'       : Item(status=' M', wc_rev='2'),
+      'A/B/F'             : Item(status='  ', wc_rev='2'),
+      'A/B/lambda'        : Item(status='R ', copied='+', wc_rev='-'),
+      'A/B/new'           : Item(status='A ', copied='+', wc_rev='-'),
+      'A/G_new'           : Item(status='A ', copied='+', wc_rev='-'),
+      'A/G_new/rho'       : Item(status='R ', copied='+', wc_rev='-'),
+      'iota'              : Item(status='  ', wc_rev='2'),
+      'A_new'             : Item(status='A ', wc_rev='0'),
+      'A_new/alpha'       : Item(status='A ', copied='+', wc_rev='-'),
+    })
+  run_and_verify_status_no_server(sbox.wc_dir, expected_status)
+
+  svntest.actions.run_and_verify_svn(None, 'Reverted.*', [],
+                                     'revert', '-R', sbox.wc_dir)
+
+  expected_status = svntest.wc.State(sbox.wc_dir,
+    {
+      ''                  : Item(status='  ', wc_rev='2'),
+      'A'                 : Item(status='  ', wc_rev='2'),
+      'A/D'               : Item(status='  ', wc_rev='2'),
+      'A/D/H'             : Item(status='  ', wc_rev='2'),
+      'A/D/H/omega'       : Item(status='  ', wc_rev='2'),
+      'A/D/H/psi'         : Item(status='  ', wc_rev='2'),
+      'A/D/H/chi'         : Item(status='  ', wc_rev='2'),
+      'A/D/gamma'         : Item(status='  ', wc_rev='2'),
+      'A/D/G'             : Item(status='  ', wc_rev='2'),
+      'A/B'               : Item(status='  ', wc_rev='2'),
+      'A/B/F'             : Item(status='  ', wc_rev='2'),
+      'A/B/E'             : Item(status='  ', wc_rev='2'),
+      'A/B/E/beta'        : Item(status='  ', wc_rev='2'),
+      'A/B/E/alpha'       : Item(status='  ', wc_rev='2'),
+      'A/B/lambda'        : Item(status='  ', wc_rev='2'),
+      'iota'              : Item(status='  ', wc_rev='2'),
+    })
+  run_and_verify_status_no_server(sbox.wc_dir, expected_status)
+
+def x3_1_4_0(sbox):
+  "3x same wc upgrade 1.4.0 test"
+
+  sbox.build(create_wc = False)
+  replace_sbox_with_tarfile(sbox, 'wc-3x-1.4.0.tar.bz2', dir='wc-1.4.0')
+
+  do_x3_upgrade(sbox)
+
+def x3_1_4_6(sbox):
+  "3x same wc upgrade 1.4.6 test"
+
+  sbox.build(create_wc = False)
+  replace_sbox_with_tarfile(sbox, 'wc-3x-1.4.6.tar.bz2', dir='wc-1.4.6')
+
+  do_x3_upgrade(sbox)
+
+def x3_1_6_12(sbox):
+  "3x same wc upgrade 1.6.12 test"
+
+  sbox.build(create_wc = False)
+  replace_sbox_with_tarfile(sbox, 'wc-3x-1.6.12.tar.bz2', dir='wc-1.6.12')
+
+  do_x3_upgrade(sbox)
+
+
 ########################################################################
 # Run the tests
 
@@ -352,7 +461,10 @@ test_list = [ None,
               update_1_5,
               logs_left_1_5,
               upgrade_wcprops,
-              basic_upgrade_1_0
+              basic_upgrade_1_0,
+              x3_1_4_0,
+              x3_1_4_6,
+              x3_1_6_12,
              ]
 
 

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_client/client-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_client/client-test.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_client/client-test.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_client/client-test.c Tue Aug 10 22:07:24 2010
@@ -342,16 +342,8 @@ test_patch(const svn_test_opts_t *opts,
 
   /* Check out the HEAD revision */
   SVN_ERR(svn_dirent_get_absolute(&cwd, "", pool));
-
-  if (cwd[0] == '/')
-    repos_url = apr_pstrcat(pool, "file://", cwd,
-                            "/test-patch-repos", NULL);
-  else
-    /* On Windows CWD is always in "X:/..." style */
-    repos_url = apr_pstrcat(pool, "file:///", cwd,
-                            "/test-patch-repos", NULL);
-
-  repos_url = svn_uri_canonicalize(repos_url, pool);
+  SVN_ERR(svn_uri_get_file_url_from_dirent(&repos_url, "test-patch-repos",
+                                           pool));
 
   /* Put wc inside an unversioned directory.  Checking out a 1.7 wc
      directly inside a 1.6 wc doesn't work reliably, an intervening
@@ -408,6 +400,139 @@ test_patch(const svn_test_opts_t *opts,
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_wc_add_scenarios(const svn_test_opts_t *opts,
+                      apr_pool_t *pool)
+{
+  svn_repos_t *repos;
+  svn_fs_t *fs;
+  svn_fs_txn_t *txn;
+  svn_fs_root_t *txn_root;
+  const char *repos_url;
+  const char *wc_path;
+  svn_revnum_t committed_rev;
+  svn_client_ctx_t *ctx;
+  svn_opt_revision_t rev, peg_rev;
+  const char *new_dir_path;
+  const char *ex_file_path;
+  const char *ex_dir_path;
+  const char *ex2_dir_path;
+
+  /* Create a filesytem and repository. */
+  SVN_ERR(svn_test__create_repos(&repos, "test-wc-add-repos",
+                                 opts, pool));
+  fs = svn_repos_fs(repos);
+
+  /* Prepare a txn to receive the greek tree. */
+  SVN_ERR(svn_fs_begin_txn2(&txn, fs, 0, 0, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_test__create_greek_tree(txn_root, pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &committed_rev, txn, pool));
+
+  SVN_ERR(svn_uri_get_file_url_from_dirent(&repos_url, "test-wc-add-repos",
+                                           pool));
+
+  SVN_ERR(svn_dirent_get_absolute(&wc_path, "test-wc-add", pool));
+  SVN_ERR(svn_io_make_dir_recursively(wc_path, pool));
+  svn_test_add_dir_cleanup(wc_path);
+
+  rev.kind = svn_opt_revision_head;
+  peg_rev.kind = svn_opt_revision_unspecified;
+  SVN_ERR(svn_client_create_context(&ctx, pool));
+  /* Checkout greek tree as wc_path */
+  SVN_ERR(svn_client_checkout3(NULL, repos_url, wc_path, &peg_rev, &rev,
+                               svn_depth_infinity, FALSE, FALSE, ctx, pool));
+
+  /* Now checkout again as wc_path/NEW */
+  new_dir_path = svn_dirent_join(wc_path, "NEW", pool);
+  SVN_ERR(svn_client_checkout3(NULL, repos_url, new_dir_path, &peg_rev, &rev,
+                               svn_depth_infinity, FALSE, FALSE,
+                               ctx, pool));
+
+  ex_dir_path = svn_dirent_join(wc_path, "NEW_add", pool);
+  ex2_dir_path = svn_dirent_join(wc_path, "NEW_add2", pool);
+  SVN_ERR(svn_io_dir_make(ex_dir_path, APR_OS_DEFAULT, pool));
+  SVN_ERR(svn_io_dir_make(ex2_dir_path, APR_OS_DEFAULT, pool));
+
+  SVN_ERR(svn_io_open_uniquely_named(NULL, &ex_file_path, wc_path, "new_file",
+                                     NULL, svn_io_file_del_none, pool, pool));
+
+  /* Now use an access baton to do some add operations like an old client
+     might do */
+  {
+    svn_wc_adm_access_t *adm_access, *adm2;
+    svn_boolean_t locked;
+
+    SVN_ERR(svn_wc_adm_open3(&adm_access, NULL, wc_path, TRUE, -1, NULL, NULL,
+                             pool));
+
+    /* Fix up copy as add with history */
+    SVN_ERR(svn_wc_add3(new_dir_path, adm_access, svn_depth_infinity,
+                        repos_url, committed_rev, NULL, NULL, NULL, NULL,
+                        pool));
+
+    /* Verify if the paths are locked now */
+    SVN_ERR(svn_wc_locked(&locked, wc_path, pool));
+    SVN_TEST_ASSERT(locked && "wc_path locked");
+    SVN_ERR(svn_wc_locked(&locked, new_dir_path, pool));
+    SVN_TEST_ASSERT(locked && "new_path locked");
+
+    SVN_ERR(svn_wc_adm_retrieve(&adm2, adm_access, new_dir_path, pool));
+    SVN_TEST_ASSERT(adm2 != NULL && "available in set");
+
+    /* Add local (new) file */
+    SVN_ERR(svn_wc_add3(ex_file_path, adm_access, svn_depth_unknown, NULL,
+                        SVN_INVALID_REVNUM, NULL, NULL, NULL, NULL, pool));
+
+    /* Add local (new) directory */
+    SVN_ERR(svn_wc_add3(ex_dir_path, adm_access, svn_depth_infinity, NULL,
+                        SVN_INVALID_REVNUM, NULL, NULL, NULL, NULL, pool));
+
+    SVN_ERR(svn_wc_adm_retrieve(&adm2, adm_access, ex_dir_path, pool));
+    SVN_TEST_ASSERT(adm2 != NULL && "available in set");
+
+    /* Add empty directory with copy trail */
+    SVN_ERR(svn_wc_add3(ex2_dir_path, adm_access, svn_depth_infinity,
+                        repos_url, committed_rev, NULL, NULL, NULL, NULL,
+                        pool));
+
+    SVN_ERR(svn_wc_adm_retrieve(&adm2, adm_access, ex2_dir_path, pool));
+    SVN_TEST_ASSERT(adm2 != NULL && "available in set");
+
+    SVN_ERR(svn_wc_adm_close2(adm_access, pool));
+  }
+
+  /* Some simple status calls to verify that the paths are added */
+  {
+    svn_wc_status3_t *status;
+
+    SVN_ERR(svn_wc_status3(&status, ctx->wc_ctx, new_dir_path, pool, pool));
+
+    SVN_TEST_ASSERT(status->node_status == svn_wc_status_added
+                    && status->copied
+                    && !strcmp(status->repos_relpath, "NEW"));
+
+    SVN_ERR(svn_wc_status3(&status, ctx->wc_ctx, ex_file_path, pool, pool));
+
+    SVN_TEST_ASSERT(status->node_status == svn_wc_status_added
+                    && !status->copied);
+
+    SVN_ERR(svn_wc_status3(&status, ctx->wc_ctx, ex_dir_path, pool, pool));
+
+    SVN_TEST_ASSERT(status->node_status == svn_wc_status_added
+                    && !status->copied);
+
+    SVN_ERR(svn_wc_status3(&status, ctx->wc_ctx, ex2_dir_path, pool, pool));
+
+    SVN_TEST_ASSERT(status->node_status == svn_wc_status_added
+                    && status->copied);
+  }
+
+  /* ### Add a commit? */
+
+  return SVN_NO_ERROR;
+}
+
 /* ========================================================================== */
 
 struct svn_test_descriptor_t test_funcs[] =
@@ -418,5 +543,6 @@ struct svn_test_descriptor_t test_funcs[
     SVN_TEST_PASS2(test_args_to_target_array,
                    "test svn_client_args_to_target_array"),
     SVN_TEST_OPTS_PASS(test_patch, "test svn_client_patch"),
+    SVN_TEST_OPTS_PASS(test_wc_add_scenarios, "test svn_wc_add3 scenarios"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_diff/parse-diff-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_diff/parse-diff-test.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_diff/parse-diff-test.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_diff/parse-diff-test.c Tue Aug 10 22:07:24 2010
@@ -56,30 +56,160 @@ static const char *unidiff =
   "Name: svn:mergeinfo"                                                 NL
   ""                                                                    NL;
 
+static const char *git_unidiff =
+  "Index: A/mu (deleted)"                                               NL
+  "===================================================================" NL
+  "git --diff a/A/mu b/A/mu"                                            NL
+  "deleted file mode 100644"                                            NL
+  "Index: A/C/gamma"                                                    NL
+  "===================================================================" NL
+  "git --diff a/A/C/gamma b/A/C/gamma"                                  NL
+  "--- a/A/C/gamma\t(revision 2)"                                       NL
+  "+++ b/A/C/gamma\t(working copy)"                                     NL
+  "@@ -1 +1,2 @@"                                                       NL
+  " This is the file 'gamma'."                                          NL
+  "+some more bytes to 'gamma'"                                         NL
+  "Index: iota"                                                         NL
+  "===================================================================" NL
+  "git --diff a/iota b/iota.copied"                                     NL
+  "copy from iota"                                                      NL
+  "copy to iota.copied"                                                 NL
+  "Index: new"                                                          NL
+  "===================================================================" NL
+  "git --diff a/new b/new"                                              NL
+  "new file mode 100644"                                                NL
+  ""                                                                    NL;
+
+static const char *git_tree_and_text_unidiff =
+  "Index: iota.copied"                                                  NL
+  "===================================================================" NL
+  "git --diff a/iota b/iota.copied"                                     NL
+  "copy from iota"                                                      NL
+  "copy to iota.copied"                                                 NL
+  "@@ -1 +1,2 @@"                                                       NL
+  " This is the file 'iota'."                                           NL
+  "+some more bytes to 'iota'"                                          NL
+  "Index: A/mu.moved"                                                   NL
+  "===================================================================" NL
+  "git --diff a/A/mu b/A/mu.moved"                                      NL
+  "move from A/mu"                                                      NL
+  "move to A/mu.moved"                                                  NL
+  "@@ -1 +1,2 @@"                                                       NL
+  " This is the file 'mu'."                                             NL
+  "+some more bytes to 'mu'"                                            NL
+  ""                                                                    NL;
+
+  static const char *property_unidiff =
+  "Index: iota"                                                         NL
+  "===================================================================" NL
+  "--- iota"                                                            NL
+  "+++ iota"                                                            NL
+  ""                                                                    NL
+  "Property changes on: iota"                                           NL
+  "___________________________________________________________________" NL
+  "Deleted: prop_del"                                                   NL
+  "## -1 +0,0 ##"                                                       NL
+  "-value"                                                              NL
+  ""                                                                    NL
+  "Property changes on: iota"                                           NL
+  "___________________________________________________________________" NL
+  "Added: prop_add"                                                     NL
+  "## -0,0 +1 ##"                                                       NL
+  "+value"                                                              NL
+  ""                                                                    NL
+  "Property changes on: iota"                                           NL
+  "___________________________________________________________________" NL
+  "Modified: prop_mod"                                                  NL
+  "## -1 +1 ##"                                                         NL
+  "-value"                                                              NL
+  "+new value"                                                          NL;
+
+  /* ### Add edge cases like context lines stripped from leading whitespaces
+   * ### that starts with 'Added: ', 'Deleted: ' or 'Modified: '. */
+  static const char *property_and_text_unidiff =
+  "Index: iota"                                                         NL
+  "===================================================================" NL
+  "--- iota"                                                            NL
+  "+++ iota"                                                            NL
+  "@@ -1 +1,2 @@"                                                       NL
+  " This is the file 'iota'."                                           NL
+  "+some more bytes to 'iota'"                                          NL
+  ""                                                                    NL
+  "Property changes on: iota"                                           NL
+  "___________________________________________________________________" NL
+  "Added: prop_add"                                                     NL
+  "## -0,0 +1 ##"                                                       NL
+  "+value"                                                              NL;
+
+/* Create a PATCH_FILE with name FNAME containing the contents of DIFF. */
 static svn_error_t *
-test_parse_unidiff(apr_pool_t *pool)
+create_patch_file(apr_file_t **patch_file, const char *fname,
+                  const char *diff, apr_pool_t *pool)
 {
-  apr_file_t *patch_file;
-  apr_status_t status;
+  apr_off_t pos = 0;
   apr_size_t len;
-  const char *fname = "test_parse_unidiff.patch";
-  svn_boolean_t reverse;
-  svn_boolean_t ignore_whitespace;
-  int i;
-  apr_pool_t *iterpool;
+  apr_status_t status;
 
   /* Create a patch file. */
-  status = apr_file_open(&patch_file, fname,
+  status = apr_file_open(patch_file, fname,
                         (APR_READ | APR_WRITE | APR_CREATE | APR_TRUNCATE |
                          APR_DELONCLOSE), APR_OS_DEFAULT, pool);
   if (status != APR_SUCCESS)
     return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "Cannot open '%s'",
                              fname);
-  len = strlen(unidiff);
-  status = apr_file_write_full(patch_file, unidiff, len, &len);
-  if (status || len != strlen(unidiff))
+  len = strlen(diff);
+  status = apr_file_write_full(*patch_file, diff, len, &len);
+  if (status || len != strlen(diff))
     return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
                              "Cannot write to '%s'", fname);
+  SVN_ERR(svn_io_file_seek(*patch_file, APR_SET, &pos, pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* Check that CONTENT equals what's inside EXPECTED. */
+static svn_error_t *
+check_content(svn_stream_t *content, const char *expected, apr_pool_t *pool)
+{
+  svn_stream_t *exp;
+  svn_stringbuf_t *exp_buf;
+  svn_stringbuf_t *content_buf;
+  svn_boolean_t exp_eof;
+  svn_boolean_t content_eof;
+
+  exp = svn_stream_from_string(svn_string_create(expected, pool), 
+                               pool);
+
+  while (TRUE)
+  {
+    SVN_ERR(svn_stream_readline(exp, &exp_buf, NL, &exp_eof, pool));
+    SVN_ERR(svn_stream_readline(content, &content_buf, NL, &content_eof,
+                                pool));
+    SVN_TEST_ASSERT(exp_eof == content_eof);
+    if (exp_eof)
+      break;
+    if (strcmp(exp_buf->data, content_buf->data))
+      return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                               "Expected '%s' but was '%s'", exp_buf->data,
+                               content_buf->data);
+  }
+
+  SVN_TEST_ASSERT(content_buf->len == 0);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_parse_unidiff(apr_pool_t *pool)
+{
+  apr_file_t *patch_file;
+  const char *fname = "test_parse_unidiff.patch";
+  svn_boolean_t reverse;
+  svn_boolean_t ignore_whitespace;
+  int i;
+  apr_pool_t *iterpool;
+
+  SVN_ERR(create_patch_file(&patch_file, fname, unidiff, pool));
 
   reverse = FALSE;
   ignore_whitespace = FALSE;
@@ -88,8 +218,6 @@ test_parse_unidiff(apr_pool_t *pool)
     {
       svn_patch_t *patch;
       svn_hunk_t *hunk;
-      svn_stringbuf_t *buf;
-      svn_boolean_t eof;
       apr_off_t pos;
       svn_stream_t *original_text;
       svn_stream_t *modified_text;
@@ -105,10 +233,10 @@ test_parse_unidiff(apr_pool_t *pool)
       SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, reverse,
                                         ignore_whitespace, iterpool, 
                                         iterpool));
-      SVN_ERR_ASSERT(patch);
-      SVN_ERR_ASSERT(! strcmp(patch->old_filename, "A/C/gamma"));
-      SVN_ERR_ASSERT(! strcmp(patch->new_filename, "A/C/gamma"));
-      SVN_ERR_ASSERT(patch->hunks->nelts == 1);
+      SVN_TEST_ASSERT(patch);
+      SVN_TEST_ASSERT(! strcmp(patch->old_filename, "A/C/gamma"));
+      SVN_TEST_ASSERT(! strcmp(patch->new_filename, "A/C/gamma"));
+      SVN_TEST_ASSERT(patch->hunks->nelts == 1);
 
       hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_hunk_t *);
       if (reverse)
@@ -124,42 +252,30 @@ test_parse_unidiff(apr_pool_t *pool)
           modified_text = hunk->modified_text;
         }
 
-      /* Make sure original text was parsed correctly. */
-      SVN_ERR(svn_stream_readline(original_text, &buf, NL, &eof, pool));
-      SVN_ERR_ASSERT(! eof);
-      SVN_ERR_ASSERT(! strcmp(buf->data, "This is the file 'gamma'."));
-      /* Now we should get EOF. */
-      SVN_ERR(svn_stream_readline(original_text, &buf, NL, &eof, pool));
-      SVN_ERR_ASSERT(eof);
-      SVN_ERR_ASSERT(buf->len == 0);
-
-      /* Make sure modified text was parsed correctly. */
-      SVN_ERR(svn_stream_readline(modified_text, &buf, NL, &eof, pool));
-      SVN_ERR_ASSERT(! eof);
-      SVN_ERR_ASSERT(! strcmp(buf->data, "This is the file 'gamma'."));
-      SVN_ERR(svn_stream_readline(modified_text, &buf, NL, &eof, pool));
-      SVN_ERR_ASSERT(! eof);
-      SVN_ERR_ASSERT(! strcmp(buf->data, "some more bytes to 'gamma'"));
-      /* Now we should get EOF. */
-      SVN_ERR(svn_stream_readline(modified_text, &buf, NL, &eof, pool));
-      SVN_ERR_ASSERT(eof);
-      SVN_ERR_ASSERT(buf->len == 0);
+      SVN_ERR(check_content(original_text,
+                            "This is the file 'gamma'." NL,
+                            pool));
+
+      SVN_ERR(check_content(modified_text,
+                            "This is the file 'gamma'." NL
+                            "some more bytes to 'gamma'" NL,
+                            pool));
 
       /* Parse the second patch. */
       SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, reverse, 
                                         ignore_whitespace, pool, pool));
-      SVN_ERR_ASSERT(patch);
+      SVN_TEST_ASSERT(patch);
       if (reverse)
         {
-          SVN_ERR_ASSERT(! strcmp(patch->new_filename, "A/D/gamma.orig"));
-          SVN_ERR_ASSERT(! strcmp(patch->old_filename, "A/D/gamma"));
+          SVN_TEST_ASSERT(! strcmp(patch->new_filename, "A/D/gamma.orig"));
+          SVN_TEST_ASSERT(! strcmp(patch->old_filename, "A/D/gamma"));
         }
       else
         {
-          SVN_ERR_ASSERT(! strcmp(patch->old_filename, "A/D/gamma.orig"));
-          SVN_ERR_ASSERT(! strcmp(patch->new_filename, "A/D/gamma"));
+          SVN_TEST_ASSERT(! strcmp(patch->old_filename, "A/D/gamma.orig"));
+          SVN_TEST_ASSERT(! strcmp(patch->new_filename, "A/D/gamma"));
         }
-      SVN_ERR_ASSERT(patch->hunks->nelts == 1);
+      SVN_TEST_ASSERT(patch->hunks->nelts == 1);
 
       hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_hunk_t *);
       if (reverse)
@@ -175,26 +291,14 @@ test_parse_unidiff(apr_pool_t *pool)
           modified_text = hunk->modified_text;
         }
 
-      /* Make sure original text was parsed correctly. */
-      SVN_ERR(svn_stream_readline(original_text, &buf, NL, &eof, pool));
-      SVN_ERR_ASSERT(! eof);
-      SVN_ERR_ASSERT(! strcmp(buf->data, "This is the file 'gamma'."));
-      SVN_ERR(svn_stream_readline(original_text, &buf, NL, &eof, pool));
-      SVN_ERR_ASSERT(! eof);
-      SVN_ERR_ASSERT(! strcmp(buf->data, "some less bytes to 'gamma'"));
-      /* Now we should get EOF. */
-      SVN_ERR(svn_stream_readline(original_text, &buf, NL, &eof, pool));
-      SVN_ERR_ASSERT(eof);
-      SVN_ERR_ASSERT(buf->len == 0);
-
-      /* Make sure modified text was parsed correctly. */
-      SVN_ERR(svn_stream_readline(modified_text, &buf, NL, &eof, pool));
-      SVN_ERR_ASSERT(! eof);
-      SVN_ERR_ASSERT(! strcmp(buf->data, "This is the file 'gamma'."));
-      /* Now we should get EOF. */
-      SVN_ERR(svn_stream_readline(modified_text, &buf, NL, &eof, pool));
-      SVN_ERR_ASSERT(eof);
-      SVN_ERR_ASSERT(buf->len == 0);
+      SVN_ERR(check_content(original_text,
+                            "This is the file 'gamma'." NL
+                            "some less bytes to 'gamma'" NL,
+                            pool));
+
+      SVN_ERR(check_content(modified_text,
+                            "This is the file 'gamma'." NL,
+                            pool));
 
       reverse = !reverse;
     }
@@ -202,6 +306,253 @@ test_parse_unidiff(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_parse_git_diff(apr_pool_t *pool)
+{
+  /* ### Should we check for reversed diffs? */
+
+  apr_file_t *patch_file;
+  svn_patch_t *patch;
+  svn_hunk_t *hunk;
+  const char *fname = "test_parse_git_diff.patch";
+
+  SVN_ERR(create_patch_file(&patch_file, fname, git_unidiff, pool));
+
+  /* Parse a deleted empty file */
+  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, 
+                                    FALSE, /* reverse */
+                                    FALSE, /* ignore_whitespace */ 
+                                    pool, pool));
+  SVN_TEST_ASSERT(patch);
+  SVN_TEST_ASSERT(! strcmp(patch->old_filename, "A/mu"));
+  SVN_TEST_ASSERT(! strcmp(patch->new_filename, "A/mu"));
+  SVN_TEST_ASSERT(patch->operation == svn_diff_op_deleted);
+  SVN_TEST_ASSERT(patch->hunks->nelts == 0);
+
+  /* Parse a modified file. */
+  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, 
+                                    FALSE, /* reverse */
+                                    FALSE, /* ignore_whitespace */ 
+                                    pool, pool));
+  SVN_TEST_ASSERT(patch);
+  SVN_TEST_ASSERT(! strcmp(patch->old_filename, "A/C/gamma"));
+  SVN_TEST_ASSERT(! strcmp(patch->new_filename, "A/C/gamma"));
+  SVN_TEST_ASSERT(patch->operation == svn_diff_op_modified);
+  SVN_TEST_ASSERT(patch->hunks->nelts == 1);
+  
+  hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_hunk_t *);
+
+  SVN_ERR(check_content(hunk->original_text,
+                        "This is the file 'gamma'." NL,
+                        pool));
+
+  SVN_ERR(check_content(hunk->modified_text,
+                        "This is the file 'gamma'." NL
+                        "some more bytes to 'gamma'" NL,
+                        pool));
+
+  /* Parse a copied empty file */
+  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, 
+                                    FALSE, /* reverse */
+                                    FALSE, /* ignore_whitespace */ 
+                                    pool, pool));
+
+  SVN_TEST_ASSERT(patch);
+  SVN_TEST_ASSERT(! strcmp(patch->old_filename, "iota"));
+  SVN_TEST_ASSERT(! strcmp(patch->new_filename, "iota.copied"));
+  SVN_TEST_ASSERT(patch->operation == svn_diff_op_copied);
+  SVN_TEST_ASSERT(patch->hunks->nelts == 0);
+
+  /* Parse an added empty file */
+  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, 
+                                    FALSE, /* reverse */
+                                    FALSE, /* ignore_whitespace */ 
+                                    pool, pool));
+
+  SVN_TEST_ASSERT(patch);
+  SVN_TEST_ASSERT(! strcmp(patch->old_filename, "new"));
+  SVN_TEST_ASSERT(! strcmp(patch->new_filename, "new"));
+  SVN_TEST_ASSERT(patch->operation == svn_diff_op_added);
+  SVN_TEST_ASSERT(patch->hunks->nelts == 0);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_parse_git_tree_and_text_diff(apr_pool_t *pool)
+{
+  /* ### Should we check for reversed diffs? */
+
+  apr_file_t *patch_file;
+  svn_patch_t *patch;
+  svn_hunk_t *hunk;
+  const char *fname = "test_parse_git_tree_and_text_diff.patch";
+
+  SVN_ERR(create_patch_file(&patch_file, fname, git_tree_and_text_unidiff,
+                            pool));
+
+  /* Parse a copied file with text modifications. */
+  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, 
+                                    FALSE, /* reverse */
+                                    FALSE, /* ignore_whitespace */ 
+                                    pool, pool));
+  SVN_TEST_ASSERT(patch);
+  SVN_TEST_ASSERT(! strcmp(patch->old_filename, "iota"));
+  SVN_TEST_ASSERT(! strcmp(patch->new_filename, "iota.copied"));
+  SVN_TEST_ASSERT(patch->operation == svn_diff_op_copied);
+  SVN_TEST_ASSERT(patch->hunks->nelts == 1);
+  
+  hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_hunk_t *);
+
+  SVN_ERR(check_content(hunk->original_text,
+                        "This is the file 'iota'." NL,
+                        pool));
+
+  SVN_ERR(check_content(hunk->modified_text,
+                        "This is the file 'iota'." NL
+                        "some more bytes to 'iota'" NL,
+                        pool));
+
+  /* Parse a moved file with text modifications. */
+  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, 
+                                    FALSE, /* reverse */
+                                    FALSE, /* ignore_whitespace */ 
+                                    pool, pool));
+  SVN_TEST_ASSERT(patch);
+  SVN_TEST_ASSERT(! strcmp(patch->old_filename, "A/mu"));
+  SVN_TEST_ASSERT(! strcmp(patch->new_filename, "A/mu.moved"));
+  SVN_TEST_ASSERT(patch->operation == svn_diff_op_moved);
+  SVN_TEST_ASSERT(patch->hunks->nelts == 1);
+  
+  hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_hunk_t *);
+
+  SVN_ERR(check_content(hunk->original_text,
+                        "This is the file 'mu'." NL,
+                        pool));
+
+  SVN_ERR(check_content(hunk->modified_text,
+                        "This is the file 'mu'." NL
+                        "some more bytes to 'mu'" NL,
+                        pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* Tests to parse a diff with three property changes, one is added, one is
+ * modified and one is deleted. */
+static svn_error_t *
+test_parse_property_diff(apr_pool_t *pool)
+{
+  apr_file_t *patch_file;
+  svn_patch_t *patch;
+  svn_hunk_t *hunk;
+  apr_array_header_t *hunks;
+  const char *fname = "test_parse_property_diff.patch";
+
+  SVN_ERR(create_patch_file(&patch_file, fname, property_unidiff, pool));
+
+  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, 
+                                    FALSE, /* reverse */
+                                    FALSE, /* ignore_whitespace */ 
+                                    pool, pool));
+  SVN_TEST_ASSERT(patch);
+  SVN_TEST_ASSERT(! strcmp(patch->old_filename, "iota"));
+  SVN_TEST_ASSERT(! strcmp(patch->new_filename, "iota"));
+  SVN_TEST_ASSERT(patch->hunks->nelts == 0);
+  SVN_TEST_ASSERT(apr_hash_count(patch->property_hunks) == 3);
+
+  /* Check the added property */
+  hunks = apr_hash_get(patch->property_hunks, "prop_add", APR_HASH_KEY_STRING);
+  SVN_TEST_ASSERT(hunks->nelts == 1);
+  hunk = APR_ARRAY_IDX(hunks, 0 , svn_hunk_t *);
+
+  SVN_ERR(check_content(hunk->original_text,
+                        "",
+                        pool));
+
+  SVN_ERR(check_content(hunk->modified_text,
+                        "value" NL,
+                        pool));
+
+  /* Check the deleted property */
+  hunks = apr_hash_get(patch->property_hunks, "prop_del", APR_HASH_KEY_STRING);
+  SVN_TEST_ASSERT(hunks->nelts == 1);
+  hunk = APR_ARRAY_IDX(hunks, 0 , svn_hunk_t *);
+
+  SVN_ERR(check_content(hunk->original_text,
+                        "value" NL,
+                        pool));
+
+  SVN_ERR(check_content(hunk->modified_text,
+                        "",
+                        pool));
+
+  /* Check the modified property */
+  hunks = apr_hash_get(patch->property_hunks, "prop_mod", APR_HASH_KEY_STRING);
+  SVN_TEST_ASSERT(hunks->nelts == 1);
+  hunk = APR_ARRAY_IDX(hunks, 0 , svn_hunk_t *);
+
+  SVN_ERR(check_content(hunk->original_text,
+                        "value" NL,
+                        pool));
+
+  SVN_ERR(check_content(hunk->modified_text,
+                        "new value" NL,
+                        pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_parse_property_and_text_diff(apr_pool_t *pool)
+{
+  apr_file_t *patch_file;
+  svn_patch_t *patch;
+  svn_hunk_t *hunk;
+  apr_array_header_t *hunks;
+  const char *fname = "test_parse_property_and_text_diff.patch";
+
+  SVN_ERR(create_patch_file(&patch_file, fname, property_and_text_unidiff,
+                            pool));
+
+  SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, 
+                                    FALSE, /* reverse */
+                                    FALSE, /* ignore_whitespace */ 
+                                    pool, pool));
+  SVN_TEST_ASSERT(patch);
+  SVN_TEST_ASSERT(! strcmp(patch->old_filename, "iota"));
+  SVN_TEST_ASSERT(! strcmp(patch->new_filename, "iota"));
+  SVN_TEST_ASSERT(patch->hunks->nelts == 1);
+  SVN_TEST_ASSERT(apr_hash_count(patch->property_hunks) == 1);
+
+  /* Check contents of text hunk */
+  hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_hunk_t *);
+
+  SVN_ERR(check_content(hunk->original_text,
+                        "This is the file 'iota'." NL,
+                        pool));
+
+  SVN_ERR(check_content(hunk->modified_text,
+                        "This is the file 'iota'." NL
+                        "some more bytes to 'iota'" NL,
+                        pool));
+
+  /* Check the added property */
+  hunks = apr_hash_get(patch->property_hunks, "prop_add", APR_HASH_KEY_STRING);
+  SVN_TEST_ASSERT(hunks->nelts == 1);
+  hunk = APR_ARRAY_IDX(hunks, 0 , svn_hunk_t *);
+
+  SVN_ERR(check_content(hunk->original_text,
+                        "",
+                        pool));
+
+  SVN_ERR(check_content(hunk->modified_text,
+                        "value" NL,
+                        pool));
+
+  return SVN_NO_ERROR;
+}
+
 /* ========================================================================== */
 
 struct svn_test_descriptor_t test_funcs[] =
@@ -209,5 +560,13 @@ struct svn_test_descriptor_t test_funcs[
     SVN_TEST_NULL,
     SVN_TEST_PASS2(test_parse_unidiff,
                    "test unidiff parsing"),
+    SVN_TEST_PASS2(test_parse_git_diff,
+                    "test git unidiff parsing"),
+    SVN_TEST_PASS2(test_parse_git_tree_and_text_diff,
+                    "test git unidiff parsing of tree and text changes"),
+    SVN_TEST_PASS2(test_parse_property_diff,
+                   "test property unidiff parsing"),
+    SVN_TEST_PASS2(test_parse_property_and_text_diff,
+                   "test property and text unidiff parsing"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_fs/fs-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_fs/fs-test.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_fs/fs-test.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_fs/fs-test.c Tue Aug 10 22:07:24 2010
@@ -586,6 +586,19 @@ list_directory(const svn_test_opts_t *op
 }
 
 
+/* If EXPR raises SVN_ERR_BAD_PROPERTY_VALUE, continue; else, fail
+ * the test. */
+#define FAILS_WITH_BPV(expr) \
+  do { \
+      svn_error_t *__err = (expr); \
+      if (!__err || __err->apr_err != SVN_ERR_BAD_PROPERTY_VALUE) \
+        return svn_error_create(SVN_ERR_TEST_FAILED, __err, \
+                                "svn_fs_change_rev_prop2() failed to " \
+                                "detect unexpected old value"); \
+      else \
+        svn_error_clear(__err); \
+  } while (0)
+
 static svn_error_t *
 revision_props(const svn_test_opts_t *opts,
                apr_pool_t *pool)
@@ -638,6 +651,34 @@ revision_props(const svn_test_opts_t *op
   s1.len = value->len;
   SVN_ERR(svn_fs_change_rev_prop(fs, 0, "flower", &s1, pool));
 
+  /* Test svn_fs_change_rev_prop2().  If the whole block goes through, then
+   * it is a no-op (it undoes all changes it makes). */
+    {
+      const svn_string_t s2 = { "wrong value", 11 };
+      const svn_string_t *s2_p = &s2;
+      const svn_string_t *s1_p = &s1;
+      const svn_string_t *unset = NULL;
+      const svn_string_t *s1_dup;
+
+      /* Value of "flower" is 's1'. */
+
+      FAILS_WITH_BPV(svn_fs_change_rev_prop2(fs, 0, "flower", &s2_p, s1_p, pool));
+      s1_dup = svn_string_dup(&s1, pool);
+      SVN_ERR(svn_fs_change_rev_prop2(fs, 0, "flower", &s1_dup, s2_p, pool));
+
+      /* Value of "flower" is 's2'. */
+
+      FAILS_WITH_BPV(svn_fs_change_rev_prop2(fs, 0, "flower", &s1_p, NULL, pool));
+      SVN_ERR(svn_fs_change_rev_prop2(fs, 0, "flower", &s2_p, NULL, pool));
+
+      /* Value of "flower" is <not set>. */
+
+      FAILS_WITH_BPV(svn_fs_change_rev_prop2(fs, 0, "flower", &s2_p, s1_p, pool));
+      SVN_ERR(svn_fs_change_rev_prop2(fs, 0, "flower", &unset, s1_p, pool));
+
+      /* Value of "flower" is 's1'. */
+    }
+
   /* Obtain a list of all current properties, and make sure it matches
      the expected values. */
   SVN_ERR(svn_fs_revision_proplist(&proplist, fs, 0, pool));

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_fs_fs/fs-pack-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_fs_fs/fs-pack-test.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_fs_fs/fs-pack-test.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_fs_fs/fs-pack-test.c Tue Aug 10 22:07:24 2010
@@ -80,12 +80,6 @@ write_format(const char *path,
                                   contents, strlen(contents),
                                   svn_io_file_del_none, pool));
 
-#ifdef WIN32
-      /* make the destination writable, but only on Windows, because
-         Windows does not let us replace read-only files. */
-      SVN_ERR(svn_io_set_file_read_write(path, TRUE, pool));
-#endif /* WIN32 */
-
       /* rename the temp file as the real destination */
       SVN_ERR(svn_io_file_rename(path_tmp, path, pool));
     }

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_ra_local/ra-local-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_ra_local/ra-local-test.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_ra_local/ra-local-test.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/libsvn_ra_local/ra-local-test.c Tue Aug 10 22:07:24 2010
@@ -55,7 +55,7 @@ make_and_open_local_repos(svn_ra_session
   SVN_ERR(svn_test__create_repos(&repos, repos_name, opts, pool));
   SVN_ERR(svn_ra_initialize(pool));
 
-  SVN_ERR(svn_test__current_directory_url(&url, repos_name, pool));
+  SVN_ERR(svn_uri_get_file_url_from_dirent(&url, repos_name, pool));
 
   SVN_ERR(svn_ra_open3(session,
                        url,
@@ -146,13 +146,6 @@ split_url_syntax(apr_pool_t *pool)
       (SVN_ERR_TEST_FAILED, NULL,
        "svn_ra_local__split_URL failed to catch bad URL (scheme)");
 
-  /* Use only single slash after scheme */
-  apr_err = try_split_url("file:/path/to/repos", pool);
-  if (apr_err != SVN_ERR_RA_ILLEGAL_URL)
-    return svn_error_create
-      (SVN_ERR_TEST_FAILED, NULL,
-       "svn_ra_local__split_URL failed to catch bad URL (slashes)");
-
   /* Use only a hostname, with no path */
   apr_err = try_split_url("file://hostname", pool);
   if (apr_err != SVN_ERR_RA_ILLEGAL_URL)
@@ -223,7 +216,7 @@ check_split_url(const char *repos_path,
   /* Create a filesystem and repository */
   SVN_ERR(svn_test__create_repos(&repos, repos_path, opts, pool));
 
-  SVN_ERR(svn_test__current_directory_url(&root_url, repos_path, pool));
+  SVN_ERR(svn_uri_get_file_url_from_dirent(&root_url, repos_path, pool));
   if (in_repos_path)
     url = apr_pstrcat(pool, root_url, in_repos_path, NULL);
   else