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

svn commit: r1533871 [1/2] - in /subversion/branches/invoke-diff-cmd-feature: ./ build/win32/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ca...

Author: gbg
Date: Sun Oct 20 10:11:04 2013
New Revision: 1533871

URL: http://svn.apache.org/r1533871
Log:
On the invoke-diff-cmd branch: merge of r1526469 through r1533866.                                         

Added:
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_TunnelChannel.cpp
      - copied unchanged from r1533866, subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_TunnelChannel.cpp
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/TunnelAgent.java
      - copied unchanged from r1533866, subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/TunnelAgent.java
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/RequestChannel.java
      - copied unchanged from r1533866, subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/RequestChannel.java
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ResponseChannel.java
      - copied unchanged from r1533866, subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ResponseChannel.java
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/TunnelChannel.java
      - copied unchanged from r1533866, subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/TunnelChannel.java
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/config_pool.c
      - copied unchanged from r1533866, subversion/trunk/subversion/libsvn_repos/config_pool.c
    subversion/branches/invoke-diff-cmd-feature/tools/client-side/svn-bench/null-info-cmd.c
      - copied unchanged from r1533866, subversion/trunk/tools/client-side/svn-bench/null-info-cmd.c
Removed:
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIThreadData.cpp
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIThreadData.h
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/libsvnjavahl.la.c
Modified:
    subversion/branches/invoke-diff-cmd-feature/   (props changed)
    subversion/branches/invoke-diff-cmd-feature/build.conf
    subversion/branches/invoke-diff-cmd-feature/build/win32/svn.rc
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/ClientContext.cpp
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/ClientContext.h
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/GlobalConfig.h   (props changed)
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIByteArray.cpp
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIByteArray.h
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIStackElement.cpp
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIStackElement.h
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIUtil.cpp
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIUtil.h
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/OperationContext.cpp
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/OperationContext.h
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSession.cpp
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSession.h
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSessionContext.cpp
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSessionContext.h
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/SVNClient.cpp
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigLib.cpp   (props changed)
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
    subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java
    subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_repos_private.h
    subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_subr_private.h
    subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_client.h
    subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_io.h
    subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_ra.h
    subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_types.h
    subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_version.h
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/list.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/merge.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/ra.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/cached_data.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/transaction.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/tree.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_ra_svn/client.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_ra_svn/marshal.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/authz.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/dump.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/config.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/config_file.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/config_impl.h
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/file.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/prefix_string.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/root_pools.c   (props changed)
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/stream.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/string.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/time.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/win32_crashrpt.c
    subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db.c
    subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/logger.c   (props changed)
    subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/logger.h   (props changed)
    subversion/branches/invoke-diff-cmd-feature/subversion/tests/libsvn_ra/ra-test.c
    subversion/branches/invoke-diff-cmd-feature/subversion/tests/libsvn_subr/root-pools-test.c   (props changed)
    subversion/branches/invoke-diff-cmd-feature/subversion/tests/libsvn_subr/stream-test.c
    subversion/branches/invoke-diff-cmd-feature/subversion/tests/libsvn_wc/op-depth-test.c
    subversion/branches/invoke-diff-cmd-feature/tools/client-side/svn-bench/cl.h
    subversion/branches/invoke-diff-cmd-feature/tools/client-side/svn-bench/null-log-cmd.c
    subversion/branches/invoke-diff-cmd-feature/tools/client-side/svn-bench/svn-bench.c

Propchange: subversion/branches/invoke-diff-cmd-feature/
------------------------------------------------------------------------------
  Merged /subversion/trunk:r1531701-1533866

Modified: subversion/branches/invoke-diff-cmd-feature/build.conf
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/build.conf?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/build.conf (original)
+++ subversion/branches/invoke-diff-cmd-feature/build.conf Sun Oct 20 10:11:04 2013
@@ -79,6 +79,9 @@ private-built-includes =
         subversion/bindings/javahl/include/org_apache_subversion_javahl_util_ConfigImpl_Category.h
         subversion/bindings/javahl/include/org_apache_subversion_javahl_util_ConfigLib.h
         subversion/bindings/javahl/include/org_apache_subversion_javahl_util_DiffLib.h
+        subversion/bindings/javahl/include/org_apache_subversion_javahl_util_TunnelChannel.h
+        subversion/bindings/javahl/include/org_apache_subversion_javahl_util_RequestChannel.h
+        subversion/bindings/javahl/include/org_apache_subversion_javahl_util_ResponseChannel.h
 
 test-scripts =
         subversion/tests/cmdline/*_tests.py
@@ -683,7 +686,7 @@ type = lib
 path = subversion/bindings/javahl/native
 libs = libsvn_repos libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_diff 
        libsvn_subr libsvn_fs aprutil apriconv apr java-sdk
-sources = *.cpp *.c
+sources = *.cpp
 add-deps = $(javahl_java_DEPS) $(javahl_callback_javah_DEPS)
            $(javahl_remote_javah_DEPS) $(javahl_types_javah_DEPS)
            $(javahl_util_javah_DEPS) $(javahl_javah_DEPS)

Modified: subversion/branches/invoke-diff-cmd-feature/build/win32/svn.rc
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/build/win32/svn.rc?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/build/win32/svn.rc (original)
+++ subversion/branches/invoke-diff-cmd-feature/build/win32/svn.rc Sun Oct 20 10:11:04 2013
@@ -25,9 +25,17 @@
 #endif
 
 #include <winresrc.h>
-#include <apr_general.h>
+
+#define SVN_WIN32_RESOURCE_COMPILATION
 #include "../../subversion/include/svn_version.h"
 
+#ifndef APR_STRINGIFY
+/** Properly quote a value as a string in the C preprocessor */
+#define APR_STRINGIFY(n) APR_STRINGIFY_HELPER(n)
+/** Helper macro for APR_STRINGIFY */
+#define APR_STRINGIFY_HELPER(n) #n
+#endif
+
 #ifndef _DEBUG
 # if SVN_VER_REVISION == 0
 #  define SVN_FILEFLAGS VS_FF_PRERELEASE

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/ClientContext.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/ClientContext.cpp?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/ClientContext.cpp (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/ClientContext.cpp Sun Oct 20 10:11:04 2013
@@ -70,12 +70,38 @@ ClientContext::ClientContext(jobject jsv
     m_context->conflict_baton2 = m_jctx;
 
     m_context->client_name = getClientName();
+
+    if (m_jtunnelcb)
+      {
+        m_context->check_tunnel_func = checkTunnel;
+        m_context->open_tunnel_func = openTunnel;
+        m_context->close_tunnel_func = closeTunnel;
+        m_context->tunnel_baton = m_jtunnelcb;
+      }
 }
 
 ClientContext::~ClientContext()
 {
 }
 
+void ClientContext::setTunnelCallback(jobject jtunnelcb)
+{
+  OperationContext::setTunnelCallback(jtunnelcb);
+  if (m_jtunnelcb)
+    {
+      m_context->check_tunnel_func = checkTunnel;
+      m_context->open_tunnel_func = openTunnel;
+      m_context->close_tunnel_func = closeTunnel;
+      m_context->tunnel_baton = m_jtunnelcb;
+    }
+  else
+    {
+      m_context->check_tunnel_func = NULL;
+      m_context->open_tunnel_func = NULL;
+      m_context->close_tunnel_func = NULL;
+      m_context->tunnel_baton = NULL;
+    }
+}
 
 /* Helper function to make sure that we don't keep dangling pointers in ctx.
    Note that this function might be called multiple times if getContext()

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/ClientContext.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/ClientContext.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/ClientContext.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/ClientContext.h Sun Oct 20 10:11:04 2013
@@ -64,6 +64,7 @@ class ClientContext : public OperationCo
  public:
   ClientContext(jobject jsvnclient, SVN::Pool &pool);
   virtual ~ClientContext();
+  virtual void setTunnelCallback(jobject jtunnelcb);
 
   svn_client_ctx_t *getContext(CommitMessage *message, SVN::Pool &in_pool);
 };

Propchange: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/GlobalConfig.h
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIByteArray.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIByteArray.cpp?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIByteArray.cpp (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIByteArray.cpp Sun Oct 20 10:11:04 2013
@@ -32,30 +32,24 @@
  * @param flag that the underlying byte array reference should be deleted at
  *        destruction
  */
-JNIByteArray::JNIByteArray(jbyteArray jba, bool deleteByteArray)
-{
-  m_array = jba;
-  m_deleteByteArray = deleteByteArray;
-  if (jba != NULL)
-    {
-      // Get the bytes.
-      JNIEnv *env = JNIUtil::getEnv();
-      m_data = env->GetByteArrayElements(jba, NULL);
-    }
-  else
-    {
-      m_data = NULL;
-    }
-}
+JNIByteArray::JNIByteArray(jbyteArray jba,
+                           bool deleteByteArray,
+                           bool abortOnRelease)
+  : m_array(jba),
+    m_data(!jba ? NULL
+           : JNIUtil::getEnv()->GetByteArrayElements(jba, NULL)),
+    m_deleteByteArray(deleteByteArray),
+    m_abortOnRelease(abortOnRelease)
+{}
 
 JNIByteArray::~JNIByteArray()
 {
   if (m_array != NULL)
     {
       // Release the bytes
-      JNIUtil::getEnv()->ReleaseByteArrayElements(m_array,
-                                                  m_data,
-                                                  JNI_ABORT);
+      JNIUtil::getEnv()->ReleaseByteArrayElements(
+          m_array, m_data,
+          (m_abortOnRelease ? JNI_ABORT: JNI_COMMIT));
       if (m_deleteByteArray)
         // And if needed the byte array.
         JNIUtil::getEnv()->DeleteLocalRef(m_array);

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIByteArray.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIByteArray.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIByteArray.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIByteArray.h Sun Oct 20 10:11:04 2013
@@ -51,11 +51,18 @@ class JNIByteArray
    * at destruction.
    */
   bool m_deleteByteArray;
+
+  /**
+   * False if changes to the array should be committed to the Java VM.
+   */
+  bool m_abortOnRelease;
  public:
   bool isNull() const;
   const signed char *getBytes() const;
   int getLength();
-  JNIByteArray(jbyteArray jba, bool deleteByteArray = false);
+  JNIByteArray(jbyteArray jba,
+               bool deleteByteArray = false,
+               bool abortOnRelease = true);
   ~JNIByteArray();
 };
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIStackElement.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIStackElement.cpp?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIStackElement.cpp (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIStackElement.cpp Sun Oct 20 10:11:04 2013
@@ -27,7 +27,6 @@
 #include "JNIStackElement.h"
 #include "JNIUtil.h"
 #include "JNIStringHolder.h"
-#include "JNIThreadData.h"
 #include <apr_strings.h>
 
 /**
@@ -74,7 +73,7 @@ JNIStackElement::JNIStackElement(JNIEnv 
 
           // Copy the result to a buffer.
           JNIStringHolder name(reinterpret_cast<jstring>(oStr));
-          strncat(m_objectID, name, JNIUtil::formatBufferSize -1);
+          strncat(m_objectID, name, sizeof(m_objectID) - 1);
           env->DeleteLocalRef(oStr);
         }
 
@@ -86,8 +85,8 @@ JNIStackElement::JNIStackElement(JNIEnv 
       m_method = method;
 
       // Generate the log message.
-      char *buffer = JNIUtil::getFormatBuffer();
-      apr_snprintf(buffer, JNIUtil::formatBufferSize,
+      char buffer[2048];
+      apr_snprintf(buffer, sizeof(buffer),
                    "entry class %s method %s object %s", m_clazz, m_method,
                    m_objectID);
       JNIUtil::logMessage(buffer);
@@ -110,11 +109,10 @@ JNIStackElement::~JNIStackElement()
   if (m_clazz != NULL)
     {
       // Generate a log message.
-      char *buffer = JNIUtil::getFormatBuffer();
-      apr_snprintf(buffer, JNIUtil::formatBufferSize,
+      char buffer[2048];
+      apr_snprintf(buffer, sizeof(buffer),
                    "exit class %s method %s object %s", m_clazz,
                    m_method, m_objectID);
       JNIUtil::logMessage(buffer);
     }
-  JNIThreadData::popThreadData();
 }

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIStackElement.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIStackElement.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIStackElement.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIStackElement.h Sun Oct 20 10:11:04 2013
@@ -73,7 +73,7 @@ class JNIStackElement
    * A buffer for the result for jthis.toString to identify the
    * object.
    */
-  char m_objectID[JNIUtil::formatBufferSize];
+  char m_objectID[2048];
 };
 
 #endif // JNISTACKELEMENT_H

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIUtil.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIUtil.cpp?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIUtil.cpp (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIUtil.cpp Sun Oct 20 10:11:04 2013
@@ -68,10 +68,10 @@ extern "C" {
 #include "SVNBase.h"
 #include "JNIMutex.h"
 #include "JNICriticalSection.h"
-#include "JNIThreadData.h"
 #include "JNIStringHolder.h"
 #include "Pool.h"
 
+
 // Static members of JNIUtil are allocated here.
 apr_pool_t *JNIUtil::g_pool = NULL;
 std::list<SVNBase*> JNIUtil::g_finalizedObjects;
@@ -81,10 +81,39 @@ JNIMutex *JNIUtil::g_configMutex = NULL;
 bool JNIUtil::g_initException;
 bool JNIUtil::g_inInit;
 JNIEnv *JNIUtil::g_initEnv;
-char JNIUtil::g_initFormatBuffer[formatBufferSize];
 int JNIUtil::g_logLevel = JNIUtil::noLog;
 std::ofstream JNIUtil::g_logStream;
 
+namespace {
+JavaVM *g_jvm = NULL;
+} // anonymous namespace
+
+extern "C" JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM *jvm, void*)
+{
+  g_jvm = jvm;
+  return JNI_VERSION_1_2;
+}
+
+extern "C" JNIEXPORT void JNICALL
+JNI_OnUnload(JavaVM*, void*)
+{}
+
+/**
+ * Return the JNI environment to use
+ * @return the JNI environment
+ */
+JNIEnv *JNIUtil::getEnv()
+{
+  // During init -> look into the global variable.
+  if (g_inInit)
+    return g_initEnv;
+
+  void* penv;
+  g_jvm->GetEnv(&penv, JNI_VERSION_1_2);
+  return static_cast<JNIEnv*>(penv);
+}
+
 /**
  * Initialize the environment for all requests.
  * @param env   the JNI environment for this request
@@ -94,9 +123,6 @@ bool JNIUtil::JNIInit(JNIEnv *env)
   // Clear all standing exceptions.
   env->ExceptionClear();
 
-  // Remember the env parameter for the remainder of the request.
-  setEnv(env);
-
   // Lock the list of finalized objects.
   JNICriticalSection cs(*g_finalizedObjectsMutex) ;
   if (isExceptionThrown())
@@ -361,14 +387,6 @@ bool JNIUtil::JNIGlobalInit(JNIEnv *env)
   if (isExceptionThrown())
     return false;
 
-  // initialized the thread local storage
-  if (!JNIThreadData::initThreadData())
-    return false;
-
-  setEnv(env);
-  if (isExceptionThrown())
-    return false;
-
   g_initEnv = NULL;
   g_inInit = false;
 
@@ -399,8 +417,6 @@ void JNIUtil::raiseThrowable(const char 
     return;
 
   env->ThrowNew(clazz, message);
-  setExceptionThrown();
-  env->DeleteLocalRef(clazz);
 }
 
 void
@@ -662,7 +678,7 @@ std::string JNIUtil::makeSVNErrorMessage
   return buffer;
 }
 
-void JNIUtil::handleSVNError(svn_error_t *err)
+void JNIUtil::wrappedHandleSVNError(svn_error_t *err)
 {
   jstring jmessage;
   jobject jstack;
@@ -793,7 +809,16 @@ void JNIUtil::handleSVNError(svn_error_t
 #endif
 
   env->Throw(static_cast<jthrowable>(env->PopLocalFrame(nativeException)));
+}
 
+void JNIUtil::handleSVNError(svn_error_t *err)
+{
+  try {
+    wrappedHandleSVNError(err);
+  } catch (...) {
+    svn_error_clear(err);
+    throw;
+  }
   svn_error_clear(err);
 }
 
@@ -816,100 +841,55 @@ void JNIUtil::enqueueForDeletion(SVNBase
  */
 void JNIUtil::handleAPRError(int error, const char *op)
 {
-  char *buffer = getFormatBuffer();
-  if (buffer == NULL)
-    return;
+  char buffer[2048];
 
-  apr_snprintf(buffer, formatBufferSize,
+  apr_snprintf(buffer, sizeof(buffer),
                _("an error occurred in function %s with return value %d"),
                op, error);
 
   throwError(buffer);
 }
 
-/**
- * Return if an exception has been detected.
- * @return a exception has been detected
- */
-bool JNIUtil::isExceptionThrown()
-{
-  // During init -> look in the global member.
-  if (g_inInit)
-    return g_initException;
-
-  // Look in the thread local storage.
-  JNIThreadData *data = JNIThreadData::getThreadData();
-  return data == NULL || data->m_exceptionThrown;
-}
-
-/**
- * Store the JNI environment for this request in the thread local
- * storage.
- * @param env   the JNI environment
- */
-void JNIUtil::setEnv(JNIEnv *env)
+namespace {
+const char* known_exception_to_cstring(apr_pool_t* pool)
 {
-  JNIThreadData::pushNewThreadData();
-  JNIThreadData *data = JNIThreadData::getThreadData();
-  data->m_env = env;
-  data->m_exceptionThrown = false;
-}
+  JNIEnv *env = JNIUtil::getEnv();
+  jthrowable t = env->ExceptionOccurred();
+  jclass cls = env->GetObjectClass(t);
 
-/**
- * Return the JNI environment to use
- * @return the JNI environment
- */
-JNIEnv *JNIUtil::getEnv()
-{
-  // During init -> look into the global variable.
-  if (g_inInit)
-    return g_initEnv;
+  jstring jclass_name;
+  {
+    jmethodID mid = env->GetMethodID(cls, "getClass", "()Ljava/lang/Class;");
+    jobject clsobj = env->CallObjectMethod(t, mid);
+    jclass basecls = env->GetObjectClass(clsobj);
+    mid = env->GetMethodID(basecls, "getName", "()Ljava/lang/String;");
+    jclass_name = (jstring) env->CallObjectMethod(clsobj, mid);
+  }
 
-  // Look in the thread local storage.
-  JNIThreadData *data = JNIThreadData::getThreadData();
-  return data->m_env;
-}
+  jstring jmessage;
+  {
+    jmethodID mid = env->GetMethodID(cls, "getMessage",
+                                     "()Ljava/lang/String;");
+    jmessage = (jstring) env->CallObjectMethod(t, mid);
+  }
 
-/**
- * Check if a Java exception has been thrown.
- * @return is a Java exception has been thrown
- */
-bool JNIUtil::isJavaExceptionThrown()
-{
-  JNIEnv *env = getEnv();
-  if (env->ExceptionCheck())
+  JNIStringHolder class_name(jclass_name);
+  if (jmessage)
     {
-      // Retrieving the exception removes it so we rethrow it here.
-      jthrowable exp = env->ExceptionOccurred();
-      env->ExceptionDescribe();
-      env->Throw(exp);
-      env->DeleteLocalRef(exp);
-      setExceptionThrown();
-      return true;
+      JNIStringHolder message(jmessage);
+      return apr_pstrcat(pool, class_name.c_str(), ": ", message.c_str(), NULL);
     }
-  return false;
+  else
+    return class_name.pstrdup(pool);
+  // ### Conditionally add t.printStackTrace() to msg?
 }
 
-namespace {
 const char* exception_to_cstring(apr_pool_t* pool)
 {
   const char *msg;
-  JNIEnv *env = JNIUtil::getEnv();
-  if (env->ExceptionCheck())
+  if (JNIUtil::getEnv()->ExceptionCheck())
     {
-      jthrowable t = env->ExceptionOccurred();
-      static jmethodID getMessage = 0;
-      if (getMessage == 0)
-        {
-          jclass clazz = env->FindClass("java/lang/Throwable");
-          getMessage = env->GetMethodID(clazz, "getMessage",
-                                        "()Ljava/lang/String;");
-          env->DeleteLocalRef(clazz);
-        }
-      jstring jmsg = (jstring) env->CallObjectMethod(t, getMessage);
-      JNIStringHolder tmp(jmsg);
-      msg = tmp.pstrdup(pool);
-      // ### Conditionally add t.printStackTrace() to msg?
+      msg = known_exception_to_cstring(pool);
     }
   else
     {
@@ -931,8 +911,11 @@ JNIUtil::checkJavaException(apr_status_t
   if (!getEnv()->ExceptionCheck())
     return SVN_NO_ERROR;
   svn_error_t* err = svn_error_create(errorcode, NULL, NULL);
-  err->message = apr_psprintf(err->pool, _("Java exception: %s"),
-                              exception_to_cstring(err->pool));
+  const char* const msg = known_exception_to_cstring(err->pool);
+  if (msg)
+    err->message = apr_psprintf(err->pool, _("Java exception: %s"), msg);
+  else
+    err->message = _("Java exception");
   return err;
 }
 
@@ -952,25 +935,6 @@ jstring JNIUtil::makeJString(const char 
   return env->NewStringUTF(txt);
 }
 
-void
-JNIUtil::setExceptionThrown(bool flag)
-{
-  if (g_inInit)
-    {
-      // During global initialization, store any errors that occur
-      // in a global variable (since thread-local storage may not
-      // yet be available).
-      g_initException = flag;
-    }
-  else
-    {
-      // When global initialization is complete, thread-local
-      // storage should be available, so store the error there.
-      JNIThreadData *data = JNIThreadData::getThreadData();
-      data->m_exceptionThrown = flag;
-    }
-}
-
 /**
  * Initialite the log file.
  * @param level the log level
@@ -994,23 +958,6 @@ void JNIUtil::initLogFile(int level, jst
 }
 
 /**
- * Returns a buffer to format error messages.
- * @return a buffer for formating error messages
- */
-char *JNIUtil::getFormatBuffer()
-{
-  if (g_inInit) // during init -> use the global buffer
-    return g_initFormatBuffer;
-
-  // use the buffer in the thread local storage
-  JNIThreadData *data = JNIThreadData::getThreadData();
-  if (data == NULL) // if that does not exists -> use the global buffer
-    return g_initFormatBuffer;
-
-  return data->m_formatBuffer;
-}
-
-/**
  * Returns the current log level.
  * @return the log level
  */
@@ -1150,8 +1097,6 @@ void JNIUtil::throwNullPointerException(
     return;
 
   env->ThrowNew(clazz, message);
-  setExceptionThrown();
-  env->DeleteLocalRef(clazz);
 }
 
 svn_error_t *JNIUtil::preprocessPath(const char *&path, apr_pool_t *pool)

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIUtil.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIUtil.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIUtil.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/JNIUtil.h Sun Oct 20 10:11:04 2013
@@ -73,17 +73,18 @@ class JNIUtil
   static apr_time_t getDate(jobject jdate);
   static void logMessage(const char *message);
   static int getLogLevel();
-  static char *getFormatBuffer();
   static void initLogFile(int level, jstring path);
   static jstring makeJString(const char *txt);
-  static bool isJavaExceptionThrown();
   static JNIEnv *getEnv();
-  static void setEnv(JNIEnv *);
 
   /**
    * @return Whether any Throwable has been raised.
    */
-  static bool isExceptionThrown();
+  static bool isExceptionThrown() { return isJavaExceptionThrown(); }
+  static bool isJavaExceptionThrown()
+    {
+      return getEnv()->ExceptionCheck();
+    }
 
   static void handleAPRError(int error, const char *op);
 
@@ -149,7 +150,6 @@ class JNIUtil
   static bool JNIGlobalInit(JNIEnv *env);
   static bool JNIInit(JNIEnv *env);
   static bool initializeJNIRuntime();
-  enum { formatBufferSize = 2048 };
   enum { noLog, errorLog, exceptionLog, entryLog } LogLevel;
 
   /**
@@ -158,13 +158,9 @@ class JNIUtil
   static JNIMutex *g_configMutex;
 
  private:
+  static void wrappedHandleSVNError(svn_error_t *err);
   static void putErrorsInTrace(svn_error_t *err,
                                std::vector<jobject> &stackTrace);
-  /**
-   * Set the appropriate global or thread-local flag that an exception
-   * has been thrown to @a flag.
-   */
-  static void setExceptionThrown(bool flag = true);
 
   /**
    * The log level of this module.
@@ -209,11 +205,6 @@ class JNIUtil
   static JNIEnv *g_initEnv;
 
   /**
-   * Fuffer the format error messages during initialization.
-   */
-  static char g_initFormatBuffer[formatBufferSize];
-
-  /**
    * The stream to write log messages to.
    */
   static std::ofstream g_logStream;

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/OperationContext.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/OperationContext.cpp?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/OperationContext.cpp (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/OperationContext.cpp Sun Oct 20 10:11:04 2013
@@ -24,8 +24,11 @@
  * @brief Implementation of the class OperationContext
  */
 
+#include <apr_file_io.h>
+
 #include "svn_client.h"
 #include "private/svn_wc_private.h"
+#include "private/svn_dep_compat.h"
 #include "svn_private_config.h"
 
 #include "GlobalConfig.h"
@@ -44,7 +47,8 @@ OperationContext::OperationContext(SVN::
     m_cancelOperation(0),
     m_pool(&pool),
     m_jctx(NULL),
-    m_jcfgcb(NULL)
+    m_jcfgcb(NULL),
+    m_jtunnelcb(NULL)
 {}
 
 void
@@ -92,6 +96,8 @@ OperationContext::~OperationContext()
   env->DeleteGlobalRef(m_jctx);
   if (m_jcfgcb)
     env->DeleteGlobalRef(m_jcfgcb);
+  if (m_jtunnelcb)
+    env->DeleteGlobalRef(m_jtunnelcb);
 }
 
 apr_hash_t *
@@ -295,6 +301,26 @@ const Prompter& OperationContext::getPro
   return *m_prompter;
 }
 
+void OperationContext::setTunnelCallback(jobject jtunnelcb)
+{
+  JNIEnv *env = JNIUtil::getEnv();
+  if (jtunnelcb)
+    {
+      jtunnelcb = env->NewGlobalRef(jtunnelcb);
+      if (JNIUtil::isJavaExceptionThrown())
+        return;
+    }
+
+  if (m_jtunnelcb)
+    env->DeleteGlobalRef(m_jtunnelcb);
+  m_jtunnelcb = jtunnelcb;
+}
+
+jobject OperationContext::getTunnelCallback() const
+{
+  return m_jtunnelcb;
+}
+
 void
 OperationContext::cancelOperation()
 {
@@ -440,3 +466,193 @@ OperationContext::notifyConfigLoad()
   env->CallVoidMethod(jcbimpl, dispose_mid);
   env->DeleteLocalRef(jcbimpl);
 }
+
+namespace {
+class TunnelContext
+{
+public:
+  explicit TunnelContext(apr_pool_t *pool)
+    : request_in(NULL),
+      request_out(NULL),
+      response_in(NULL),
+      response_out(NULL)
+    {
+#if APR_VERSION_AT_LEAST(1, 3, 0)
+      status = apr_file_pipe_create_ex(&request_in, &request_out,
+                                       APR_FULL_BLOCK, pool);
+      if (!status)
+        status = apr_file_pipe_create_ex(&response_in, &response_out,
+                                         APR_FULL_BLOCK, pool);
+#else
+      // XXX APR compatibility note:
+      // Versions of APR before 1.3 do not have the extended pipe
+      // API. Just create a default pipe and just hope that it returns
+      // a blocking handle.
+      status = apr_file_pipe_create(&request_in, &request_out, pool);
+      if (!status)
+        status = apr_file_pipe_create(&response_in, &response_out, pool);
+#endif
+    }
+
+  ~TunnelContext()
+    {
+      apr_file_close(request_out);
+      apr_file_close(response_in);
+    }
+
+  apr_file_t *request_in;
+  apr_file_t *request_out;
+  apr_file_t *response_in;
+  apr_file_t *response_out;
+  apr_status_t status;
+};
+
+jobject create_Channel(const char *class_name, JNIEnv *env, apr_file_t *fd)
+{
+  jclass cls = env->FindClass(class_name);
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+  jmethodID ctor = env->GetMethodID(cls, "<init>", "(J)V");
+  if (JNIUtil::isJavaExceptionThrown())
+    return NULL;
+  return env->NewObject(cls, ctor, reinterpret_cast<jlong>(fd));
+}
+
+jobject create_RequestChannel(JNIEnv *env, apr_file_t *fd)
+{
+  return create_Channel(JAVA_PACKAGE"/util/RequestChannel", env, fd);
+}
+jobject create_ResponseChannel(JNIEnv *env, apr_file_t *fd)
+{
+  return create_Channel(JAVA_PACKAGE"/util/ResponseChannel", env, fd);
+}
+} // anonymous namespace
+
+svn_boolean_t
+OperationContext::checkTunnel(void *tunnel_baton, const char *tunnel_name)
+{
+  JNIEnv *env = JNIUtil::getEnv();
+
+  jstring jtunnel_name = JNIUtil::makeJString(tunnel_name);
+  if (JNIUtil::isJavaExceptionThrown())
+    return false;
+
+  static jmethodID mid = 0;
+  if (0 == mid)
+    {
+      jclass cls = env->FindClass(JAVA_PACKAGE"/callback/TunnelAgent");
+      if (JNIUtil::isJavaExceptionThrown())
+        return false;
+      mid = env->GetMethodID(cls, "checkTunnel",
+                             "(Ljava/lang/String;)Z");
+        if (JNIUtil::isJavaExceptionThrown())
+          return false;
+    }
+
+  jobject jtunnelcb = jobject(tunnel_baton);
+  jboolean check = env->CallBooleanMethod(jtunnelcb, mid, jtunnel_name);
+  if (JNIUtil::isJavaExceptionThrown())
+    return false;
+
+  return svn_boolean_t(check);
+}
+
+svn_error_t *
+OperationContext::openTunnel(apr_file_t **request, apr_file_t **response,
+                             void **tunnel_context, void *tunnel_baton,
+                             const char *tunnel_name, const char *user,
+                             const char *hostname, int port,
+                             apr_pool_t *pool)
+{
+  TunnelContext *tc = new TunnelContext(pool);
+  if (tc->status)
+    {
+      delete tc;
+      return svn_error_trace(
+          svn_error_wrap_apr(tc->status, _("Could not open tunnel streams")));
+    }
+
+  *tunnel_context = tc;
+  *request = tc->request_out;
+  *response = tc->response_in;
+
+  JNIEnv *env = JNIUtil::getEnv();
+
+  jobject jrequest = create_RequestChannel(env, tc->request_in);
+  SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+  jobject jresponse = create_ResponseChannel(env, tc->response_out);
+  SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+  jstring jtunnel_name = JNIUtil::makeJString(tunnel_name);
+  SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+  jstring juser = JNIUtil::makeJString(user);
+  SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+  jstring jhostname = JNIUtil::makeJString(hostname);
+  SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+  static jmethodID mid = 0;
+  if (0 == mid)
+    {
+      jclass cls = env->FindClass(JAVA_PACKAGE"/callback/TunnelAgent");
+      SVN_JNI_CATCH(, SVN_ERR_BASE);
+      SVN_JNI_CATCH(
+          mid = env->GetMethodID(cls, "openTunnel",
+                                 "(Ljava/nio/channels/ReadableByteChannel;"
+                                 "Ljava/nio/channels/WritableByteChannel;"
+                                 "Ljava/lang/String;"
+                                 "Ljava/lang/String;"
+                                 "Ljava/lang/String;I)V"),
+          SVN_ERR_BASE);
+    }
+
+  jobject jtunnelcb = jobject(tunnel_baton);
+  SVN_JNI_CATCH(
+      env->CallVoidMethod(jtunnelcb, mid, jrequest, jresponse,
+                          jtunnel_name, juser, jhostname, jint(port)),
+      SVN_ERR_BASE);
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+OperationContext::closeTunnel(void *tunnel_context, void *tunnel_baton,
+                              const char *tunnel_name, const char *user,
+                              const char *hostname, int port)
+{
+  delete static_cast<TunnelContext*>(tunnel_context);
+
+  jstring jtunnel_name = JNIUtil::makeJString(tunnel_name);
+  SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+  jstring juser = JNIUtil::makeJString(user);
+  SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+  jstring jhostname = JNIUtil::makeJString(hostname);
+  SVN_JNI_CATCH(, SVN_ERR_BASE);
+
+  JNIEnv *env = JNIUtil::getEnv();
+
+  static jmethodID mid = 0;
+  if (0 == mid)
+    {
+      jclass cls = env->FindClass(JAVA_PACKAGE"/callback/TunnelAgent");
+      SVN_JNI_CATCH(, SVN_ERR_BASE);
+      SVN_JNI_CATCH(
+          mid = env->GetMethodID(cls, "closeTunnel",
+                                 "(Ljava/lang/String;"
+                                 "Ljava/lang/String;"
+                                 "Ljava/lang/String;I)V"),
+          SVN_ERR_BASE);
+    }
+
+  jobject jtunnelcb = jobject(tunnel_baton);
+  SVN_JNI_CATCH(
+      env->CallVoidMethod(jtunnelcb, mid,
+                          jtunnel_name, juser, jhostname, jint(port)),
+      SVN_ERR_BASE);
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/OperationContext.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/OperationContext.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/OperationContext.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/OperationContext.h Sun Oct 20 10:11:04 2013
@@ -59,9 +59,27 @@ class OperationContext
 
   jobject m_jctx;
   jobject m_jcfgcb;
+  jobject m_jtunnelcb;
+
   static void progress(apr_off_t progressVal, apr_off_t total,
                        void *baton, apr_pool_t *pool);
   void notifyConfigLoad();
+
+  static svn_boolean_t checkTunnel(
+      void *tunnel_baton, const char *tunnel_name);
+
+  static svn_error_t *openTunnel(
+      apr_file_t **request, apr_file_t **response,
+      void **tunnel_context, void *tunnel_baton,
+      const char *tunnel_name, const char *user,
+      const char *hostname, int port,
+      apr_pool_t *pool);
+
+  static svn_error_t *closeTunnel(
+      void *tunnel_context, void *tunnel_baton,
+      const char *tunnel_name, const char *user,
+      const char *hostname, int port);
+
  public:
   OperationContext(SVN::Pool &pool);
   void attachJavaObject(jobject contextHolder, const char *contextClassType, const char *contextFieldName, jfieldID * ctxFieldID);
@@ -98,6 +116,9 @@ class OperationContext
 
   static svn_error_t * clientName(void *baton, const char **name, apr_pool_t *pool);
   virtual const char * getClientName() const;
+
+  virtual void setTunnelCallback(jobject jtunnelcb);
+  jobject getTunnelCallback() const;
 };
 
 #endif // JAVAHL_OPERATION_CONTEXT_H

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSession.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSession.cpp?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSession.cpp (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSession.cpp Sun Oct 20 10:11:04 2013
@@ -68,7 +68,7 @@ RemoteSession::open(jint jretryAttempts,
                     jstring jurl, jstring juuid,
                     jstring jconfigDirectory,
                     jstring jusername, jstring jpassword,
-                    jobject jprompter, jobject jprogress)
+                    jobject jprompter, jobject jprogress, jobject jtunnelcb)
 {
   JNIEnv *env = JNIUtil::getEnv();
 
@@ -111,7 +111,7 @@ RemoteSession::open(jint jretryAttempts,
   jobject jremoteSession = open(
       jretryAttempts, url.c_str(), uuid,
       (jconfigDirectory ? configDirectory.c_str() : NULL),
-      usernameStr, passwordStr, prompter, jprogress);
+      usernameStr, passwordStr, prompter, jprogress, jtunnelcb);
   if (JNIUtil::isExceptionThrown() || !jremoteSession)
     {
       delete prompter;
@@ -125,7 +125,7 @@ RemoteSession::open(jint jretryAttempts,
                     const char* url, const char* uuid,
                     const char* configDirectory,
                     const char*  usernameStr, const char*  passwordStr,
-                    Prompter*& prompter, jobject jprogress)
+                    Prompter*& prompter, jobject jprogress, jobject jtunnelcb)
 {
   /*
    * Initialize ra layer if we have not done so yet
@@ -139,7 +139,7 @@ RemoteSession::open(jint jretryAttempts,
 
   RemoteSession* session = new RemoteSession(
       jretryAttempts, url, uuid, configDirectory,
-      usernameStr, passwordStr, prompter);
+      usernameStr, passwordStr, prompter, jtunnelcb);
   if (JNIUtil::isJavaExceptionThrown() || !session)
     {
       delete session;
@@ -201,11 +201,11 @@ RemoteSession::RemoteSession(int retryAt
                              const char* url, const char* uuid,
                              const char* configDirectory,
                              const char*  username, const char*  password,
-                             Prompter*& prompter)
+                             Prompter*& prompter, jobject jtunnelcb)
   : m_session(NULL), m_context(NULL)
 {
   m_context = new RemoteSessionContext(
-      pool, configDirectory, username, password, prompter);
+      pool, configDirectory, username, password, prompter, jtunnelcb);
   if (JNIUtil::isJavaExceptionThrown())
     return;
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSession.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSession.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSession.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSession.h Sun Oct 20 10:11:04 2013
@@ -48,12 +48,14 @@ class RemoteSession : public SVNBase
                         jstring jurl, jstring juuid,
                         jstring jconfigDirectory,
                         jstring jusername, jstring jpassword,
-                        jobject jprompter, jobject jprogress);
+                        jobject jprompter, jobject jprogress,
+                        jobject jtunnelcb);
     static jobject open(jint jretryAttempts,
                         const char* url, const char* uuid,
                         const char* configDirectory,
                         const char* username, const char* password,
-                        Prompter*& prompter, jobject jprogress);
+                        Prompter*& prompter, jobject jprogress,
+                        jobject jtunnelcb);
     ~RemoteSession();
 
     void cancelOperation() const { m_context->cancelOperation(); }
@@ -117,7 +119,7 @@ class RemoteSession : public SVNBase
                   const char* url, const char* uuid,
                   const char* configDirectory,
                   const char* username, const char* password,
-                  Prompter*& prompter);
+                  Prompter*& prompter, jobject jtunnelcb);
 
     svn_ra_session_t* m_session;
     RemoteSessionContext* m_context;

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSessionContext.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSessionContext.cpp?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSessionContext.cpp (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSessionContext.cpp Sun Oct 20 10:11:04 2013
@@ -33,7 +33,7 @@
 RemoteSessionContext::RemoteSessionContext(
     SVN::Pool &pool, const char* configDirectory,
     const char* usernameStr, const char* passwordStr,
-    Prompter* prompter)
+    Prompter* prompter, jobject jtunnelcb)
   : OperationContext(pool), m_raCallbacks(NULL)
 {
   setConfigDirectory(configDirectory);
@@ -44,6 +44,7 @@ RemoteSessionContext::RemoteSessionConte
     password(passwordStr);
 
   setPrompt(prompter);
+  setTunnelCallback(jtunnelcb);
 
   /*
    * Setup callbacks
@@ -68,6 +69,14 @@ RemoteSessionContext::RemoteSessionConte
    * Don't set deprecated callback
    */
   m_raCallbacks->open_tmp_file = NULL;
+
+  if (m_jtunnelcb)
+    {
+      m_raCallbacks->check_tunnel_func = checkTunnel;
+      m_raCallbacks->open_tunnel_func = openTunnel;
+      m_raCallbacks->close_tunnel_func = closeTunnel;
+      m_raCallbacks->tunnel_baton = m_jtunnelcb;
+    }
 }
 
 RemoteSessionContext::~RemoteSessionContext()

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSessionContext.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSessionContext.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSessionContext.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/RemoteSessionContext.h Sun Oct 20 10:11:04 2013
@@ -37,7 +37,7 @@ class RemoteSessionContext : public Oper
     RemoteSessionContext(SVN::Pool &pool,
                          const char* jconfigDirectory,
                          const char* jusername, const char* jpassword,
-                         Prompter* prompter);
+                         Prompter* prompter, jobject jtunnelcb);
     virtual ~RemoteSessionContext();
     void activate(jobject jremoteSession, jobject jprogress);
     void * getCallbackBaton();

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/SVNClient.cpp?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/SVNClient.cpp (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/SVNClient.cpp Sun Oct 20 10:11:04 2013
@@ -1343,10 +1343,10 @@ jstring SVNClient::getVersionInfo(const 
         }
         else
         {
-            char *message = JNIUtil::getFormatBuffer();
-            apr_snprintf(message, JNIUtil::formatBufferSize,
+            char buffer[2048];
+            apr_snprintf(buffer, sizeof(buffer),
                          _("'%s' not versioned, and not exported\n"), path);
-            return JNIUtil::makeJString(message);
+            return JNIUtil::makeJString(buffer);
         }
     }
 
@@ -1511,10 +1511,6 @@ SVNClient::openRemoteSession(const char*
                     ctx, subPool.getPool()),
                 NULL);
 
-    jobject jctx = context.getSelf();
-    if (JNIUtil::isJavaExceptionThrown())
-        return NULL;
-
     /* Decouple the RemoteSession's context from SVNClient's context
        by creating a copy of the prompter here. */
     Prompter* prompter = new Prompter(context.getPrompter());
@@ -1525,7 +1521,7 @@ SVNClient::openRemoteSession(const char*
         retryAttempts, path_info.url.c_str(), path_info.uuid.c_str(),
         context.getConfigDirectory(),
         context.getUsername(), context.getPassword(),
-        prompter, jctx);
+        prompter, context.getSelf(), context.getTunnelCallback());
     if (JNIUtil::isJavaExceptionThrown())
       delete prompter;
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp Sun Oct 20 10:11:04 2013
@@ -275,6 +275,21 @@ Java_org_apache_subversion_javahl_SVNCli
 }
 
 JNIEXPORT void JNICALL
+Java_org_apache_subversion_javahl_SVNClient_setTunnelAgent
+(JNIEnv *env, jobject jthis, jobject jtunnelcb)
+{
+  JNIEntry(SVNClient, setPrompt);
+  SVNClient *cl = SVNClient::getCppObject(jthis);
+  if (cl == NULL)
+    {
+      JNIUtil::throwError(_("bad C++ this"));
+      return;
+    }
+
+  cl->getClientContext().setTunnelCallback(jtunnelcb);
+}
+
+JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_SVNClient_logMessages
 (JNIEnv *env, jobject jthis, jstring jpath, jobject jpegRevision,
  jobject jranges, jboolean jstopOnCopy, jboolean jdisoverPaths,

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp Sun Oct 20 10:11:04 2013
@@ -40,7 +40,8 @@ Java_org_apache_subversion_javahl_remote
     jstring jurl, jstring juuid,
     jstring jconfigDirectory,
     jstring jusername, jstring jpassword,
-    jobject jprompter, jobject jprogress)
+    jobject jprompter, jobject jprogress,
+    jobject jtunnelcb)
 {
   //JNI macros need jthis but this is a static call
   JNIEntryStatic(RemoteFactory, open);
@@ -50,7 +51,7 @@ Java_org_apache_subversion_javahl_remote
    */
   jobject jremoteSession = RemoteSession::open(
       jretryAttempts, jurl, juuid,
-      jconfigDirectory, jusername, jpassword, jprompter, jprogress);
+      jconfigDirectory, jusername, jpassword, jprompter, jprogress, jtunnelcb);
   if (JNIUtil::isJavaExceptionThrown())
     return NULL;
 

Propchange: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigLib.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java Sun Oct 20 10:11:04 2013
@@ -134,6 +134,12 @@ public interface ISVNClient
     void setPrompt(UserPasswordCallback prompt);
 
     /**
+     * Set callbacks for ra_svn tunnel handling.
+     * @since 1.9
+     */
+    void setTunnelAgent(TunnelAgent tunnelAgent);
+
+    /**
      * Retrieve the log messages for an item.
      * @param path          path or url to get the log message for.
      * @param pegRevision   revision to interpret path

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java Sun Oct 20 10:11:04 2013
@@ -132,6 +132,8 @@ public class SVNClient implements ISVNCl
 
     public native void setPrompt(UserPasswordCallback prompt);
 
+    public native void setTunnelAgent(TunnelAgent tunnelAgent);
+
     public native void logMessages(String path, Revision pegRevision,
                                    List<RevisionRange> revisionRanges,
                                    boolean stopOnCopy, boolean discoverPath,

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java Sun Oct 20 10:11:04 2013
@@ -59,13 +59,15 @@ public class RemoteFactory
     public RemoteFactory(String configDirectory,
                          String username, String password,
                          UserPasswordCallback prompt,
-                         ProgressCallback progress)
+                         ProgressCallback progress,
+                         TunnelAgent tunnelAgent)
     {
         setConfigDirectory(configDirectory);
         setUsername(username);
         setPassword(password);
         setPrompt(prompt);
         setProgressCallback(progress);
+        setTunnelAgent(tunnelAgent);
     }
 
     /**
@@ -125,6 +127,14 @@ public class RemoteFactory
     }
 
     /**
+     * Set callbacks for ra_svn tunnel handling.
+     */
+    public void setTunnelAgent(TunnelAgent tunnelAgent)
+    {
+        this.tunnelAgent = tunnelAgent;
+    }
+
+    /**
      * Open a persistent session to a repository.
      * <p>
      * <b>Note:</b> The URL can point to a subtree of the repository.
@@ -141,7 +151,7 @@ public class RemoteFactory
             throws ClientException, SubversionException
     {
         return open(1, url, null, configDirectory,
-                    username, password, prompt, progress);
+                    username, password, prompt, progress, tunnelAgent);
     }
 
     /**
@@ -168,7 +178,7 @@ public class RemoteFactory
             throw new IllegalArgumentException(
                 "retryAttempts must be positive");
         return open(retryAttempts, url, null, configDirectory,
-                    username, password, prompt, progress);
+                    username, password, prompt, progress, tunnelAgent);
     }
 
     /**
@@ -195,7 +205,7 @@ public class RemoteFactory
         if (reposUUID == null)
             throw new IllegalArgumentException("reposUUID may not be null");
         return open(1, url, reposUUID, configDirectory,
-                    username, password, prompt, progress);
+                    username, password, prompt, progress, tunnelAgent);
     }
 
     /**
@@ -229,7 +239,7 @@ public class RemoteFactory
             throw new IllegalArgumentException(
                 "retryAttempts must be positive");
         return open(retryAttempts, url, reposUUID, configDirectory,
-                    username, password, prompt, progress);
+                    username, password, prompt, progress, tunnelAgent);
     }
 
     private String configDirectory;
@@ -237,6 +247,7 @@ public class RemoteFactory
     private String password;
     private UserPasswordCallback prompt;
     private ProgressCallback progress;
+    private TunnelAgent tunnelAgent;
 
     /* Native factory implementation. */
     private static native ISVNRemote open(int retryAttempts,
@@ -244,6 +255,7 @@ public class RemoteFactory
                                           String configDirectory,
                                           String username, String password,
                                           UserPasswordCallback prompt,
-                                          ProgressCallback progress)
+                                          ProgressCallback progress,
+                                          TunnelAgent tunnelAgent)
             throws ClientException, SubversionException;
 }

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java Sun Oct 20 10:11:04 2013
@@ -33,6 +33,9 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.ByteArrayOutputStream;
 import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
 import java.text.ParseException;
 import java.util.Collection;
 import java.util.Arrays;
@@ -3776,6 +3779,106 @@ public class BasicTests extends SVNTests
         assertEquals(1, result.size());
     }
 
+    private class Tunnel extends Thread implements TunnelAgent
+    {
+        public boolean checkTunnel(String name)
+        {
+            return name.equals("test");
+        }
+
+        public void openTunnel(ReadableByteChannel request,
+                               WritableByteChannel response,
+                               String name, String user,
+                               String hostname, int port)
+        {
+            this.request = request;
+            this.response = response;
+            start();
+        }
+
+        public void closeTunnel(String name, String user,
+                                String hostname, int port)
+            throws Throwable
+        {
+            request.close();
+            join();
+            response.close();
+        }
+
+        private ReadableByteChannel request;
+        private WritableByteChannel response;
+
+        public void run()
+        {
+
+            int index = 0;
+            byte[] raw_data = new byte[1024];
+            ByteBuffer data = ByteBuffer.wrap(raw_data);
+            while(index < commands.length && request.isOpen()) {
+                try {
+                    byte[] command = commands[index++];
+                    response.write(ByteBuffer.wrap(command));
+                } catch (IOException ex) {
+                    break;
+                }
+
+                try {
+                    data.clear();
+                    request.read(data);
+                } catch (Throwable ex) {}
+            }
+
+            try {
+                response.close();
+                request.close();
+            } catch (Throwable t) {}
+        }
+
+        private final byte[][] commands = new byte[][]{
+            // Initial capabilities negotiation
+            ("( success ( 2 2 ( ) " +
+             "( edit-pipeline svndiff1 absent-entries commit-revprops " +
+             "depth log-revprops atomic-revprops partial-replay " +
+             "inherited-props ephemeral-txnprops file-revs-reverse " +
+             ") ) ) ").getBytes(),
+
+            // Response for successful connection
+            ("( success ( ( ANONYMOUS EXTERNAL ) " +
+             "36:e3c8c113-03ba-4ec5-a8e6-8fc555e57b91 ) ) ").getBytes(),
+
+            // Response to authentication request
+            ("( success ( ) ) ( success ( " +
+             "36:e3c8c113-03ba-4ec5-a8e6-8fc555e57b91 " +
+             "24:svn+test://localhost/foo ( mergeinfo ) ) ) ").getBytes(),
+
+            // Response to revprop request
+            ("( success ( ( ) 0: ) ) ( success ( ( 4:fake ) ) ) ").getBytes()
+        };
+    }
+
+    /**
+     * Test tunnel handling.
+     */
+    public void testTunnelAgent() throws Throwable
+    {
+        byte[] revprop;
+        SVNClient cl = new SVNClient();
+        try {
+            cl.notification2(new MyNotifier());
+            cl.setPrompt(new DefaultPromptUserPassword());
+            cl.username(USERNAME);
+            cl.setProgressCallback(new DefaultProgressListener());
+            cl.setConfigDirectory(conf.getAbsolutePath());
+
+            cl.setTunnelAgent(new Tunnel());
+            revprop = cl.revProperty("svn+test://localhost/foo", "svn:log",
+                                     Revision.getInstance(0L));
+        } finally {
+            cl.dispose();
+        }
+        assertEquals("fake", new String(revprop));
+    }
+
     /**
      * @return <code>file</code> converted into a -- possibly
      * <code>canonical</code>-ized -- Subversion-internal path

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java Sun Oct 20 10:11:04 2013
@@ -111,7 +111,8 @@ public class SVNRemoteTests extends SVNT
             session = new RemoteFactory(
                 super.conf.getAbsolutePath(),
                 USERNAME, PASSWORD,
-                new DefaultPromptUserPassword(), null)
+                new DefaultPromptUserPassword(),
+                null, null)
                 .openRemoteSession(getTestRepoUrl());
         }
         catch (ClientException ex)
@@ -138,7 +139,8 @@ public class SVNRemoteTests extends SVNT
                 new RemoteFactory(
                     super.conf.getAbsolutePath(),
                     USERNAME, PASSWORD,
-                    new DefaultPromptUserPassword(), null)
+                    new DefaultPromptUserPassword(),
+                    null, null)
                     .openRemoteSession(prefix + "repositorydoesnotexisthere");
             }
             finally

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java Sun Oct 20 10:11:04 2013
@@ -355,7 +355,7 @@ class SVNTests extends TestCase
         }
     }
 
-    private static class DefaultProgressListener implements ProgressCallback
+    protected static class DefaultProgressListener implements ProgressCallback
     {
 
         public void onProgress(ProgressEvent event)

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_repos_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_repos_private.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_repos_private.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_repos_private.h Sun Oct 20 10:11:04 2013
@@ -32,6 +32,7 @@
 #include "svn_types.h"
 #include "svn_repos.h"
 #include "svn_editor.h"
+#include "svn_config.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -124,6 +125,66 @@ svn_repos__replay_ev2(svn_fs_root_t *roo
                       void *authz_read_baton,
                       apr_pool_t *scratch_pool);
 
+/* Given a PATH which might be a relative repo URL (^/), an absolute
+ * local repo URL (file://), an absolute path outside of the repo
+ * or a location in the Windows registry.
+ *
+ * Retrieve the configuration data that PATH points at and parse it into
+ * CFG_P allocated in POOL.
+ *
+ * If PATH cannot be parsed as a config file then an error is returned.  The
+ * contents of CFG_P is then undefined.  If MUST_EXIST is TRUE, a missing
+ * authz file is also an error.
+ *
+ * REPOS_ROOT points at the root of the repos you are
+ * going to apply the authz against, can be NULL if you are sure that you
+ * don't have a repos relative URL in PATH. */
+svn_error_t *
+svn_repos__retrieve_config(svn_config_t **cfg_p,
+                           const char *path,
+                           svn_boolean_t must_exist,
+                           apr_pool_t *pool);
+
+/**
+ * @defgroup svn_config_pool Configuration object pool API
+ * @{
+ */
+
+/* Opaque thread-safe factory and container for configuration objects.
+ *
+ * Instances handed out are read-only and may be given to multiple callers
+ * from multiple threads.  Configuration objects no longer referenced by
+ * any user may linger for a while before being cleaned up.
+ */
+typedef struct svn_repos__config_pool_t svn_repos__config_pool_t;
+
+/* Create a new configuration pool object with a minim lifetime determined
+ * by POOL and return it in *CONFIG_POOL.  References to any configuration
+ * in the *CONFIG_POOL will keep the latter alive beyond POOL cleanup.
+ */
+svn_error_t *
+svn_repos__config_pool_create(svn_repos__config_pool_t **config_pool,
+                              apr_pool_t *pool);
+
+/* Set *CFG to a read-only reference to the current contents of the
+ * configuration specified by PATH.  If the latter is a URL, we read the
+ * data from a local repository.  REGISTRY: urls are not supported.
+ * CONFIG_POOL will store the configuration and make further callers use
+ * the same instance if the content matches.
+ *
+ * POOL determines the minimum lifetime of *CFG.
+ *
+ * Note: The read-only behavior is not enforced, yet. 
+ */
+svn_error_t *
+svn_repos__config_pool_get(svn_config_t **cfg,
+                           svn_repos__config_pool_t *config_pool,
+                           const char *path,
+                           apr_pool_t *pool);
+
+/** @} */
+
+
 
 #ifdef __cplusplus
 }

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_subr_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_subr_private.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_subr_private.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_subr_private.h Sun Oct 20 10:11:04 2013
@@ -26,6 +26,7 @@
 
 #include "svn_types.h"
 #include "svn_io.h"
+#include "svn_config.h"
 
 
 #ifdef __cplusplus
@@ -462,7 +463,16 @@ svn_root_pools__release_pool(apr_pool_t 
 
 /** @} */
 
+/**
+ * @defgroup svn_config_private Private configuration handling API
+ * @{
+ */
 
+/* Future attempts to modify CFG will trigger an assertion. */
+void svn_config__set_read_only(svn_config_t *cfg,
+                               apr_pool_t *scratch_pool);
+
+/** @} */
 
 #ifdef __cplusplus
 }

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_client.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_client.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_client.h Sun Oct 20 10:11:04 2013
@@ -1019,23 +1019,41 @@ typedef struct svn_client_ctx_t
    * @Since New in 1.9. */
   apr_off_t progress;
 
+  /** Check-tunnel callback
+   *
+   * If not @c NULL, and open_tunnel_func is also not @c NULL, this
+   * callback will be invoked to check if open_tunnel_func should be
+   * used to create a specific tunnel, or if the default tunnel
+   * implementation (either built-in or configured in the client
+   * configuration file) should be used instead.
+   * @since New in 1.9.
+   */
+  svn_ra_check_tunnel_func_t check_tunnel_func;
+
   /** Open-tunnel callback
-   * If not @c null, this callback will be invoked to create an ra_svn
-   * connection that needs a tunnel, overriding any tunnel definitions
-   * in the client config file. This callback is used only for ra_svn
-   * and ignored by the other RA modules.
+   *
+   * If not @c NULL, this callback will be invoked to create a tunnel
+   * for a ra_svn connection that needs one, overriding any tunnel
+   * definitions in the client config file. This callback is used only
+   * for ra_svn and ignored by the other RA modules.
    * @since New in 1.9.
    */
   svn_ra_open_tunnel_func_t open_tunnel_func;
 
   /** Close-tunnel callback
-   * If not @c null, this callback will be invoked when the pool that
+   *
+   * If not @c NULL, this callback will be invoked when the pool that
    * owns the connection created by the open_tunnel callback is
    * cleared or destroyed. This callback is used only for ra_svn and
    * ignored by the other RA modules.
    * @since New in 1.9.
    */
   svn_ra_close_tunnel_func_t close_tunnel_func;
+
+  /** A baton used with open_tunnel_func and close_tunnel_func.
+   * @since New in 1.9.
+   */
+  void *tunnel_baton;
 } svn_client_ctx_t;
 
 /** Initialize a client context.

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_io.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_io.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_io.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_io.h Sun Oct 20 10:11:04 2013
@@ -1070,6 +1070,20 @@ svn_error_t *
 svn_stream_for_stdout(svn_stream_t **out,
                       apr_pool_t *pool);
 
+/** Set @a *str to a string buffer allocated in @a pool that contains all
+ * data from the current position in @a stream to its end.  @a len_hint
+ * specifies the initial capacity of the string buffer and may be 0.  The
+ * buffer gets automatically resized to fit the actual amount of data being
+ * read from @a stream.
+ *
+ * @since New in 1.9.
+ */
+svn_error_t *
+svn_stringbuf_from_stream(svn_stringbuf_t **str,
+                          svn_stream_t *stream,
+                          apr_size_t len_hint,
+                          apr_pool_t *pool);
+
 /** Return a generic stream connected to stringbuf @a str.  Allocate the
  * stream in @a pool.
  */

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_ra.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_ra.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_ra.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_ra.h Sun Oct 20 10:11:04 2013
@@ -272,6 +272,18 @@ typedef svn_error_t *(*svn_ra_replay_rev
 
 
 /**
+ * Callback function that checks if an ra_svn tunnel called
+ * @a tunnel_name is handled by the callbakcs or the default
+ * implementation.
+ *
+ * @a tunnel_baton is the baton as originally passed to ra_open.
+ *
+ * @since New in 1.9.
+ */
+typedef svn_boolean_t (*svn_ra_check_tunnel_func_t)(
+    void *tunnel_baton, const char *tunnel_name);
+
+/**
  * Callback function for opening a tunnel in ra_svn.
  *
  * Given the @a tunnel_name, tunnel @a user and server @a hostname and
@@ -281,15 +293,15 @@ typedef svn_error_t *(*svn_ra_replay_rev
  * @a request and @a response are the standard input and output,
  * respectively, of the process on the other end of the tunnel.
  *
- * @a tunnel_baton will be passed on to the close-unnel callback.
+ * @a tunnel_context will be passed on to the close-unnel callback.
  *
- * @a open_baton is the baton as originally passed to ra_open.
+ * @a tunnel_baton is the baton as originally passed to ra_open.
  *
  * @since New in 1.9.
  */
 typedef svn_error_t *(*svn_ra_open_tunnel_func_t)(
     apr_file_t **request, apr_file_t **response,
-    void **tunnel_baton, void *open_baton,
+    void **tunnel_context, void *tunnel_baton,
     const char *tunnel_name, const char *user,
     const char *hostname, int port,
     apr_pool_t *pool);
@@ -309,7 +321,7 @@ typedef svn_error_t *(*svn_ra_open_tunne
  * @since New in 1.9.
  */
 typedef svn_error_t *(*svn_ra_close_tunnel_func_t)(
-    void *tunnel_baton, void *open_baton,
+    void *tunnel_context, void *tunnel_baton,
     const char *tunnel_name, const char *user,
     const char *hostname, int port);
 
@@ -581,24 +593,41 @@ typedef struct svn_ra_callbacks2_t
    */
   svn_ra_get_wc_contents_func_t get_wc_contents;
 
+  /** Check-tunnel callback
+   *
+   * If not @c NULL, and open_tunnel_func is also not @c NULL, this
+   * callback will be invoked to check if open_tunnel_func should be
+   * used to create a specific tunnel, or if the default tunnel
+   * implementation (either built-in or configured in the client
+   * configuration file) should be used instead.
+   * @since New in 1.9.
+   */
+  svn_ra_check_tunnel_func_t check_tunnel_func;
+
   /** Open-tunnel callback
-   * If not @c null, this callback will be invoked to create an ra_svn
-   * connection that needs a tunnel, overriding any tunnel definitions
-   * in the client config file. This callback is used only for ra_svn
-   * and ignored by the other RA modules.
+   *
+   * If not @c NULL, this callback will be invoked to create a tunnel
+   * for a ra_svn connection that needs one, overriding any tunnel
+   * definitions in the client config file. This callback is used only
+   * for ra_svn and ignored by the other RA modules.
    * @since New in 1.9.
    */
-  svn_ra_open_tunnel_func_t open_tunnel;
+  svn_ra_open_tunnel_func_t open_tunnel_func;
 
   /** Close-tunnel callback
-   * If not @c null, this callback will be invoked when the pool that
+   *
+   * If not @c NULL, this callback will be invoked when the pool that
    * owns the connection created by the open_tunnel callback is
    * cleared or destroyed. This callback is used only for ra_svn and
    * ignored by the other RA modules.
    * @since New in 1.9.
    */
-  svn_ra_close_tunnel_func_t close_tunnel;
+  svn_ra_close_tunnel_func_t close_tunnel_func;
 
+  /** A baton used with open_tunnel_func and close_tunnel_func.
+   * @since New in 1.9.
+   */
+  void *tunnel_baton;
 } svn_ra_callbacks2_t;
 
 /** Similar to svn_ra_callbacks2_t, except that the progress

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_types.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_types.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_types.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_types.h Sun Oct 20 10:11:04 2013
@@ -70,7 +70,13 @@ extern "C" {
  */
 #ifndef SVN_EXPERIMENTAL
 # if !defined(SWIGPERL) && !defined(SWIGPYTHON) && !defined(SWIGRUBY)
-#  if !defined(__clang__) && defined(__GNUC__) \
+#  if defined(__has_attribute)
+#    if __has_attribute(__warning__)
+#      define SVN_EXPERIMENTAL __attribute__((warning("experimental function used")))
+#    else
+#      define SVN_EXPERIMENTAL
+#    endif
+#  elif !defined(__llvm__) && defined(__GNUC__) \
       && (__GNUC__ >= 4 || (__GNUC__==3 && __GNUC_MINOR__>=1))
 #   define SVN_EXPERIMENTAL __attribute__((warning("experimental function used")))
 #  elif defined(_MSC_VER) && _MSC_VER >= 1300

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_version.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_version.h?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_version.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_version.h Sun Oct 20 10:11:04 2013
@@ -28,15 +28,13 @@
 #define SVN_VERSION_H
 
 /* Hack to prevent the resource compiler from including
-   apr_general.h.  It doesn't resolve the include paths
-   correctly and blows up without this.
- */
-#ifndef APR_STRINGIFY
+   apr and other headers. */
+#ifndef SVN_WIN32_RESOURCE_COMPILATION
 #include <apr_general.h>
-#endif
 #include <apr_tables.h>
 
 #include "svn_types.h"
+#endif
 
 #ifdef __cplusplus
 extern "C" {

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/list.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/list.c?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/list.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/list.c Sun Oct 20 10:11:04 2013
@@ -128,6 +128,10 @@ get_dir_contents(apr_uint32_t dirent_fie
     }
   SVN_ERR(err);
 
+ /* Locks will often be empty.  Prevent pointless lookups in that case. */
+ if (locks && apr_hash_count(locks) == 0)
+   locks = NULL;
+
  /* Filter out svn:externals from all properties hash. */
   if (prop_hash)
     prop_val = svn_hash_gets(prop_hash, SVN_PROP_EXTERNALS);

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/merge.c?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/merge.c Sun Oct 20 10:11:04 2013
@@ -12301,7 +12301,16 @@ find_base_on_target(svn_client__pathrev_
   return SVN_NO_ERROR;
 }
 
-/* The body of client_find_automatic_merge(), which see.
+/* Find the last point at which the branch at S_T->source was completely
+ * merged to the branch at S_T->target or vice-versa.
+ *
+ * Fill in S_T->source_branch and S_T->target_branch and S_T->yca.
+ * Set *BASE_P to the merge base.  Set *IS_REINTEGRATE_LIKE to true if
+ * an automatic merge from source to target would be a reintegration
+ * merge: that is, if the last automatic merge was in the opposite
+ * direction; or to false otherwise.
+ *
+ * If there is no youngest common ancestor, throw an error.
  */
 static svn_error_t *
 find_automatic_merge(svn_client__pathrev_t **base_p,
@@ -12371,6 +12380,9 @@ find_automatic_merge(svn_client__pathrev
  * Like find_automatic_merge() except that the target is
  * specified by @a target_path_or_url at @a target_revision, which must
  * refer to a repository location, instead of by a WC path argument.
+ *
+ * Set *MERGE_P to a new structure with all fields filled in except the
+ * 'allow_*' flags.
  */
 static svn_error_t *
 find_automatic_merge_no_wc(automatic_merge_t **merge_p,
@@ -12446,6 +12458,8 @@ client_find_automatic_merge(automatic_me
   source_and_target_t *s_t = apr_palloc(result_pool, sizeof(*s_t));
   automatic_merge_t *merge = apr_palloc(result_pool, sizeof(*merge));
 
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
+
   /* "Open" the target WC.  Check the target WC for mixed-rev, local mods and
    * switched subtrees yet to faster exit and notify user before contacting
    * with server.  After we find out what kind of merge is required, then if a
@@ -12477,6 +12491,7 @@ client_find_automatic_merge(automatic_me
                                ctx, result_pool, scratch_pool));
   merge->yca = s_t->yca;
   merge->right = s_t->source;
+  merge->target = &s_t->target->loc;
   merge->allow_mixed_rev = allow_mixed_rev;
   merge->allow_local_mods = allow_local_mods;
   merge->allow_switched_subtrees = allow_switched_subtrees;
@@ -12667,12 +12682,18 @@ svn_client_get_merging_summary(svn_boole
                  && (target_revision->kind == svn_opt_revision_unspecified
                      || target_revision->kind == svn_opt_revision_working);
   if (target_is_wc)
-    SVN_ERR(client_find_automatic_merge(
-              &merge,
-              source_path_or_url, source_revision,
-              target_path_or_url,
-              TRUE, TRUE, TRUE,  /* allow_* */
-              ctx, scratch_pool, scratch_pool));
+    {
+      const char *target_abspath;
+
+      SVN_ERR(svn_dirent_get_absolute(&target_abspath, target_path_or_url,
+                                      scratch_pool));
+      SVN_ERR(client_find_automatic_merge(
+                &merge,
+                source_path_or_url, source_revision,
+                target_abspath,
+                TRUE, TRUE, TRUE,  /* allow_* */
+                ctx, scratch_pool, scratch_pool));
+    }
   else
     SVN_ERR(find_automatic_merge_no_wc(
               &merge,

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/ra.c?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/ra.c Sun Oct 20 10:11:04 2013
@@ -350,8 +350,10 @@ svn_client__open_ra_session_internal(svn
   cbtable->get_client_string = get_client_string;
   if (base_dir_abspath)
     cbtable->get_wc_contents = get_wc_contents;
-  cbtable->open_tunnel = ctx->open_tunnel_func;
-  cbtable->close_tunnel = ctx->close_tunnel_func;
+  cbtable->check_tunnel_func = ctx->check_tunnel_func;
+  cbtable->open_tunnel_func = ctx->open_tunnel_func;
+  cbtable->close_tunnel_func = ctx->close_tunnel_func;
+  cbtable->tunnel_baton = ctx->tunnel_baton;
 
   cb->commit_items = commit_items;
   cb->ctx = ctx;

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/cached_data.c?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/cached_data.c Sun Oct 20 10:11:04 2013
@@ -1751,12 +1751,12 @@ get_dir_contents(apr_hash_t *entries,
       apr_size_t len = noderev->data_rep->expanded_size
                      ? (apr_size_t)noderev->data_rep->expanded_size
                      : (apr_size_t)noderev->data_rep->size;
-      svn_stringbuf_t *text = svn_stringbuf_create_ensure(len, text_pool);
-      text->len = len;
+      svn_stringbuf_t *text;
 
       /* The representation is immutable.  Read it normally. */
-      SVN_ERR(svn_fs_fs__get_contents(&contents, fs, noderev->data_rep, text_pool));
-      SVN_ERR(svn_stream_read(contents, text->data, &text->len));
+      SVN_ERR(svn_fs_fs__get_contents(&contents, fs, noderev->data_rep,
+                                      text_pool));
+      SVN_ERR(svn_stringbuf_from_stream(&text, contents, len, text_pool));
       SVN_ERR(svn_stream_close(contents));
 
       /* de-serialize hash */

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/transaction.c?rev=1533871&r1=1533870&r2=1533871&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/transaction.c Sun Oct 20 10:11:04 2013
@@ -2707,15 +2707,18 @@ write_final_changed_path_info(apr_off_t 
 
   /* all moves specify the "copy-from-rev" as REV-1 */
   if (svn_fs_fs__supports_move(fs))
-    for (hi = apr_hash_first(pool, changed_paths); hi; hi = apr_hash_next(hi))
-      {
-        svn_fs_path_change2_t *change;
-        apr_hash_this(hi, NULL, NULL, (void **)&change);
+    {
+      for (hi = apr_hash_first(pool, changed_paths);
+           hi;
+           hi = apr_hash_next(hi))
+        {
+          svn_fs_path_change2_t *change = svn__apr_hash_index_val(hi);
 
-        if (   (change->change_kind == svn_fs_path_change_move)
-            || (change->change_kind == svn_fs_path_change_movereplace))
-          change->copyfrom_rev = new_rev - 1;
-      }
+          if (   (change->change_kind == svn_fs_path_change_move)
+              || (change->change_kind == svn_fs_path_change_movereplace))
+            change->copyfrom_rev = new_rev - 1;
+        }
+    }
 
   SVN_ERR(svn_fs_fs__write_changes(svn_stream_from_aprfile2(file, TRUE, pool),
                                    fs, changed_paths, TRUE, pool));