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 2010/08/02 16:31:05 UTC

svn commit: r981523 [1/2] - in /subversion/branches/issue-2779-dev: ./ subversion/bindings/swig/python/libsvn_swig_py/ subversion/bindings/swig/python/tests/ subversion/bindings/swig/python/tests/trac/versioncontrol/tests/ subversion/include/ subversio...

Author: cmpilato
Date: Mon Aug  2 14:31:04 2010
New Revision: 981523

URL: http://svn.apache.org/viewvc?rev=981523&view=rev
Log:
Sync with trunk changes. (Merged /subversion/trunk:r980925-981513).

Added:
    subversion/branches/issue-2779-dev/subversion/tests/cmdline/svnrdump_tests_data/skeleton.dump
      - copied unchanged from r981513, subversion/trunk/subversion/tests/cmdline/svnrdump_tests_data/skeleton.dump
Removed:
    subversion/branches/issue-2779-dev/subversion/svnrdump/dumpfile_parser.c
Modified:
    subversion/branches/issue-2779-dev/   (props changed)
    subversion/branches/issue-2779-dev/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c
    subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/auth.py
    subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/client.py
    subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/core.py
    subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/delta.py
    subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/mergeinfo.py
    subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/pool.py
    subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/ra.py
    subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/repository.py
    subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py
    subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/utils.py
    subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/wc.py
    subversion/branches/issue-2779-dev/subversion/include/svn_dirent_uri.h
    subversion/branches/issue-2779-dev/subversion/libsvn_client/diff.c
    subversion/branches/issue-2779-dev/subversion/libsvn_client/patch.c
    subversion/branches/issue-2779-dev/subversion/libsvn_client/prop_commands.c
    subversion/branches/issue-2779-dev/subversion/libsvn_diff/diff_memory.c
    subversion/branches/issue-2779-dev/subversion/libsvn_fs_fs/fs_fs.c
    subversion/branches/issue-2779-dev/subversion/libsvn_ra_neon/props.c
    subversion/branches/issue-2779-dev/subversion/libsvn_ra_serf/commit.c
    subversion/branches/issue-2779-dev/subversion/libsvn_subr/dirent_uri.c
    subversion/branches/issue-2779-dev/subversion/libsvn_wc/adm_files.c
    subversion/branches/issue-2779-dev/subversion/libsvn_wc/adm_ops.c
    subversion/branches/issue-2779-dev/subversion/libsvn_wc/deprecated.c
    subversion/branches/issue-2779-dev/subversion/libsvn_wc/node.c
    subversion/branches/issue-2779-dev/subversion/libsvn_wc/update_editor.c
    subversion/branches/issue-2779-dev/subversion/libsvn_wc/workqueue.c
    subversion/branches/issue-2779-dev/subversion/svnrdump/dump_editor.c   (props changed)
    subversion/branches/issue-2779-dev/subversion/svnrdump/dump_editor.h   (props changed)
    subversion/branches/issue-2779-dev/subversion/svnrdump/load_editor.c   (contents, props changed)
    subversion/branches/issue-2779-dev/subversion/svnrdump/load_editor.h   (contents, props changed)
    subversion/branches/issue-2779-dev/subversion/svnrdump/svnrdump.1   (props changed)
    subversion/branches/issue-2779-dev/subversion/svnrdump/svnrdump.c
    subversion/branches/issue-2779-dev/subversion/tests/cmdline/diff_tests.py
    subversion/branches/issue-2779-dev/subversion/tests/cmdline/revert_tests.py
    subversion/branches/issue-2779-dev/subversion/tests/cmdline/svnrdump_tests.py
    subversion/branches/issue-2779-dev/subversion/tests/cmdline/svntest/actions.py
    subversion/branches/issue-2779-dev/subversion/tests/cmdline/svntest/main.py
    subversion/branches/issue-2779-dev/subversion/tests/libsvn_subr/dirent_uri-test.c
    subversion/branches/issue-2779-dev/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd
    subversion/branches/issue-2779-dev/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd

Propchange: subversion/branches/issue-2779-dev/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Aug  2 14:31:04 2010
@@ -34,4 +34,4 @@
 /subversion/branches/tc_url_rev:874351-874483
 /subversion/branches/tree-conflicts:868291-873154
 /subversion/branches/tree-conflicts-notify:873926-874008
-/subversion/trunk:965496-980924
+/subversion/trunk:965496-981513

Modified: subversion/branches/issue-2779-dev/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c (original)
+++ subversion/branches/issue-2779-dev/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c Mon Aug  2 14:31:04 2010
@@ -1320,6 +1320,61 @@ commit_item_array_to_list(const apr_arra
 
 /*** Errors ***/
 
+/* Convert a given SubversionException to an svn_error_t. On failure returns
+   NULL and sets a Python exception. */
+static svn_error_t *exception_to_error(PyObject * exc)
+{
+	const char *message, *file = NULL;
+	apr_status_t apr_err;
+	long line = 0;
+	PyObject *apr_err_ob = NULL, *child_ob = NULL, *message_ob = NULL;
+	PyObject *file_ob = NULL, *line_ob = NULL;
+    svn_error_t *rv = NULL, *child = NULL;
+
+	if ((apr_err_ob = PyObject_GetAttrString(exc, "apr_err")) == NULL)
+	    goto finished;
+	apr_err = (apr_status_t) PyInt_AsLong(apr_err_ob);
+	if (PyErr_Occurred()) goto finished;
+
+	if ((message_ob = PyObject_GetAttrString(exc, "message")) == NULL)
+	    goto finished;
+	message = PyString_AsString(message_ob);
+	if (PyErr_Occurred()) goto finished;
+
+	if ((file_ob = PyObject_GetAttrString(exc, "file")) == NULL)
+	    goto finished;
+	if (file_ob != Py_None)
+	    file = PyString_AsString(file_ob);
+	if (PyErr_Occurred()) goto finished;
+
+	if ((line_ob = PyObject_GetAttrString(exc, "line")) == NULL)
+	    goto finished;
+	if (line_ob != Py_None)
+	    line = PyInt_AsLong(line_ob);
+	if (PyErr_Occurred()) goto finished;
+
+	if ((child_ob = PyObject_GetAttrString(exc, "child")) == NULL)
+	    goto finished;
+	/* We could check if the child is a Subversion exception too,
+	   but let's just apply duck typing. */
+	if (child_ob != Py_None)
+	    child = exception_to_error(child_ob);
+	if (PyErr_Occurred()) goto finished;
+
+	rv = svn_error_create(apr_err, child, message);
+	/* Somewhat hacky, but we need to preserve original file/line info. */
+	rv->file = file ? apr_pstrdup(rv->pool, file) : NULL;
+	rv->line = line;
+
+finished:
+	Py_XDECREF(child_ob);
+	Py_XDECREF(line_ob);
+	Py_XDECREF(file_ob);
+	Py_XDECREF(message_ob);
+	Py_XDECREF(apr_err_ob);
+	return rv;
+}
+
 /* If the currently set Python exception is a valid SubversionException,
    clear exception state and transform it into a Subversion error.
    Otherwise, return a Subversion error about an exception in a callback. */
@@ -1327,48 +1382,36 @@ static svn_error_t *callback_exception_e
 {
   PyObject *svn_module = NULL, *svn_exc = NULL;
   PyObject *exc, *exc_type, *exc_traceback;
-  PyObject *message_ob = NULL, *apr_err_ob = NULL;
-  const char *message;
-  int apr_err;
   svn_error_t *rv = NULL;
 
   PyErr_Fetch(&exc_type, &exc, &exc_traceback);
 
   if ((svn_module = PyImport_ImportModule("svn.core")) == NULL)
-    goto finished;
-  if ((svn_exc = PyObject_GetAttrString(svn_module, "SubversionException"))
-      == NULL)
-    goto finished;
-
-  if (!PyErr_GivenExceptionMatches(exc_type, svn_exc))
-    {
-      PyErr_Restore(exc_type, exc, exc_traceback);
-      exc = exc_type = exc_traceback = NULL;
       goto finished;
-    }
 
-  if ((apr_err_ob = PyObject_GetAttrString(exc, "apr_err")) == NULL)
-    goto finished;
-  apr_err = PyInt_AsLong(apr_err_ob);
-  if (PyErr_Occurred()) goto finished;
+  svn_exc = PyObject_GetAttrString(svn_module, "SubversionException");
+  Py_DECREF(svn_module);
 
-  if ((message_ob = PyObject_GetAttrString(exc, "message")) == NULL)
-    goto finished;
-  message = PyString_AsString(message_ob);
-  if (PyErr_Occurred()) goto finished;
+  if (svn_exc == NULL)
+      goto finished;
 
-  /* A possible improvement here would be to convert the whole
-     SubversionException chain. */
-  rv = svn_error_create(apr_err, NULL, message);
+  if (PyErr_GivenExceptionMatches(exc_type, svn_exc))
+    {
+      rv = exception_to_error(exc);
+    }
+  else
+    {
+      PyErr_Restore(exc_type, exc, exc_traceback);
+      exc_type = exc = exc_traceback = NULL;
+    }
 
 finished:
-  Py_XDECREF(exc);
+  Py_XDECREF(svn_exc);
   Py_XDECREF(exc_type);
+  Py_XDECREF(exc);
   Py_XDECREF(exc_traceback);
-  Py_XDECREF(svn_module);
-  Py_XDECREF(svn_exc);
-  Py_XDECREF(apr_err_ob);
-  Py_XDECREF(message_ob);
+  /* By now, either rv is set and the exception is cleared, or rv is NULL
+     and an exception is pending (possibly a new one). */
   return rv ? rv : svn_error_create(SVN_ERR_SWIG_PY_EXCEPTION_SET, NULL,
                                     "Python callback raised an exception");
 }

Modified: subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/auth.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/auth.py?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/auth.py (original)
+++ subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/auth.py Mon Aug  2 14:31:04 2010
@@ -110,7 +110,8 @@ class SubversionAuthTestCase(unittest.Te
     self.assert_(creds is not None)
 
 def suite():
-    return unittest.makeSuite(SubversionAuthTestCase, 'test')
+    return unittest.defaultTestLoader.loadTestsFromTestCase(
+      SubversionAuthTestCase)
 
 if __name__ == '__main__':
     runner = unittest.TextTestRunner()

Modified: subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/client.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/client.py?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/client.py (original)
+++ subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/client.py Mon Aug  2 14:31:04 2010
@@ -22,8 +22,6 @@ import unittest, os, weakref, setup_path
 
 from svn import core, client, wc
 
-from trac.versioncontrol.tests.svn_fs import SubversionRepositoryTestSetup, \
-  REPOS_PATH, REPOS_URL
 try:
   # Python >=3.0
   from urllib.parse import urljoin
@@ -71,6 +69,8 @@ class SubversionClientTestCase(unittest.
     self.client_ctx.auth_baton = core.svn_auth_open(providers)
 
     self.temper = utils.Temper()
+    (_, self.repos_path, self.repos_uri) = self.temper.alloc_known_repo(
+      'trac/versioncontrol/tests/svnrepos.dump', suffix='-client')
 
   def tearDown(self):
     # We have to free client_ctx first, since it may be holding handles
@@ -162,10 +162,10 @@ class SubversionClientTestCase(unittest.
     path = self.temper.alloc_empty_dir('-checkout')
 
     self.assertRaises(ValueError, client.checkout2,
-                      REPOS_URL, path, None, None, True, True,
+                      self.repos_uri, path, None, None, True, True,
                       self.client_ctx)
 
-    client.checkout2(REPOS_URL, path, rev, rev, True, True,
+    client.checkout2(self.repos_uri, path, rev, rev, True, True,
             self.client_ctx)
 
   def test_info(self):
@@ -174,19 +174,19 @@ class SubversionClientTestCase(unittest.
     # Run info
     revt = core.svn_opt_revision_t()
     revt.kind = core.svn_opt_revision_head
-    client.info(REPOS_URL, revt, revt, self.info_receiver,
+    client.info(self.repos_uri, revt, revt, self.info_receiver,
                 False, self.client_ctx)
 
     # Check output from running info. This also serves to verify that
     # the internal 'info' object is still valid
-    self.assertEqual(self.path, os.path.basename(REPOS_PATH))
+    self.assertEqual(self.path, os.path.basename(self.repos_path))
     self.info.assert_valid()
-    self.assertEqual(self.info.URL, REPOS_URL)
-    self.assertEqual(self.info.repos_root_URL, REPOS_URL)
+    self.assertEqual(self.info.URL, self.repos_uri)
+    self.assertEqual(self.info.repos_root_URL, self.repos_uri)
 
   def test_mkdir_url(self):
     """Test svn_client_mkdir2 on a file:// URL"""
-    directory = urljoin(REPOS_URL+"/", "dir1")
+    directory = urljoin(self.repos_uri+"/", "dir1")
 
     commit_info = client.mkdir2((directory,), self.client_ctx)
     self.assertEqual(commit_info.revision, 13)
@@ -194,16 +194,16 @@ class SubversionClientTestCase(unittest.
 
   def test_mkdir_url_with_revprops(self):
     """Test svn_client_mkdir3 on a file:// URL, with added revprops"""
-    directory = urljoin(REPOS_URL+"/", "some/deep/subdir")
+    directory = urljoin(self.repos_uri+"/", "some/deep/subdir")
 
     commit_info = client.mkdir3((directory,), 1, {'customprop':'value'},
                                 self.client_ctx)
-    self.assertEqual(commit_info.revision, 14)
+    self.assertEqual(commit_info.revision, 13)
     self.assertEqual(self.log_message_func_calls, 1)
 
   def test_log3_url(self):
     """Test svn_client_log3 on a file:// URL"""
-    directory = urljoin(REPOS_URL+"/", "trunk/dir1")
+    directory = urljoin(self.repos_uri+"/", "trunk/dir1")
 
     start = core.svn_opt_revision_t()
     end = core.svn_opt_revision_t()
@@ -233,7 +233,7 @@ class SubversionClientTestCase(unittest.
 
     self.received_revisions = []
 
-    client.log5((REPOS_URL,), end, (rev_range,), 0, False, True, False, (),
+    client.log5((self.repos_uri,), end, (rev_range,), 0, False, True, False, (),
         self.log_entry_receiver, self.client_ctx)
 
     self.assertEqual(self.received_revisions, range(0, 5))
@@ -241,22 +241,22 @@ class SubversionClientTestCase(unittest.
   def test_uuid_from_url(self):
     """Test svn_client_uuid_from_url on a file:// URL"""
     self.assert_(isinstance(
-                 client.uuid_from_url(REPOS_URL, self.client_ctx),
+                 client.uuid_from_url(self.repos_uri, self.client_ctx),
                  basestring))
 
   def test_url_from_path(self):
     """Test svn_client_url_from_path for a file:// URL"""
-    self.assertEquals(client.url_from_path(REPOS_URL), REPOS_URL)
+    self.assertEquals(client.url_from_path(self.repos_uri), self.repos_uri)
 
     rev = core.svn_opt_revision_t()
     rev.kind = core.svn_opt_revision_head
 
     path = self.temper.alloc_empty_dir('-url_from_path')
 
-    client.checkout2(REPOS_URL, path, rev, rev, True, True,
+    client.checkout2(self.repos_uri, path, rev, rev, True, True,
                      self.client_ctx)
 
-    self.assertEquals(client.url_from_path(path), REPOS_URL)
+    self.assertEquals(client.url_from_path(path), self.repos_uri)
 
   def test_uuid_from_path(self):
     """Test svn_client_uuid_from_path."""
@@ -265,20 +265,20 @@ class SubversionClientTestCase(unittest.
 
     path = self.temper.alloc_empty_dir('-uuid_from_path')
 
-    client.checkout2(REPOS_URL, path, rev, rev, True, True,
+    client.checkout2(self.repos_uri, path, rev, rev, True, True,
                      self.client_ctx)
 
     wc_adm = wc.adm_open3(None, path, False, 0, None)
 
     self.assertEquals(client.uuid_from_path(path, wc_adm, self.client_ctx),
-                      client.uuid_from_url(REPOS_URL, self.client_ctx))
+                      client.uuid_from_url(self.repos_uri, self.client_ctx))
 
     self.assert_(isinstance(client.uuid_from_path(path, wc_adm,
                             self.client_ctx), basestring))
 
   def test_open_ra_session(self):
       """Test svn_client_open_ra_session()."""
-      client.open_ra_session(REPOS_URL, self.client_ctx)
+      client.open_ra_session(self.repos_uri, self.client_ctx)
 
 
   def test_info_file(self):
@@ -290,7 +290,7 @@ class SubversionClientTestCase(unittest.
     rev.kind = core.svn_opt_revision_head
     wc_path = self.temper.alloc_empty_dir('-info_file')
 
-    client.checkout2(REPOS_URL, wc_path, rev, rev, True, True,
+    client.checkout2(self.repos_uri, wc_path, rev, rev, True, True,
                      self.client_ctx)
     adm_access = wc.adm_open3(None, wc_path, True, -1, None)
 
@@ -298,7 +298,7 @@ class SubversionClientTestCase(unittest.
       # Test 1: Run info -r BASE. We expect the size value to be filled in.
       rev.kind = core.svn_opt_revision_base
       readme_path = '%s/trunk/README.txt' % wc_path
-      readme_url = '%s/trunk/README.txt' % REPOS_URL
+      readme_url = '%s/trunk/README.txt' % self.repos_uri
       client.info(readme_path, rev, rev, self.info_receiver,
                   False, self.client_ctx)
 
@@ -340,7 +340,7 @@ class SubversionClientTestCase(unittest.
     head.kind = core.svn_opt_revision_head
     wc_path = self.temper.alloc_empty_dir('-merge_peg3')
 
-    client.checkout3(REPOS_URL, wc_path, head, head, core.svn_depth_infinity,
+    client.checkout3(self.repos_uri, wc_path, head, head, core.svn_depth_infinity,
                      True, False, self.client_ctx)
 
     # Let's try to backport a change from the v1x branch
@@ -375,8 +375,8 @@ class SubversionClientTestCase(unittest.
     self.assertEqual(readme_text, 'This is a test.\n')
 
 def suite():
-    return unittest.makeSuite(SubversionClientTestCase, 'test',
-                              suiteClass=SubversionRepositoryTestSetup)
+    return unittest.defaultTestLoader.loadTestsFromTestCase(
+      SubversionClientTestCase)
 
 if __name__ == '__main__':
     runner = unittest.TextTestRunner()

Modified: subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/core.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/core.py?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/core.py (original)
+++ subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/core.py Mon Aug  2 14:31:04 2010
@@ -20,7 +20,8 @@
 #
 import unittest
 
-import svn.core
+import svn.core, svn.client
+import utils
 
 class SubversionCoreTestCase(unittest.TestCase):
   """Test cases for the basic SWIG Subversion core"""
@@ -46,8 +47,67 @@ class SubversionCoreTestCase(unittest.Te
             svn.core.svn_mime_type_validate, "this\nis\ninvalid\n")
     svn.core.svn_mime_type_validate("unknown/but-valid; charset=utf8")
 
+  def test_exception_interoperability(self):
+    """Test if SubversionException is correctly converted into svn_error_t
+    and vice versa."""
+    t = utils.Temper()
+    (_, _, repos_uri) = t.alloc_empty_repo(suffix='-core')
+    rev = svn.core.svn_opt_revision_t()
+    rev.kind = svn.core.svn_opt_revision_head
+    ctx = svn.client.create_context()
+    
+    class Receiver:
+      def __call__(self, path, info, pool):
+        raise self.e
+    
+    rec = Receiver()
+    args = (repos_uri, rev, rev, rec, svn.core.svn_depth_empty, None, ctx)
+
+    try:
+      # ordinary Python exceptions must be passed through
+      rec.e = TypeError()
+      self.assertRaises(TypeError, svn.client.info2, *args)
+      
+      # SubversionException will be translated into an svn_error_t, propagated
+      # through the call chain and translated back to SubversionException.
+      rec.e = svn.core.SubversionException("Bla bla bla.",
+                                           svn.core.SVN_ERR_INCORRECT_PARAMS,
+                                           file=__file__, line=866)
+      rec.e.child = svn.core.SubversionException("Yada yada.",
+                                             svn.core.SVN_ERR_INCOMPLETE_DATA)
+      self.assertRaises(svn.core.SubversionException, svn.client.info2, *args)
+      
+      # It must remain unchanged through the process.
+      try:
+        svn.client.info2(*args)
+      except svn.core.SubversionException as exc:
+        # find the original exception
+        while exc.file != rec.e.file: exc = exc.child
+        
+        self.assertEqual(exc.message, rec.e.message)
+        self.assertEqual(exc.apr_err, rec.e.apr_err)
+        self.assertEqual(exc.line, rec.e.line)
+        self.assertEqual(exc.child.message, rec.e.child.message)
+        self.assertEqual(exc.child.apr_err, rec.e.child.apr_err)
+        self.assertEqual(exc.child.child, None)
+        self.assertEqual(exc.child.file, None)
+        self.assertEqual(exc.child.line, 0)
+        
+      # Incomplete SubversionExceptions must trigger Python exceptions, which
+      # will be passed through.
+      rec.e = svn.core.SubversionException("No fields except message.")
+      # e.apr_err is None but should be an int
+      self.assertRaises(TypeError, svn.client.info2, args)
+    finally:
+      # This would happen without the finally block as well, but we expliticly
+      # order the operations so that the cleanup is not hindered by any open
+      # handles.
+      del ctx
+      t.cleanup()
+
 def suite():
-    return unittest.makeSuite(SubversionCoreTestCase, 'test')
+    return unittest.defaultTestLoader.loadTestsFromTestCase(
+      SubversionCoreTestCase)
 
 if __name__ == '__main__':
     runner = unittest.TextTestRunner()

Modified: subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/delta.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/delta.py?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/delta.py (original)
+++ subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/delta.py Mon Aug  2 14:31:04 2010
@@ -48,7 +48,7 @@ class DeltaTestCase(unittest.TestCase):
     window_handler(None, baton)
 
 def suite():
-  return unittest.makeSuite(DeltaTestCase, 'test')
+  return unittest.defaultTestLoader.loadTestsFromTestCase(DeltaTestCase)
 
 if __name__ == '__main__':
   runner = unittest.TextTestRunner()

Modified: subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/mergeinfo.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/mergeinfo.py?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/mergeinfo.py (original)
+++ subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/mergeinfo.py Mon Aug  2 14:31:04 2010
@@ -19,21 +19,8 @@
 #
 #
 import unittest, os
-
-from sys import version_info # For Python version check
-if version_info[0] >= 3:
-  # Python >=3.0
-  from io import StringIO
-else:
-  # Python <3.0
-  try:
-    from cStringIO import StringIO
-  except ImportError:
-    from StringIO import StringIO
-
 from svn import core, repos, fs
-
-from trac.versioncontrol.tests.svn_fs import REPOS_PATH
+import utils
 
 class RevRange:
   """ Proxy object for a revision range, used for comparison. """
@@ -58,22 +45,16 @@ class SubversionMergeinfoTestCase(unitte
        created by dumping the repository generated for command line log
        tests 16.  If it needs to be updated (mergeinfo format changes, for
        example), we can go there to get a new version."""
-    dumpfile = open(os.path.join(os.path.split(__file__)[0],
-                                 'data', 'mergeinfo.dump'), 'rb')
-    # Remove any existing repository to ensure a fresh start
-    self.tearDown()
-    self.repos = repos.svn_repos_create(REPOS_PATH, '', '', None, None)
-    repos.svn_repos_load_fs2(self.repos, dumpfile, StringIO(),
-                             repos.svn_repos_load_uuid_ignore, '',
-                             0, 0, None)
+    self.temper = utils.Temper()
+    (self.repos, _, _) = self.temper.alloc_known_repo('data/mergeinfo.dump',
+                                                      suffix='-mergeinfo')
     self.fs = repos.fs(self.repos)
     self.rev = fs.youngest_rev(self.fs)
 
   def tearDown(self):
-    self.fs = None
-    self.repos = None
-    if os.path.exists(REPOS_PATH):
-      repos.delete(REPOS_PATH)
+    del self.fs
+    del self.repos
+    self.temper.cleanup()
 
   def test_mergeinfo_parse(self):
     """Test svn_mergeinfo_parse()"""
@@ -176,7 +157,8 @@ class SubversionMergeinfoTestCase(unitte
 
 
 def suite():
-    return unittest.makeSuite(SubversionMergeinfoTestCase, 'test')
+    return unittest.defaultTestLoader.loadTestsFromTestCase(
+      SubversionMergeinfoTestCase)
 
 if __name__ == '__main__':
     runner = unittest.TextTestRunner()

Modified: subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/pool.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/pool.py?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/pool.py (original)
+++ subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/pool.py Mon Aug  2 14:31:04 2010
@@ -219,7 +219,7 @@ class PoolTestCase(unittest.TestCase):
     svn_pool_destroy(svn_pool_create())
 
 def suite():
-  return unittest.makeSuite(PoolTestCase, 'test')
+  return unittest.defaultTestLoader.loadTestsFromTestCase(PoolTestCase)
 
 if __name__ == '__main__':
   runner = unittest.TextTestRunner()

Modified: subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/ra.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/ra.py?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/ra.py (original)
+++ subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/ra.py Mon Aug  2 14:31:04 2010
@@ -28,9 +28,8 @@ if version_info[0] >= 3:
 else:
   # Python <3.0
   from StringIO import StringIO
-
-from trac.versioncontrol.tests.svn_fs import SubversionRepositoryTestSetup, \
-  REPOS_PATH, REPOS_URL
+  
+import utils
 
 class SubversionRepositoryAccessTestCase(unittest.TestCase):
   """Test cases for the Subversion repository layer"""
@@ -38,24 +37,23 @@ class SubversionRepositoryAccessTestCase
   def setUp(self):
     """Load a Subversion repository"""
 
-    # Isolate each test from the others with a fresh repository.
-    # Eventually, we should move this into a shared TestCase base
-    # class that all test cases in this directory can use.
-    SubversionRepositoryTestSetup().setUp()
-
     ra.initialize()
-
+    self.temper = utils.Temper()
+    # Isolate each test from the others with a fresh repository.
+    
     # Open repository directly for cross-checking
-    self.repos = repos.open(REPOS_PATH)
+    (self.repos, _, self.repos_uri) = self.temper.alloc_known_repo(
+      'trac/versioncontrol/tests/svnrepos.dump', suffix='-ra')
     self.fs = repos.fs(self.repos)
 
     self.callbacks = ra.Callbacks()
-    self.ra_ctx = ra.open2(REPOS_URL, self.callbacks, {})
+    self.ra_ctx = ra.open2(self.repos_uri, self.callbacks, {})
 
   def tearDown(self):
     self.ra_ctx = None
     self.fs = None
     self.repos = None
+    self.temper.cleanup()
 
   def test_get_file(self):
     # Test getting the properties of a file
@@ -73,7 +71,7 @@ class SubversionRepositoryAccessTestCase
 
   def test_get_repos_root(self):
     root = ra.get_repos_root(self.ra_ctx)
-    self.assertEqual(root,REPOS_URL)
+    self.assertEqual(root,self.repos_uri)
 
   def test_get_uuid(self):
     ra_uuid = ra.get_uuid(self.ra_ctx)
@@ -100,7 +98,8 @@ class SubversionRepositoryAccessTestCase
 
     self.assertEqual(dirents, {})
 
-    (dirents, _, _) = ra.get_dir2(self.ra_ctx, 'trunk', 10, core.SVN_DIRENT_KIND)
+    (dirents, _, _) = ra.get_dir2(self.ra_ctx, 'trunk', 10,
+                                  core.SVN_DIRENT_KIND)
 
     self.assert_('README2.txt' in dirents)
     self.assertEqual(dirents['README2.txt'].kind, core.svn_node_file)
@@ -252,10 +251,11 @@ class SubversionRepositoryAccessTestCase
 
     sess_url = ra.get_session_url(self.ra_ctx)
     try:
-        ra.reparent(self.ra_ctx, REPOS_URL+"/trunk")
+        ra.reparent(self.ra_ctx, self.repos_uri+"/trunk")
         reporter, reporter_baton = ra.do_diff2(self.ra_ctx, fs_revnum,
                                                "README.txt", 0, 0, 1,
-                                               REPOS_URL+"/trunk/README.txt",
+                                               self.repos_uri
+                                                 +"/trunk/README.txt",
                                                e_ptr, e_baton)
         reporter.set_path(reporter_baton, "", 0, True, None)
         reporter.finish_report(reporter_baton)
@@ -376,7 +376,7 @@ class SubversionRepositoryAccessTestCase
 
   def test_namestring(self):
     # Only ra-{neon,serf} support this right now.
-    if REPOS_URL.startswith('http'):
+    if self.repos_uri.startswith('http'):
       called = [False]
       def cb(pool):
         called[0] = True
@@ -386,7 +386,8 @@ class SubversionRepositoryAccessTestCase
       self.assert_(called[0])
 
 def suite():
-    return unittest.makeSuite(SubversionRepositoryAccessTestCase, 'test')
+    return unittest.defaultTestLoader.loadTestsFromTestCase(
+      SubversionRepositoryAccessTestCase)
 
 if __name__ == '__main__':
     runner = unittest.TextTestRunner()

Modified: subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/repository.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/repository.py?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/repository.py (original)
+++ subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/repository.py Mon Aug  2 14:31:04 2010
@@ -18,7 +18,7 @@
 # under the License.
 #
 #
-import unittest, setup_path, tempfile
+import unittest, setup_path
 from sys import version_info # For Python version check
 if version_info[0] >= 3:
   # Python >=3.0
@@ -28,9 +28,7 @@ else:
   from StringIO import StringIO
 from svn import core, repos, fs, delta
 from svn.core import SubversionException
-
-from trac.versioncontrol.tests.svn_fs import SubversionRepositoryTestSetup, \
-  REPOS_PATH
+import utils
 
 class ChangeReceiver(delta.Editor):
   """A delta editor which saves textdeltas for later use"""
@@ -55,13 +53,16 @@ class SubversionRepositoryTestCase(unitt
 
   def setUp(self):
     """Load a Subversion repository"""
-    self.repos = repos.open(REPOS_PATH)
+    self.temper = utils.Temper()
+    (self.repos, _, _) = self.temper.alloc_known_repo(
+      'trac/versioncontrol/tests/svnrepos.dump', suffix='-repository')
     self.fs = repos.fs(self.repos)
     self.rev = fs.youngest_rev(self.fs)
 
   def tearDown(self):
     self.fs = None
     self.repos = None
+    self.temper.cleanup()
 
   def test_cease_invocation(self):
     """Test returning SVN_ERR_CEASE_INVOCATION from a callback"""
@@ -81,9 +82,8 @@ class SubversionRepositoryTestCase(unitt
        using a config hash"""
     fs_config = { "fs-type": "fsfs" }
     for i in range(5):
-      path = core.svn_dirent_internal_style(tempfile.mkdtemp("-test" + str(i)))
+      path = self.temper.alloc_empty_dir(suffix='-repository-create%d' % i)
       repos.create(path, "", "", None, fs_config)
-      repos.delete(path)
 
   def test_dump_fs2(self):
     """Test the dump_fs2 function"""
@@ -197,8 +197,8 @@ class SubversionRepositoryTestCase(unitt
                      "Youngest revision")
 
 def suite():
-    return unittest.makeSuite(SubversionRepositoryTestCase, 'test',
-                              suiteClass=SubversionRepositoryTestSetup)
+    return unittest.defaultTestLoader.loadTestsFromTestCase(
+      SubversionRepositoryTestCase)
 
 if __name__ == '__main__':
     runner = unittest.TextTestRunner()

Modified: subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py (original)
+++ subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py Mon Aug  2 14:31:04 2010
@@ -361,8 +361,9 @@ class SubversionRepositoryTestCase(unitt
 
 
 def suite():
-    return unittest.makeSuite(SubversionRepositoryTestCase, 'test',
-                              suiteClass=SubversionRepositoryTestSetup)
+    loader = unittest.TestLoader()
+    loader.suiteClass = SubversionRepositoryTestSetup
+    return loader.loadTestsFromTestCase(SubversionRepositoryTestCase)
 
 if __name__ == '__main__':
     runner = unittest.TextTestRunner()

Modified: subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/utils.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/utils.py?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/utils.py (original)
+++ subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/utils.py Mon Aug  2 14:31:04 2010
@@ -18,13 +18,9 @@
 # under the License.
 #
 #
-import tempfile, urllib
+import os.path, sys, tempfile, urllib
 from svn import core, repos
-
-try:
-  from io import StringIO
-except ImportError:
-  from StringIO import StringIO
+from StringIO import StringIO
 
 class Temper(object):
   """Class to simplify allocation and cleanup of dummy Subversion
@@ -49,21 +45,31 @@ class Temper(object):
     self._cleanup_list.append((temp_dir_name, core.svn_io_remove_dir))
     return temp_dir_name
 
-  def alloc_repo(self, suffix = ""):
-    """Creates an empty repository. Returns a tuple of its handle, path and
+  def alloc_empty_repo(self, suffix = ""):
+    """Create an empty repository. Returns a tuple of its handle, path and
        file: URI in canonical internal form."""
     temp_path = tempfile.mkdtemp(suffix)
     repo_path = core.svn_dirent_internal_style(temp_path)
-    repo_uri = core.svn_uri_canonicalize(Temper._file_uri_for_path(temp_path))
+    repo_uri = core.svn_uri_canonicalize(file_uri_for_path(temp_path))
     handle = repos.create(repo_path, None, None, None, None)
     self._cleanup_list.append((repo_path, repos.svn_repos_delete))
     return (handle, repo_path, repo_uri)
+
+  def alloc_known_repo(self, repo_id, suffix = ""):
+    """Create a temporary repository and fill it with the contents of the
+       specified dump. repo_id is the path to the dump, relative to the script's
+       location. Returns the same as alloc_empty_repo."""
+    dump_path = os.path.join(os.path.dirname(sys.argv[0]), repo_id)
+    (handle, repo_path, repo_uri) = self.alloc_empty_repo(suffix=suffix)
+    repos.svn_repos_load_fs2(handle, open(dump_path, 'rb'), StringIO(),
+                             repos.load_uuid_default, None, False, False, None)
+    return (handle, repo_path, repo_uri)
     
-  @classmethod
-  def _file_uri_for_path(cls, path):
-    uri_path = urllib.pathname2url(path)
-
-    # pathname2url claims to return the path part of the URI, but on Windows
-    # it returns both the authority and path parts for no reason, which
-    # means we have to trim the leading slashes to "normalize" the result.
-    return 'file:///' + uri_path.lstrip('/')
+def file_uri_for_path(path):
+  """Return the file: URI corresponding to the given path."""
+  uri_path = urllib.pathname2url(path)
+
+  # pathname2url claims to return the path part of the URI, but on Windows
+  # it returns both the authority and path parts for no reason, which
+  # means we have to trim the leading slashes to "normalize" the result.
+  return 'file:///' + uri_path.lstrip('/')

Modified: subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/wc.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/wc.py?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/wc.py (original)
+++ subversion/branches/issue-2779-dev/subversion/bindings/swig/python/tests/wc.py Mon Aug  2 14:31:04 2010
@@ -30,9 +30,7 @@ import svn.diff
 from svn import core, repos, wc, client
 from svn import delta, ra
 from svn.core import SubversionException, SVN_INVALID_REVNUM
-
-from trac.versioncontrol.tests.svn_fs import SubversionRepositoryTestSetup, \
-  REPOS_PATH, REPOS_URL
+import utils
 
 class SubversionWorkingCopyTestCase(unittest.TestCase):
   """Test cases for the Subversion working copy layer"""
@@ -40,23 +38,21 @@ class SubversionWorkingCopyTestCase(unit
   def setUp(self):
     """Load a Subversion repository"""
 
-    # Isolate each test from the others with a fresh repository.
-    # Eventually, we should move this into a shared TestCase base
-    # class that all test cases in this directory can use.
-    SubversionRepositoryTestSetup().setUp()
+    self.temper = utils.Temper()
 
-    # Open repository directly for cross-checking
-    self.repos = repos.open(REPOS_PATH)
+    # Isolate each test from the others with a fresh repository.
+    (self.repos, _, self.repos_uri) = self.temper.alloc_known_repo(
+      'trac/versioncontrol/tests/svnrepos.dump', suffix='-wc-repo')
     self.fs = repos.fs(self.repos)
 
-    self.path = core.svn_dirent_internal_style(tempfile.mktemp())
+    self.path = self.temper.alloc_empty_dir(suffix='-wc-wc')
 
     client_ctx = client.create_context()
 
     rev = core.svn_opt_revision_t()
     rev.kind = core.svn_opt_revision_head
 
-    client.checkout2(REPOS_URL, self.path, rev, rev, True, True,
+    client.checkout2(self.repos_uri, self.path, rev, rev, True, True,
             client_ctx)
 
     self.wc = wc.adm_open3(None, self.path, True, -1, None)
@@ -159,7 +155,7 @@ class SubversionWorkingCopyTestCase(unit
       self.assert_(wc.check_wc(self.path) > 0)
 
   def test_get_ancestry(self):
-      self.assertEqual([REPOS_URL, 12],
+      self.assertEqual([self.repos_uri, 12],
                        wc.get_ancestry(self.path, self.wc))
 
   def test_status(self):
@@ -237,7 +233,7 @@ class SubversionWorkingCopyTestCase(unit
     # Setup ra_ctx.
     ra.initialize()
     callbacks = ra.Callbacks()
-    ra_ctx = ra.open2(REPOS_URL, callbacks, None, None)
+    ra_ctx = ra.open2(self.repos_uri, callbacks, None, None)
 
     # Get commit editor.
     commit_info = [None]
@@ -294,7 +290,7 @@ class SubversionWorkingCopyTestCase(unit
   def test_diff_editor4(self):
     pool = None
     depth = core.svn_depth_infinity
-    url = REPOS_URL
+    url = self.repos_uri
 
     # cause file_changed: Replace README.txt's contents.
     readme_path = '%s/trunk/README.txt' % self.path
@@ -441,16 +437,14 @@ class SubversionWorkingCopyTestCase(unit
     self.assertEqual(got_diffs, expected_diffs)
 
   def tearDown(self):
-      try:
-        wc.adm_close(self.wc)
-        core.svn_io_remove_dir(self.path)
-      except:
-        print('Error in tearDown: %s' % sys.exc_info()[0])
+      wc.adm_close(self.wc)
       self.fs = None
       self.repos = None
+      self.temper.cleanup()
 
 def suite():
-    return unittest.makeSuite(SubversionWorkingCopyTestCase, 'test')
+    return unittest.defaultTestLoader.loadTestsFromTestCase(
+      SubversionWorkingCopyTestCase)
 
 if __name__ == '__main__':
     runner = unittest.TextTestRunner()

Modified: subversion/branches/issue-2779-dev/subversion/include/svn_dirent_uri.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/include/svn_dirent_uri.h?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/include/svn_dirent_uri.h (original)
+++ subversion/branches/issue-2779-dev/subversion/include/svn_dirent_uri.h Mon Aug  2 14:31:04 2010
@@ -766,20 +766,22 @@ svn_uri_condense_targets(const char **pc
                          apr_pool_t *scratch_pool);
 
 /** Check that when @a path is joined to @a base_path, the resulting path
- * is still under BASE_PATH in the local filesystem. If not, return @c FALSE.
- * If @c TRUE is returned, @a *full_path will be set to the absolute path
- * of @a path, allocated in @a pool.
+ * is still under BASE_PATH in the local filesystem. If not, set @a under_root
+ * to @c FALSE. If @a under_root is @c TRUE is returned, and @a result_path is
+ * not @c NULL, then @a *result_path will be set to the absolute path of @a
+ * path, allocated in @a result_pool.
  *
  * Note: Use of this function is strongly encouraged. Do not roll your own.
  * (http://cve.mitre.org/cgi-bin/cvename.cgi?name=2007-3846)
  *
  * @since New in 1.7.
  */
-svn_boolean_t
-svn_dirent_is_under_root(char **full_path,
+svn_error_t *
+svn_dirent_is_under_root(svn_boolean_t *under_root,
+                         const char **result_path,
                          const char *base_path,
                          const char *path,
-                         apr_pool_t *pool);
+                         apr_pool_t *result_pool);
 
 /** Set @a *dirent to the path corresponding to the file:// URL @a url, using
  * the platform-specific file:// rules.

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_client/diff.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_client/diff.c Mon Aug  2 14:31:04 2010
@@ -1412,7 +1412,7 @@ diff_prepare_repos_repos(const struct di
   /* Do the same for the first target. */
   SVN_ERR(svn_ra_reparent(ra_session, drr->url1, pool));
   SVN_ERR(svn_client__get_revision_number(&drr->rev1, NULL, ctx->wc_ctx,
-           (params->path1 == drr->url1) ? NULL : params_path1_abspath,
+           (strcmp(params->path1, drr->url1) == 0) ? NULL : params_path1_abspath,
            ra_session, params->revision1, pool));
   SVN_ERR(svn_ra_check_path(ra_session, "", drr->rev1, &kind1, pool));
   if (kind1 == svn_node_none)
@@ -1735,7 +1735,7 @@ diff_repos_wc(const char *path1,
 
   /* Tell the RA layer we want a delta to change our txn to URL1 */
   SVN_ERR(svn_client__get_revision_number(&rev, NULL, ctx->wc_ctx,
-                                          (path1 == url1) ? NULL : abspath1,
+                                          (strcmp(path1, url1) == 0) ? NULL : abspath1,
                                           ra_session, revision1, pool));
 
   if (!reverse)

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_client/patch.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_client/patch.c Mon Aug  2 14:31:04 2010
@@ -145,7 +145,7 @@ typedef struct patch_target_t {
   /* The absolute path of the target on the filesystem.
    * Any symlinks the path from the patch file may contain are resolved.
    * Is not always known, so it may be NULL. */
-  char *local_abspath;
+  const char *local_abspath;
 
   /* The target file, read-only, seekable. This is NULL in case the target
    * file did not exist prior to patch application. */
@@ -337,12 +337,18 @@ resolve_target_path(patch_target_t *targ
                     apr_pool_t *scratch_pool)
 {
   const char *stripped_path;
+  const char *full_path;
   svn_wc_status3_t *status;
   svn_error_t *err;
+  svn_boolean_t under_root;
 
   target->canon_path_from_patchfile = svn_dirent_internal_style(
                                         path_from_patchfile, result_pool);
-  if (target->canon_path_from_patchfile[0] == '\0')
+
+  /* We allow properties to be set on the wc root dir.
+   * ### Do we need to check for empty paths here, shouldn't the parser
+   * ### guarentee that the paths returned are non-empty? */
+  if (! prop_changes_only && target->canon_path_from_patchfile[0] == '\0')
     {
       /* An empty patch target path? What gives? Skip this. */
       target->skipped = TRUE;
@@ -362,7 +368,6 @@ resolve_target_path(patch_target_t *targ
       target->local_relpath = svn_dirent_is_child(local_abspath, stripped_path,
                                                   result_pool);
 
-      /* ### We need to allow setting props on the wc root dir */
       if (! target->local_relpath)
         {
           /* The target path is either outside of the working copy
@@ -380,8 +385,11 @@ resolve_target_path(patch_target_t *targ
 
   /* Make sure the path is secure to use. We want the target to be inside
    * of the working copy and not be fooled by symlinks it might contain. */
-  if (! svn_dirent_is_under_root(&target->local_abspath, local_abspath,
-                                 target->local_relpath, result_pool))
+  SVN_ERR(svn_dirent_is_under_root(&under_root,
+                                   &full_path, local_abspath,
+                                   target->local_relpath, result_pool));
+
+  if (! under_root)
     {
       /* The target path is outside of the working copy. Skip it. */
       target->skipped = TRUE;
@@ -389,6 +397,9 @@ resolve_target_path(patch_target_t *targ
       return SVN_NO_ERROR;
     }
 
+  SVN_ERR(svn_dirent_get_absolute(&target->local_abspath, full_path,
+                                  result_pool));
+
   /* Skip things we should not be messing with. */
   err = svn_wc_status3(&status, wc_ctx, target->local_abspath,
                        result_pool, scratch_pool);

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_client/prop_commands.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_client/prop_commands.c Mon Aug  2 14:31:04 2010
@@ -118,7 +118,8 @@ propset_walk_cb(const char *local_abspat
 
   err = svn_wc_prop_set4(wb->wc_ctx, local_abspath, wb->propname, wb->propval,
                          wb->force, wb->notify_func, wb->notify_baton, pool);
-  if (err && err->apr_err == SVN_ERR_ILLEGAL_TARGET)
+  if (err && (err->apr_err == SVN_ERR_ILLEGAL_TARGET
+              || err->apr_err == SVN_ERR_WC_INVALID_SCHEDULE))
     {
       svn_error_clear(err);
       err = SVN_NO_ERROR;

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_diff/diff_memory.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_diff/diff_memory.c Mon Aug  2 14:31:04 2010
@@ -519,8 +519,13 @@ output_unified_diff_modified(void *baton
   targ_orig = (targ_orig < 0) ? 0 : targ_orig;
   targ_mod = modified_start;
 
+  /* If the changed ranges are far enough apart (no overlapping or
+   * connecting context), flush the current hunk. */
   if (btn->next_token + SVN_DIFF__UNIFIED_CONTEXT_SIZE < targ_orig)
     SVN_ERR(output_unified_flush_hunk(btn, btn->hunk_delimiter));
+  /* Adjust offset if it's not the first hunk. */
+  else if (btn->hunk_length[0] != 0)
+    targ_orig = btn->next_token;
 
   if (btn->hunk_length[0] == 0
       && btn->hunk_length[1] == 0)

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_fs_fs/fs_fs.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_fs_fs/fs_fs.c Mon Aug  2 14:31:04 2010
@@ -1288,16 +1288,16 @@ upgrade_body(void *baton, apr_pool_t *po
     case svn_node_none:
       SVN_ERR(write_config(fs, pool));
       break;
-    case svn_node_dir:
+    case svn_node_file:
+      break;
+    default:
       return svn_error_return(svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
-                                                _("'%s' is a directory. "
-                                                  "Please move it out of "
+                                                _("'%s' is not a regular file."
+                                                  " Please move it out of "
                                                   "the way and try again"),
                                                 svn_dirent_join(fs->path,
                                                                 PATH_CONFIG,
                                                                 pool)));
-    default:
-      break;
     }
 
   /* If we're already up-to-date, there's nothing else to be done here. */
@@ -1546,10 +1546,15 @@ svn_fs_fs__hotcopy(const char *src_path,
               const char *src_abspath;
               const char *dst_abspath;
               const char *config_relpath;
+              svn_error_t *err2;
 
               config_relpath = svn_dirent_join(src_path, PATH_CONFIG, pool);
-              SVN_ERR(svn_dirent_get_absolute(&src_abspath, src_path, pool));
-              SVN_ERR(svn_dirent_get_absolute(&dst_abspath, dst_path, pool));
+              err2 = svn_dirent_get_absolute(&src_abspath, src_path, pool);
+              if (err2)
+                return svn_error_return(svn_error_compose_create(err, err2));
+              err2 = svn_dirent_get_absolute(&dst_abspath, dst_path, pool);
+              if (err2)
+                return svn_error_return(svn_error_compose_create(err, err2));
               
               /* ### hack: strip off the 'db/' directory from paths so
                * ### they make sense to the user */

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_ra_neon/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_ra_neon/props.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_ra_neon/props.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_ra_neon/props.c Mon Aug  2 14:31:04 2010
@@ -1031,36 +1031,22 @@ svn_error_t *svn_ra_neon__get_baseline_i
 }
 
 
-/* Helper function for svn_ra_neon__do_proppatch() below. */
-static void
-append_setprop(svn_stringbuf_t *body,
-               const char *name,
-               const svn_string_t *value,
-               apr_pool_t *pool)
+/* Helper function for append_setprop() below. */
+static svn_error_t *
+get_encoding_and_cdata(const char **encoding_p,
+                       const char **cdata_p,
+                       const svn_string_t *value,
+                       apr_pool_t *pool)
 {
-  const char *encoding = "";
+  const char *encoding;
   const char *xml_safe;
-  const char *xml_tag_name;
 
-  /* Map property names to namespaces */
-#define NSLEN (sizeof(SVN_PROP_PREFIX) - 1)
-  if (strncmp(name, SVN_PROP_PREFIX, NSLEN) == 0)
-    {
-      xml_tag_name = apr_pstrcat(pool, "S:", name + NSLEN, NULL);
-    }
-#undef NSLEN
-  else
+  /* Easy out. */
+  if (value == NULL)
     {
-      xml_tag_name = apr_pstrcat(pool, "C:", name, NULL);
-    }
-
-  /* If there is no value, just generate an empty tag and get outta
-     here. */
-  if (! value)
-    {
-      svn_stringbuf_appendcstr(body,
-                               apr_psprintf(pool, "<%s />", xml_tag_name));
-      return;
+      *encoding_p = "";
+      *cdata_p = "";
+      return SVN_NO_ERROR;
     }
 
   /* If a property is XML-safe, XML-encode it.  Else, base64-encode
@@ -1070,6 +1056,7 @@ append_setprop(svn_stringbuf_t *body,
       svn_stringbuf_t *xml_esc = NULL;
       svn_xml_escape_cdata_string(&xml_esc, value, pool);
       xml_safe = xml_esc->data;
+      encoding = "";
     }
   else
     {
@@ -1079,11 +1066,41 @@ append_setprop(svn_stringbuf_t *body,
       xml_safe = base64ed->data;
     }
 
+  *encoding_p = encoding;
+  *cdata_p = xml_safe;
+  return SVN_NO_ERROR;
+}
+
+/* Helper function for svn_ra_neon__do_proppatch() below. */
+static svn_error_t *
+append_setprop(svn_stringbuf_t *body,
+               const char *name,
+               const svn_string_t *value,
+               apr_pool_t *pool)
+{
+  const char *encoding;
+  const char *xml_safe;
+  const char *xml_tag_name;
+
+  /* Map property names to namespaces */
+#define NSLEN (sizeof(SVN_PROP_PREFIX) - 1)
+  if (strncmp(name, SVN_PROP_PREFIX, NSLEN) == 0)
+    {
+      xml_tag_name = apr_pstrcat(pool, "S:", name + NSLEN, NULL);
+    }
+#undef NSLEN
+  else
+    {
+      xml_tag_name = apr_pstrcat(pool, "C:", name, NULL);
+    }
+
+  SVN_ERR(get_encoding_and_cdata(&encoding, &xml_safe, value, pool));
+
   svn_stringbuf_appendcstr(body,
                            apr_psprintf(pool,"<%s %s>%s</%s>",
                                         xml_tag_name, encoding,
                                         xml_safe, xml_tag_name));
-  return;
+  return SVN_NO_ERROR;
 }
 
 
@@ -1124,7 +1141,7 @@ svn_ra_neon__do_proppatch(svn_ra_neon__s
           void *val;
           svn_pool_clear(subpool);
           apr_hash_this(hi, &key, NULL, &val);
-          append_setprop(body, key, val, subpool);
+          SVN_ERR(append_setprop(body, key, val, subpool));
         }
       svn_stringbuf_appendcstr(body, "</D:prop></D:set>");
     }
@@ -1138,7 +1155,7 @@ svn_ra_neon__do_proppatch(svn_ra_neon__s
         {
           const char *name = APR_ARRAY_IDX(prop_deletes, n, const char *);
           svn_pool_clear(subpool);
-          append_setprop(body, name, NULL, subpool);
+          SVN_ERR(append_setprop(body, name, NULL, subpool));
         }
       svn_stringbuf_appendcstr(body, "</D:prop></D:remove>");
     }

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_ra_serf/commit.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_ra_serf/commit.c Mon Aug  2 14:31:04 2010
@@ -633,6 +633,46 @@ checkout_file(file_context_t *file)
   return SVN_NO_ERROR;
 }
 
+/* Helper function for proppatch_walker() below. */
+static svn_error_t *
+get_encoding_and_cdata(const char **encoding_p,
+                       serf_bucket_t **cdata_bkt_p,
+                       serf_bucket_alloc_t *alloc,
+                       const svn_string_t *value,
+                       apr_pool_t *pool)
+{
+  const char *encoding;
+  const char *cdata;
+  apr_size_t len; /* of cdata */
+
+  SVN_ERR_ASSERT(value);
+
+  /* If a property is XML-safe, XML-encode it.  Else, base64-encode
+     it. */
+  if (svn_xml_is_xml_safe(value->data, value->len))
+    {
+      svn_stringbuf_t *xml_esc = NULL;
+      svn_xml_escape_cdata_string(&xml_esc, value, pool);
+      encoding = NULL;
+      cdata = xml_esc->data;
+      len = xml_esc->len;
+    }
+  else
+    {
+      const svn_string_t *base64ed = svn_base64_encode_string2(value, TRUE,
+                                                               pool);
+      encoding = "base64";
+      cdata = base64ed->data;
+      len = base64ed->len;
+    }
+
+  /* ENCODING, CDATA, and LEN are now set. */
+
+  *encoding_p = encoding;
+  *cdata_bkt_p = SERF_BUCKET_SIMPLE_STRING_LEN(cdata, len, alloc);
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *
 proppatch_walker(void *baton,
                  const char *ns, apr_ssize_t ns_len,
@@ -641,15 +681,11 @@ proppatch_walker(void *baton,
                  apr_pool_t *pool)
 {
   serf_bucket_t *body_bkt = baton;
+  serf_bucket_t *cdata_bkt;
   serf_bucket_alloc_t *alloc;
-  svn_boolean_t binary_prop;
+  const char *encoding;
   char *prop_name;
 
-  if (svn_xml_is_xml_safe(val->data, val->len))
-    binary_prop = FALSE;
-  else
-    binary_prop = TRUE;
-
   /* Use the namespace prefix instead of adding the xmlns attribute to support
      property names containing ':' */
   if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0)
@@ -660,24 +696,14 @@ proppatch_walker(void *baton,
 
   alloc = body_bkt->allocator;
 
+  SVN_ERR(get_encoding_and_cdata(&encoding, &cdata_bkt, alloc, val, pool));
+
   svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, prop_name,
-                                    "V:encoding", binary_prop ? "base64" : NULL,
+                                    "V:encoding", encoding,
                                     NULL);
-
-  if (binary_prop)
-    {
-      serf_bucket_t *tmp_bkt;
-      val = svn_base64_encode_string2(val, TRUE, pool);
-      tmp_bkt = SERF_BUCKET_SIMPLE_STRING_LEN(val->data, val->len, alloc);
-      serf_bucket_aggregate_append(body_bkt, tmp_bkt);
-    }
-  else
-    {
-      svn_ra_serf__add_cdata_len_buckets(body_bkt, alloc, val->data, val->len);
-    }
-
-
+  serf_bucket_aggregate_append(body_bkt, cdata_bkt);
   svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, prop_name);
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_subr/dirent_uri.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_subr/dirent_uri.c Mon Aug  2 14:31:04 2010
@@ -2254,21 +2254,42 @@ svn_uri_condense_targets(const char **pc
   return SVN_NO_ERROR;
 }
 
-svn_boolean_t
-svn_dirent_is_under_root(char **full_path,
+svn_error_t *
+svn_dirent_is_under_root(svn_boolean_t *under_root,
+                         const char **abspath,
                          const char *base_path,
                          const char *path,
                          apr_pool_t *pool)
 
 {
   apr_status_t status;
+  char *full_path;
+
+  *under_root = FALSE;
+  if (abspath)
+    *abspath = NULL;
+
+  status = apr_filepath_merge(&full_path,
+                              base_path,
+                              path,
+                              APR_FILEPATH_NOTABOVEROOT
+                              | APR_FILEPATH_SECUREROOTTEST,
+                              pool);
 
-  status = apr_filepath_merge(
-     full_path, base_path, path,
-     APR_FILEPATH_NOTABOVEROOT | APR_FILEPATH_SECUREROOTTEST,
-     pool);
+  if (status == APR_SUCCESS)
+    {
+      if (abspath)
+        *abspath = svn_dirent_canonicalize(full_path, pool);
+      *under_root = TRUE;
+      return SVN_NO_ERROR;
+    }
+  else if (status == APR_EABOVEROOT)
+    {
+      *under_root = FALSE;
+      return SVN_NO_ERROR;
+    }
 
-  return status == APR_SUCCESS ? TRUE : FALSE;
+  return svn_error_wrap_apr(status, NULL);
 }
 
 svn_error_t *

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_wc/adm_files.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_wc/adm_files.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_wc/adm_files.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_wc/adm_files.c Mon Aug  2 14:31:04 2010
@@ -648,6 +648,24 @@ svn_wc__internal_ensure_adm(svn_wc__db_t
                               "revision %ld in '%s'"),
                             revision, db_revision, local_abspath);
 
+      if (!db_repos_root_url)
+        {
+          if (status == svn_wc__db_status_added)
+            SVN_ERR(svn_wc__db_scan_addition(NULL, NULL,
+                                             &db_repos_relpath,
+                                             &db_repos_root_url,
+                                             &db_repos_uuid,
+                                             NULL, NULL, NULL, NULL,
+                                             db, local_abspath,
+                                             scratch_pool, scratch_pool));
+          else
+            SVN_ERR(svn_wc__db_scan_base_repos(&db_repos_relpath,
+                                               &db_repos_root_url,
+                                               &db_repos_uuid,
+                                               db, local_abspath,
+                                               scratch_pool, scratch_pool));
+        }
+
       /* The caller gives us a URL which should match the entry. However,
          some callers compensate for an old problem in entry->url and pass
          the copyfrom_url instead. See ^/notes/api-errata/wc002.txt. As

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_wc/adm_ops.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_wc/adm_ops.c Mon Aug  2 14:31:04 2010
@@ -1653,7 +1653,17 @@ revert_internal(svn_wc__db_t *db,
   else if (err)
     return svn_error_return(err);
   else
-    unversioned = FALSE;
+    switch (status)
+      {
+        case svn_wc__db_status_not_present:
+        case svn_wc__db_status_absent:
+        case svn_wc__db_status_excluded:
+          unversioned = TRUE;
+          break;
+        default:
+          unversioned = FALSE;
+          break;
+      }
 
   SVN_ERR(svn_wc__db_op_read_tree_conflict(&tree_conflict, db, local_abspath,
                                            pool, pool));
@@ -1666,9 +1676,13 @@ revert_internal(svn_wc__db_t *db,
   SVN_ERR(svn_io_check_path(local_abspath, &disk_kind, pool));
   if (!unversioned && (db_kind == svn_wc__db_kind_dir))
     {
+#ifndef SVN_WC__SINGLE_DB
       if ((disk_kind != svn_node_dir)
           && (status != svn_wc__db_status_added)
           && (status != svn_wc__db_status_obstructed_add))
+#else
+      if (disk_kind == svn_node_file)
+#endif
         {
           /* When the directory itself is missing, we can't revert without
              hitting the network.  Someday a '--force' option will
@@ -1687,7 +1701,9 @@ revert_internal(svn_wc__db_t *db,
 
   /* Safeguard 2:  can we handle this entry's recorded kind? */
   if (!unversioned
-      && (db_kind != svn_wc__db_kind_file) && (db_kind != svn_wc__db_kind_dir))
+      && (db_kind != svn_wc__db_kind_file)
+      && (db_kind != svn_wc__db_kind_dir)
+      && (db_kind != svn_wc__db_kind_symlink))
     return svn_error_createf
       (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
        _("Cannot revert '%s': unsupported entry node kind"),

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_wc/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_wc/deprecated.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_wc/deprecated.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_wc/deprecated.c Mon Aug  2 14:31:04 2010
@@ -2150,13 +2150,19 @@ svn_wc_prop_set3(const char *name,
 {
   svn_wc_context_t *wc_ctx;
   const char *local_abspath;
+  svn_error_t *err;
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
                                          svn_wc__adm_get_db(adm_access), pool));
 
-  SVN_ERR(svn_wc_prop_set4(wc_ctx, local_abspath, name, value, skip_checks,
-                           notify_func, notify_baton, pool));
+  err = svn_wc_prop_set4(wc_ctx, local_abspath, name, value, skip_checks,
+                         notify_func, notify_baton, pool);
+
+  if (err && err->apr_err == SVN_ERR_WC_INVALID_SCHEDULE)
+    svn_error_clear(err);
+  else
+    SVN_ERR(err);
 
   return svn_error_return(svn_wc_context_destroy(wc_ctx));
 }

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_wc/node.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_wc/node.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_wc/node.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_wc/node.c Mon Aug  2 14:31:04 2010
@@ -626,7 +626,7 @@ svn_wc__node_get_copyfrom_info(const cha
                                                         is_copy_target,
                                                         wc_ctx->db,
                                                         local_abspath,
-                                                        scratch_pool,
+                                                        result_pool,
                                                         scratch_pool));
 }
 

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_wc/update_editor.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_wc/update_editor.c Mon Aug  2 14:31:04 2010
@@ -1279,9 +1279,12 @@ check_path_under_root(const char *base_p
                       const char *add_path,
                       apr_pool_t *pool)
 {
-  char *full_path;
+  const char *full_path;
+  svn_boolean_t under_root;
 
-  if (! svn_dirent_is_under_root(&full_path, base_path, add_path, pool))
+  SVN_ERR(svn_dirent_is_under_root(&under_root, &full_path, base_path, add_path, pool));
+
+  if (! under_root)
     {
       return svn_error_createf(
           SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
@@ -3168,6 +3171,12 @@ close_directory(void *dir_baton,
       if (new_changed_author != NULL)
         changed_author = new_changed_author;
 
+#ifdef SINGLE_DB
+      /* If no depth is set yet, set to infinity. */
+      if (depth == svn_depth_unknown)
+        depth = svn_depth_infinity;
+#endif
+
       /* Do we have new properties to install? Or shall we simply retain
          the prior set of properties? If we're installing new properties,
          then we also want to write them to an old-style props file.  */

Modified: subversion/branches/issue-2779-dev/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/libsvn_wc/workqueue.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/branches/issue-2779-dev/subversion/libsvn_wc/workqueue.c Mon Aug  2 14:31:04 2010
@@ -293,6 +293,16 @@ run_revert(svn_wc__db_t *db,
     {
       SVN__NOT_IMPLEMENTED();
     }
+#ifdef SVN_WC__SINGLE_DB
+  else if (kind == svn_wc__db_kind_dir)
+    {
+      svn_node_kind_t disk_kind;
+      SVN_ERR(svn_io_check_path(local_abspath, &disk_kind, scratch_pool));
+
+      if (disk_kind == svn_node_none)
+        SVN_ERR(svn_io_dir_make(local_abspath, APR_OS_DEFAULT, scratch_pool));
+    }
+#endif
 
   if (kind == svn_wc__db_kind_dir)
     parent_abspath = local_abspath;

Propchange: subversion/branches/issue-2779-dev/subversion/svnrdump/dump_editor.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: subversion/branches/issue-2779-dev/subversion/svnrdump/dump_editor.h
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/issue-2779-dev/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/svnrdump/load_editor.c?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/issue-2779-dev/subversion/svnrdump/load_editor.c Mon Aug  2 14:31:04 2010
@@ -22,11 +22,14 @@
  * ====================================================================
  */
 
+#include "svn_dirent_uri.h"
+#include "svn_cmdline.h"
 #include "svn_pools.h"
 #include "svn_delta.h"
 #include "svn_repos.h"
+#include "svn_props.h"
 #include "svn_ra.h"
-#include "svn_cmdline.h"
+#include "svn_io.h"
 
 #include "load_editor.h"
 
@@ -35,50 +38,368 @@ commit_callback(const svn_commit_info_t 
                 void *baton,
                 apr_pool_t *pool)
 {
-  SVN_ERR(svn_cmdline_printf(pool, "r%ld committed by %s at %s\n",
-                             commit_info->revision,
-                             (commit_info->author
-                              ? commit_info->author : "(no author)"),
-                             commit_info->date));
+  SVN_ERR(svn_cmdline_printf(pool, "* Loaded revision %ld\n",
+                             commit_info->revision));
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+new_revision_record(void **revision_baton,
+		    apr_hash_t *headers,
+		    void *parse_baton,
+		    apr_pool_t *pool)
+{
+  struct revision_baton *rb;
+  struct parse_baton *pb;
+  apr_hash_index_t *hi;
+
+  rb = apr_pcalloc(pool, sizeof(*rb));
+  pb = parse_baton;
+  pb->pool = svn_pool_create(pool);
+  rb->pb = pb;
+
+  for (hi = apr_hash_first(pool, headers); hi; hi = apr_hash_next(hi))
+    {
+      const void *key;
+      void *val;
+      const char *hname, *hval;
+
+      apr_hash_this(hi, &key, NULL, &val);
+      hname = key;
+      hval = val;
+
+      if (strcmp(hname, SVN_REPOS_DUMPFILE_REVISION_NUMBER) == 0)
+        rb->rev = atoi(hval);
+    }
+  /* Set the commit_editor/ commit_edit_baton to NULL and wait for
+     them to be created in new_node_record */
+  
+  rb->pb->commit_editor = NULL;
+  rb->pb->commit_edit_baton = NULL;
+  rb->revprop_table = apr_hash_make(pb->pool);
+
+  *revision_baton = rb;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+uuid_record(const char *uuid,
+            void *parse_baton,
+            apr_pool_t *pool)
+{
+  struct parse_baton *pb;
+  pb = parse_baton;
+  pb->uuid = apr_pstrdup(pool, uuid);
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+new_node_record(void **node_baton,
+                apr_hash_t *headers,
+                void *revision_baton,
+                apr_pool_t *pool)
+{
+  struct node_baton *nb;
+  struct revision_baton *rb;
+  apr_hash_index_t *hi;
+  void *file_baton;
+  void *child_baton;
+  const struct svn_delta_editor_t *commit_editor;
+  void *commit_edit_baton;
+  struct commit_edit_baton *eb;
+  void *root_baton;
+
+  rb = revision_baton;
+  nb = apr_pcalloc(rb->pb->pool, sizeof(*nb));
+  nb->rb = rb;
+
+  nb->copyfrom_path = NULL;
+  nb->copyfrom_rev = SVN_INVALID_REVNUM;
+
+  commit_editor = rb->pb->commit_editor;
+  commit_edit_baton = rb->pb->commit_edit_baton;
+
+  /* If the creation of commit_editor is pending, create it now and
+     open_root on it */
+  if (!commit_editor) {
+      SVN_ERR(svn_ra_get_commit_editor3(rb->pb->session, &commit_editor,
+                                        &commit_edit_baton, rb->revprop_table,
+                                        commit_callback, NULL, NULL, FALSE,
+                                        rb->pb->pool));
+
+      rb->pb->commit_editor = commit_editor;
+      rb->pb->commit_edit_baton = commit_edit_baton;
+
+      SVN_ERR(commit_editor->open_root(commit_edit_baton, rb->rev - 1,
+                                       rb->pb->pool, &root_baton));
+      rb->dir_baton = root_baton;
+
+  }
+
+  for (hi = apr_hash_first(rb->pb->pool, headers); hi; hi = apr_hash_next(hi))
+    {
+      const void *key;
+      void *val;
+      const char *hname, *hval;
+
+      apr_hash_this(hi, &key, NULL, &val);
+      hname = key;
+      hval = val;
+
+      /* Parse the different kinds of headers we can encounter and
+         stuff them into the node_baton for writing later */
+      if (strcmp(hname, SVN_REPOS_DUMPFILE_NODE_PATH) == 0)
+        nb->path = apr_pstrdup(rb->pb->pool, hval);
+      if (strcmp(hname, SVN_REPOS_DUMPFILE_NODE_KIND) == 0)
+        nb->kind = strcmp(hval, "file") == 0 ? svn_node_file : svn_node_dir;
+      if (strcmp(hname, SVN_REPOS_DUMPFILE_NODE_ACTION) == 0)
+        {
+          if (strcmp(hval, "add") == 0)
+            nb->action = svn_node_action_add;
+          if (strcmp(hval, "change") == 0)
+            nb->action = svn_node_action_change;
+          if (strcmp(hval, "delete") == 0)
+            nb->action = svn_node_action_delete;
+          if (strcmp(hval, "replace") == 0)
+            nb->action = svn_node_action_replace;
+        }
+      if (strcmp(hname, SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV) == 0)
+        nb->copyfrom_rev = atoi(hval);
+      if (strcmp(hname, SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH) == 0)
+        {
+          /* Due to a historical detail in the commit editor, it
+             demands that the copyfrom_path includes the URI to the
+             repository; to implement this, the edit_baton structure
+             from commit.c had to be imported as a commit_edit_baton
+             structure in load_editor.h */
+          eb = commit_edit_baton;
+          nb->copyfrom_path = svn_uri_join(eb->repos_url,
+                                           apr_pstrdup(rb->pb->pool, hval),
+                                           rb->pb->pool);
+        }
+    }
+
+  switch (nb->action)
+    {
+    case svn_node_action_add:
+      if (nb->kind == svn_node_file)
+        {
+          SVN_ERR(commit_editor->add_file(nb->path, nb->rb->dir_baton,
+                                          nb->copyfrom_path, nb->copyfrom_rev,
+                                          rb->pb->pool, &file_baton));
+          nb->file_baton = file_baton;
+        }
+      else if(nb->kind == svn_node_dir)
+        {
+          SVN_ERR(commit_editor->add_directory(nb->path, nb->rb->dir_baton,
+                                               nb->copyfrom_path, nb->copyfrom_rev,
+                                               rb->pb->pool, &child_baton));
+          nb->rb->dir_baton = child_baton;
+        }
+      break;
+    default:
+      break;
+    }
+
+  *node_baton = nb;
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+set_revision_property(void *baton,
+                      const char *name,
+                      const svn_string_t *value)
+{
+  struct revision_baton *rb;
+  rb = baton;
+
+  if (rb->rev > 0)
+    {
+      apr_hash_set(rb->revprop_table, apr_pstrdup(rb->pb->pool, name),
+                   APR_HASH_KEY_STRING, svn_string_dup(value, rb->pb->pool));
+    }
+  else
+    /* Special handling for revision 0; this is safe because the
+       commit_editor hasn't been created yet. */
+    svn_ra_change_rev_prop(rb->pb->session, rb->rev, name, value,
+                           rb->pb->pool);
+
+  /* Remember any datestamp/ author that passes through (see comment
+     in close_revision). */
+  if (!strcmp(name, SVN_PROP_REVISION_DATE))
+    rb->datestamp = svn_string_dup(value, rb->pb->pool);
+  if (!strcmp(name, SVN_PROP_REVISION_AUTHOR))
+    rb->author = svn_string_dup(value, rb->pb->pool);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+set_node_property(void *baton,
+                  const char *name,
+                  const svn_string_t *value)
+{
+  struct node_baton *nb;
+  const struct svn_delta_editor_t *commit_editor;
+  apr_pool_t *pool;
+  nb = baton;
+  commit_editor = nb->rb->pb->commit_editor;
+  pool = nb->rb->pb->pool;
+
+  if (nb->kind == svn_node_file)
+    SVN_ERR(commit_editor->change_file_prop(nb->file_baton, name,
+                                            value, pool));
+  else
+    SVN_ERR(commit_editor->change_dir_prop(nb->rb->dir_baton, name,
+                                           value, pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+delete_node_property(void *baton,
+                     const char *name)
+{
+  struct node_baton *nb;
+  const struct svn_delta_editor_t *commit_editor;
+  apr_pool_t *pool;
+  nb = baton;
+  commit_editor = nb->rb->pb->commit_editor;
+  pool = nb->rb->pb->pool;
+
+  if (nb->kind == svn_node_file)
+    SVN_ERR(commit_editor->change_file_prop(nb->file_baton, name,
+                                            NULL, pool));
+  else
+    SVN_ERR(commit_editor->change_dir_prop(nb->rb->dir_baton, name,
+                                           NULL, pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+remove_node_props(void *baton)
+{
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+set_fulltext(svn_stream_t **stream,
+             void *node_baton)
+{
+  /* ### Not implemented */
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+apply_textdelta(svn_txdelta_window_handler_t *handler,
+                void **handler_baton,
+                void *node_baton)
+{
+  struct node_baton *nb;
+  const struct svn_delta_editor_t *commit_editor;
+  apr_pool_t *pool;
+  nb = node_baton;
+  commit_editor = nb->rb->pb->commit_editor;
+  pool = nb->rb->pb->pool;
+  return commit_editor->apply_textdelta(nb->file_baton, NULL, pool,
+                                        handler, handler_baton);
+}
+
+static svn_error_t *
+close_node(void *baton)
+{
+  struct node_baton *nb;
+  const struct svn_delta_editor_t *commit_editor;
+  apr_pool_t * pool;
+  nb = baton;
+  pool = nb->rb->pb->pool;
+  commit_editor = nb->rb->pb->commit_editor;
+  if (nb->kind == svn_node_file)
+    SVN_ERR(commit_editor->close_file(nb->file_baton, NULL,
+                                      pool));
+  else if (nb->kind == svn_node_dir)
+    SVN_ERR(commit_editor->close_directory(nb->rb->dir_baton,
+                                           pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+close_revision(void *baton)
+{
+  struct revision_baton *rb;
+  const svn_delta_editor_t *commit_editor;
+  void *commit_edit_baton;
+  rb = baton;
+
+  commit_editor = rb->pb->commit_editor;
+  commit_edit_baton = rb->pb->commit_edit_baton;
+
+  /* r0 doesn't have a corresponding commit_editor; we fake it */
+  if (rb->rev == 0)
+    SVN_ERR(svn_cmdline_printf(rb->pb->pool, "* Loaded revision 0\n"));
+  else
+    SVN_ERR(commit_editor->close_edit(commit_edit_baton, rb->pb->pool));
+
+  /* svn_fs_commit_txn rewrites the datestamp/ author property-
+     rewrite it by hand after closing the commit_editor. */
+  SVN_ERR(svn_ra_change_rev_prop(rb->pb->session, rb->rev,
+                                 SVN_PROP_REVISION_DATE,
+                                 rb->datestamp, rb->pb->pool));
+  SVN_ERR(svn_ra_change_rev_prop(rb->pb->session, rb->rev,
+                                 SVN_PROP_REVISION_AUTHOR,
+                                 rb->author, rb->pb->pool));
+
+  svn_pool_destroy(rb->pb->pool);
+
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
-drive_load_editor(const svn_delta_editor_t *editor,
-                  void *edit_baton,
-                  svn_stream_t *stream,
-                  apr_pool_t *pool)
+get_dumpstream_loader(const svn_repos_parse_fns2_t **parser,
+                      void **parse_baton,
+                      svn_ra_session_t *session,
+                      apr_pool_t *pool)
 {
-  const svn_repos_parse_fns2_t *parser;
-  void *pb;
+  svn_repos_parse_fns2_t *pf;
+  struct parse_baton *pb;
 
-  SVN_ERR(build_dumpfile_parser(&parser, &pb, editor, edit_baton, pool));
-  SVN_ERR(svn_repos_parse_dumpstream2(stream, parser, pb,
-                                      NULL, NULL, pool));
+  pf = apr_pcalloc(pool, sizeof(*pf));
+  pf->new_revision_record = new_revision_record;
+  pf->uuid_record = uuid_record;
+  pf->new_node_record = new_node_record;
+  pf->set_revision_property = set_revision_property;
+  pf->set_node_property = set_node_property;
+  pf->delete_node_property = delete_node_property;
+  pf->remove_node_props = remove_node_props;
+  pf->set_fulltext = set_fulltext;
+  pf->apply_textdelta = apply_textdelta;
+  pf->close_node = close_node;
+  pf->close_revision = close_revision;
+
+  pb = apr_pcalloc(pool, sizeof(*pb));
+  pb->session = session;
+
+  *parser = pf;
+  *parse_baton = pb;
 
   return SVN_NO_ERROR;
 }
 
-/* The load editor is a essentially a dumpfile parser connected to a
-   commit editor. It can be driven using drive_load_editor(). */
 svn_error_t *
-get_load_editor(const svn_delta_editor_t **editor,
-                void **edit_baton,
-                svn_ra_session_t *session,
-                apr_pool_t *pool)
+drive_dumpstream_loader(svn_stream_t *stream,
+                        const svn_repos_parse_fns2_t *parser,
+                        void *parse_baton,
+                        svn_ra_session_t *session,
+                        apr_pool_t *pool)
 {
-  const svn_delta_editor_t *delta_editor;
-  apr_hash_t *revprop_table;
-  void *delta_edit_baton;
-
-  revprop_table = apr_hash_make(pool);
- 
-  /* Call the commit editor and get back a delta_editor and delta_editor_baton */
-  SVN_ERR(svn_ra_get_commit_editor3(session, &delta_editor, &delta_edit_baton,
-                                    revprop_table, commit_callback,
-                                    NULL, NULL, FALSE, pool));
-  *editor = delta_editor;
-  *edit_baton = delta_edit_baton;
+  void *pb;
+  pb = parse_baton;
+
+  SVN_ERR(svn_repos_parse_dumpstream2(stream, parser,parse_baton,
+                                      NULL, NULL, pool));
 
   return SVN_NO_ERROR;
 }

Propchange: subversion/branches/issue-2779-dev/subversion/svnrdump/load_editor.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/issue-2779-dev/subversion/svnrdump/load_editor.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-2779-dev/subversion/svnrdump/load_editor.h?rev=981523&r1=981522&r2=981523&view=diff
==============================================================================
--- subversion/branches/issue-2779-dev/subversion/svnrdump/load_editor.h (original)
+++ subversion/branches/issue-2779-dev/subversion/svnrdump/load_editor.h Mon Aug  2 14:31:04 2010
@@ -35,6 +35,8 @@ struct parse_baton
 {
   const svn_delta_editor_t *commit_editor;
   void *commit_edit_baton;
+  svn_ra_session_t *session;
+  const char *uuid;
   apr_pool_t *pool;
 };
 
@@ -62,8 +64,10 @@ struct node_baton
 struct revision_baton
 {
   svn_revnum_t rev;
+  apr_hash_t *revprop_table;
 
   const svn_string_t *datestamp;
+  const svn_string_t *author;
 
   struct parse_baton *pb;
   apr_pool_t *pool;
@@ -71,17 +75,81 @@ struct revision_baton
 };
 
 /**
- * Build up a @a parser for parsing a dumpfile stream from @a stream
+ * Imported from commit.c
+ * (see comment in new_node_record in load_editor.h)
+ */
+struct commit_edit_baton
+{
+  apr_pool_t *pool;
+
+  /** Supplied when the editor is created: **/
+
+  /* Revision properties to set for this commit. */
+  apr_hash_t *revprop_table;
+
+  /* Callback to run when the commit is done. */
+  svn_commit_callback2_t commit_callback;
+  void *commit_callback_baton;
+
+  /* Callback to check authorizations on paths. */
+  svn_repos_authz_callback_t authz_callback;
+  void *authz_baton;
+
+  /* The already-open svn repository to commit to. */
+  svn_repos_t *repos;
+
+  /* URL to the root of the open repository. */
+  const char *repos_url;
+
+  /* The name of the repository (here for convenience). */
+  const char *repos_name;
+
+  /* The filesystem associated with the REPOS above (here for
+     convenience). */
+  svn_fs_t *fs;
+
+  /* Location in fs where the edit will begin. */
+  const char *base_path;
+
+  /* Does this set of interfaces 'own' the commit transaction? */
+  svn_boolean_t txn_owner;
+
+  /* svn transaction associated with this edit (created in
+     open_root, or supplied by the public API caller). */
+  svn_fs_txn_t *txn;
+
+  /** Filled in during open_root: **/
+
+  /* The name of the transaction. */
+  const char *txn_name;
+
+  /* The object representing the root directory of the svn txn. */
+  svn_fs_root_t *txn_root;
+
+  /** Filled in when the edit is closed: **/
+
+  /* The new revision created by this commit. */
+  svn_revnum_t *new_rev;
+
+  /* The date (according to the repository) of this commit. */
+  const char **committed_date;
+
+  /* The author (also according to the repository) of this commit. */
+  const char **committed_author;
+};
+
+
+/**
+ * Build up a load editor @a parser for parsing a dumpfile stream from @a stream
  * set to fire the appropriate callbacks in load editor along with a
  * @a parser_baton, using @a pool for all memory allocations. The
  * @a editor/ @a edit_baton are central to the functionality of the
  *  parser.
  */
 svn_error_t *
-build_dumpfile_parser(const svn_repos_parse_fns2_t **parser,
+get_dumpstream_loader(const svn_repos_parse_fns2_t **parser,
                       void **parse_baton,
-                      const struct svn_delta_editor_t *editor,
-                      void *edit_baton,
+                      svn_ra_session_t *session,
                       apr_pool_t *pool);
 
 /**
@@ -89,20 +157,10 @@ build_dumpfile_parser(const svn_repos_pa
  * @a pool for all memory allocations.
  */
 svn_error_t *
-drive_load_editor(const svn_delta_editor_t *editor,
-                  void *edit_baton,
-                  svn_stream_t *stream,
-                  apr_pool_t *pool);
-
-/**
- * Get a load editor @a editor along with an @a edit_baton allocated
- * in @a pool. The load editor will commit revisions to @a session
- * when driven using drive_load_editor().
- */
-svn_error_t *
-get_load_editor(const svn_delta_editor_t **editor,
-                void **edit_baton,
-                svn_ra_session_t *session,
-                apr_pool_t *pool);
+drive_dumpstream_loader(svn_stream_t *stream,
+                        const svn_repos_parse_fns2_t *parser,
+                        void *parse_baton,
+                        svn_ra_session_t *session,
+                        apr_pool_t *pool);
 
 #endif

Propchange: subversion/branches/issue-2779-dev/subversion/svnrdump/load_editor.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: subversion/branches/issue-2779-dev/subversion/svnrdump/svnrdump.1
------------------------------------------------------------------------------
    svn:eol-style = native