svn commit: r1934047 - in subversion/branches/javahl-1.15: . subversion/bindings/javahl/native subversion/bindings/javahl/src/org/apache/subversion/javahl

[email protected]
Newsgroups gmane.comp.version-control.subversion.svn
Message-ID <177841498193.988327.2610410323878224522@svn03-he-fi>
Author: brane
Date: Sun May 10 12:09:41 2026
New Revision: 1934047

Log:
On the javahl-1.15 branch: Update diff wrappers to capture stderr.

* BRANCH-README: Update TODO and DONE lists.

[in subversion/bindings/javahl/src/org/apache/subversion/javahl/]

* ISVNClient.java (ISVNClient.diff): Add new overload.
* SVNClient.java (SVNClient.diff): Add new native method and update the
   compatibility wrappers.

[in subversion/bindings/javahl/native/]

* OutputStream.cpp
  (OutputStream::OutputStream): Use initializer list.
  (OutputStream::getStream): Return an empty stream when the Java object is NULL.
  (OutputStream::write, OutputStream::close): Rename 'that' to 'stream'.
   Use static_cast<> to cast from 'void*', reinterpret_cast<> is just
   so wrong in this context.

* SVNClient.h (SVNClient::diff),
  SVNClient.cpp (SVNClient::diff): Add errStream parameter and update the
   call into the native library.

* org_apache_subversion_javahl_SVNClient.cpp (ENAMETOOLONG): Update the
   native method implementations.

Modified:
   subversion/branches/javahl-1.15/BRANCH-README
   subversion/branches/javahl-1.15/subversion/bindings/javahl/native/OutputStream.cpp
   subversion/branches/javahl-1.15/subversion/bindings/javahl/native/SVNClient.cpp
   subversion/branches/javahl-1.15/subversion/bindings/javahl/native/SVNClient.h
   subversion/branches/javahl-1.15/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
   subversion/branches/javahl-1.15/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
   subversion/branches/javahl-1.15/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java

Modified: subversion/branches/javahl-1.15/BRANCH-README
==============================================================================
--- subversion/branches/javahl-1.15/BRANCH-README	Sun May 10 11:24:26 2026	(r1934046)
+++ subversion/branches/javahl-1.15/BRANCH-README	Sun May 10 12:09:41 2026	(r1934047)
@@ -4,7 +4,6 @@
 This is a temporary working branch to update JavaHL for 1.15.0.
 
 TODO:
-  * Update SVNClient.diff to capture stderr.
   * Fix Java warnings where possible without breaking the JRE ABI
 
 DONE:
@@ -23,3 +22,4 @@ DONE:
   * Use updated JavaHL APIs (in tests):
     - SVNClient.checkout
     - SVNClient.list, .callback.ListCallback
+  * Update SVNClient.diff to capture stderr.

Modified: subversion/branches/javahl-1.15/subversion/bindings/javahl/native/OutputStream.cpp
==============================================================================
--- subversion/branches/javahl-1.15/subversion/bindings/javahl/native/OutputStream.cpp	Sun May 10 11:24:26 2026	(r1934046)
+++ subversion/branches/javahl-1.15/subversion/bindings/javahl/native/OutputStream.cpp	Sun May 10 12:09:41 2026	(r1934047)
@@ -33,9 +33,8 @@
  * @param jthis the Java object to be stored
  */
 OutputStream::OutputStream(jobject jthis)
-{
-  m_jthis = jthis;
-}
+  : m_jthis(jthis)
+{}
 
 /**
  * Destroy an Inputer object.
@@ -54,6 +53,9 @@ OutputStream::~OutputStream()
  */
 svn_stream_t *OutputStream::getStream(const SVN::Pool &pool)
 {
+  if (m_jthis == NULL)
+    return svn_stream_empty(pool.getPool());
+
   // Create a stream with this as the baton and set the write and
   // close functions.
   svn_stream_t *ret = svn_stream_create(this, pool.getPool());
@@ -76,7 +78,7 @@ svn_error_t *OutputStream::write(void *b
   JNIEnv *env = JNIUtil::getEnv();
 
   // An object of our class is passed in as the baton.
-  OutputStream *that = static_cast<OutputStream *>(baton);
+  OutputStream *stream = static_cast<OutputStream *>(baton);
 
   // The method id will not change during the time this library is
   // loaded, so it can be cached.
@@ -100,7 +102,7 @@ svn_error_t *OutputStream::write(void *b
     return SVN_NO_ERROR;
 
   // write the data
-  env->CallObjectMethod(that->m_jthis, mid, data);
+  env->CallObjectMethod(stream->m_jthis, mid, data);
   if (JNIUtil::isJavaExceptionThrown())
     return SVN_NO_ERROR;
 
@@ -119,7 +121,7 @@ svn_error_t *OutputStream::close(void *b
   JNIEnv *env = JNIUtil::getEnv();
 
   // An object of our class is passed in as the baton
-  OutputStream *that = reinterpret_cast<OutputStream*>(baton);
+  OutputStream *stream = static_cast<OutputStream*>(baton);
 
   // The method id will not change during the time this library is
   // loaded, so it can be cached.
@@ -138,7 +140,7 @@ svn_error_t *OutputStream::close(void *b
     }
 
   // Call the Java object, to close the stream.
-  env->CallVoidMethod(that->m_jthis, mid);
+  env->CallVoidMethod(stream->m_jthis, mid);
   // No need to check for exception here because we return anyway.
 
   return SVN_NO_ERROR;

Modified: subversion/branches/javahl-1.15/subversion/bindings/javahl/native/SVNClient.cpp
==============================================================================
--- subversion/branches/javahl-1.15/subversion/bindings/javahl/native/SVNClient.cpp	Sun May 10 11:24:26 2026	(r1934046)
+++ subversion/branches/javahl-1.15/subversion/bindings/javahl/native/SVNClient.cpp	Sun May 10 12:09:41 2026	(r1934047)
@@ -1017,8 +1017,8 @@ void SVNClient::propertySetRemote(const
 void SVNClient::diff(const char *target1, Revision &revision1,
                      const char *target2, Revision &revision2,
                      Revision *pegRevision, const char *relativeToDir,
-                     OutputStream &outputStream, svn_depth_t depth,
-                     StringArray &changelists,
+                     OutputStream &outputStream, OutputStream &errorStream,
+                     svn_depth_t depth, StringArray &changelists,
                      bool ignoreAncestry, bool noDiffDelete, bool force,
                      bool showCopiesAsAdds, bool ignoreProps, bool propsOnly,
                      DiffOptions const& options)
@@ -1063,8 +1063,7 @@ void SVNClient::diff(const char *target1
                                    options.formatMergeinfo(),
                                    SVN_APR_LOCALE_CHARSET,
                                    outputStream.getStream(subPool),
-                                   // Discard stderr; TODO: Update JavaHL API
-                                   svn_stream_empty(subPool.getPool()),
+                                   errorStream.getStream(subPool),
                                    changelists.array(subPool),
                                    ctx,
                                    subPool.getPool()),
@@ -1094,8 +1093,7 @@ void SVNClient::diff(const char *target1
                                options.formatMergeinfo(),
                                SVN_APR_LOCALE_CHARSET,
                                outputStream.getStream(subPool),
-                               // Discard stderr; TODO: Update JavaHL API
-                               svn_stream_empty(subPool.getPool()),
+                               errorStream.getStream(subPool),
                                changelists.array(subPool),
                                ctx,
                                subPool.getPool()),
@@ -1105,27 +1103,30 @@ void SVNClient::diff(const char *target1
 
 void SVNClient::diff(const char *target1, Revision &revision1,
                      const char *target2, Revision &revision2,
-                     const char *relativeToDir, OutputStream &outputStream,
+                     const char *relativeToDir,
+                     OutputStream &outputStream, OutputStream &errorStream,
                      svn_depth_t depth, StringArray &changelists,
                      bool ignoreAncestry, bool noDiffDelete, bool force,
                      bool showCopiesAsAdds, bool ignoreProps, bool propsOnly,
                      DiffOptions const& options)
 {
     diff(target1, revision1, target2, revision2, NULL, relativeToDir,
-         outputStream, depth, changelists, ignoreAncestry, noDiffDelete, force,
-         showCopiesAsAdds, ignoreProps, propsOnly, options);
+         outputStream, errorStream, depth, changelists, ignoreAncestry,
+         noDiffDelete, force, showCopiesAsAdds, ignoreProps, propsOnly,
+         options);
 }
 
 void SVNClient::diff(const char *target, Revision &pegRevision,
                      Revision &startRevision, Revision &endRevision,
-                     const char *relativeToDir, OutputStream &outputStream,
+                     const char *relativeToDir,
+                     OutputStream &outputStream, OutputStream &errorStream,
                      svn_depth_t depth, StringArray &changelists,
                      bool ignoreAncestry, bool noDiffDelete, bool force,
                      bool showCopiesAsAdds, bool ignoreProps, bool propsOnly,
                      DiffOptions const& options)
 {
     diff(target, startRevision, NULL, endRevision, &pegRevision,
-         relativeToDir, outputStream, depth, changelists,
+         relativeToDir, outputStream, errorStream, depth, changelists,
          ignoreAncestry, noDiffDelete, force, showCopiesAsAdds,
          ignoreProps, propsOnly, options);
 }

Modified: subversion/branches/javahl-1.15/subversion/bindings/javahl/native/SVNClient.h
==============================================================================
--- subversion/branches/javahl-1.15/subversion/bindings/javahl/native/SVNClient.h	Sun May 10 11:24:26 2026	(r1934046)
+++ subversion/branches/javahl-1.15/subversion/bindings/javahl/native/SVNClient.h	Sun May 10 12:09:41 2026	(r1934047)
@@ -208,14 +208,16 @@ class SVNClient :public SVNBase
                          StringArray &changelists);
   void diff(const char *target1, Revision &revision1,
             const char *target2, Revision &revision2,
-            const char *relativeToDir, OutputStream &outputStream,
+            const char *relativeToDir,
+            OutputStream &outputStream, OutputStream &errorStream,
             svn_depth_t depth, StringArray &changelists,
             bool ignoreAncestry, bool noDiffDelete, bool force,
             bool showCopiesAsAdds, bool ignoreProps, bool propsOnly,
             DiffOptions const& options);
   void diff(const char *target, Revision &pegevision,
             Revision &startRevision, Revision &endRevision,
-            const char *relativeToDir, OutputStream &outputStream,
+            const char *relativeToDir,
+            OutputStream &outputStream, OutputStream &errorStream,
             svn_depth_t depth, StringArray &changelists,
             bool ignoreAncestry, bool noDiffDelete, bool force,
             bool showCopiesAsAdds, bool ignoreProps, bool propsOnly,
@@ -246,8 +248,8 @@ class SVNClient :public SVNBase
   void diff(const char *target1, Revision &revision1,
             const char *target2, Revision &revision2,
             Revision *pegRevision, const char *relativeToDir,
-            OutputStream &outputStream, svn_depth_t depth,
-            StringArray &changelists,
+            OutputStream &outputStream, OutputStream &errorStream,
+            svn_depth_t depth, StringArray &changelists,
             bool ignoreAncestry, bool noDiffDelete, bool force,
             bool showCopiesAsAdds, bool ignoreProps, bool propsOnly,
             DiffOptions const& options);

Modified: subversion/branches/javahl-1.15/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
==============================================================================
--- subversion/branches/javahl-1.15/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp	Sun May 10 11:24:26 2026	(r1934046)
+++ subversion/branches/javahl-1.15/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp	Sun May 10 12:09:41 2026	(r1934047)
@@ -1330,10 +1330,10 @@ JNIEXPORT void JNICALL Java_org_apache_s
 }
 
 JNIEXPORT void JNICALL
-Java_org_apache_subversion_javahl_SVNClient_diff__Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Ljava_io_OutputStream_2Lorg_apache_subversion_javahl_types_Depth_2Ljava_util_Collection_2ZZZZZZLorg_apache_subversion_javahl_types_DiffOptions_2
+Java_org_apache_subversion_javahl_SVNClient_diff__Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Ljava_io_OutputStream_2Ljava_io_OutputStream_2Lorg_apache_subversion_javahl_types_Depth_2Ljava_util_Collection_2ZZZZZZLorg_apache_subversion_javahl_types_DiffOptions_2
 (JNIEnv *env, jobject jthis, jstring jtarget1, jobject jrevision1,
  jstring jtarget2, jobject jrevision2, jstring jrelativeToDir,
- jobject jstream, jobject jdepth, jobject jchangelists,
+ jobject joutStream, jobject jerrStream, jobject jdepth, jobject jchangelists,
  jboolean jignoreAncestry, jboolean jnoDiffDeleted, jboolean jforce,
  jboolean jcopiesAsAdds, jboolean jignoreProps, jboolean jpropsOnly,
  jobject jdiffOptions)
@@ -1365,7 +1365,11 @@ Java_org_apache_subversion_javahl_SVNCli
   if (JNIUtil::isExceptionThrown())
     return;
 
-  OutputStream dataOut(jstream);
+  OutputStream outStream(joutStream);
+  if (JNIUtil::isExceptionThrown())
+    return;
+
+  OutputStream errStream(jerrStream);
   if (JNIUtil::isExceptionThrown())
     return;
 
@@ -1377,7 +1381,8 @@ Java_org_apache_subversion_javahl_SVNCli
   if (JNIUtil::isExceptionThrown())
     return;
 
-  cl->diff(target1, revision1, target2, revision2, relativeToDir, dataOut,
+  cl->diff(target1, revision1, target2, revision2,
+           relativeToDir, outStream, errStream,
            EnumMapper::toDepth(jdepth), changelists,
            jignoreAncestry ? true:false,
            jnoDiffDeleted ? true:false, jforce ? true:false,
@@ -1386,10 +1391,10 @@ Java_org_apache_subversion_javahl_SVNCli
 }
 
 JNIEXPORT void JNICALL
-Java_org_apache_subversion_javahl_SVNClient_diff__Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Lorg_apache_subversion_javahl_types_Revision_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Ljava_io_OutputStream_2Lorg_apache_subversion_javahl_types_Depth_2Ljava_util_Collection_2ZZZZZZLorg_apache_subversion_javahl_types_DiffOptions_2
+Java_org_apache_subversion_javahl_SVNClient_diff__Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Lorg_apache_subversion_javahl_types_Revision_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Ljava_io_OutputStream_2Ljava_io_OutputStream_2Lorg_apache_subversion_javahl_types_Depth_2Ljava_util_Collection_2ZZZZZZLorg_apache_subversion_javahl_types_DiffOptions_2
 (JNIEnv *env, jobject jthis, jstring jtarget, jobject jpegRevision,
  jobject jstartRevision, jobject jendRevision, jstring jrelativeToDir,
- jobject jstream, jobject jdepth, jobject jchangelists,
+ jobject joutStream, jobject jerrStream, jobject jdepth, jobject jchangelists,
  jboolean jignoreAncestry, jboolean jnoDiffDeleted, jboolean jforce,
  jboolean jcopiesAsAdds, jboolean jignoreProps, jboolean jpropsOnly,
  jobject jdiffOptions)
@@ -1417,7 +1422,11 @@ Java_org_apache_subversion_javahl_SVNCli
   if (JNIUtil::isExceptionThrown())
     return;
 
-  OutputStream dataOut(jstream);
+  OutputStream outStream(joutStream);
+  if (JNIUtil::isExceptionThrown())
+    return;
+
+  OutputStream errStream(jerrStream);
   if (JNIUtil::isExceptionThrown())
     return;
 
@@ -1434,7 +1443,7 @@ Java_org_apache_subversion_javahl_SVNCli
     return;
 
   cl->diff(target, pegRevision, startRevision, endRevision, relativeToDir,
-           dataOut, EnumMapper::toDepth(jdepth), changelists,
+           outStream, errStream, EnumMapper::toDepth(jdepth), changelists,
            jignoreAncestry ? true:false,
            jnoDiffDeleted ? true:false, jforce ? true:false,
            jcopiesAsAdds ? true:false, jignoreProps ? true:false,

Modified: subversion/branches/javahl-1.15/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
==============================================================================
--- subversion/branches/javahl-1.15/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java	Sun May 10 11:24:26 2026	(r1934046)
+++ subversion/branches/javahl-1.15/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java	Sun May 10 12:09:41 2026	(r1934047)
@@ -951,6 +951,7 @@ public interface ISVNClient
      * @param revision2     second revision
      * @param relativeToDir index path is relative to this path
      * @param outStream     the stream to which difference are written
+     * @param errStream     the stream to which error messages are written
      * @param depth         how deep to traverse into subdirectories
      * @param ignoreAncestry ignore if files are not related
      * @param noDiffDeleted no output on deleted files
@@ -961,6 +962,23 @@ public interface ISVNClient
      * @param propsOnly     show property changes only
      * @param options       additional options for controlling the output
      * @throws ClientException
+     * @since 1.15
+     * @see svn_client_diff7
+     */
+    void diff(String target1, Revision revision1, String target2,
+              Revision revision2, String relativeToDir,
+              OutputStream outStream, OutputStream errStream,
+              Depth depth, Collection<String> changelists,
+              boolean ignoreAncestry, boolean noDiffDeleted, boolean force,
+              boolean copiesAsAdds, boolean ignoreProps, boolean propsOnly,
+              DiffOptions options)
+            throws ClientException;
+
+    /**
+     * Display the differences between two paths
+     * <p>
+     * Behaves exactly like the 1.15 version except that it discards stderr.
+     * @throws ClientException
      * @since 1.8
      */
     void diff(String target1, Revision revision1, String target2,
@@ -979,6 +997,7 @@ public interface ISVNClient
      * @param revision2     second revision
      * @param relativeToDir index path is relative to this path
      * @param outFileName   file name where difference are written
+     * @param errFileName   file name where error messages are written
      * @param depth         how deep to traverse into subdirectories
      * @param ignoreAncestry ignore if files are not related
      * @param noDiffDeleted no output on deleted files
@@ -989,6 +1008,23 @@ public interface ISVNClient
      * @param propsOnly     show property changes only
      * @param options       additional options for controlling the output
      * @throws ClientException
+     * @since 1.15
+     * @see svn_client_diff7
+     */
+    void diff(String target1, Revision revision1, String target2,
+              Revision revision2, String relativeToDir,
+              String outFileName, String errFileName,
+              Depth depth, Collection<String> changelists,
+              boolean ignoreAncestry, boolean noDiffDeleted, boolean force,
+              boolean copiesAsAdds, boolean ignoreProps, boolean propsOnly,
+              DiffOptions options)
+            throws ClientException;
+
+    /**
+     * Display the differences between two paths
+     * <p>
+     * Behaves exactly like the 1.15 version except that it discards stderr.
+     * @throws ClientException
      * @since 1.8
      */
     void diff(String target1, Revision revision1, String target2,
@@ -1057,6 +1093,7 @@ public interface ISVNClient
      * @param endRevision   second Revision to compare
      * @param relativeToDir index path is relative to this path
      * @param outStream     the stream to which difference are written
+     * @param errStream     the stream to which error messages are written
      * @param depth         how deep to traverse into subdirectories
      * @param changelists  if non-null, filter paths using changelists
      * @param ignoreAncestry ignore if files are not related
@@ -1068,6 +1105,23 @@ public interface ISVNClient
      * @param propsOnly     show property changes only
      * @param options       additional options for controlling the output
      * @throws ClientException
+     * @since 1.15
+     * @see svn_client_diff_peg7
+     */
+    void diff(String target, Revision pegRevision, Revision startRevision,
+              Revision endRevision, String relativeToDir,
+              OutputStream outStream, OutputStream errStream,
+              Depth depth, Collection<String> changelists,
+              boolean ignoreAncestry, boolean noDiffDeleted, boolean force,
+              boolean copiesAsAdds, boolean ignoreProps, boolean propsOnly,
+              DiffOptions options)
+            throws ClientException;
+
+    /**
+     * Display the differences between two paths
+     * <p>
+     * Behaves exactly like the 1.15 version except that it discards stderr.
+     * @throws ClientException
      * @since 1.8
      */
     void diff(String target, Revision pegRevision, Revision startRevision,
@@ -1086,6 +1140,7 @@ public interface ISVNClient
      * @param endRevision   second Revision to compare
      * @param relativeToDir index path is relative to this path
      * @param outFileName   file name where difference are written
+     * @param errFileName   file name where error messages are written
      * @param depth         how deep to traverse into subdirectories
      * @param changelists  if non-null, filter paths using changelists
      * @param ignoreAncestry ignore if files are not related
@@ -1097,6 +1152,23 @@ public interface ISVNClient
      * @param propsOnly     show property changes only
      * @param options       additional options for controlling the output
      * @throws ClientException
+     * @since 1.15
+     * @see svn_client_diff_peg7
+     */
+    void diff(String target, Revision pegRevision, Revision startRevision,
+              Revision endRevision, String relativeToDir,
+              String outFileName, String errFileName,
+              Depth depth, Collection<String> changelists,
+              boolean ignoreAncestry, boolean noDiffDeleted, boolean force,
+              boolean copiesAsAdds, boolean ignoreProps, boolean propsOnly,
+              DiffOptions options)
+            throws ClientException;
+
+    /**
+     * Display the differences between two paths
+     * <p>
+     * Behaves exactly like the 1.15 version except that it discards stderr.
+     * @throws ClientException
      * @since 1.8
      */
     void diff(String target, Revision pegRevision, Revision startRevision,

Modified: subversion/branches/javahl-1.15/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
==============================================================================
--- subversion/branches/javahl-1.15/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java	Sun May 10 11:24:26 2026	(r1934046)
+++ subversion/branches/javahl-1.15/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java	Sun May 10 12:09:41 2026	(r1934047)
@@ -513,42 +513,87 @@ public class SVNClient implements ISVNCl
                         discoverChangedPaths, depth, revProps, callback);
     }
 
-    public void diff(String target1, Revision revision1, String target2,
-                     Revision revision2, String relativeToDir,
-                     String outFileName, Depth depth,
-                     Collection<String> changelists,
+    // svn_client_diff7
+
+    @Override
+    public void diff(String target1, Revision revision1,
+                     String target2, Revision revision2,
+                     String relativeToDir,
+                     String outFileName,
+                     Depth depth, Collection<String> changelists,
                      boolean ignoreAncestry, boolean noDiffDeleted,
                      boolean force, boolean copiesAsAdds)
             throws ClientException
     {
-        try {
-            OutputStream stream = new FileOutputStream(outFileName);
-            diff(target1, revision1, target2, revision2, relativeToDir,
-                 stream, depth, changelists, ignoreAncestry, noDiffDeleted,
-                 force, copiesAsAdds, false, false, null);
-        } catch (FileNotFoundException ex) {
-            throw ClientException.fromException(ex);
-        }
+        diff(target1, revision1, target2, revision2,
+             relativeToDir, outFileName, /*errFileName*/ null,
+             depth, changelists, ignoreAncestry, noDiffDeleted,
+             force, copiesAsAdds, /*ignoreProps*/ false, /*propsOnly*/ false,
+             /*options*/ null);
     }
 
-    public void diff(String target1, Revision revision1, String target2,
-                     Revision revision2, String relativeToDir,
-                     OutputStream stream, Depth depth,
-                     Collection<String> changelists,
+    @Override
+    public void diff(String target1, Revision revision1,
+                     String target2, Revision revision2,
+                     String relativeToDir,
+                     OutputStream outStream,
+                     Depth depth, Collection<String> changelists,
                      boolean ignoreAncestry, boolean noDiffDeleted,
                      boolean force, boolean copiesAsAdds,
                      boolean ignoreProps, boolean propsOnly)
             throws ClientException
     {
-        diff(target1, revision1, target2, revision2, relativeToDir,
-             stream, depth, changelists, ignoreAncestry, noDiffDeleted,
-             force, copiesAsAdds, ignoreProps, propsOnly, null);
+        diff(target1, revision1, target2, revision2,
+             relativeToDir, outStream, /*errStream*/ null,
+             depth, changelists, ignoreAncestry, noDiffDeleted,
+             force, copiesAsAdds, ignoreProps, propsOnly,
+             /*options*/ null);
     }
 
-    public void diff(String target1, Revision revision1, String target2,
-                     Revision revision2, String relativeToDir,
-                     String outFileName, Depth depth,
-                     Collection<String> changelists,
+    @Override
+    public void diff(String target1, Revision revision1,
+                     String target2, Revision revision2,
+                     String relativeToDir,
+                     String outFileName,
+                     Depth depth, Collection<String> changelists,
+                     boolean ignoreAncestry, boolean noDiffDeleted,
+                     boolean force, boolean copiesAsAdds,
+                     boolean ignoreProps, boolean propsOnly,
+                     DiffOptions options)
+            throws ClientException
+    {
+        diff(target1, revision1, target2, revision2,
+             relativeToDir, outFileName, /*errFileName*/ null,
+             depth, changelists, ignoreAncestry, noDiffDeleted,
+             force, copiesAsAdds, ignoreProps, propsOnly,
+             options);
+    }
+
+    @Override
+    public void diff(String target1, Revision revision1,
+                     String target2, Revision revision2,
+                     String relativeToDir,
+                     OutputStream outStream,
+                     Depth depth, Collection<String> changelists,
+                     boolean ignoreAncestry, boolean noDiffDeleted,
+                     boolean force, boolean copiesAsAdds,
+                     boolean ignoreProps, boolean propsOnly,
+                     DiffOptions options)
+            throws ClientException
+    {
+        diff(target1, revision1, target2, revision2,
+             relativeToDir, outStream, /*errStream*/ null,
+             depth, changelists, ignoreAncestry, noDiffDeleted,
+             force, copiesAsAdds, ignoreProps, propsOnly,
+             options);
+    }
+
+    @Override
+    public void diff(String target1, Revision revision1,
+                     String target2, Revision revision2,
+                     String relativeToDir,
+                     String outFileName, String errFileName,
+                     Depth depth, Collection<String> changelists,
                      boolean ignoreAncestry, boolean noDiffDeleted,
                      boolean force, boolean copiesAsAdds,
                      boolean ignoreProps, boolean propsOnly,
@@ -556,62 +601,112 @@ public class SVNClient implements ISVNCl
             throws ClientException
     {
         try {
-            OutputStream stream = new FileOutputStream(outFileName);
-            diff(target1, revision1, target2, revision2, relativeToDir,
-                 stream, depth, changelists, ignoreAncestry, noDiffDeleted,
-                 force, copiesAsAdds, ignoreProps, propsOnly, options);
+            OutputStream outStream = new FileOutputStream(outFileName);
+            OutputStream errStream = errFileName == null
+                ? null : new FileOutputStream(errFileName);
+
+            diff(target1, revision1, target2, revision2,
+                 relativeToDir, outStream, errStream,
+                 depth, changelists, ignoreAncestry, noDiffDeleted,
+                 force, copiesAsAdds, ignoreProps, propsOnly,
+                 options);
         } catch (FileNotFoundException ex) {
             throw ClientException.fromException(ex);
         }
     }
 
-    public native void diff(String target1, Revision revision1, String target2,
-                            Revision revision2, String relativeToDir,
-                            OutputStream stream, Depth depth,
-                            Collection<String> changelists,
+    @Override
+    public native void diff(String target1, Revision revision1,
+                            String target2, Revision revision2,
+                            String relativeToDir,
+                            OutputStream outStream, OutputStream errStream,
+                            Depth depth, Collection<String> changelists,
                             boolean ignoreAncestry, boolean noDiffDeleted,
                             boolean force, boolean copiesAsAdds,
                             boolean ignoreProps, boolean propsOnly,
                             DiffOptions options)
             throws ClientException;
 
+    // svn_client_diff_peg7
 
-
+    @Override
     public void diff(String target, Revision pegRevision,
                      Revision startRevision, Revision endRevision,
-                     String relativeToDir, String outFileName,
+                     String relativeToDir,
+                     String outFileName,
                      Depth depth, Collection<String> changelists,
                      boolean ignoreAncestry, boolean noDiffDeleted,
                      boolean force, boolean copiesAsAdds)
             throws ClientException
     {
-        try {
-            OutputStream stream = new FileOutputStream(outFileName);
-            diff(target, pegRevision, startRevision, endRevision,
-                 relativeToDir, stream, depth, changelists, ignoreAncestry,
-                 noDiffDeleted, force, copiesAsAdds, false, false, null);
-        } catch (FileNotFoundException ex) {
-            throw ClientException.fromException(ex);
-        }
+        diff(target, pegRevision, startRevision, endRevision,
+             relativeToDir, outFileName, /*errFileName*/ null,
+             depth, changelists, ignoreAncestry, noDiffDeleted,
+             force, copiesAsAdds, /*ignoreProps*/ false, /*propsOnly*/ false,
+             /*options*/ null);
     }
 
+    @Override
     public void diff(String target, Revision pegRevision,
                      Revision startRevision, Revision endRevision,
-                     String relativeToDir, OutputStream stream,
+                     String relativeToDir,
+                     OutputStream outStream,
                      Depth depth, Collection<String> changelists,
                      boolean ignoreAncestry, boolean noDiffDeleted,
                      boolean force, boolean copiesAsAdds,
                      boolean ignoreProps, boolean propsOnly)
             throws ClientException
     {
-        diff(target, pegRevision, startRevision, endRevision, relativeToDir,
-             stream, depth, changelists, ignoreAncestry, noDiffDeleted,
-             force, copiesAsAdds, ignoreProps, propsOnly, null);
+        diff(target, pegRevision, startRevision, endRevision,
+             relativeToDir, outStream, /*errStream*/ null,
+             depth, changelists, ignoreAncestry, noDiffDeleted,
+             force, copiesAsAdds, ignoreProps, propsOnly,
+             /*options*/ null);
+    }
+
+    @Override
+    public void diff(String target, Revision pegRevision,
+                     Revision startRevision, Revision endRevision,
+                     String relativeToDir,
+                     String outFileName,
+                     Depth depth, Collection<String> changelists,
+                     boolean ignoreAncestry, boolean noDiffDeleted,
+                     boolean force, boolean copiesAsAdds,
+                     boolean ignoreProps, boolean propsOnly,
+                     DiffOptions options)
+            throws ClientException
+    {
+        diff(target, pegRevision, startRevision, endRevision,
+             relativeToDir, outFileName, /*errFileName*/ null,
+             depth, changelists, ignoreAncestry, noDiffDeleted,
+             force, copiesAsAdds, ignoreProps, propsOnly,
+             options);
+    }
+
+    @Override
+    public void diff(String target, Revision pegRevision,
+                     Revision startRevision, Revision endRevision,
+                     String relativeToDir,
+                     OutputStream outStream,
+                     Depth depth, Collection<String> changelists,
+                     boolean ignoreAncestry, boolean noDiffDeleted,
+                     boolean force, boolean copiesAsAdds,
+                     boolean ignoreProps, boolean propsOnly,
+                     DiffOptions options)
+            throws ClientException
+    {
+        diff(target, pegRevision, startRevision, endRevision,
+             relativeToDir, outStream, /*errStream*/ null,
+             depth, changelists, ignoreAncestry, noDiffDeleted,
+             force, copiesAsAdds, ignoreProps, propsOnly,
+             options);
     }
 
+    @Override
     public void diff(String target, Revision pegRevision,
                      Revision startRevision, Revision endRevision,
-                     String relativeToDir, String outFileName,
+                     String relativeToDir,
+                     String outFileName, String errFileName,
                      Depth depth, Collection<String> changelists,
                      boolean ignoreAncestry, boolean noDiffDeleted,
                      boolean force, boolean copiesAsAdds,
@@ -620,18 +715,25 @@ public class SVNClient implements ISVNCl
             throws ClientException
     {
         try {
-            OutputStream stream = new FileOutputStream(outFileName);
-            diff(target, pegRevision, startRevision, endRevision, relativeToDir,
-                 stream, depth, changelists, ignoreAncestry, noDiffDeleted,
-                 force, copiesAsAdds, ignoreProps, propsOnly, options);
+            OutputStream outStream = new FileOutputStream(outFileName);
+            OutputStream errStream = errFileName == null
+                ? null : new FileOutputStream(errFileName);
+
+            diff(target, pegRevision, startRevision, endRevision,
+                 relativeToDir, outStream, errStream,
+                 depth, changelists, ignoreAncestry, noDiffDeleted,
+                 force, copiesAsAdds, ignoreProps, propsOnly,
+                 options);
         } catch (FileNotFoundException ex) {
             throw ClientException.fromException(ex);
         }
     }
 
+    @Override
     public native void diff(String target, Revision pegRevision,
                             Revision startRevision, Revision endRevision,
-                            String relativeToDir, OutputStream stream,
+                            String relativeToDir,
+                            OutputStream outStream, OutputStream errStream,
                             Depth depth, Collection<String> changelists,
                             boolean ignoreAncestry, boolean noDiffDeleted,
                             boolean force, boolean copiesAsAdds,
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.