I took a stab at writing the JavaHL boiler-plate code for this, as attached,
though I'm unfamiliar with JavaHL. It seems to require modifying 5 java files
and creating 3 new ones. Is that right, JavaHL experts? It seems a lot.
The implementation in the core library is empty, as yet, in the attached patch.
- Julian
>> interface MergeinfoDiffCallback {
>> void mergeinfoDiff(int revision,
>> Map<String, Mergeinfo> pathToAddedMergeinfo,
>> Map<String, Mergeinfo> pathToRemovedMergeinfo);
>> }
>>
>> void getMergeinfoDiff(String rootPath,
>> long fromRev, long toRev,
>> MergeinfoDiffCallback callback)
>> throws ClientException;
Add boiler-plate code in JavaHL for a new API to get per-revision mergeinfo
diffs.
Suggested by: Marc Strapetz <marc.strapetz{_AT_}syntevo.com>
* subversion/include/svn_ra.h,
subversion/libsvn_ra/ra_loader.c
(svn_ra_get_mergeinfo): New function, with an empty implementation.
In subversion/bindings/javahl/:
* native/MergeinfoDiffCallback.h,
native/MergeinfoDiffCallback.cpp
New files, copied from LogMessageCallback.* and adjusted.
* native/org_apache_subversion_javahl_remote_RemoteSession.cpp
(Java_org_apache_subversion_javahl_remote_RemoteSession_getMergeinfoDiffs):
New function.
* native/RemoteSession.h,
native/RemoteSession.cpp
(getMergeinfoDiffs): New method.
* src/org/apache/subversion/javahl/callback/MergeinfoDiffCallback.java
New file, copied from LogMessageCallback.java and adjusted.
* src/org/apache/subversion/javahl/ISVNRemote.java
(getMergeinfoDiffs): New method.
* src/org/apache/subversion/javahl/remote/RemoteSession.java
(svn_ra_get_mergeinfo_diffs): New function.
--This line, and those below, will be ignored--
Index: subversion/bindings/javahl/native/MergeinfoDiffCallback.cpp
===================================================================
--- subversion/bindings/javahl/native/MergeinfoDiffCallback.cpp (revision 1568992)
+++ subversion/bindings/javahl/native/MergeinfoDiffCallback.cpp (working copy)
@@ -17,60 +17,65 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
* @endcopyright
*
- * @file LogMessageCallback.cpp
- * @brief Implementation of the class LogMessageCallback
+ * @file MergeinfoDiffCallback.cpp
+ * @brief Implementation of the class MergeinfoDiffCallback
*/
-#include "LogMessageCallback.h"
+#include "MergeinfoDiffCallback.h"
#include "CreateJ.h"
#include "EnumMapper.h"
#include "JNIUtil.h"
#include "svn_time.h"
#include "svn_sorts.h"
#include "svn_compat.h"
/**
- * Create a LogMessageCallback object
+ * Create a MergeinfoDiffCallback object
* @param jcallback the Java callback object.
*/
-LogMessageCallback::LogMessageCallback(jobject jcallback)
+MergeinfoDiffCallback::MergeinfoDiffCallback(jobject jcallback)
{
m_callback = jcallback;
}
/**
- * Destroy a LogMessageCallback object
+ * Destroy a MergeinfoDiffCallback object
*/
-LogMessageCallback::~LogMessageCallback()
+MergeinfoDiffCallback::~MergeinfoDiffCallback()
{
// The m_callback does not need to be destroyed because it is the
- // passed in parameter to the Java SVNClientInterface.logMessages
+ // passed in parameter to the Java ISVNRemote.getMergeinfoDiffs
// method.
}
svn_error_t *
-LogMessageCallback::callback(void *baton,
- svn_log_entry_t *log_entry,
- apr_pool_t *pool)
+MergeinfoDiffCallback::callback(void *baton,
+ svn_revnum_t revision,
+ svn_mergeinfo_t *added_mergeinfo,
+ svn_mergeinfo_t *deleted_mergeinfo,
+ apr_pool_t *pool)
{
if (baton)
- return static_cast<LogMessageCallback *>(baton)->singleMessage(
- log_entry, pool);
+ return static_cast<MergeinfoDiffCallback *>(baton)->singleMessage(
+ revision, added_mergeinfo, deleted_mergeinfo, pool);
return SVN_NO_ERROR;
}
/**
- * Callback called for a single log message
+ * Callback called for a single mergeinfo diff
*/
svn_error_t *
-LogMessageCallback::singleMessage(svn_log_entry_t *log_entry, apr_pool_t *pool)
+MergeinfoDiffCallback::singleMessage(svn_revnum_t revision,
+ svn_mergeinfo_t *added_mergeinfo,
+ svn_mergeinfo_t *deleted_mergeinfo,
+ apr_pool_t *pool)
{
JNIEnv *env = JNIUtil::getEnv();
// Create a local frame for our references
env->PushLocalFrame(LOCAL_FRAME_SIZE);
if (JNIUtil::isJavaExceptionThrown())
@@ -78,55 +83,41 @@ LogMessageCallback::singleMessage(svn_lo
// The method id will not change during the time this library is
// loaded, so it can be cached.
static jmethodID sm_mid = 0;
if (sm_mid == 0)
{
- jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/LogMessageCallback");
+ jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/MergeinfoDiffCallback");
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN(SVN_NO_ERROR);
sm_mid = env->GetMethodID(clazz,
"singleMessage",
- "(Ljava/util/Set;JLjava/util/Map;Z)V");
+ "(JLjava/util/Map;Ljava/util/Map;)V");
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN(SVN_NO_ERROR);
}
- jobject jChangedPaths = NULL;
- if (log_entry->changed_paths)
+ jobject jAddedMergeinfo = NULL;
+ if (added_mergeinfo)
{
- apr_hash_index_t *hi;
- std::vector<jobject> jcps;
-
- for (hi = apr_hash_first(pool, log_entry->changed_paths);
- hi;
- hi = apr_hash_next(hi))
- {
- const char *path =
- reinterpret_cast<const char *>(svn__apr_hash_index_key(hi));
- svn_log_changed_path2_t *log_item =
- reinterpret_cast<svn_log_changed_path2_t *>(svn__apr_hash_index_val(hi));
-
- jobject cp = CreateJ::ChangedPath(path, log_item);
-
- jcps.push_back(cp);
- }
-
- jChangedPaths = CreateJ::Set(jcps);
+ // TODO:
+ // jAddedMergeinfo = MergeinfoAsMap(added_mergeinfo);
}
- jobject jrevprops = NULL;
- if (log_entry->revprops != NULL && apr_hash_count(log_entry->revprops) > 0)
- jrevprops = CreateJ::PropertyMap(log_entry->revprops, pool);
+ jobject jDeletedMergeinfo = NULL;
+ if (deleted_mergeinfo)
+ {
+ // TODO:
+ // jDeletedMergeinfo = MergeinfoAsMap(deleted_mergeinfo);
+ }
env->CallVoidMethod(m_callback,
sm_mid,
- jChangedPaths,
- (jlong)log_entry->revision,
- jrevprops,
- (jboolean)log_entry->has_children);
+ (jlong)revision,
+ jAddedMergeinfo,
+ jDeletedMergeinfo);
// No need to check for an exception here, because we return anyway.
env->PopLocalFrame(NULL);
return SVN_NO_ERROR;
}
Index: subversion/bindings/javahl/native/MergeinfoDiffCallback.h
===================================================================
--- subversion/bindings/javahl/native/MergeinfoDiffCallback.h (revision 1568992)
+++ subversion/bindings/javahl/native/MergeinfoDiffCallback.h (working copy)
@@ -17,40 +17,45 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
* @endcopyright
*
- * @file LogMessageCallback.h
- * @brief Interface of the class LogMessageCallback
+ * @file MergeinfoDiffCallback.h
+ * @brief Interface of the class MergeinfoDiffCallback
*/
-#ifndef LOGMESSAGECALLBACK_H
-#define LOGMESSAGECALLBACK_H
+#ifndef MERGEINFODIFFCALLBACK_H
+#define MERGEINFODIFFCALLBACK_H
#include <jni.h>
#include "svn_client.h"
/**
* This class holds a Java callback object, which will receive every
- * log message for which the callback information is requested.
+ * mergeinfo diff for which the callback information is requested.
*/
-class LogMessageCallback
+class MergeinfoDiffCallback
{
public:
- LogMessageCallback(jobject jcallback);
- ~LogMessageCallback();
+ MergeinfoDiffCallback(jobject jcallback);
+ ~MergeinfoDiffCallback();
static svn_error_t *callback(void *baton,
- svn_log_entry_t *log_entry,
+ svn_revnum_t revision,
+ svn_mergeinfo_t *added_mergeinfo,
+ svn_mergeinfo_t *deleted_mergeinfo,
apr_pool_t *pool);
protected:
- svn_error_t *singleMessage(svn_log_entry_t *log_entry, apr_pool_t *pool);
+ svn_error_t *singleMessage(svn_revnum_t revision,
+ svn_mergeinfo_t *added_mergeinfo,
+ svn_mergeinfo_t *deleted_mergeinfo,
+ apr_pool_t *pool);
private:
/**
* This a local reference to the Java object.
*/
jobject m_callback;
};
-#endif // LOGMESSAGECALLBACK_H
+#endif // MERGEINFODIFFCALLBACK_H
Index: subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
===================================================================
--- subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp (revision 1569061)
+++ subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp (working copy)
@@ -222,12 +222,25 @@
RemoteSession *ras = RemoteSession::getCppObject(jthis);
CPPADDR_NULL_PTR(ras, NULL);
return ras->getMergeinfo(jpaths, jrevision, jinherit, jinclude_descendants);
}
+JNIEXPORT void JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getMergeinfoDiffs(
+ JNIEnv *env, jobject jthis, jstring jrelpath, jlong jfromRev, jlong jtoRev,
+ jobject jmergeinfo_diff_callback)
+{
+ JNIEntry(SVNReposAccess, nativeGetMergeinfoDiffs);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras,);
+
+ ras->getMergeinfoDiffs(jrelpath, jfromRev, jtoRev,
+ jmergeinfo_diff_callback);
+}
+
// TODO: update
// TODO: switch
JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_remote_RemoteSession_nativeStatus(
JNIEnv *env, jobject jthis, jstring jstatus_target, jlong jrevision,
Index: subversion/bindings/javahl/native/RemoteSession.cpp
===================================================================
--- subversion/bindings/javahl/native/RemoteSession.cpp (revision 1569061)
+++ subversion/bindings/javahl/native/RemoteSession.cpp (working copy)
@@ -39,12 +39,13 @@
#include "svn_delta.h"
#include "CreateJ.h"
#include "EnumMapper.h"
#include "Iterator.h"
#include "LogMessageCallback.h"
+#include "MergeinfoDiffCallback.h"
#include "OutputStream.h"
#include "Prompter.h"
#include "Revision.h"
#include "RemoteSession.h"
#include "EditorProxy.h"
#include "StateReporter.h"
@@ -759,12 +760,31 @@
env->DeleteLocalRef(jmergeinfo);
}
return jcatalog;
}
+void
+RemoteSession::getMergeinfoDiffs(jstring jpath,
+ jlong jfromRev, jlong jtoRev,
+ jobject jcallback)
+{
+ SVN::Pool subPool(pool);
+ Relpath path(jpath, subPool);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+ SVN_JNI_ERR(path.error_occurred(),);
+
+ MergeinfoDiffCallback receiver(jcallback);
+ SVN_JNI_ERR(svn_ra_get_mergeinfo_diffs(
+ m_session, path.c_str(),
+ svn_revnum_t(jfromRev), svn_revnum_t(jtoRev),
+ receiver.callback, &receiver,
+ subPool.getPool()),);
+}
+
// TODO: update
// TODO: switch
namespace {
svn_error_t*
status_unlock_func(void* baton, const char* path, apr_pool_t* scratch_pool)
Index: subversion/bindings/javahl/native/RemoteSession.h
===================================================================
--- subversion/bindings/javahl/native/RemoteSession.h (revision 1569061)
+++ subversion/bindings/javahl/native/RemoteSession.h (working copy)
@@ -78,12 +78,14 @@ class RemoteSession : public SVNBase
jlong getFile(jlong jrevision, jstring jpath,
jobject jcontents, jobject jproperties);
jlong getDirectory(jlong jrevision, jstring jpath, jint jdirent_fields,
jobject jdirents, jobject jproperties);
jobject getMergeinfo(jobject jpaths, jlong jrevision, jobject jinherit,
jboolean jinclude_descendants);
+ void getMergeinfoDiffs(jstring jrootPath, jlong jfromRev, jlong jtoRev,
+ jobject jcallback);
// TODO: update
// TODO: switch
void status(jobject jthis, jstring jstatus_target,
jlong jrevision, jobject jdepth,
jobject jstatus_editor, jobject jreporter);
// TODO: diff
Index: subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/MergeinfoDiffCallback.java
===================================================================
--- subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/MergeinfoDiffCallback.java (revision 1568992)
+++ subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/MergeinfoDiffCallback.java (working copy)
@@ -21,46 +21,27 @@
* @endcopyright
*/
package org.apache.subversion.javahl.callback;
import org.apache.subversion.javahl.ISVNClient;
-import org.apache.subversion.javahl.types.ChangePath;
+import org.apache.subversion.javahl.types.Mergeinfo;
import java.util.Map;
-import java.util.Set;
/**
- * This interface is used to receive every log message for the log
- * messages found by a {@link ISVNClient#logMessages} call.
- *
- * All log messages are returned in a list, which is terminated by an
- * invocation of this callback with the revision set to SVN_INVALID_REVNUM.
- *
- * If the includeMergedRevisions parameter to {@link ISVNClient#logMessages}
- * is true, then messages returned through this callback may have the
- * hasChildren parameter set. This parameter indicates that a separate list,
- * which includes messages for merged revisions, will immediately follow.
- * This list is also terminated with SVN_INVALID_REVNUM, after which the
- * previous log message list continues.
- *
- * Log message lists may be nested arbitrarily deep, depending on the ancestry
- * of the requested paths.
+ * This interface is used to receive each mergeinfo diff
+ * found by a {@link ISVNRemote#getMergeinfoDiffs} call.
*/
-public interface LogMessageCallback
+public interface MergeinfoDiffCallback
{
/**
* The method will be called for every log message.
*
- * @param changedPaths a set of the paths that were changed
- * @param revision the revision of the commit
- * @param revprops All of the requested revision properties,
- * possibly including svn:date, svn:author,
- * and svn:log.
- * @param hasChildren when merge sensitive option was requested,
- * whether or not this entry has child entries.
+ * @param revision the revision of the commit
+ * @param pathToAddedMergeinfo mapping from path to added mergeinfo
+ * @param pathToDeletedMergeinfo mapping from path to deleted mergeinfo
*/
- public void singleMessage(Set<ChangePath> changedPaths,
- long revision,
- Map<String, byte[]> revprops,
- boolean hasChildren);
+ public void mergeinfoDiff(long revision,
+ Map<String, Mergeinfo> pathToAddedMergeinfo,
+ Map<String, Mergeinfo> pathToRemovedMergeinfo);
}
Index: subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java
===================================================================
--- subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java (revision 1569061)
+++ subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java (working copy)
@@ -337,12 +337,20 @@ public interface ISVNRemote
*/
Map<String, Mergeinfo> getMergeinfo(Iterable<String> paths, long revision,
Mergeinfo.Inheritance inherit,
boolean includeDescendants)
throws ClientException;
+ /**
+ * TODO: Doc string...
+ */
+ void getMergeinfoDiffs(String rootPath,
+ long fromRev, long toRev,
+ MergeinfoDiffCallback callback)
+ throws ClientException;
+
// TODO: update
// TODO: switch
/**
* Ask for a description of the status of a working copy with
* respect to <code>revision</code> of the session's repository,
Index: subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java
===================================================================
--- subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java (revision 1569061)
+++ subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java (working copy)
@@ -182,12 +182,20 @@ public class RemoteSession extends JNIOb
public native Map<String, Mergeinfo>
getMergeinfo(Iterable<String> paths, long revision,
Mergeinfo.Inheritance inherit,
boolean includeDescendants)
throws ClientException;
+ public void getMergeinfoDiffs(String rootPath,
+ long fromRev, long toRev,
+ MergeinfoDiffCallback callback)
+ throws ClientException
+ {
+ nativeGetMergeinfoDiffs(rootPath, fromRev, toRev, callback);
+ }
+
// TODO: update
// TODO: switch
public ISVNReporter status(String statusTarget,
long revision, Depth depth,
RemoteStatus receiver)
@@ -335,12 +343,17 @@ public class RemoteSession extends JNIOb
throws ClientException;
private native long nativeGetDirectory(long revision, String path,
int direntFields,
Map<String, DirEntry> dirents,
Map<String, byte[]> properties)
throws ClientException;
+ private native void nativeGetMergeinfoDiffs(String rootPath,
+ long fromRev,
+ long toRev,
+ MergeinfoDiffCallback callback)
+ throws ClientException;
private native void nativeStatus(String statusTarget,
long revision, Depth depth,
ISVNEditor statusEditor,
ISVNReporter reporter)
throws ClientException;
private native boolean nativeHasCapability(String capability)
Index: subversion/include/svn_ra.h
===================================================================
--- subversion/include/svn_ra.h (revision 1569061)
+++ subversion/include/svn_ra.h (working copy)
@@ -1187,12 +1187,40 @@
svn_revnum_t revision,
svn_mergeinfo_inheritance_t inherit,
svn_boolean_t include_descendants,
apr_pool_t *pool);
/**
+ * TODO: ...
+ *
+ * @since New in 1.9.
+ */
+typedef svn_error_t *(*svn_ra_mergeinfo_diff_func_t)(
+ void *baton,
+ svn_revnum_t revision,
+ svn_mergeinfo_t *added_mergeinfo,
+ svn_mergeinfo_t *deleted_mergeinfo,
+ apr_pool_t *scratch_pool);
+
+/**
+ * TODO: ...
+ *
+ * RELPATH is relative to the URL of SESSION.
+ *
+ * @since New in 1.9.
+ */
+svn_error_t *
+svn_ra_get_mergeinfo_diffs(svn_ra_session_t *session,
+ const char *relpath,
+ svn_revnum_t from_rev,
+ svn_revnum_t to_rev,
+ svn_ra_mergeinfo_diff_func_t mergeinfo_diff_func,
+ void *mergeinfo_diff_baton,
+ apr_pool_t *scratch_pool);
+
+/**
* Ask the RA layer to update a working copy to a new revision.
*
* The client initially provides an @a update_editor/@a update_baton to the
* RA layer; this editor contains knowledge of where the change will
* begin in the working copy (when @c open_root() is called).
*
Index: subversion/libsvn_ra/ra_loader.c
===================================================================
--- subversion/libsvn_ra/ra_loader.c (revision 1569061)
+++ subversion/libsvn_ra/ra_loader.c (working copy)
@@ -826,12 +826,33 @@
return session->vtable->get_mergeinfo(session, catalog, paths,
revision, inherit,
include_descendants, pool);
}
svn_error_t *
+svn_ra_get_mergeinfo_diffs(svn_ra_session_t *session,
+ const char *relpath,
+ svn_revnum_t from_rev,
+ svn_revnum_t to_rev,
+ svn_ra_mergeinfo_diff_func_t mergeinfo_diff_func,
+ void *mergeinfo_diff_baton,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(from_rev));
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(to_rev));
+ SVN_ERR_ASSERT(from_rev <= to_rev);
+
+ /* If server supports the mergeinfo-diffs capability, then use it,
+ * else report an unsupported feature. (Or do we want to fall back to
+ * fetching all the mergeinfo and diffing it on the client side?) */
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_ra_do_update3(svn_ra_session_t *session,
const svn_ra_reporter3_t **reporter,
void **report_baton,
svn_revnum_t revision_to_update_to,
const char *update_target,
svn_depth_t depth,