On the javahl-1.7-extensions branch:
Sync JavaHL changes from trunk up to r1494655.
git-svn-id: https://svn.apache.org/repos/asf/subversion/branches/javahl-1.7-extensions@1494817 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/Makefile.in b/Makefile.in
index bab4577..d9758fc 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -440,10 +440,12 @@
extraclean-javahl: clean-javahl
-check-javahl: javahl javahl-compat
+#check-javahl: javahl javahl-compat
+check-javahl: javahl
@FIX_JAVAHL_LIB@
$(JAVA) "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" -Djava.library.path=@JAVAHL_OBJDIR@:$(libdir) -classpath $(javahl_tests_PATH):$(javahl_tests_CLASSPATH) "-Dtest.tests=$(JAVAHL_TESTS)" org.apache.subversion.javahl.RunTests
- $(JAVA) "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" -Djava.library.path=@JAVAHL_OBJDIR@:$(libdir) -classpath $(javahl_compat_tests_PATH):$(javahl_tests_CLASSPATH) "-Dtest.tests=$(JAVAHL_TESTS)" org.tigris.subversion.javahl.RunTests
+
+# $(JAVA) "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" -Djava.library.path=@JAVAHL_OBJDIR@:$(libdir) -classpath $(javahl_compat_tests_PATH):$(javahl_tests_CLASSPATH) "-Dtest.tests=$(JAVAHL_TESTS)" org.tigris.subversion.javahl.RunTests
# "make check CLEANUP=true" will clean up directories for successful tests.
# "make check TESTS=subversion/tests/cmdline/basic_tests.py"
diff --git a/build.conf b/build.conf
index 9587ca3..3d21479 100644
--- a/build.conf
+++ b/build.conf
@@ -57,6 +57,8 @@
subversion/bindings/javahl/include/org_apache_subversion_javahl_types_Version.h
subversion/bindings/javahl/include/org_apache_subversion_javahl_types_Revision.h
subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_UserPasswordCallback.h
+ subversion/bindings/javahl/include/org_apache_subversion_javahl_remote_RemoteSession.h
+ subversion/bindings/javahl/include/org_apache_subversion_javahl_remote_RemoteFactory.h
test-scripts =
@@ -529,6 +531,7 @@
path = subversion/bindings/javahl/src/org/apache/subversion/javahl
subversion/bindings/javahl/src/org/apache/subversion/javahl/callback
subversion/bindings/javahl/src/org/apache/subversion/javahl/types
+ subversion/bindings/javahl/src/org/apache/subversion/javahl/remote
src-root = subversion/bindings/javahl/src
sources = *.java
install = javahl-java
@@ -583,6 +586,17 @@
install = javahl-javah
link-cmd = $(COMPILE_JAVAHL_JAVAH) -force
+[javahl-remote-javah]
+type = javah
+path = subversion/bindings/javahl/src/org/apache/subversion/javahl/remote
+classes = subversion/bindings/javahl/classes
+headers = subversion/bindings/javahl/include
+package = org.apache.subversion.javahl.remote
+sources = *.java
+add-deps = $(javahl_java_DEPS)
+install = javahl-javah
+link-cmd = $(COMPILE_JAVAHL_JAVAH) -force
+
[javahl-callback-javah]
type = javah
path = subversion/bindings/javahl/src/org/apache/subversion/javahl/callback
@@ -612,7 +626,7 @@
libs = libsvn_repos libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_diff
libsvn_subr libsvn_fs aprutil apriconv apr neon
sources = *.cpp *.c
-add-deps = $(javahl_javah_DEPS) $(javahl_java_DEPS) $(javahl_callback_javah_DEPS) $(javahl_types_javah_DEPS)
+add-deps = $(javahl_javah_DEPS) $(javahl_java_DEPS) $(javahl_callback_javah_DEPS) $(javahl_types_javah_DEPS) $(javahl_remote_javah_DEPS)
install = javahl-lib
# need special build rule to include -I$(JDK)/include/jni.h
compile-cmd = $(COMPILE_JAVAHL_CXX)
diff --git a/subversion/bindings/javahl/README b/subversion/bindings/javahl/README
index c8cdaf2..bcbba3f 100644
--- a/subversion/bindings/javahl/README
+++ b/subversion/bindings/javahl/README
@@ -5,7 +5,7 @@
a high level Java API for Subversion, which was originally targeted for
implementors of GUI clients and IDE plug-ins for Subversion. JavaHL
currently provides a minimal-but-complete set of APIs which expose the
-core Subversion C API to Java. It requires a JRE 1.2+ (runtime).
+core Subversion C API to Java. It requires a JRE 1.5+ (runtime).
It is currently quite mature, and can be considered for production use.
@@ -14,7 +14,7 @@
------------
JavaHL should compile and run under Linux, Win32, and Mac OS X with a
-JDK 1.3+.
+JDK 1.5+.
Its build will produce both a native library (libsvnjavahl-1.so on Unix
or libsvnjavahl-1.dll on Win32) and a platform independent archive of
@@ -62,9 +62,6 @@
Subclipse, Eclipse IDE plug-in <http://subclipse.tigris.org/>
-Svn-Up, Swing GUI and plug-in for the IDEA IDE
-<http://svnup.tigris.org/>
-
Why not 100% pure Java?
-----------------------
diff --git a/subversion/bindings/javahl/native/BlameCallback.cpp b/subversion/bindings/javahl/native/BlameCallback.cpp
index f0f84ad..5973707 100644
--- a/subversion/bindings/javahl/native/BlameCallback.cpp
+++ b/subversion/bindings/javahl/native/BlameCallback.cpp
@@ -61,11 +61,9 @@
apr_pool_t *pool)
{
if (baton)
- return ((BlameCallback *)baton)->singleLine(start_revnum, end_revnum,
- line_no, revision, rev_props,
- merged_revision,
- merged_rev_props, merged_path,
- line, local_change, pool);
+ return static_cast<BlameCallback *>(baton)->singleLine(start_revnum,
+ end_revnum, line_no, revision, rev_props, merged_revision,
+ merged_rev_props, merged_path, line, local_change, pool);
return SVN_NO_ERROR;
}
diff --git a/subversion/bindings/javahl/native/ChangelistCallback.cpp b/subversion/bindings/javahl/native/ChangelistCallback.cpp
index 5a9c9fc..d04ba32 100644
--- a/subversion/bindings/javahl/native/ChangelistCallback.cpp
+++ b/subversion/bindings/javahl/native/ChangelistCallback.cpp
@@ -53,7 +53,8 @@
apr_pool_t *pool)
{
if (baton)
- ((ChangelistCallback *)baton)->doChangelist(path, changelist, pool);
+ static_cast<ChangelistCallback *>(baton)->doChangelist(path, changelist,
+ pool);
return SVN_NO_ERROR;
}
diff --git a/subversion/bindings/javahl/native/ClientContext.cpp b/subversion/bindings/javahl/native/ClientContext.cpp
index b7e2de1..d8fe608 100644
--- a/subversion/bindings/javahl/native/ClientContext.cpp
+++ b/subversion/bindings/javahl/native/ClientContext.cpp
@@ -39,39 +39,12 @@
ClientContext::ClientContext(jobject jsvnclient, SVN::Pool &pool)
- : m_prompter(NULL),
- m_cancelOperation(false)
+ : OperationContext(pool)
{
- JNIEnv *env = JNIUtil::getEnv();
-
- /* Grab a global reference to the Java object embedded in the parent Java
- object. */
static jfieldID ctxFieldID = 0;
- if (ctxFieldID == 0)
- {
- jclass clazz = env->GetObjectClass(jsvnclient);
- if (JNIUtil::isJavaExceptionThrown())
- return;
+ attachJavaObject(jsvnclient, "L"JAVA_PACKAGE"/SVNClient$ClientContext;", "clientContext", &ctxFieldID);
- ctxFieldID = env->GetFieldID(clazz, "clientContext",
- "L"JAVA_PACKAGE"/SVNClient$ClientContext;");
- if (JNIUtil::isJavaExceptionThrown() || ctxFieldID == 0)
- return;
-
- env->DeleteLocalRef(clazz);
- }
-
- jobject jctx = env->GetObjectField(jsvnclient, ctxFieldID);
- if (JNIUtil::isJavaExceptionThrown())
- return;
-
- m_jctx = env->NewGlobalRef(jctx);
- if (JNIUtil::isJavaExceptionThrown())
- return;
-
- env->DeleteLocalRef(jctx);
-
- SVN_JNI_ERR(svn_client_create_context(&m_context, pool.getPool()),
+ SVN_JNI_ERR(svn_client_create_context(&m_context,pool.getPool()),
);
/* Clear the wc_ctx as we don't want to maintain this unconditionally
@@ -95,23 +68,18 @@
m_context->conflict_func2 = resolve;
m_context->conflict_baton2 = m_jctx;
- m_context->client_name = "javahl";
- m_pool = &pool;
+ m_context->client_name = getClientName();
}
ClientContext::~ClientContext()
{
- delete m_prompter;
-
- JNIEnv *env = JNIUtil::getEnv();
- env->DeleteGlobalRef(m_jctx);
}
/* 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()
is called on the same pool.
-
+
The use of this function assumes a proper subpool behavior by its user,
(read: SVNClient) usually per request.
*/
@@ -125,7 +93,7 @@
static apr_status_t clear_ctx_ptrs(void *ptr)
{
- clearctx_baton_t *bt = (clearctx_baton_t*)ptr;
+ clearctx_baton_t *bt = reinterpret_cast<clearctx_baton_t*>(ptr);
/* Reset all values to those before overwriting by getContext. */
*bt->ctx = *bt->backup;
@@ -139,7 +107,6 @@
ClientContext::getContext(CommitMessage *message, SVN::Pool &in_pool)
{
apr_pool_t *pool = in_pool.getPool();
- svn_auth_baton_t *ab;
svn_client_ctx_t *ctx = m_context;
/* Make a temporary copy of ctx to restore at pool cleanup to avoid
@@ -148,127 +115,25 @@
Note that this allows creating a stack of context changes if
the function is invoked multiple times with different pools.
*/
- clearctx_baton_t *bt = (clearctx_baton_t *)apr_pcalloc(pool, sizeof(*bt));
+ clearctx_baton_t *bt =
+ reinterpret_cast<clearctx_baton_t *>(apr_pcalloc(pool, sizeof(*bt)));
bt->ctx = ctx;
- bt->backup = (svn_client_ctx_t*)apr_pmemdup(pool, ctx, sizeof(*ctx));
+ bt->backup =
+ reinterpret_cast<svn_client_ctx_t*>(apr_pmemdup(pool, ctx, sizeof(*ctx)));
apr_pool_cleanup_register(in_pool.getPool(), bt, clear_ctx_ptrs,
clear_ctx_ptrs);
-
if (!ctx->config)
{
- const char *configDir = m_configDir.c_str();
- if (m_configDir.empty())
- configDir = NULL;
- SVN_JNI_ERR(svn_config_get_config(&(ctx->config), configDir,
- m_pool->getPool()),
- NULL);
+ apr_hash_t * configData = getConfigData();
+ ctx->config = configData;
bt->backup->config = ctx->config;
}
- svn_config_t *config = (svn_config_t *) apr_hash_get(ctx->config,
- SVN_CONFIG_CATEGORY_CONFIG,
- APR_HASH_KEY_STRING);
-
- /* The whole list of registered providers */
- apr_array_header_t *providers;
-
- /* Populate the registered providers with the platform-specific providers */
- SVN_JNI_ERR(svn_auth_get_platform_specific_client_providers(&providers,
- config,
- pool),
- NULL);
-
- /* Use the prompter (if available) to prompt for password and cert
- * caching. */
- svn_auth_plaintext_prompt_func_t plaintext_prompt_func = NULL;
- void *plaintext_prompt_baton = NULL;
- svn_auth_plaintext_passphrase_prompt_func_t plaintext_passphrase_prompt_func;
- void *plaintext_passphrase_prompt_baton = NULL;
-
- if (m_prompter != NULL)
- {
- plaintext_prompt_func = Prompter::plaintext_prompt;
- plaintext_prompt_baton = m_prompter;
- plaintext_passphrase_prompt_func = Prompter::plaintext_passphrase_prompt;
- plaintext_passphrase_prompt_baton = m_prompter;
- }
-
- /* The main disk-caching auth providers, for both
- * 'username/password' creds and 'username' creds. */
- svn_auth_provider_object_t *provider;
-
- svn_auth_get_simple_provider2(&provider, plaintext_prompt_func,
- plaintext_prompt_baton, pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- svn_auth_get_username_provider(&provider, pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- /* The server-cert, client-cert, and client-cert-password providers. */
- SVN_JNI_ERR(svn_auth_get_platform_specific_provider(&provider,
- "windows",
- "ssl_server_trust",
- pool),
- NULL);
-
- if (provider)
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- svn_auth_get_ssl_server_trust_file_provider(&provider, pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
- svn_auth_get_ssl_client_cert_file_provider(&provider, pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
- svn_auth_get_ssl_client_cert_pw_file_provider2(&provider,
- plaintext_passphrase_prompt_func,
- plaintext_passphrase_prompt_baton, pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- if (m_prompter != NULL)
- {
- /* Two basic prompt providers: username/password, and just username.*/
- provider = m_prompter->getProviderSimple(in_pool);
-
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- provider = m_prompter->getProviderUsername(in_pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- /* Three ssl prompt providers, for server-certs, client-certs,
- * and client-cert-passphrases. */
- provider = m_prompter->getProviderServerSSLTrust(in_pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- provider = m_prompter->getProviderClientSSL(in_pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- provider = m_prompter->getProviderClientSSLPassword(in_pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
- }
-
- /* Build an authentication baton to give to libsvn_client. */
- svn_auth_open(&ab, providers, pool);
-
- /* Place any default --username or --password credentials into the
- * auth_baton's run-time parameter hash. ### Same with --no-auth-cache? */
- if (!m_userName.empty())
- svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_USERNAME,
- apr_pstrdup(in_pool.getPool(),
- m_userName.c_str()));
- if (!m_passWord.empty())
- svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_PASSWORD,
- apr_pstrdup(in_pool.getPool(),
- m_passWord.c_str()));
- /* Store where to retrieve authentication data? */
- if (!m_configDir.empty())
- svn_auth_set_parameter(ab, SVN_AUTH_PARAM_CONFIG_DIR,
- apr_pstrdup(in_pool.getPool(),
- m_configDir.c_str()));
-
- ctx->auth_baton = ab;
+ ctx->auth_baton = getAuthBaton(in_pool);
ctx->log_msg_baton3 = message;
- m_cancelOperation = false;
+ resetCancelRequest();
SVN_JNI_ERR(svn_wc_context_create(&ctx->wc_ctx, NULL,
in_pool.getPool(), in_pool.getPool()),
@@ -278,60 +143,6 @@
}
void
-ClientContext::username(const char *pi_username)
-{
- m_userName = (pi_username == NULL ? "" : pi_username);
-}
-
-void
-ClientContext::password(const char *pi_password)
-{
- m_passWord = (pi_password == NULL ? "" : pi_password);
-}
-
-void
-ClientContext::setPrompt(Prompter *prompter)
-{
- delete m_prompter;
- m_prompter = prompter;
-}
-
-void
-ClientContext::setConfigDirectory(const char *configDir)
-{
- // A change to the config directory may necessitate creation of
- // the config templates.
- SVN::Pool requestPool;
- SVN_JNI_ERR(svn_config_ensure(configDir, requestPool.getPool()), );
-
- m_configDir = (configDir == NULL ? "" : configDir);
- m_context->config = NULL;
-}
-
-const char *
-ClientContext::getConfigDirectory() const
-{
- return m_configDir.c_str();
-}
-
-void
-ClientContext::cancelOperation()
-{
- m_cancelOperation = true;
-}
-
-svn_error_t *
-ClientContext::checkCancel(void *cancelBaton)
-{
- ClientContext *that = (ClientContext *)cancelBaton;
- if (that->m_cancelOperation)
- return svn_error_create(SVN_ERR_CANCELLED, NULL,
- _("Operation cancelled"));
- else
- return SVN_NO_ERROR;
-}
-
-void
ClientContext::notify(void *baton,
const svn_wc_notify_t *notify,
apr_pool_t *pool)
@@ -365,54 +176,6 @@
env->DeleteLocalRef(jInfo);
}
-void
-ClientContext::progress(apr_off_t progressVal, apr_off_t total,
- void *baton, apr_pool_t *pool)
-{
- jobject jctx = (jobject) baton;
- JNIEnv *env = JNIUtil::getEnv();
-
- // Create a local frame for our references
- env->PushLocalFrame(LOCAL_FRAME_SIZE);
- if (JNIUtil::isJavaExceptionThrown())
- return;
-
- static jmethodID mid = 0;
- if (mid == 0)
- {
- jclass clazz = env->GetObjectClass(jctx);
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NOTHING();
-
- mid = env->GetMethodID(clazz, "onProgress",
- "(L"JAVA_PACKAGE"/ProgressEvent;)V");
- if (JNIUtil::isJavaExceptionThrown() || mid == 0)
- POP_AND_RETURN_NOTHING();
- }
-
- static jmethodID midCT = 0;
- jclass clazz = env->FindClass(JAVA_PACKAGE"/ProgressEvent");
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NOTHING();
-
- if (midCT == 0)
- {
- midCT = env->GetMethodID(clazz, "<init>", "(JJ)V");
- if (JNIUtil::isJavaExceptionThrown() || midCT == 0)
- POP_AND_RETURN_NOTHING();
- }
-
- // Call the Java method.
- jobject jevent = env->NewObject(clazz, midCT,
- (jlong) progressVal, (jlong) total);
- if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NOTHING();
-
- env->CallVoidMethod(jctx, mid, jevent);
-
- POP_AND_RETURN_NOTHING();
-}
-
svn_error_t *
ClientContext::resolve(svn_wc_conflict_result_t **result,
const svn_wc_conflict_description2_t *desc,
diff --git a/subversion/bindings/javahl/native/ClientContext.h b/subversion/bindings/javahl/native/ClientContext.h
index de3ece1..bd0aae9 100644
--- a/subversion/bindings/javahl/native/ClientContext.h
+++ b/subversion/bindings/javahl/native/ClientContext.h
@@ -29,6 +29,8 @@
#include <string>
+#include "OperationContext.h"
+
#include "svn_types.h"
#include "svn_client.h"
@@ -36,7 +38,6 @@
#include "Pool.h"
#include "JNIStringHolder.h"
-class Prompter;
class CommitMessage;
/**
@@ -44,25 +45,14 @@
* and implements the functions read & close of svn_stream_t.
*
*/
-class ClientContext
+class ClientContext : public OperationContext
{
private:
svn_client_ctx_t *m_context;
- const SVN::Pool *m_pool;
- jobject m_jctx;
-
- std::string m_userName;
- std::string m_passWord;
- std::string m_configDir;
-
- Prompter *m_prompter;
- bool m_cancelOperation;
protected:
static void notify(void *baton, const svn_wc_notify_t *notify,
apr_pool_t *pool);
- static void progress(apr_off_t progressVal, apr_off_t total,
- void *baton, apr_pool_t *pool);
static svn_error_t *resolve(svn_wc_conflict_result_t **result,
const svn_wc_conflict_description2_t *desc,
void *baton,
@@ -73,24 +63,9 @@
public:
ClientContext(jobject jsvnclient, SVN::Pool &pool);
- ~ClientContext();
-
- static svn_error_t *checkCancel(void *cancelBaton);
+ virtual ~ClientContext();
svn_client_ctx_t *getContext(CommitMessage *message, SVN::Pool &in_pool);
-
- void username(const char *pi_username);
- void password(const char *pi_password);
- void setPrompt(Prompter *prompter);
- void cancelOperation();
- const char *getConfigDirectory() const;
-
- /**
- * Set the configuration directory, taking the usual steps to
- * ensure that Subversion's config file templates exist in the
- * specified location.
- */
- void setConfigDirectory(const char *configDir);
};
#endif // CLIENTCONTEXT_H
diff --git a/subversion/bindings/javahl/native/CommitCallback.cpp b/subversion/bindings/javahl/native/CommitCallback.cpp
index e765a04..2ffe326 100644
--- a/subversion/bindings/javahl/native/CommitCallback.cpp
+++ b/subversion/bindings/javahl/native/CommitCallback.cpp
@@ -57,7 +57,7 @@
apr_pool_t *pool)
{
if (baton)
- return ((CommitCallback *)baton)->commitInfo(commit_info, pool);
+ return static_cast<CommitCallback *>(baton)->commitInfo(commit_info, pool);
return SVN_NO_ERROR;
}
diff --git a/subversion/bindings/javahl/native/CommitMessage.cpp b/subversion/bindings/javahl/native/CommitMessage.cpp
index 4f8db5f..a947f97 100644
--- a/subversion/bindings/javahl/native/CommitMessage.cpp
+++ b/subversion/bindings/javahl/native/CommitMessage.cpp
@@ -50,9 +50,9 @@
void *baton,
apr_pool_t *pool)
{
- if (baton && ((CommitMessage *)baton)->m_jcommitMessage)
- return ((CommitMessage *)baton)->getCommitMessage(log_msg, tmp_file,
- commit_items, pool);
+ if (baton && static_cast<CommitMessage *>(baton)->m_jcommitMessage)
+ return static_cast<CommitMessage *>(baton)->getCommitMessage(
+ log_msg, tmp_file, commit_items, pool);
*log_msg = NULL;
*tmp_file = NULL;
diff --git a/subversion/bindings/javahl/native/CopySources.cpp b/subversion/bindings/javahl/native/CopySources.cpp
index 4137f18..0ae471d 100644
--- a/subversion/bindings/javahl/native/CopySources.cpp
+++ b/subversion/bindings/javahl/native/CopySources.cpp
@@ -95,12 +95,13 @@
std::vector<jobject> sources = m_copySources.vector();
apr_array_header_t *copySources =
- apr_array_make(p, sources.size(), sizeof(svn_client_copy_source_t *));
+ apr_array_make(p, static_cast<int>(sources.size()),
+ sizeof(svn_client_copy_source_t *));
for (std::vector<jobject>::const_iterator it = sources.begin();
it < sources.end(); ++it)
{
svn_client_copy_source_t *src =
- (svn_client_copy_source_t *) apr_palloc(p, sizeof(*src));
+ reinterpret_cast<svn_client_copy_source_t *>(apr_palloc(p, sizeof(*src)));
// Extract the path or URL from the copy source.
static jmethodID getPath = 0;
@@ -141,10 +142,8 @@
// TODO: Default this to svn_opt_revision_undefined (or HEAD)
Revision rev(jrev);
- src->revision = (const svn_opt_revision_t *)
- apr_palloc(p, sizeof(*src->revision));
- memcpy((void *) src->revision, rev.revision(),
- sizeof(*src->revision));
+ src->revision = reinterpret_cast<const svn_opt_revision_t *>
+ (apr_pmemdup(p, rev.revision(), sizeof(*src->revision)));
env->DeleteLocalRef(jrev);
// Extract pegRevision from the copy source.
@@ -161,10 +160,8 @@
return NULL;
Revision pegRev(jPegRev, true);
- src->peg_revision = (const svn_opt_revision_t *)
- apr_palloc(p, sizeof(*src->peg_revision));
- memcpy((void *) src->peg_revision, pegRev.revision(),
- sizeof(*src->peg_revision));
+ src->peg_revision = reinterpret_cast<const svn_opt_revision_t *>
+ (apr_pmemdup(p, pegRev.revision(), sizeof(*src->peg_revision)));
env->DeleteLocalRef(jPegRev);
APR_ARRAY_PUSH(copySources, svn_client_copy_source_t *) = src;
diff --git a/subversion/bindings/javahl/native/CreateJ.cpp b/subversion/bindings/javahl/native/CreateJ.cpp
index 8bf9f30..fdde2ec 100644
--- a/subversion/bindings/javahl/native/CreateJ.cpp
+++ b/subversion/bindings/javahl/native/CreateJ.cpp
@@ -20,8 +20,8 @@
* ====================================================================
* @endcopyright
*
- * @file ConflictResolverCallback.cpp
- * @brief Implementation of the class ConflictResolverCallback.
+ * @file CreateJ.cpp
+ * @brief Implementation of the class CreateJ.
*/
#include "svn_error.h"
@@ -35,6 +35,7 @@
#include "../include/org_apache_subversion_javahl_CommitItemStateFlags.h"
#include "svn_path.h"
+#include "svn_props.h"
#include "private/svn_wc_private.h"
jobject
@@ -150,7 +151,8 @@
static jmethodID ctor = 0;
if (ctor == 0)
{
- ctor = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;J"
+ ctor = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;"
+ "Ljava/lang/String;J"
"Ljava/lang/String;"
"L"JAVA_PACKAGE"/types/NodeKind;"
")V");
@@ -168,7 +170,7 @@
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN_NULL;
- jobject jversion = env->NewObject(clazz, ctor, jreposURL,
+ jobject jversion = env->NewObject(clazz, ctor, jreposURL, NULL,
(jlong)version->peg_rev, jpathInRepos,
jnodeKind);
if (JNIUtil::isJavaExceptionThrown())
@@ -206,9 +208,9 @@
POP_AND_RETURN_NULL;
}
- jbyteArray jdigest = JNIUtil::makeJByteArray(
- (const signed char *)checksum->digest,
- svn_checksum_size(checksum));
+ jbyteArray jdigest
+ = JNIUtil::makeJByteArray(checksum->digest,
+ static_cast<int>(svn_checksum_size(checksum)));
if (JNIUtil::isExceptionThrown())
POP_AND_RETURN_NULL;
@@ -418,6 +420,72 @@
}
jobject
+CreateJ::LockMap(const apr_hash_t *locks, apr_pool_t *pool)
+{
+ JNIEnv *env = JNIUtil::getEnv();
+
+ if (locks == NULL)
+ return NULL;
+
+ // Create a local frame for our references
+ env->PushLocalFrame(LOCAL_FRAME_SIZE);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ jclass clazz = env->FindClass("java/util/HashMap");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ static jmethodID init_mid = 0;
+ if (init_mid == 0)
+ {
+ init_mid = env->GetMethodID(clazz, "<init>", "()V");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+ }
+
+ static jmethodID put_mid = 0;
+ if (put_mid == 0)
+ {
+ put_mid = env->GetMethodID(clazz, "put",
+ "(Ljava/lang/Object;Ljava/lang/Object;)"
+ "Ljava/lang/Object;");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+ }
+
+ jobject map = env->NewObject(clazz, init_mid);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ apr_hash_index_t *hi;
+ int i = 0;
+ for (hi = apr_hash_first(pool, (apr_hash_t *) locks); hi;
+ hi = apr_hash_next(hi), ++i)
+ {
+ const char *key = (const char *) svn__apr_hash_index_key(hi);
+ const svn_lock_t *lock = (const svn_lock_t *) svn__apr_hash_index_val(hi);
+
+ jstring jpath = JNIUtil::makeJString(key);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ jobject jlock = Lock(lock);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ env->CallObjectMethod(map, put_mid, jpath, jlock);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NULL;
+
+ env->DeleteLocalRef(jpath);
+ env->DeleteLocalRef(jlock);
+ }
+
+ return env->PopLocalFrame(map);
+}
+
+jobject
CreateJ::ChangedPath(const char *path, svn_log_changed_path2_t *log_item)
{
JNIEnv *env = JNIUtil::getEnv();
@@ -429,7 +497,7 @@
jclass clazzCP = env->FindClass(JAVA_PACKAGE"/types/ChangePath");
if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN(SVN_NO_ERROR);
+ POP_AND_RETURN_NULL;
static jmethodID midCP = 0;
if (midCP == 0)
@@ -442,7 +510,7 @@
"L"JAVA_PACKAGE"/types/Tristate;"
"L"JAVA_PACKAGE"/types/Tristate;)V");
if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN(SVN_NO_ERROR);
+ POP_AND_RETURN_NULL;
}
jstring jpath = JNIUtil::makeJString(path);
@@ -506,6 +574,7 @@
"ZZZZZL"JAVA_PACKAGE"/types/Lock;"
"L"JAVA_PACKAGE"/types/Lock;"
"JJL"JAVA_PACKAGE"/types/NodeKind;"
+ "Ljava/lang/String;Ljava/lang/String;"
"Ljava/lang/String;Ljava/lang/String;)V");
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN_NULL;
@@ -525,6 +594,8 @@
jstring jLastCommitAuthor = NULL;
jobject jLocalLock = NULL;
jstring jChangelist = NULL;
+ jstring jMovedFromAbspath = NULL;
+ jstring jMovedToAbspath = NULL;
enum svn_wc_status_kind text_status = status->node_status;
@@ -604,7 +675,8 @@
jIsSwitched, jIsFileExternal, jLocalLock,
jReposLock,
jOODLastCmtRevision, jOODLastCmtDate,
- jOODKind, jOODLastCmtAuthor, jChangelist);
+ jOODKind, jOODLastCmtAuthor, jChangelist,
+ jMovedFromAbspath, jMovedToAbspath);
return env->PopLocalFrame(ret);
}
@@ -711,7 +783,13 @@
jlong jhunkModifiedStart = wcNotify->hunk_modified_start;
jlong jhunkModifiedLength = wcNotify->hunk_modified_length;
jlong jhunkMatchedLine = wcNotify->hunk_matched_line;
- jint jhunkFuzz = wcNotify->hunk_fuzz;
+ jint jhunkFuzz = static_cast<jint>(wcNotify->hunk_fuzz);
+ if (jhunkFuzz != wcNotify->hunk_fuzz)
+ {
+ env->ThrowNew(env->FindClass("java.lang.ArithmeticException"),
+ "Overflow converting C svn_linenum_t to Java int");
+ POP_AND_RETURN_NULL;
+ }
// call the Java method
jobject jInfo = env->NewObject(clazz, midCT, jPath, jAction,
@@ -810,7 +888,8 @@
"(Ljava/lang/String;"
"L"JAVA_PACKAGE"/types/NodeKind;"
"ILjava/lang/String;"
- "Ljava/lang/String;J)V");
+ "Ljava/lang/String;J"
+ "Ljava/lang/String;)V");
if (JNIUtil::isExceptionThrown())
POP_AND_RETURN_NULL;
}
@@ -837,6 +916,9 @@
if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_IS_COPY)
jstateFlags |=
org_apache_subversion_javahl_CommitItemStateFlags_IsCopy;
+ if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN)
+ jstateFlags |=
+ org_apache_subversion_javahl_CommitItemStateFlags_LockToken;
jstring jurl = JNIUtil::makeJString(item->url);
if (JNIUtil::isJavaExceptionThrown())
@@ -851,7 +933,7 @@
// create the Java object
jobject jitem = env->NewObject(clazz, midConstructor, jpath,
jnodeKind, jstateFlags, jurl,
- jcopyUrl, jcopyRevision);
+ jcopyUrl, jcopyRevision, NULL);
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN_NULL;
@@ -1019,21 +1101,22 @@
POP_AND_RETURN_NULL;
apr_hash_index_t *hi;
- int i = 0;
for (hi = apr_hash_first(apr_hash_pool_get(prop_hash), prop_hash);
- hi; hi = apr_hash_next(hi), ++i)
+ hi; hi = apr_hash_next(hi))
{
const char *key;
svn_string_t *val;
- apr_hash_this(hi, (const void **)&key, NULL, (void **)&val);
+ apr_hash_this(hi,
+ reinterpret_cast<const void **>(&key),
+ NULL,
+ reinterpret_cast<void **>(&val));
jstring jpropName = JNIUtil::makeJString(key);
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN_NULL;
- jbyteArray jpropVal = JNIUtil::makeJByteArray(
- (const signed char *)val->data, val->len);
+ jbyteArray jpropVal = JNIUtil::makeJByteArray(val);
if (JNIUtil::isJavaExceptionThrown())
POP_AND_RETURN_NULL;
@@ -1048,6 +1131,7 @@
return env->PopLocalFrame(map);
}
+
jobject CreateJ::Set(std::vector<jobject> &objects)
{
JNIEnv *env = JNIUtil::getEnv();
diff --git a/subversion/bindings/javahl/native/CreateJ.h b/subversion/bindings/javahl/native/CreateJ.h
index eacb9b4..c1ad307 100644
--- a/subversion/bindings/javahl/native/CreateJ.h
+++ b/subversion/bindings/javahl/native/CreateJ.h
@@ -55,6 +55,9 @@
Lock(const svn_lock_t *lock);
static jobject
+ LockMap(const apr_hash_t *locks, apr_pool_t *pool);
+
+ static jobject
ChangedPath(const char *path, svn_log_changed_path2_t *log_item);
static jobject
diff --git a/subversion/bindings/javahl/native/DiffSummaryReceiver.cpp b/subversion/bindings/javahl/native/DiffSummaryReceiver.cpp
index d9173e2..f4cf052 100644
--- a/subversion/bindings/javahl/native/DiffSummaryReceiver.cpp
+++ b/subversion/bindings/javahl/native/DiffSummaryReceiver.cpp
@@ -46,7 +46,7 @@
apr_pool_t *pool)
{
if (baton)
- return ((DiffSummaryReceiver *) baton)->onSummary(diff, pool);
+ return static_cast<DiffSummaryReceiver *>(baton)->onSummary(diff, pool);
return SVN_NO_ERROR;
}
diff --git a/subversion/bindings/javahl/native/EnumMapper.cpp b/subversion/bindings/javahl/native/EnumMapper.cpp
index c41cc02..089ef6f 100644
--- a/subversion/bindings/javahl/native/EnumMapper.cpp
+++ b/subversion/bindings/javahl/native/EnumMapper.cpp
@@ -81,7 +81,8 @@
jobject EnumMapper::mapNotifyState(svn_wc_notify_state_t state)
{
// We're assuming a valid value for the C enum above
- return mapEnum(JAVA_PACKAGE"/ClientNotifyInformation$Status", (int) state);
+ return mapEnum(JAVA_PACKAGE"/ClientNotifyInformation$Status",
+ static_cast<int>(state));
}
/**
@@ -90,13 +91,15 @@
jobject EnumMapper::mapNotifyAction(svn_wc_notify_action_t action)
{
// We're assuming a valid value for the C enum above
- return mapEnum(JAVA_PACKAGE"/ClientNotifyInformation$Action", (int) action);
+ return mapEnum(JAVA_PACKAGE"/ClientNotifyInformation$Action",
+ static_cast<int>(action));
}
jobject EnumMapper::mapReposNotifyNodeAction(svn_node_action action)
{
// We're assuming a valid value for the C enum above
- return mapEnum(JAVA_PACKAGE"/ReposNotifyInformation$NodeAction", (int) action);
+ return mapEnum(JAVA_PACKAGE"/ReposNotifyInformation$NodeAction",
+ static_cast<int>(action));
}
/**
@@ -105,7 +108,8 @@
jobject EnumMapper::mapReposNotifyAction(svn_repos_notify_action_t action)
{
// We're assuming a valid value for the C enum above
- return mapEnum(JAVA_PACKAGE"/ReposNotifyInformation$Action", (int) action);
+ return mapEnum(JAVA_PACKAGE"/ReposNotifyInformation$Action",
+ static_cast<int>(action));
}
/**
@@ -114,7 +118,8 @@
jobject EnumMapper::mapNodeKind(svn_node_kind_t nodeKind)
{
// We're assuming a valid value for the C enum above
- return mapEnum(JAVA_PACKAGE"/types/NodeKind", (int) nodeKind);
+ return mapEnum(JAVA_PACKAGE"/types/NodeKind",
+ static_cast<int>(nodeKind));
}
/**
@@ -123,7 +128,8 @@
jobject EnumMapper::mapNotifyLockState(svn_wc_notify_lock_state_t state)
{
// We're assuming a valid value for the C enum above
- return mapEnum(JAVA_PACKAGE"/ClientNotifyInformation$LockStatus", (int) state);
+ return mapEnum(JAVA_PACKAGE"/ClientNotifyInformation$LockStatus",
+ static_cast<int>(state));
}
/**
@@ -132,7 +138,8 @@
jobject EnumMapper::mapScheduleKind(svn_wc_schedule_t schedule)
{
// We're assuming a valid value for the C enum above
- return mapEnum(JAVA_PACKAGE"/types/Info$ScheduleKind", (int) schedule);
+ return mapEnum(JAVA_PACKAGE"/types/Info$ScheduleKind",
+ static_cast<int>(schedule));
}
/**
@@ -142,31 +149,36 @@
{
// We're assuming a valid value for the C enum above
// The offset here is +1
- return mapEnum(JAVA_PACKAGE"/types/Status$Kind", ((int) svnKind) - 1);
+ return mapEnum(JAVA_PACKAGE"/types/Status$Kind",
+ static_cast<int>(svnKind) - 1);
}
jobject EnumMapper::mapChecksumKind(svn_checksum_kind_t kind)
{
// We're assuming a valid value for the C enum above
- return mapEnum(JAVA_PACKAGE"/types/Checksum$Kind", (int) kind);
+ return mapEnum(JAVA_PACKAGE"/types/Checksum$Kind",
+ static_cast<int>(kind));
}
jobject EnumMapper::mapConflictKind(svn_wc_conflict_kind_t kind)
{
// We're assuming a valid value for the C enum above
- return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Kind", (int) kind);
+ return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Kind",
+ static_cast<int>(kind));
}
jobject EnumMapper::mapConflictAction(svn_wc_conflict_action_t action)
{
// We're assuming a valid value for the C enum above
- return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Action", (int) action);
+ return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Action",
+ static_cast<int>(action));
}
jobject EnumMapper::mapConflictReason(svn_wc_conflict_reason_t reason)
{
// We're assuming a valid value for the C enum above
- return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Reason", (int) reason);
+ return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Reason",
+ static_cast<int>(reason));
}
int EnumMapper::toMergeinfoLogKind(jobject jLogKind)
@@ -182,45 +194,47 @@
svn_depth_t EnumMapper::toDepth(jobject jdepth)
{
// The offset for depths is -2
- return (svn_depth_t) (getOrdinal(JAVA_PACKAGE"/types/Depth", jdepth) - 2);
+ return static_cast<svn_depth_t>(getOrdinal(JAVA_PACKAGE"/types/Depth", jdepth) - 2);
}
jobject EnumMapper::mapDepth(svn_depth_t depth)
{
// We're assuming a valid value for the C enum above
// The offset for depths is -2
- return mapEnum(JAVA_PACKAGE"/types/Depth", ((int) depth) + 2);
+ return mapEnum(JAVA_PACKAGE"/types/Depth", static_cast<int>(depth) + 2);
}
jobject EnumMapper::mapOperation(svn_wc_operation_t operation)
{
// We're assuming a valid value for the C enum above
- return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Operation", (int) operation);
+ return mapEnum(JAVA_PACKAGE"/ConflictDescriptor$Operation",
+ static_cast<int>(operation));
}
jobject EnumMapper::mapTristate(svn_tristate_t tristate)
{
// We're assuming a valid value for the C enum above
return mapEnum(JAVA_PACKAGE"/types/Tristate",
- (int) (tristate - svn_tristate_false));
+ static_cast<int>(tristate - svn_tristate_false));
}
svn_wc_conflict_choice_t EnumMapper::toConflictChoice(jobject jchoice)
{
- return (svn_wc_conflict_choice_t) getOrdinal(
- JAVA_PACKAGE"/ConflictResult$Choice", jchoice);
+ return static_cast<svn_wc_conflict_choice_t>
+ (getOrdinal(JAVA_PACKAGE"/ConflictResult$Choice", jchoice));
}
svn_opt_revision_kind EnumMapper::toRevisionKind(jobject jkind)
{
- return (svn_opt_revision_kind) getOrdinal(JAVA_PACKAGE"/types/Revision$Kind",
- jkind);
+ return static_cast<svn_opt_revision_kind>
+ (getOrdinal(JAVA_PACKAGE"/types/Revision$Kind", jkind));
}
jobject EnumMapper::mapSummarizeKind(svn_client_diff_summarize_kind_t sKind)
{
// We're assuming a valid value for the C enum above
- return mapEnum(JAVA_PACKAGE"/DiffSummary$DiffKind", (int) sKind);
+ return mapEnum(JAVA_PACKAGE"/DiffSummary$DiffKind",
+ static_cast<int>(sKind));
}
jobject EnumMapper::mapEnum(const char *clazzName, int index)
@@ -282,5 +296,5 @@
POP_AND_RETURN(-1);
env->PopLocalFrame(NULL);
- return (int) jorder;
+ return static_cast<int>(jorder);
}
diff --git a/subversion/bindings/javahl/native/File.cpp b/subversion/bindings/javahl/native/File.cpp
index 7a56f71..76e92dd 100644
--- a/subversion/bindings/javahl/native/File.cpp
+++ b/subversion/bindings/javahl/native/File.cpp
@@ -82,7 +82,7 @@
/* We don't remove the local ref for jabsolutePath here, because
JNIStringHolder expects that ref to be valid for the life of
the object, which in this case is allocated on the stack.
-
+
So we just "leak" the reference, and it will get cleaned up when
we eventually exit back to Java-land. */
env->DeleteLocalRef(clazz);
diff --git a/subversion/bindings/javahl/native/InfoCallback.cpp b/subversion/bindings/javahl/native/InfoCallback.cpp
index 6ac44d1..8a9e375 100644
--- a/subversion/bindings/javahl/native/InfoCallback.cpp
+++ b/subversion/bindings/javahl/native/InfoCallback.cpp
@@ -52,7 +52,7 @@
apr_pool_t *pool)
{
if (baton)
- return ((InfoCallback *)baton)->singleInfo(path, info, pool);
+ return static_cast<InfoCallback *>(baton)->singleInfo(path, info, pool);
return SVN_NO_ERROR;
}
diff --git a/subversion/bindings/javahl/native/InputStream.cpp b/subversion/bindings/javahl/native/InputStream.cpp
index 5e8b238..1c73ba2 100644
--- a/subversion/bindings/javahl/native/InputStream.cpp
+++ b/subversion/bindings/javahl/native/InputStream.cpp
@@ -70,7 +70,7 @@
{
JNIEnv *env = JNIUtil::getEnv();
// An object of our class is passed in as the baton.
- InputStream *that = (InputStream*)baton;
+ InputStream *that = static_cast<InputStream *>(baton);
// The method id will not change during the time this library is
// loaded, so it can be cached.
@@ -89,8 +89,7 @@
}
// Allocate a Java byte array to read the data.
- jbyteArray data = JNIUtil::makeJByteArray((const signed char*)buffer,
- *len);
+ jbyteArray data = JNIUtil::makeJByteArray(buffer, static_cast<int>(*len));
if (JNIUtil::isJavaExceptionThrown())
return SVN_NO_ERROR;
@@ -99,6 +98,14 @@
if (JNIUtil::isJavaExceptionThrown())
return SVN_NO_ERROR;
+ /*
+ * Convert -1 from InputStream.read that means EOF, 0 which is subversion equivalent
+ */
+ if(jread == -1)
+ {
+ jread = 0;
+ }
+
// Put the Java byte array into a helper object to retrieve the
// data bytes.
JNIByteArray outdata(data, true);
@@ -107,7 +114,7 @@
// Catch when the Java method tells us it read too much data.
if (jread > (jint) *len)
- jread = -1;
+ jread = 0;
// In the case of success copy the data back to the Subversion
// buffer.
@@ -130,7 +137,7 @@
JNIEnv *env = JNIUtil::getEnv();
// An object of our class is passed in as the baton
- InputStream *that = (InputStream*)baton;
+ InputStream *that = reinterpret_cast<InputStream*>(baton);
// The method id will not change during the time this library is
// loaded, so it can be cached.
diff --git a/subversion/bindings/javahl/native/JNICriticalSection.cpp b/subversion/bindings/javahl/native/JNICriticalSection.cpp
index c36349a..5efa2c5 100644
--- a/subversion/bindings/javahl/native/JNICriticalSection.cpp
+++ b/subversion/bindings/javahl/native/JNICriticalSection.cpp
@@ -39,7 +39,7 @@
JNICriticalSection::JNICriticalSection(JNIMutex &mutex)
{
m_mutex = &mutex;
- apr_status_t apr_err = apr_thread_mutex_lock (mutex.m_mutex);
+ apr_status_t apr_err = apr_thread_mutex_lock(mutex.m_mutex);
if (apr_err)
{
JNIUtil::handleAPRError(apr_err, "apr_thread_mutex_lock");
@@ -53,7 +53,7 @@
*/
JNICriticalSection::~JNICriticalSection()
{
- apr_status_t apr_err = apr_thread_mutex_unlock (m_mutex->m_mutex);
+ apr_status_t apr_err = apr_thread_mutex_unlock(m_mutex->m_mutex);
if (apr_err)
{
JNIUtil::handleAPRError(apr_err, "apr_thread_mutex_unlock");
diff --git a/subversion/bindings/javahl/native/JNIMutex.cpp b/subversion/bindings/javahl/native/JNIMutex.cpp
index d5bc4f3..e718b25 100644
--- a/subversion/bindings/javahl/native/JNIMutex.cpp
+++ b/subversion/bindings/javahl/native/JNIMutex.cpp
@@ -38,7 +38,7 @@
JNIMutex::JNIMutex(apr_pool_t *pool)
{
apr_status_t apr_err =
- apr_thread_mutex_create (&m_mutex, APR_THREAD_MUTEX_NESTED, pool);
+ apr_thread_mutex_create(&m_mutex, APR_THREAD_MUTEX_NESTED, pool);
if (apr_err)
JNIUtil::handleAPRError(apr_err, "apr_thread_mutex_create");
}
@@ -48,7 +48,7 @@
*/
JNIMutex::~JNIMutex()
{
- apr_status_t apr_err = apr_thread_mutex_destroy (m_mutex);
+ apr_status_t apr_err = apr_thread_mutex_destroy(m_mutex);
if (apr_err)
JNIUtil::handleAPRError(apr_err, "apr_thread_mutex_destroy");
}
diff --git a/subversion/bindings/javahl/native/JNIStackElement.cpp b/subversion/bindings/javahl/native/JNIStackElement.cpp
index 7c00109..2ca6c6e 100644
--- a/subversion/bindings/javahl/native/JNIStackElement.cpp
+++ b/subversion/bindings/javahl/native/JNIStackElement.cpp
@@ -58,20 +58,28 @@
return;
}
- // This will call java.lang.Object.toString, even when it is
- // overriden.
- jobject oStr = env->CallNonvirtualObjectMethod(jthis, jlo, mid);
- if (JNIUtil::isJavaExceptionThrown())
- return;
-
- // Copy the result to a buffer.
- JNIStringHolder name(reinterpret_cast<jstring>(oStr));
*m_objectID = 0;
- strncat(m_objectID, name, JNIUtil::formatBufferSize -1);
+
+ if(jthis == NULL)
+ {
+ strcpy(m_objectID, "<static>");
+ }
+ else
+ {
+ // This will call java.lang.Object.toString, even when it is
+ // overriden.
+ jobject oStr = env->CallNonvirtualObjectMethod(jthis, jlo, mid);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ // Copy the result to a buffer.
+ JNIStringHolder name(reinterpret_cast<jstring>(oStr));
+ strncat(m_objectID, name, JNIUtil::formatBufferSize -1);
+ env->DeleteLocalRef(oStr);
+ }
// Release the Java string.
env->DeleteLocalRef(jlo);
- env->DeleteLocalRef(oStr);
// Remember the parameter for the exit of the method.
m_clazz = clazz;
diff --git a/subversion/bindings/javahl/native/JNIThreadData.cpp b/subversion/bindings/javahl/native/JNIThreadData.cpp
index d950e7a..e3ce334 100644
--- a/subversion/bindings/javahl/native/JNIThreadData.cpp
+++ b/subversion/bindings/javahl/native/JNIThreadData.cpp
@@ -124,7 +124,7 @@
}
JNIThreadData *newData = new JNIThreadData();
newData->m_previous =data;
- apr_err = apr_threadkey_private_set (newData, g_key);
+ apr_err = apr_threadkey_private_set(newData, g_key);
if (apr_err)
{
JNIUtil::handleAPRError(apr_err, "apr_threadkey_private_set");
@@ -151,7 +151,7 @@
JNIThreadData *oldData = data->m_previous;
delete data;
- apr_err = apr_threadkey_private_set (oldData, g_key);
+ apr_err = apr_threadkey_private_set(oldData, g_key);
if (apr_err)
{
JNIUtil::handleAPRError(apr_err, "apr_threadkey_private_set");
diff --git a/subversion/bindings/javahl/native/JNIThreadData.h b/subversion/bindings/javahl/native/JNIThreadData.h
index 629b35d..55d4141 100644
--- a/subversion/bindings/javahl/native/JNIThreadData.h
+++ b/subversion/bindings/javahl/native/JNIThreadData.h
@@ -21,7 +21,7 @@
* @endcopyright
*
* @file JNIThreadData.h
- * @brief Interface of the class JNIData
+ * @brief Interface of the class JNIThreadData
*/
#ifndef JNITHREADDATA_H
diff --git a/subversion/bindings/javahl/native/JNIUtil.cpp b/subversion/bindings/javahl/native/JNIUtil.cpp
index 109e250..c7b76f6 100644
--- a/subversion/bindings/javahl/native/JNIUtil.cpp
+++ b/subversion/bindings/javahl/native/JNIUtil.cpp
@@ -37,9 +37,13 @@
#include <apr_lib.h>
#include "svn_pools.h"
+#include "svn_fs.h"
+#include "svn_ra.h"
+#include "svn_utf.h"
#include "svn_wc.h"
#include "svn_dso.h"
#include "svn_path.h"
+#include "svn_cache_config.h"
#include <apr_file_info.h>
#include "svn_private_config.h"
#ifdef WIN32
@@ -175,6 +179,19 @@
apr_allocator_max_free_set(allocator, 1);
}
+ svn_utf_initialize(g_pool); /* Optimize character conversions */
+ svn_fs_initialize(g_pool); /* Avoid some theoretical issues */
+ svn_ra_initialize(g_pool);
+
+ /* We shouldn't fill the JVMs memory with FS cache data unless explictly
+ requested. */
+ {
+ svn_cache_config_t settings = *svn_cache_config_get();
+ settings.cache_size = 0;
+ settings.file_handle_count = 0;
+ settings.single_threaded = FALSE;
+ svn_cache_config_set(&settings);
+ }
#ifdef ENABLE_NLS
#ifdef WIN32
@@ -194,7 +211,7 @@
GetModuleFileNameW(moduleHandle, ucs2_path, inwords);
inwords = lstrlenW(ucs2_path);
outbytes = outlength = 3 * (inwords + 1);
- utf8_path = (char *)apr_palloc(pool, outlength);
+ utf8_path = reinterpret_cast<char *>(apr_palloc(pool, outlength));
apr_err = apr_conv_ucs2_to_utf8((const apr_wchar_t *) ucs2_path,
&inwords, utf8_path, &outbytes);
if (!apr_err && (inwords > 0 || outbytes == 0))
@@ -223,7 +240,7 @@
/* See http://svn.apache.org/repos/asf/subversion/trunk/notes/asp-dot-net-hack.txt */
/* ### This code really only needs to be invoked by consumers of
### the libsvn_wc library, which basically means SVNClient. */
- if (getenv ("SVN_ASP_DOT_NET_HACK"))
+ if (getenv("SVN_ASP_DOT_NET_HACK"))
{
err = svn_wc_set_adm_dir("_svn", g_pool);
if (err)
@@ -240,6 +257,8 @@
}
#endif
+ svn_error_set_malfunction_handler(svn_error_raise_on_malfunction);
+
// Build all mutexes.
g_finalizedObjectsMutex = new JNIMutex(g_pool);
if (isExceptionThrown())
@@ -377,7 +396,7 @@
char *tmp_path;
char *path = svn_dirent_dirname(err->file, err->pool);
- while (tmp_path = strchr(path, '/'))
+ while ((tmp_path = strchr(path, '/')))
*tmp_path = '.';
jstring jmethodName = makeJString(path);
@@ -493,8 +512,14 @@
if (isJavaExceptionThrown())
POP_AND_RETURN_NOTHING();
- jobjectArray jStackTrace = env->NewObjectArray(newStackTrace.size(), stClazz,
- NULL);
+ const jsize stSize = static_cast<jsize>(newStackTrace.size());
+ if (stSize != newStackTrace.size())
+ {
+ env->ThrowNew(env->FindClass("java.lang.ArithmeticException"),
+ "Overflow converting C size_t to JNI jsize");
+ POP_AND_RETURN_NOTHING();
+ }
+ jobjectArray jStackTrace = env->NewObjectArray(stSize, stClazz, NULL);
if (isJavaExceptionThrown())
POP_AND_RETURN_NOTHING();
@@ -771,12 +796,37 @@
return ret;
}
+apr_time_t
+JNIUtil::getDate(jobject jdate)
+{
+ JNIEnv *env = getEnv();
+ jclass clazz = env->FindClass("java/util/Date");
+ if (isJavaExceptionThrown())
+ return 0;
+
+ static jmethodID mid = 0;
+ if (mid == 0)
+ {
+ mid = env->GetMethodID(clazz, "getTime", "()J");
+ if (isJavaExceptionThrown())
+ return 0;
+ }
+
+ jlong jmillis = env->CallLongMethod(jdate, mid);
+ if (isJavaExceptionThrown())
+ return 0;
+
+ env->DeleteLocalRef(clazz);
+
+ return jmillis * 1000;
+}
+
/**
* Create a Java byte array from an array of characters.
* @param data the character array
* @param length the number of characters in the array
*/
-jbyteArray JNIUtil::makeJByteArray(const signed char *data, int length)
+jbyteArray JNIUtil::makeJByteArray(const void *data, int length)
{
if (data == NULL)
{
@@ -808,6 +858,15 @@
}
/**
+ * Create a Java byte array from an svn_string_t.
+ * @param str the string
+ */
+jbyteArray JNIUtil::makeJByteArray(const svn_string_t *str)
+{
+ return JNIUtil::makeJByteArray(str->data, static_cast<int>(str->len));
+}
+
+/**
* Build the error message from the svn error into buffer. This
* method calls itselft recursively for all the chained errors
*
@@ -837,7 +896,21 @@
buffer.append(svn_strerror(err->apr_err, errbuf, sizeof(errbuf)));
/* Otherwise, this must be an APR error code. */
else
- buffer.append(apr_strerror(err->apr_err, errbuf, sizeof(errbuf)));
+ {
+ /* Messages coming from apr_strerror are in the native
+ encoding, it's a good idea to convert them to UTF-8. */
+ const char* utf8_message;
+ apr_strerror(err->apr_err, errbuf, sizeof(errbuf));
+ svn_error_t* utf8_err = svn_utf_cstring_to_utf8(
+ &utf8_message, errbuf, err->pool);
+ if (utf8_err)
+ {
+ /* Use fuzzy transliteration instead. */
+ svn_error_clear(utf8_err);
+ utf8_message = svn_utf_cstring_from_utf8_fuzzy(errbuf, err->pool);
+ }
+ buffer.append(utf8_message);
+ }
buffer.append("\n");
}
if (err->message)
diff --git a/subversion/bindings/javahl/native/JNIUtil.h b/subversion/bindings/javahl/native/JNIUtil.h
index f122556..7eda7d3 100644
--- a/subversion/bindings/javahl/native/JNIUtil.h
+++ b/subversion/bindings/javahl/native/JNIUtil.h
@@ -41,6 +41,8 @@
#define JAVA_PACKAGE "org/apache/subversion/javahl"
+struct svn_string_t;
+
/**
* Class to hold a number of JNI related utility methods. No Objects
* of this class are ever created.
@@ -62,8 +64,10 @@
int aprErr = -1);
static void throwNullPointerException(const char *message);
- static jbyteArray makeJByteArray(const signed char *data, int length);
+ static jbyteArray makeJByteArray(const void *data, int length);
+ static jbyteArray makeJByteArray(const svn_string_t *str);
static jobject createDate(apr_time_t time);
+ static apr_time_t getDate(jobject jdate);
static void logMessage(const char *message);
static int getLogLevel();
static char *getFormatBuffer();
@@ -214,9 +218,9 @@
*/
#define SVN_JNI_NULL_PTR_EX(expr, str, ret_val) \
- if (expr == NULL) { \
+ if ((expr) == NULL) { \
JNIUtil::throwNullPointerException(str); \
- return ret_val ; \
+ return ret_val; \
}
/**
@@ -235,7 +239,7 @@
svn_error_t *svn_jni_err__temp = (expr); \
if (svn_jni_err__temp != SVN_NO_ERROR) { \
JNIUtil::handleSVNError(svn_jni_err__temp); \
- return ret_val ; \
+ return ret_val; \
} \
} while (0)
@@ -251,7 +255,7 @@
do \
{ \
env->PopLocalFrame(NULL); \
- return ret_val ; \
+ return ret_val; \
} \
while (0)
@@ -272,4 +276,12 @@
*/
#define POP_AND_RETURN_NULL POP_AND_RETURN(NULL)
+#define CPPADDR_NULL_PTR(expr, ret_val) \
+ do { \
+ if ((expr) == NULL) { \
+ JNIUtil::throwError(_("bad C++ this")); \
+ return ret_val; \
+ } \
+ } while (0)
+
#endif // JNIUTIL_H
diff --git a/subversion/bindings/javahl/native/ListCallback.cpp b/subversion/bindings/javahl/native/ListCallback.cpp
index 385bb1d..6de8857 100644
--- a/subversion/bindings/javahl/native/ListCallback.cpp
+++ b/subversion/bindings/javahl/native/ListCallback.cpp
@@ -54,11 +54,11 @@
const svn_dirent_t *dirent,
const svn_lock_t *lock,
const char *abs_path,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
if (baton)
- return ((ListCallback *)baton)->doList(path, dirent, lock, abs_path,
- pool);
+ return static_cast<ListCallback *>(baton)->doList(
+ path, dirent, lock, abs_path, scratch_pool);
return SVN_NO_ERROR;
}
diff --git a/subversion/bindings/javahl/native/ListCallback.h b/subversion/bindings/javahl/native/ListCallback.h
index 57e17a9..ac2ec6c 100644
--- a/subversion/bindings/javahl/native/ListCallback.h
+++ b/subversion/bindings/javahl/native/ListCallback.h
@@ -45,7 +45,7 @@
const svn_dirent_t *dirent,
const svn_lock_t *lock,
const char *abs_path,
- apr_pool_t *pool);
+ apr_pool_t *scratch_pool);
protected:
svn_error_t *doList(const char *path,
diff --git a/subversion/bindings/javahl/native/LogMessageCallback.cpp b/subversion/bindings/javahl/native/LogMessageCallback.cpp
index cdd71fc..237aabf 100644
--- a/subversion/bindings/javahl/native/LogMessageCallback.cpp
+++ b/subversion/bindings/javahl/native/LogMessageCallback.cpp
@@ -57,7 +57,8 @@
apr_pool_t *pool)
{
if (baton)
- return ((LogMessageCallback *)baton)->singleMessage(log_entry, pool);
+ return static_cast<LogMessageCallback *>(baton)->singleMessage(
+ log_entry, pool);
return SVN_NO_ERROR;
}
@@ -101,9 +102,10 @@
hi;
hi = apr_hash_next(hi))
{
- const char *path = (const char *) svn__apr_hash_index_key(hi);
+ const char *path =
+ reinterpret_cast<const char *>(svn__apr_hash_index_key(hi));
svn_log_changed_path2_t *log_item =
- (svn_log_changed_path2_t *) svn__apr_hash_index_val(hi);
+ reinterpret_cast<svn_log_changed_path2_t *>(svn__apr_hash_index_val(hi));
jobject cp = CreateJ::ChangedPath(path, log_item);
diff --git a/subversion/bindings/javahl/native/OperationContext.cpp b/subversion/bindings/javahl/native/OperationContext.cpp
new file mode 100644
index 0000000..1d20446
--- /dev/null
+++ b/subversion/bindings/javahl/native/OperationContext.cpp
@@ -0,0 +1,369 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file OperationContext.cpp
+ * @brief Implementation of the class OperationContext
+ */
+
+#include "svn_client.h"
+#include "private/svn_wc_private.h"
+#include "svn_private_config.h"
+
+#include "OperationContext.h"
+#include "JNIUtil.h"
+#include "JNICriticalSection.h"
+
+#include "Prompter.h"
+#include "CreateJ.h"
+#include "EnumMapper.h"
+#include "CommitMessage.h"
+
+OperationContext::OperationContext(SVN::Pool &pool)
+ : m_config(NULL),
+ m_prompter(NULL),
+ m_cancelOperation(false),
+ m_pool(&pool),
+ m_jctx(NULL)
+{}
+
+void
+OperationContext::attachJavaObject(
+ jobject contextHolder, const char *contextClassType,
+ const char *contextFieldName, jfieldID * ctxFieldID)
+{
+ JNIEnv *env = JNIUtil::getEnv();
+
+ /* Grab a global reference to the Java object embedded in the parent
+ Java object. */
+ if ((*ctxFieldID) == 0)
+ {
+ jclass clazz = env->GetObjectClass(contextHolder);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ (*ctxFieldID) = env->GetFieldID(clazz, contextFieldName, contextClassType);
+ if (JNIUtil::isJavaExceptionThrown() || (*ctxFieldID) == 0)
+ return;
+
+ env->DeleteLocalRef(clazz);
+ }
+
+ jobject jctx = env->GetObjectField(contextHolder, (*ctxFieldID));
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ m_jctx = env->NewGlobalRef(jctx);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ env->DeleteLocalRef(jctx);
+}
+
+OperationContext::~OperationContext()
+{
+ delete m_prompter;
+
+ JNIEnv *env = JNIUtil::getEnv();
+ env->DeleteGlobalRef(m_jctx);
+}
+
+apr_hash_t *
+OperationContext::getConfigData()
+{
+ if(m_pool->getPool() == NULL)
+ {
+ JNIUtil::throwNullPointerException("pool is null");
+ }
+
+ if (m_config == NULL)
+ {
+ const char *configDir = m_configDir.c_str();
+ if (m_configDir.empty())
+ configDir = NULL;
+ SVN_JNI_ERR(
+ svn_config_get_config(&m_config, configDir, m_pool->getPool()), NULL);
+ }
+
+ return m_config;
+}
+
+svn_auth_baton_t *
+OperationContext::getAuthBaton(SVN::Pool &in_pool)
+{
+ svn_auth_baton_t *ab;
+ apr_pool_t *pool = in_pool.getPool();
+
+ apr_hash_t * configData = getConfigData();
+
+ if (configData == NULL)
+ {
+ return NULL;
+ }
+
+ svn_config_t *config = reinterpret_cast<svn_config_t *>(apr_hash_get(configData,
+ SVN_CONFIG_CATEGORY_CONFIG, APR_HASH_KEY_STRING));
+
+ /* The whole list of registered providers */
+ apr_array_header_t *providers;
+
+ /* Populate the registered providers with the platform-specific providers */
+ SVN_JNI_ERR(
+ svn_auth_get_platform_specific_client_providers(&providers, config, pool),
+ NULL);
+
+ /* Use the prompter (if available) to prompt for password and cert
+ * caching. */
+ svn_auth_plaintext_prompt_func_t plaintext_prompt_func = NULL;
+ void *plaintext_prompt_baton = NULL;
+ svn_auth_plaintext_passphrase_prompt_func_t plaintext_passphrase_prompt_func;
+ void *plaintext_passphrase_prompt_baton = NULL;
+
+ if (m_prompter != NULL)
+ {
+ plaintext_prompt_func = Prompter::plaintext_prompt;
+ plaintext_prompt_baton = m_prompter;
+ plaintext_passphrase_prompt_func = Prompter::plaintext_passphrase_prompt;
+ plaintext_passphrase_prompt_baton = m_prompter;
+ }
+
+ /* The main disk-caching auth providers, for both
+ * 'username/password' creds and 'username' creds. */
+ svn_auth_provider_object_t *provider;
+
+ svn_auth_get_simple_provider2(&provider, plaintext_prompt_func,
+ plaintext_prompt_baton, pool);
+ APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+ svn_auth_get_username_provider(&provider, pool);
+ APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+ /* The server-cert, client-cert, and client-cert-password providers. */
+ SVN_JNI_ERR(
+ svn_auth_get_platform_specific_provider(&provider, "windows", "ssl_server_trust", pool),
+ NULL);
+
+ if (provider)
+ APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+ svn_auth_get_ssl_server_trust_file_provider(&provider, pool);
+ APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+ svn_auth_get_ssl_client_cert_file_provider(&provider, pool);
+ APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+ svn_auth_get_ssl_client_cert_pw_file_provider2(&provider,
+ plaintext_passphrase_prompt_func, plaintext_passphrase_prompt_baton,
+ pool);
+ APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+ if (m_prompter != NULL)
+ {
+ /* Two basic prompt providers: username/password, and just username.*/
+ provider = m_prompter->getProviderSimple(in_pool);
+
+ APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+ provider = m_prompter->getProviderUsername(in_pool);
+ APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+ /* Three ssl prompt providers, for server-certs, client-certs,
+ * and client-cert-passphrases. */
+ provider = m_prompter->getProviderServerSSLTrust(in_pool);
+ APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+ provider = m_prompter->getProviderClientSSL(in_pool);
+ APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+ provider = m_prompter->getProviderClientSSLPassword(in_pool);
+ APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+ }
+
+ /* Build an authentication baton to give to libsvn_client. */
+ svn_auth_open(&ab, providers, pool);
+
+ /* Place any default --username or --password credentials into the
+ * auth_baton's run-time parameter hash. ### Same with --no-auth-cache? */
+ if (!m_userName.empty())
+ svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_USERNAME,
+ apr_pstrdup(in_pool.getPool(), m_userName.c_str()));
+ if (!m_passWord.empty())
+ svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DEFAULT_PASSWORD,
+ apr_pstrdup(in_pool.getPool(), m_passWord.c_str()));
+ /* Store where to retrieve authentication data? */
+ if (!m_configDir.empty())
+ svn_auth_set_parameter(ab, SVN_AUTH_PARAM_CONFIG_DIR,
+ apr_pstrdup(in_pool.getPool(), m_configDir.c_str()));
+ return ab;
+}
+
+jobject OperationContext::getSelf() const
+{
+ jobject jctx = JNIUtil::getEnv()->NewGlobalRef(m_jctx);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+ return jctx;
+}
+
+void
+OperationContext::username(const char *pi_username)
+{
+ m_userName = (pi_username == NULL ? "" : pi_username);
+}
+
+void
+OperationContext::password(const char *pi_password)
+{
+ m_passWord = (pi_password == NULL ? "" : pi_password);
+}
+
+void
+OperationContext::setPrompt(Prompter *prompter)
+{
+ delete m_prompter;
+ m_prompter = prompter;
+}
+
+void
+OperationContext::setConfigDirectory(const char *configDir)
+{
+ // A change to the config directory may necessitate creation of
+ // the config templates.
+ SVN::Pool requestPool;
+ SVN_JNI_ERR(svn_config_ensure(configDir, requestPool.getPool()), );
+
+ m_configDir = (configDir == NULL ? "" : configDir);
+
+ m_config = NULL;
+}
+
+const char *
+OperationContext::getConfigDirectory() const
+{
+ return (m_configDir.empty() ? NULL : m_configDir.c_str());
+}
+
+const char *
+OperationContext::getUsername() const
+{
+ return (m_userName.empty() ? NULL : m_userName.c_str());
+}
+
+const char *
+OperationContext::getPassword() const
+{
+ return (m_passWord.empty() ? NULL : m_passWord.c_str());
+}
+
+const Prompter& OperationContext::getPrompter() const
+{
+ return *m_prompter;
+}
+
+void
+OperationContext::cancelOperation()
+{
+ m_cancelOperation = true;
+}
+
+void
+OperationContext::resetCancelRequest()
+{
+ m_cancelOperation = false;
+}
+
+bool
+OperationContext::isCancelledOperation()
+{
+ return m_cancelOperation;
+}
+
+svn_error_t *
+OperationContext::checkCancel(void *cancelBaton)
+{
+ OperationContext *that = static_cast<OperationContext *>(cancelBaton);
+ if (that->isCancelledOperation())
+ return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Operation cancelled"));
+ else
+ return SVN_NO_ERROR;
+}
+
+void
+OperationContext::progress(apr_off_t progressVal, apr_off_t total, void *baton,
+ apr_pool_t *pool)
+{
+ jobject jctx = (jobject) baton;
+ JNIEnv *env = JNIUtil::getEnv();
+
+ // Create a local frame for our references
+ env->PushLocalFrame(LOCAL_FRAME_SIZE);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ static jmethodID mid = 0;
+ if (mid == 0)
+ {
+ jclass clazz = env->GetObjectClass(jctx);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NOTHING();
+
+ mid = env->GetMethodID(clazz, "onProgress",
+ "(L"JAVA_PACKAGE"/ProgressEvent;)V");
+ if (JNIUtil::isJavaExceptionThrown() || mid == 0)
+ POP_AND_RETURN_NOTHING();
+ }
+
+ static jmethodID midCT = 0;
+ jclass clazz = env->FindClass(JAVA_PACKAGE"/ProgressEvent");
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NOTHING();
+
+ if (midCT == 0)
+ {
+ midCT = env->GetMethodID(clazz, "<init>", "(JJ)V");
+ if (JNIUtil::isJavaExceptionThrown() || midCT == 0)
+ POP_AND_RETURN_NOTHING();
+ }
+
+ // Call the Java method.
+ jobject jevent = env->NewObject(clazz, midCT, (jlong) progressVal,
+ (jlong) total);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN_NOTHING();
+
+ env->CallVoidMethod(jctx, mid, jevent);
+
+ POP_AND_RETURN_NOTHING();
+}
+
+const char *
+OperationContext::getClientName() const
+{
+ return "javahl";
+}
+
+svn_error_t *
+OperationContext::clientName(void *baton, const char **name, apr_pool_t *pool)
+{
+ OperationContext *that = (OperationContext *) baton;
+
+ *name = that->getClientName();
+
+ return SVN_NO_ERROR;
+}
diff --git a/subversion/bindings/javahl/native/OperationContext.h b/subversion/bindings/javahl/native/OperationContext.h
new file mode 100644
index 0000000..0ea1e9f
--- /dev/null
+++ b/subversion/bindings/javahl/native/OperationContext.h
@@ -0,0 +1,100 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file OperationContext.h
+ * @brief Interface of the class OperationContext
+ */
+
+#ifndef JAVAHL_OPERATION_CONTEXT_H
+#define JAVAHL_OPERATION_CONTEXT_H
+
+#include <string>
+
+#include "svn_types.h"
+#include "svn_client.h"
+
+#include <jni.h>
+#include "Pool.h"
+#include "JNIStringHolder.h"
+
+class Prompter;
+
+/**
+ * This class contains a Java objects implementing the interface RaSharedContext
+ */
+class OperationContext
+{
+ private:
+ std::string m_userName;
+ std::string m_passWord;
+ std::string m_configDir;
+
+ apr_hash_t * m_config;
+
+ Prompter *m_prompter;
+ bool m_cancelOperation;
+
+ protected:
+ SVN::Pool *m_pool;
+
+ jobject m_jctx;
+ static void progress(apr_off_t progressVal, apr_off_t total,
+ void *baton, apr_pool_t *pool);
+ public:
+ OperationContext(SVN::Pool &pool);
+ void attachJavaObject(jobject contextHolder, const char *contextClassType, const char *contextFieldName, jfieldID * ctxFieldID);
+ virtual ~OperationContext();
+
+ static svn_error_t *checkCancel(void *cancelBaton);
+
+ virtual void username(const char *pi_username);
+ virtual void password(const char *pi_password);
+ virtual void setPrompt(Prompter *prompter);
+ svn_auth_baton_t *getAuthBaton(SVN::Pool &in_pool);
+
+ void cancelOperation();
+ void resetCancelRequest();
+ virtual bool isCancelledOperation();
+ jobject getSelf() const;
+ const char *getConfigDirectory() const;
+ const char *getUsername() const;
+ const char *getPassword() const;
+ const Prompter& getPrompter() const;
+
+ /**
+ * Set the configuration directory, taking the usual steps to
+ * ensure that Subversion's config file templates exist in the
+ * specified location.
+ */
+ void setConfigDirectory(const char *configDir);
+
+ /**
+ * Return configuration data for the context.
+ * Read it from config directory if necessary
+ */
+ apr_hash_t *getConfigData();
+
+ static svn_error_t * clientName(void *baton, const char **name, apr_pool_t *pool);
+ virtual const char * getClientName() const;
+};
+
+#endif // JAVAHL_OPERATION_CONTEXT_H
diff --git a/subversion/bindings/javahl/native/OutputStream.cpp b/subversion/bindings/javahl/native/OutputStream.cpp
index ce80a95..9e85ec5 100644
--- a/subversion/bindings/javahl/native/OutputStream.cpp
+++ b/subversion/bindings/javahl/native/OutputStream.cpp
@@ -76,7 +76,7 @@
JNIEnv *env = JNIUtil::getEnv();
// An object of our class is passed in as the baton.
- OutputStream *that = (OutputStream*)baton;
+ OutputStream *that = static_cast<OutputStream *>(baton);
// The method id will not change during the time this library is
// loaded, so it can be cached.
@@ -95,8 +95,7 @@
}
// convert the data to a Java byte array
- jbyteArray data = JNIUtil::makeJByteArray((const signed char*)buffer,
- *len);
+ jbyteArray data = JNIUtil::makeJByteArray(buffer, static_cast<int>(*len));
if (JNIUtil::isJavaExceptionThrown())
return SVN_NO_ERROR;
@@ -120,7 +119,7 @@
JNIEnv *env = JNIUtil::getEnv();
// An object of our class is passed in as the baton
- OutputStream *that = (OutputStream*)baton;
+ OutputStream *that = reinterpret_cast<OutputStream*>(baton);
// The method id will not change during the time this library is
// loaded, so it can be cached.
diff --git a/subversion/bindings/javahl/native/PatchCallback.cpp b/subversion/bindings/javahl/native/PatchCallback.cpp
index b958af6..0cff577 100644
--- a/subversion/bindings/javahl/native/PatchCallback.cpp
+++ b/subversion/bindings/javahl/native/PatchCallback.cpp
@@ -54,10 +54,9 @@
apr_pool_t *pool)
{
if (baton)
- return ((PatchCallback *)baton)->singlePatch(filtered,
- canon_path_from_patchfile,
- patch_abspath, reject_abspath,
- pool);
+ return static_cast<PatchCallback *>(baton)->singlePatch(
+ filtered, canon_path_from_patchfile, patch_abspath, reject_abspath,
+ pool);
return SVN_NO_ERROR;
}
diff --git a/subversion/bindings/javahl/native/Path.cpp b/subversion/bindings/javahl/native/Path.cpp
index 328f55b..b9c69ea 100644
--- a/subversion/bindings/javahl/native/Path.cpp
+++ b/subversion/bindings/javahl/native/Path.cpp
@@ -73,12 +73,12 @@
{
if (*pi_path == 0)
{
- m_error_occured = NULL;
+ m_error_occurred = NULL;
m_path = "";
}
else
{
- m_error_occured = JNIUtil::preprocessPath(pi_path, in_pool.getPool());
+ m_error_occurred = JNIUtil::preprocessPath(pi_path, in_pool.getPool());
m_path = pi_path;
}
@@ -108,15 +108,15 @@
Path&
Path::operator=(const Path &pi_path)
{
- m_error_occured = NULL;
+ m_error_occurred = NULL;
m_path = pi_path.m_path;
return *this;
}
- svn_error_t *Path::error_occured() const
+ svn_error_t *Path::error_occurred() const
{
- return m_error_occured;
+ return m_error_occurred;
}
jboolean Path::isValid(const char *p)
diff --git a/subversion/bindings/javahl/native/Path.h b/subversion/bindings/javahl/native/Path.h
index 2959a42..d23261e 100644
--- a/subversion/bindings/javahl/native/Path.h
+++ b/subversion/bindings/javahl/native/Path.h
@@ -41,7 +41,7 @@
// The path to be stored.
std::string m_path;
- svn_error_t *m_error_occured;
+ svn_error_t *m_error_occurred;
/**
* Initialize the class.
@@ -90,7 +90,7 @@
*/
const char *c_str() const;
- svn_error_t *error_occured() const;
+ svn_error_t *error_occurred() const;
/**
* Returns whether @a path is non-NULL and passes the @c
diff --git a/subversion/bindings/javahl/native/Pool.h b/subversion/bindings/javahl/native/Pool.h
index 4c7e2bc..a5b5f8e 100644
--- a/subversion/bindings/javahl/native/Pool.h
+++ b/subversion/bindings/javahl/native/Pool.h
@@ -39,7 +39,7 @@
{
public:
Pool();
- Pool(const Pool &parent_pool);
+ explicit Pool(const Pool &parent_pool);
Pool(apr_pool_t *parent_pool);
~Pool();
apr_pool_t *getPool() const;
diff --git a/subversion/bindings/javahl/native/Prompter.cpp b/subversion/bindings/javahl/native/Prompter.cpp
index 4ce8244..241fef3 100644
--- a/subversion/bindings/javahl/native/Prompter.cpp
+++ b/subversion/bindings/javahl/native/Prompter.cpp
@@ -40,9 +40,9 @@
* @param jprompter a global reference to the Java callback object
*/
Prompter::Prompter(jobject jprompter)
-{
- m_prompter = jprompter;
-}
+ : m_prompter(jprompter),
+ m_maySave(false)
+{}
Prompter::~Prompter()
{
@@ -427,9 +427,9 @@
svn_boolean_t may_save,
apr_pool_t *pool)
{
- Prompter *that = (Prompter*)baton;
+ Prompter *that = static_cast<Prompter *>(baton);
svn_auth_cred_simple_t *ret =
- (svn_auth_cred_simple_t*)apr_pcalloc(pool, sizeof(*ret));
+ reinterpret_cast<svn_auth_cred_simple_t*>(apr_pcalloc(pool, sizeof(*ret)));
if (!that->prompt(realm, username, may_save ? true : false))
return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
_("User canceled dialog"));
@@ -460,9 +460,9 @@
svn_boolean_t may_save,
apr_pool_t *pool)
{
- Prompter *that = (Prompter*)baton;
+ Prompter *that = static_cast<Prompter *>(baton);
svn_auth_cred_username_t *ret =
- (svn_auth_cred_username_t*)apr_pcalloc(pool, sizeof(*ret));
+ reinterpret_cast<svn_auth_cred_username_t*>(apr_pcalloc(pool, sizeof(*ret)));
const char *user = that->askQuestion(realm, _("Username: "), true,
may_save ? true : false);
if (user == NULL)
@@ -484,9 +484,9 @@
svn_boolean_t may_save,
apr_pool_t *pool)
{
- Prompter *that = (Prompter*)baton;
+ Prompter *that = static_cast<Prompter *>(baton);
svn_auth_cred_ssl_server_trust_t *ret =
- (svn_auth_cred_ssl_server_trust_t*)apr_pcalloc(pool, sizeof(*ret));
+ reinterpret_cast<svn_auth_cred_ssl_server_trust_t*>(apr_pcalloc(pool, sizeof(*ret)));
std::string question = _("Error validating server certificate for ");
question += realm;
@@ -550,9 +550,9 @@
svn_boolean_t may_save,
apr_pool_t *pool)
{
- Prompter *that = (Prompter*)baton;
+ Prompter *that = static_cast<Prompter *>(baton);
svn_auth_cred_ssl_client_cert_t *ret =
- (svn_auth_cred_ssl_client_cert_t*)apr_pcalloc(pool, sizeof(*ret));
+ reinterpret_cast<svn_auth_cred_ssl_client_cert_t*>(apr_pcalloc(pool, sizeof(*ret)));
const char *cert_file =
that->askQuestion(realm, _("client certificate filename: "), true,
may_save ? true : false);
@@ -572,9 +572,9 @@
svn_boolean_t may_save,
apr_pool_t *pool)
{
- Prompter *that = (Prompter*)baton;
+ Prompter *that = static_cast<Prompter *>(baton);
svn_auth_cred_ssl_client_cert_pw_t *ret =
- (svn_auth_cred_ssl_client_cert_pw_t*)apr_pcalloc(pool, sizeof(*ret));
+ reinterpret_cast<svn_auth_cred_ssl_client_cert_pw_t*>(apr_pcalloc(pool, sizeof(*ret)));
const char *info = that->askQuestion(realm,
_("client certificate passphrase: "),
false, may_save ? true : false);
@@ -593,7 +593,7 @@
void *baton,
apr_pool_t *pool)
{
- Prompter *that = (Prompter *) baton;
+ Prompter *that = static_cast<Prompter *>(baton);
bool result = that->askYesNo(realmstring,
_("Store password unencrypted?"),
@@ -610,7 +610,7 @@
void *baton,
apr_pool_t *pool)
{
- Prompter *that = (Prompter *) baton;
+ Prompter *that = static_cast<Prompter *>(baton);
bool result = that->askYesNo(realmstring,
_("Store passphrase unencrypted?"),
diff --git a/subversion/bindings/javahl/native/ProplistCallback.cpp b/subversion/bindings/javahl/native/ProplistCallback.cpp
index a3bcee3..2e13fd8 100644
--- a/subversion/bindings/javahl/native/ProplistCallback.cpp
+++ b/subversion/bindings/javahl/native/ProplistCallback.cpp
@@ -33,10 +33,10 @@
* Create a ProplistCallback object
* @param jcallback the Java callback object.
*/
-ProplistCallback::ProplistCallback(jobject jcallback)
-{
- m_callback = jcallback;
-}
+ProplistCallback::ProplistCallback(jobject jcallback, bool inherited)
+ : m_callback(jcallback),
+ m_inherited(inherited)
+{}
/**
* Destroy a ProplistCallback object
@@ -54,7 +54,10 @@
apr_pool_t *pool)
{
if (baton)
- return ((ProplistCallback *)baton)->singlePath(path, prop_hash, pool);
+ {
+ ProplistCallback *cb = static_cast<ProplistCallback *>(baton);
+ return cb->singlePath(path, prop_hash, pool);
+ }
return SVN_NO_ERROR;
}
@@ -78,7 +81,7 @@
// The method id will not change during the time this library is
// loaded, so it can be cached.
- static jmethodID mid = 0;
+ static volatile jmethodID mid = 0;
if (mid == 0)
{
jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/ProplistCallback");
@@ -108,3 +111,58 @@
return SVN_NO_ERROR;
}
+
+
+
+/**
+ * Callback called for a single path
+ * @param path the path name
+ * @param prop_hash the hash of properties on this path
+ * @param inherited_props list of inherited props
+ * @param pool memory pool for the use of this function
+ */
+svn_error_t *ProplistCallback::singlePath(
+ const char *path,
+ apr_hash_t *prop_hash,
+ apr_array_header_t *inherited_props,
+ apr_pool_t *pool)
+{
+ JNIEnv *env = JNIUtil::getEnv();
+
+ // Create a local frame for our references
+ env->PushLocalFrame(LOCAL_FRAME_SIZE);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ // The method id will not change during the time this library is
+ // loaded, so it can be cached.
+ static jmethodID mid = 0;
+ if (mid == 0)
+ {
+ jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/InheritedProplistCallback");
+ if (JNIUtil::isJavaExceptionThrown())
+ return SVN_NO_ERROR;
+
+ mid = env->GetMethodID(clazz, "singlePath",
+ "(Ljava/lang/String;Ljava/util/Map;Ljava/util/Collection;)V");
+ if (JNIUtil::isJavaExceptionThrown() || mid == 0)
+ POP_AND_RETURN(SVN_NO_ERROR);
+ }
+
+ // convert the parameters to their Java relatives
+ jstring jpath = JNIUtil::makeJString(path);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN(SVN_NO_ERROR);
+
+ jobject jmap = CreateJ::PropertyMap(prop_hash);
+ if (JNIUtil::isJavaExceptionThrown())
+ POP_AND_RETURN(SVN_NO_ERROR);
+
+ // call the Java method
+ env->CallVoidMethod(m_callback, mid, jpath, jmap, NULL);
+ // We return whether an exception was thrown or not.
+
+ env->PopLocalFrame(NULL);
+
+ return SVN_NO_ERROR;
+}
diff --git a/subversion/bindings/javahl/native/ProplistCallback.h b/subversion/bindings/javahl/native/ProplistCallback.h
index 72209ef..49ee94c 100644
--- a/subversion/bindings/javahl/native/ProplistCallback.h
+++ b/subversion/bindings/javahl/native/ProplistCallback.h
@@ -37,7 +37,7 @@
class ProplistCallback
{
public:
- ProplistCallback(jobject jcallback);
+ ProplistCallback(jobject jcallback, bool inherited);
~ProplistCallback();
static svn_error_t *callback(void *baton,
@@ -45,16 +45,24 @@
apr_hash_t *prop_hash,
apr_pool_t *pool);
+ bool inherited() const { return m_inherited; }
+
protected:
svn_error_t *singlePath(const char *path,
apr_hash_t *prop_hash,
apr_pool_t *pool);
+ svn_error_t *singlePath(const char *path,
+ apr_hash_t *prop_hash,
+ apr_array_header_t *inherited_props,
+ apr_pool_t *pool);
private:
/**
* This a local reference to the Java object.
*/
jobject m_callback;
+ bool m_inherited;
};
+
#endif // PROPLISTCALLBACK_H
diff --git a/subversion/bindings/javahl/native/RemoteSession.cpp b/subversion/bindings/javahl/native/RemoteSession.cpp
new file mode 100644
index 0000000..2893b0c
--- /dev/null
+++ b/subversion/bindings/javahl/native/RemoteSession.cpp
@@ -0,0 +1,441 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file RemoteSession.cpp
+ * @brief Implementation of the class RemoteSession
+ */
+
+#include <cstring>
+#include <set>
+
+#include "JNIStringHolder.h"
+#include "JNIUtil.h"
+
+#include "svn_ra.h"
+
+#include "CreateJ.h"
+#include "EnumMapper.h"
+#include "Prompter.h"
+#include "Revision.h"
+#include "RemoteSession.h"
+
+#include "svn_private_config.h"
+
+#define JAVA_CLASS_REMOTE_SESSION JAVA_PACKAGE "/remote/RemoteSession"
+
+RemoteSession *
+RemoteSession::getCppObject(jobject jthis)
+{
+ static jfieldID fid = 0;
+ jlong cppAddr = SVNBase::findCppAddrForJObject(jthis, &fid,
+ JAVA_CLASS_REMOTE_SESSION);
+ return (cppAddr == 0 ? NULL : reinterpret_cast<RemoteSession *>(cppAddr));
+}
+
+jobject
+RemoteSession::open(jint jretryAttempts,
+ jstring jurl, jstring juuid,
+ jstring jconfigDirectory,
+ jstring jusername, jstring jpassword,
+ jobject jprompter, jobject jprogress)
+{
+ JNIEnv *env = JNIUtil::getEnv();
+
+ JNIStringHolder url(jurl);
+ if (JNIUtil::isExceptionThrown())
+ return NULL;
+ env->DeleteLocalRef(jurl);
+
+ JNIStringHolder uuid(juuid);
+ if (JNIUtil::isExceptionThrown())
+ return NULL;
+ env->DeleteLocalRef(juuid);
+
+ JNIStringHolder configDirectory(jconfigDirectory);
+ if (JNIUtil::isExceptionThrown())
+ return NULL;
+ env->DeleteLocalRef(jconfigDirectory);
+
+ JNIStringHolder usernameStr(jusername);
+ if (JNIUtil::isExceptionThrown())
+ return NULL;
+ env->DeleteLocalRef(jusername);
+
+ JNIStringHolder passwordStr(jpassword);
+ if (JNIUtil::isExceptionThrown())
+ return NULL;
+ env->DeleteLocalRef(jpassword);
+
+ Prompter *prompter = NULL;
+ if (jprompter != NULL)
+ {
+ prompter = Prompter::makeCPrompter(jprompter);
+ if (JNIUtil::isExceptionThrown())
+ return NULL;
+ }
+
+ jobject jremoteSession = open(
+ jretryAttempts, url, uuid, configDirectory,
+ usernameStr, passwordStr, prompter, jprogress);
+ if (JNIUtil::isExceptionThrown() || !jremoteSession)
+ {
+ delete prompter;
+ jremoteSession = NULL;
+ }
+ return jremoteSession;
+}
+
+jobject
+RemoteSession::open(jint jretryAttempts,
+ const char* url, const char* uuid,
+ const char* configDirectory,
+ const char* usernameStr, const char* passwordStr,
+ Prompter* prompter, jobject jprogress)
+{
+ /*
+ * Initialize ra layer if we have not done so yet
+ */
+ static bool initialized = false;
+ if (!initialized)
+ {
+ SVN_JNI_ERR(svn_ra_initialize(JNIUtil::getPool()), NULL);
+ initialized = true;
+ }
+
+ jobject jthis_out = NULL;
+ RemoteSession* session = new RemoteSession(
+ &jthis_out, jretryAttempts, url, uuid, configDirectory,
+ usernameStr, passwordStr, prompter, jprogress);
+ if (JNIUtil::isJavaExceptionThrown() || !session)
+ {
+ delete session;
+ jthis_out = NULL;
+ }
+ return jthis_out;
+}
+
+
+namespace{
+ struct compare_c_strings
+ {
+ bool operator()(const char* a, const char* b)
+ {
+ return (0 < std::strcmp(a, b));
+ }
+ };
+ typedef std::set<const char*, compare_c_strings> attempt_set;
+ typedef std::pair<attempt_set::iterator, bool> attempt_insert;
+} // anonymous namespace
+
+RemoteSession::RemoteSession(jobject* jthis_out, int retryAttempts,
+ const char* url, const char* uuid,
+ const char* configDirectory,
+ const char* username, const char* password,
+ Prompter* prompter, jobject jprogress)
+ : m_session(NULL), m_context(NULL)
+{
+ // Create java session object
+ JNIEnv *env = JNIUtil::getEnv();
+
+ jclass clazz = env->FindClass(JAVA_CLASS_REMOTE_SESSION);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ static jmethodID ctor = 0;
+ if (ctor == 0)
+ {
+ ctor = env->GetMethodID(clazz, "<init>", "(J)V");
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+ }
+
+ jlong cppAddr = this->getCppAddr();
+
+ jobject jremoteSession = env->NewObject(clazz, ctor, cppAddr);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ m_context = new RemoteSessionContext(
+ jremoteSession, pool, configDirectory,
+ username, password, prompter, jprogress);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ const char* corrected_url = NULL;
+ bool cycle_detected = false;
+ attempt_set attempted;
+
+ while (retryAttempts-- >= 0)
+ {
+ SVN_JNI_ERR(
+ svn_ra_open4(&m_session, &corrected_url,
+ url, uuid, m_context->getCallbacks(),
+ m_context->getCallbackBaton(),
+ m_context->getConfigData(),
+ pool.getPool()),
+ );
+
+ if (!corrected_url)
+ break;
+
+ attempt_insert result = attempted.insert(corrected_url);
+ if (!result.second)
+ {
+ cycle_detected = true;
+ break;
+ }
+ }
+
+ if (cycle_detected)
+ {
+ jstring exmsg = JNIUtil::makeJString(
+ apr_psprintf(pool.getPool(),
+ _("Redirect cycle detected for URL '%s'"),
+ corrected_url));
+
+ jclass excls = env->FindClass(
+ JAVA_PACKAGE "/SubversionException");
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ static jmethodID exctor = 0;
+ if (exctor == 0)
+ {
+ exctor = env->GetMethodID(excls, "<init>", "(J)V");
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+ }
+
+ jobject ex = env->NewObject(excls, exctor, exmsg);
+ env->Throw(static_cast<jthrowable>(ex));
+ return;
+ }
+
+ if (corrected_url)
+ {
+ jstring exmsg = JNIUtil::makeJString(_("Too many redirects"));
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ jstring exurl = JNIUtil::makeJString(corrected_url);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ jclass excls = env->FindClass(
+ JAVA_PACKAGE "/remote/RetryOpenSession");
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ static jmethodID exctor = 0;
+ if (exctor == 0)
+ {
+ exctor = env->GetMethodID(excls, "<init>", "(JJ)V");
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+ }
+
+ jobject ex = env->NewObject(excls, exctor, exmsg, exurl);
+ env->Throw(static_cast<jthrowable>(ex));
+ return;
+ }
+
+ *jthis_out = jremoteSession;
+}
+
+RemoteSession::~RemoteSession()
+{
+ delete m_context;
+}
+
+void
+RemoteSession::dispose(jobject jthis)
+{
+ static jfieldID fid = 0;
+ SVNBase::dispose(jthis, &fid, JAVA_CLASS_REMOTE_SESSION);
+}
+
+void RemoteSession::reparent(jstring jurl)
+{
+ JNIStringHolder url(jurl);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ SVN::Pool subPool(pool);
+ SVN_JNI_ERR(svn_ra_reparent(m_session, url, subPool.getPool()), );
+}
+
+jstring
+RemoteSession::getSessionUrl()
+{
+ SVN::Pool subPool(pool);
+ const char* url;
+ SVN_JNI_ERR(svn_ra_get_session_url(m_session, &url, subPool.getPool()), NULL);
+
+ jstring jurl = JNIUtil::makeJString(url);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ return jurl;
+}
+
+jstring
+RemoteSession::getSessionRelativePath(jstring jurl)
+{
+ JNIStringHolder url(jurl);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ SVN::Pool subPool(pool);
+ const char* rel_path;
+ SVN_JNI_ERR(svn_ra_get_path_relative_to_session(
+ m_session, &rel_path, url, subPool.getPool()),
+ NULL);
+ jstring jrel_path = JNIUtil::makeJString(rel_path);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ return jrel_path;
+}
+
+jstring
+RemoteSession::getReposRelativePath(jstring jurl)
+{
+ JNIStringHolder url(jurl);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ SVN::Pool subPool(pool);
+ const char* rel_path;
+ SVN_JNI_ERR(svn_ra_get_path_relative_to_root(m_session, &rel_path, url,
+ subPool.getPool()),
+ NULL);
+
+ jstring jrel_path = JNIUtil::makeJString(rel_path);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ return jrel_path;
+}
+
+jstring
+RemoteSession::getReposUUID()
+{
+ SVN::Pool subPool(pool);
+ const char * uuid;
+ SVN_JNI_ERR(svn_ra_get_uuid2(m_session, &uuid, subPool.getPool()), NULL);
+
+ jstring juuid = JNIUtil::makeJString(uuid);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ return juuid;
+}
+
+jstring
+RemoteSession::getReposRootUrl()
+{
+ SVN::Pool subPool(pool);
+ const char* url;
+ SVN_JNI_ERR(svn_ra_get_repos_root2(m_session, &url, subPool.getPool()),
+ NULL);
+
+ jstring jurl = JNIUtil::makeJString(url);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ return jurl;
+}
+
+jlong
+RemoteSession::getLatestRevision()
+{
+ SVN::Pool subPool(pool);
+ svn_revnum_t rev;
+ SVN_JNI_ERR(svn_ra_get_latest_revnum(m_session, &rev, subPool.getPool()),
+ SVN_INVALID_REVNUM);
+ return rev;
+}
+
+jlong
+RemoteSession::getRevisionByTimestamp(jlong timestamp)
+{
+ SVN::Pool subPool(pool);
+ svn_revnum_t rev;
+ SVN_JNI_ERR(svn_ra_get_dated_revision(m_session, &rev,
+ apr_time_t(timestamp),
+ subPool.getPool()),
+ SVN_INVALID_REVNUM);
+ return rev;
+}
+
+jobject
+RemoteSession::getLocks(jstring jpath, jobject jdepth)
+{
+ JNIStringHolder path(jpath);
+ if (JNIUtil::isExceptionThrown())
+ return NULL;
+
+ svn_depth_t depth = EnumMapper::toDepth(jdepth);
+ if (JNIUtil::isExceptionThrown())
+ return NULL;
+
+ SVN::Pool subPool(pool);
+ apr_hash_t *locks;
+ SVN_JNI_ERR(svn_ra_get_locks2(m_session, &locks, path, depth,
+ subPool.getPool()),
+ NULL);
+
+ return CreateJ::LockMap(locks, subPool.getPool());
+}
+
+jobject
+RemoteSession::checkPath(jstring jpath, jlong jrevision)
+{
+ JNIStringHolder path(jpath);
+ if (JNIUtil::isExceptionThrown())
+ return NULL;
+
+ SVN::Pool subPool(pool);
+ svn_node_kind_t kind;
+ SVN_JNI_ERR(svn_ra_check_path(m_session, path,
+ svn_revnum_t(jrevision),
+ &kind, subPool.getPool()),
+ NULL);
+
+ return EnumMapper::mapNodeKind(kind);
+}
+
+jboolean
+RemoteSession::hasCapability(jstring jcapability)
+{
+ JNIStringHolder capability(jcapability);
+ if (JNIUtil::isExceptionThrown())
+ return false;
+
+ SVN::Pool subPool(pool);
+ svn_boolean_t has;
+ SVN_JNI_ERR(svn_ra_has_capability(m_session, &has, capability,
+ subPool.getPool()),
+ false);
+
+ return jboolean(has);
+}
diff --git a/subversion/bindings/javahl/native/RemoteSession.h b/subversion/bindings/javahl/native/RemoteSession.h
new file mode 100644
index 0000000..17bf1c8
--- /dev/null
+++ b/subversion/bindings/javahl/native/RemoteSession.h
@@ -0,0 +1,85 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file RemoteSession.h
+ * @brief Interface of the class RemoteSession
+ */
+
+#ifndef JAVAHL_REMOTE_SESSION_H
+#define JAVAHL_REMOTE_SESSION_H
+
+#include <jni.h>
+
+#include "svn_ra.h"
+
+#include "SVNBase.h"
+#include "RemoteSessionContext.h"
+#include "Prompter.h"
+
+/*
+ * This class wraps Ra based operations from svn_ra.h
+ */
+class RemoteSession : public SVNBase
+{
+ public:
+ static RemoteSession* getCppObject(jobject jthis);
+ static jobject open(jint jretryAttempts,
+ jstring jurl, jstring juuid,
+ jstring jconfigDirectory,
+ jstring jusername, jstring jpassword,
+ jobject jprompter, jobject jprogress);
+ static jobject open(jint jretryAttempts,
+ const char* url, const char* uuid,
+ const char* configDirectory,
+ const char* username, const char* password,
+ Prompter* prompter, jobject jprogress);
+ ~RemoteSession();
+
+ void cancelOperation() const { m_context->cancelOperation(); }
+
+ virtual void dispose(jobject jthis);
+
+ void reparent(jstring jurl);
+ jstring getSessionUrl();
+ jstring getSessionRelativePath(jstring jurl);
+ jstring getReposRelativePath(jstring jurl);
+ jstring getReposUUID();
+ jstring getReposRootUrl();
+ jlong getLatestRevision();
+
+ jlong getRevisionByTimestamp(jlong timestamp);
+ jobject getLocks(jstring jpath, jobject jdepth);
+ jobject checkPath(jstring jpath, jlong jrevision);
+ jboolean hasCapability(jstring capability);
+
+ private:
+ RemoteSession(jobject*, int retryAttempts,
+ const char* url, const char* uuid,
+ const char* configDirectory,
+ const char* username, const char* password,
+ Prompter* prompter, jobject jprogress);
+
+ svn_ra_session_t* m_session;
+ RemoteSessionContext* m_context;
+};
+
+#endif // JAVAHL_REMOTE_SESSION_H
diff --git a/subversion/bindings/javahl/native/RemoteSessionContext.cpp b/subversion/bindings/javahl/native/RemoteSessionContext.cpp
new file mode 100644
index 0000000..b5f40a8
--- /dev/null
+++ b/subversion/bindings/javahl/native/RemoteSessionContext.cpp
@@ -0,0 +1,114 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file RemoteSessionContext.cpp
+ * @brief Implementation of the class RemoteSessionContext
+ */
+
+
+#include "RemoteSessionContext.h"
+#include "JNIUtil.h"
+#include "Prompter.h"
+
+#define STRING_RETURN_SIGNATURE "()Ljava/lang/String;"
+
+RemoteSessionContext::RemoteSessionContext(
+ jobject contextHolder, SVN::Pool &pool, const char* configDirectory,
+ const char* usernameStr, const char* passwordStr,
+ Prompter* prompter, jobject jprogress)
+ : OperationContext(pool), m_raCallbacks(NULL)
+{
+ setConfigDirectory(configDirectory);
+ if (usernameStr != NULL)
+ username(usernameStr);
+
+ if (passwordStr != NULL)
+ password(passwordStr);
+
+ setPrompt(prompter);
+
+ /*
+ * Attach session context java object
+ */
+ static jfieldID ctxFieldID = 0;
+ attachJavaObject(contextHolder,
+ "L"JAVA_PACKAGE"/remote/RemoteSession$RemoteSessionContext;",
+ "sessionContext", &ctxFieldID);
+
+ /*
+ * Set the progress callback
+ */
+ JNIEnv *env = JNIUtil::getEnv();
+
+ jclass clazz = env->GetObjectClass(m_jctx);
+ if (JNIUtil::isJavaExceptionThrown())
+ return;
+
+ jmethodID mid = env->GetMethodID(
+ clazz, "setProgressCallback",
+ "(L"JAVA_PACKAGE"/callback/ProgressCallback;)V");
+ if (JNIUtil::isJavaExceptionThrown() || mid == 0)
+ return;
+
+ env->CallVoidMethod(m_jctx, mid, jprogress);
+ env->DeleteLocalRef(jprogress);
+
+ /*
+ * Setup callbacks
+ */
+ SVN_JNI_ERR(svn_ra_create_callbacks(&m_raCallbacks, m_pool->getPool()), );
+
+ m_raCallbacks->auth_baton = getAuthBaton(pool);
+ m_raCallbacks->cancel_func = checkCancel;
+ m_raCallbacks->get_client_string = clientName;
+ m_raCallbacks->progress_baton = m_jctx;
+ m_raCallbacks->progress_func = progress;
+
+ /*
+ * JNI RA layer does not work with WC so all WC callbacks are set to NULL
+ */
+ m_raCallbacks->get_wc_prop = NULL;
+ m_raCallbacks->invalidate_wc_props = NULL;
+ m_raCallbacks->push_wc_prop = NULL;
+ m_raCallbacks->set_wc_prop = NULL;
+
+ /*
+ * Don't set deprecated callback
+ */
+ m_raCallbacks->open_tmp_file = NULL;
+}
+
+RemoteSessionContext::~RemoteSessionContext()
+{
+}
+
+void *
+RemoteSessionContext::getCallbackBaton()
+{
+ return this;
+}
+
+svn_ra_callbacks2_t *
+RemoteSessionContext::getCallbacks()
+{
+ return m_raCallbacks;
+}
diff --git a/subversion/bindings/javahl/native/RemoteSessionContext.h b/subversion/bindings/javahl/native/RemoteSessionContext.h
new file mode 100644
index 0000000..7b518fd
--- /dev/null
+++ b/subversion/bindings/javahl/native/RemoteSessionContext.h
@@ -0,0 +1,49 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file RemoteSessionContext.h
+ * @brief Interface of the class RemoteSessionContext
+ */
+
+#ifndef JAVAHL_REMOTE_SESSION_CONTEXT_H
+#define JAVAHL_REMOTE_SESSION_CONTEXT_H
+
+#include "svn_ra.h"
+
+#include "OperationContext.h"
+
+class RemoteSessionContext : public OperationContext
+{
+ public:
+ RemoteSessionContext(jobject contextHolder, SVN::Pool &pool,
+ const char* jconfigDirectory,
+ const char* jusername, const char* jpassword,
+ Prompter* prompter, jobject jprogress);
+ virtual ~RemoteSessionContext();
+ void * getCallbackBaton();
+ svn_ra_callbacks2_t* getCallbacks();
+
+ private:
+ svn_ra_callbacks2_t* m_raCallbacks;
+};
+
+#endif /* JAVAHL_REMOTE_SESSION_CONTEXT_H */
diff --git a/subversion/bindings/javahl/native/ReposNotifyCallback.cpp b/subversion/bindings/javahl/native/ReposNotifyCallback.cpp
index 2b3194f..a716653 100644
--- a/subversion/bindings/javahl/native/ReposNotifyCallback.cpp
+++ b/subversion/bindings/javahl/native/ReposNotifyCallback.cpp
@@ -49,7 +49,7 @@
apr_pool_t *pool)
{
if (baton)
- ((ReposNotifyCallback *)baton)->onNotify(notify, pool);
+ static_cast<ReposNotifyCallback *>(baton)->onNotify(notify, pool);
}
/**
diff --git a/subversion/bindings/javahl/native/Revision.cpp b/subversion/bindings/javahl/native/Revision.cpp
index 32eaa47..7ba2094 100644
--- a/subversion/bindings/javahl/native/Revision.cpp
+++ b/subversion/bindings/javahl/native/Revision.cpp
@@ -31,7 +31,7 @@
const svn_opt_revision_kind Revision::START = svn_opt_revision_unspecified;
const svn_opt_revision_kind Revision::HEAD = svn_opt_revision_head;
-Revision::Revision (const svn_opt_revision_kind kind)
+Revision::Revision(const svn_opt_revision_kind kind)
{
m_revision.kind = kind;
m_revision.value.number = 0;
@@ -149,7 +149,7 @@
{
}
-const svn_opt_revision_t *Revision::revision () const
+const svn_opt_revision_t *Revision::revision() const
{
return &m_revision;
}
diff --git a/subversion/bindings/javahl/native/RevisionRange.cpp b/subversion/bindings/javahl/native/RevisionRange.cpp
index b73d5a4..677c7d5 100644
--- a/subversion/bindings/javahl/native/RevisionRange.cpp
+++ b/subversion/bindings/javahl/native/RevisionRange.cpp
@@ -20,7 +20,7 @@
* ====================================================================
* @endcopyright
*
- * @file RevisionRanges.cpp
+ * @file RevisionRange.cpp
* @brief Implementation of the class RevisionRange.
*/
@@ -87,7 +87,8 @@
return NULL;
svn_opt_revision_range_t *range =
- (svn_opt_revision_range_t *) apr_palloc(pool.getPool(), sizeof(*range));
+ reinterpret_cast<svn_opt_revision_range_t *>
+ (apr_palloc(pool.getPool(), sizeof(*range)));
range->start = *startRevision.revision();
if (JNIUtil::isExceptionThrown())
diff --git a/subversion/bindings/javahl/native/RevpropTable.cpp b/subversion/bindings/javahl/native/RevpropTable.cpp
index 2f1d7b9..f273a73 100644
--- a/subversion/bindings/javahl/native/RevpropTable.cpp
+++ b/subversion/bindings/javahl/native/RevpropTable.cpp
@@ -41,9 +41,9 @@
JNIUtil::getEnv()->DeleteLocalRef(m_revpropTable);
}
-const apr_hash_t *RevpropTable::hash(const SVN::Pool &pool)
+apr_hash_t *RevpropTable::hash(const SVN::Pool &pool, bool nullIfEmpty)
{
- if (m_revprops.size() == 0)
+ if (m_revprops.size() == 0 && nullIfEmpty)
return NULL;
apr_hash_t *revprop_table = apr_hash_make(pool.getPool());
@@ -77,7 +77,7 @@
if (jrevpropTable != NULL)
{
- static jmethodID keySet = 0, toArray = 0, get = 0;
+ static jmethodID keySet = 0, get = 0;
JNIEnv *env = JNIUtil::getEnv();
jclass mapClazz = env->FindClass("java/util/Map");
@@ -120,8 +120,8 @@
if (JNIUtil::isExceptionThrown())
return;
- m_revprops[std::string((const char *)propname)]
- = std::string((const char *)propval);
+ m_revprops[std::string(static_cast<const char *>(propname))]
+ = std::string(static_cast<const char *>(propval));
JNIUtil::getEnv()->DeleteLocalRef(jpropval);
}
diff --git a/subversion/bindings/javahl/native/RevpropTable.h b/subversion/bindings/javahl/native/RevpropTable.h
index ee5f14f..e90d89c 100644
--- a/subversion/bindings/javahl/native/RevpropTable.h
+++ b/subversion/bindings/javahl/native/RevpropTable.h
@@ -44,7 +44,7 @@
public:
RevpropTable(jobject jrevpropTable);
~RevpropTable();
- const apr_hash_t *hash(const SVN::Pool &pool);
+ apr_hash_t *hash(const SVN::Pool &pool, bool nullIfEmpty = true);
};
#endif // REVPROPTABLE_H
diff --git a/subversion/bindings/javahl/native/SVNBase.cpp b/subversion/bindings/javahl/native/SVNBase.cpp
index d8e7310..5e20f93 100644
--- a/subversion/bindings/javahl/native/SVNBase.cpp
+++ b/subversion/bindings/javahl/native/SVNBase.cpp
@@ -30,7 +30,6 @@
SVNBase::SVNBase()
: pool(JNIUtil::getPool())
{
- jthis = NULL;
}
SVNBase::~SVNBase()
@@ -58,17 +57,6 @@
if (JNIUtil::isJavaExceptionThrown())
return 0;
- if (cppAddr)
- {
- /* jthis is not guaranteed to be the same between JNI invocations, so
- we do a little dance here and store the updated version in our
- object for this invocation.
-
- findCppAddrForJObject() is, by necessity, called before any other
- methods on the C++ object, so by doing this we can guarantee a
- valid jthis pointer for subsequent uses. */
- (reinterpret_cast<SVNBase *> (cppAddr))->jthis = jthis;
- }
return cppAddr;
}
}
@@ -82,17 +70,15 @@
JNIUtil::enqueueForDeletion(this);
}
-void SVNBase::dispose(jfieldID *fid, const char *className)
+void SVNBase::dispose(jobject jthis, jfieldID *fid, const char *className)
{
- jobject my_jthis = this->jthis;
-
delete this;
JNIEnv *env = JNIUtil::getEnv();
SVNBase::findCppAddrFieldID(fid, className, env);
if (*fid == 0)
return;
- env->SetLongField(my_jthis, *fid, 0);
+ env->SetLongField(jthis, *fid, 0);
if (JNIUtil::isJavaExceptionThrown())
return;
}
@@ -111,3 +97,29 @@
}
}
}
+
+jobject SVNBase::createCppBoundObject(const char *clazzName)
+{
+ JNIEnv *env = JNIUtil::getEnv();
+
+ // Create java session object
+ jclass clazz = env->FindClass(clazzName);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ static jmethodID ctor = 0;
+ if (ctor == 0)
+ {
+ ctor = env->GetMethodID(clazz, "<init>", "(J)V");
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+ }
+
+ jlong cppAddr = this->getCppAddr();
+
+ jobject jself = env->NewObject(clazz, ctor, cppAddr);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ return jself;
+}
diff --git a/subversion/bindings/javahl/native/SVNBase.h b/subversion/bindings/javahl/native/SVNBase.h
index 18ce43a..9b3d41a 100644
--- a/subversion/bindings/javahl/native/SVNBase.h
+++ b/subversion/bindings/javahl/native/SVNBase.h
@@ -49,7 +49,7 @@
*
* @since 1.4.0
*/
- virtual void dispose() = 0;
+ virtual void dispose(jobject jthis) = 0;
/**
* This method should never be called, as @c dispose() should be
@@ -80,13 +80,12 @@
*
* @since 1.4.0
*/
- void dispose(jfieldID *fid, const char *className);
+ void dispose(jobject jthis, jfieldID *fid, const char *className);
/**
- * A pointer to the parent java object. This is not valid across JNI
- * method invocations, and so should be set in each one.
+ * Instantiates java object attached to this base object
*/
- jobject jthis;
+ jobject createCppBoundObject(const char *clazzName);
private:
/**
diff --git a/subversion/bindings/javahl/native/SVNClient.cpp b/subversion/bindings/javahl/native/SVNClient.cpp
index f8a840f..6344377 100644
--- a/subversion/bindings/javahl/native/SVNClient.cpp
+++ b/subversion/bindings/javahl/native/SVNClient.cpp
@@ -30,6 +30,7 @@
#include "DiffSummaryReceiver.h"
#include "ClientContext.h"
#include "Prompter.h"
+#include "RemoteSession.h"
#include "Pool.h"
#include "Targets.h"
#include "Revision.h"
@@ -67,10 +68,11 @@
#include <vector>
#include <iostream>
#include <sstream>
+#include <string>
SVNClient::SVNClient(jobject jthis_in)
- : context(jthis_in, pool), m_lastPath("", pool)
+ : m_lastPath("", pool), context(jthis_in, pool)
{
}
@@ -86,10 +88,10 @@
return (cppAddr == 0 ? NULL : reinterpret_cast<SVNClient *>(cppAddr));
}
-void SVNClient::dispose()
+void SVNClient::dispose(jobject jthis)
{
static jfieldID fid = 0;
- SVNBase::dispose(&fid, JAVA_PACKAGE"/SVNClient");
+ SVNBase::dispose(jthis, &fid, JAVA_PACKAGE"/SVNClient");
}
jstring SVNClient::getAdminDirectoryName()
@@ -130,7 +132,7 @@
SVN_JNI_NULL_PTR_EX(url, "path or url", );
Path urlPath(url, subPool);
- SVN_JNI_ERR(urlPath.error_occured(), );
+ SVN_JNI_ERR(urlPath.error_occurred(), );
SVN_JNI_ERR(svn_client_list2(urlPath.c_str(),
pegRevision.revision(),
@@ -161,7 +163,7 @@
callback->setWcCtx(ctx->wc_ctx);
Path checkedPath(path, subPool);
- SVN_JNI_ERR(checkedPath.error_occured(), );
+ SVN_JNI_ERR(checkedPath.error_occurred(), );
rev.kind = svn_opt_revision_unspecified;
@@ -175,6 +177,43 @@
subPool.getPool()), );
}
+/* Convert a vector of revision ranges to an APR array of same. */
+static apr_array_header_t *
+rev_range_vector_to_apr_array(std::vector<RevisionRange> &revRanges,
+ SVN::Pool &subPool)
+{
+ apr_array_header_t *ranges =
+ apr_array_make(subPool.getPool(),
+ static_cast<int>(revRanges.size()),
+ sizeof(svn_opt_revision_range_t *));
+
+ std::vector<RevisionRange>::const_iterator it;
+ for (it = revRanges.begin(); it != revRanges.end(); ++it)
+ {
+ if (it->toRange(subPool)->start.kind
+ == svn_opt_revision_unspecified
+ && it->toRange(subPool)->end.kind
+ == svn_opt_revision_unspecified)
+ {
+ svn_opt_revision_range_t *range =
+ reinterpret_cast<svn_opt_revision_range_t *>
+ (apr_pcalloc(subPool.getPool(), sizeof(*range)));
+ range->start.kind = svn_opt_revision_number;
+ range->start.value.number = 1;
+ range->end.kind = svn_opt_revision_head;
+ APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) = range;
+ }
+ else
+ {
+ APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) =
+ it->toRange(subPool);
+ }
+ if (JNIUtil::isExceptionThrown())
+ return NULL;
+ }
+ return ranges;
+}
+
void SVNClient::logMessages(const char *path, Revision &pegRevision,
std::vector<RevisionRange> &logRanges,
bool stopOnCopy, bool discoverPaths,
@@ -191,36 +230,12 @@
Targets target(path, subPool);
const apr_array_header_t *targets = target.array(subPool);
- SVN_JNI_ERR(target.error_occured(), );
+ SVN_JNI_ERR(target.error_occurred(), );
apr_array_header_t *ranges =
- apr_array_make(subPool.getPool(), logRanges.size(),
- sizeof(svn_opt_revision_range_t *));
-
- std::vector<RevisionRange>::const_iterator it;
- for (it = logRanges.begin(); it != logRanges.end(); ++it)
- {
- if (it->toRange(subPool)->start.kind
- == svn_opt_revision_unspecified
- && it->toRange(subPool)->end.kind
- == svn_opt_revision_unspecified)
- {
- svn_opt_revision_range_t *range =
- (svn_opt_revision_range_t *)apr_pcalloc(subPool.getPool(),
- sizeof(*range));
- range->start.kind = svn_opt_revision_number;
- range->start.value.number = 1;
- range->end.kind = svn_opt_revision_head;
- APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) = range;
- }
- else
- {
- APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) =
- it->toRange(subPool);
- }
- if (JNIUtil::isExceptionThrown())
- return;
- }
+ rev_range_vector_to_apr_array(logRanges, subPool);
+ if (JNIUtil::isExceptionThrown())
+ return;
SVN_JNI_ERR(svn_client_log5(targets, pegRevision.revision(), ranges,
limit, discoverPaths, stopOnCopy,
@@ -242,8 +257,8 @@
Path url(moduleName, subPool);
Path path(destPath, subPool);
- SVN_JNI_ERR(url.error_occured(), -1);
- SVN_JNI_ERR(path.error_occured(), -1);
+ SVN_JNI_ERR(url.error_occurred(), -1);
+ SVN_JNI_ERR(path.error_occurred(), -1);
svn_revnum_t rev;
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
@@ -274,7 +289,7 @@
return;
const apr_array_header_t *targets2 = targets.array(subPool);
- SVN_JNI_ERR(targets.error_occured(), );
+ SVN_JNI_ERR(targets.error_occurred(), );
SVN_JNI_ERR(svn_client_delete4(targets2, force, keep_local,
revprops.hash(subPool),
@@ -295,14 +310,15 @@
Targets target(path, subPool);
const apr_array_header_t *targets = target.array(subPool);
- SVN_JNI_ERR(target.error_occured(), );
+ SVN_JNI_ERR(target.error_occurred(), );
SVN_JNI_ERR(svn_client_revert2(targets, depth,
changelists.array(subPool), ctx,
subPool.getPool()), );
}
void SVNClient::add(const char *path,
- svn_depth_t depth, bool force, bool no_ignore,
+ svn_depth_t depth, bool force,
+ bool no_ignore, bool no_autoprops,
bool add_parents)
{
SVN::Pool subPool(pool);
@@ -310,7 +326,7 @@
SVN_JNI_NULL_PTR_EX(path, "path", );
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), );
+ SVN_JNI_ERR(intPath.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
return;
@@ -333,7 +349,7 @@
return NULL;
const apr_array_header_t *array = targets.array(subPool);
- SVN_JNI_ERR(targets.error_occured(), NULL);
+ SVN_JNI_ERR(targets.error_occurred(), NULL);
SVN_JNI_ERR(svn_client_update4(&revs, array,
revision.revision(),
depth,
@@ -369,13 +385,14 @@
{
SVN::Pool subPool(pool);
const apr_array_header_t *targets2 = targets.array(subPool);
- SVN_JNI_ERR(targets.error_occured(), );
+ SVN_JNI_ERR(targets.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(message, subPool);
if (ctx == NULL)
return;
SVN_JNI_ERR(svn_client_commit5(targets2, depth,
- noUnlock, keepChangelist, TRUE,
+ noUnlock, keepChangelist,
+ TRUE,
changelists.array(subPool),
revprops.hash(subPool),
CommitCallback::callback, callback,
@@ -399,7 +416,7 @@
}
SVN_JNI_NULL_PTR_EX(destPath, "destPath", );
Path destinationPath(destPath, subPool);
- SVN_JNI_ERR(destinationPath.error_occured(), );
+ SVN_JNI_ERR(destinationPath.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(message, subPool);
if (ctx == NULL)
@@ -414,16 +431,16 @@
void SVNClient::move(Targets &srcPaths, const char *destPath,
CommitMessage *message, bool force, bool moveAsChild,
- bool makeParents, RevpropTable &revprops,
- CommitCallback *callback)
+ bool makeParents, bool metadataOnly, bool allowMixRev,
+ RevpropTable &revprops, CommitCallback *callback)
{
SVN::Pool subPool(pool);
const apr_array_header_t *srcs = srcPaths.array(subPool);
- SVN_JNI_ERR(srcPaths.error_occured(), );
+ SVN_JNI_ERR(srcPaths.error_occurred(), );
SVN_JNI_NULL_PTR_EX(destPath, "destPath", );
Path destinationPath(destPath, subPool);
- SVN_JNI_ERR(destinationPath.error_occured(), );
+ SVN_JNI_ERR(destinationPath.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(message, subPool);
if (ctx == NULL)
@@ -446,7 +463,7 @@
return;
const apr_array_header_t *targets2 = targets.array(subPool);
- SVN_JNI_ERR(targets.error_occured(), );
+ SVN_JNI_ERR(targets.error_occurred(), );
SVN_JNI_ERR(svn_client_mkdir4(targets2, makeParents,
revprops.hash(subPool),
@@ -459,7 +476,7 @@
SVN::Pool subPool(pool);
SVN_JNI_NULL_PTR_EX(path, "path", );
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), );
+ SVN_JNI_ERR(intPath.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
@@ -474,7 +491,7 @@
SVN::Pool subPool(pool);
SVN_JNI_NULL_PTR_EX(path, "path", );
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), );
+ SVN_JNI_ERR(intPath.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
return;
@@ -492,9 +509,9 @@
SVN_JNI_NULL_PTR_EX(srcPath, "srcPath", -1);
SVN_JNI_NULL_PTR_EX(destPath, "destPath", -1);
Path sourcePath(srcPath, subPool);
- SVN_JNI_ERR(sourcePath.error_occured(), -1);
+ SVN_JNI_ERR(sourcePath.error_occurred(), -1);
Path destinationPath(destPath, subPool);
- SVN_JNI_ERR(destinationPath.error_occured(), -1);
+ SVN_JNI_ERR(destinationPath.error_occurred(), -1);
svn_revnum_t rev;
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
@@ -525,9 +542,9 @@
SVN_JNI_NULL_PTR_EX(path, "path", -1);
SVN_JNI_NULL_PTR_EX(url, "url", -1);
Path intUrl(url, subPool);
- SVN_JNI_ERR(intUrl.error_occured(), -1);
+ SVN_JNI_ERR(intUrl.error_occurred(), -1);
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), -1);
+ SVN_JNI_ERR(intPath.error_occurred(), -1);
svn_revnum_t rev;
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
@@ -552,16 +569,19 @@
void SVNClient::doImport(const char *path, const char *url,
CommitMessage *message, svn_depth_t depth,
- bool noIgnore, bool ignoreUnknownNodeTypes,
- RevpropTable &revprops, CommitCallback *callback)
+ bool noIgnore, bool noAutoProps,
+ bool ignoreUnknownNodeTypes,
+ RevpropTable &revprops,
+ ImportFilterCallback *ifCallback,
+ CommitCallback *commitCallback)
{
SVN::Pool subPool(pool);
SVN_JNI_NULL_PTR_EX(path, "path", );
SVN_JNI_NULL_PTR_EX(url, "url", );
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), );
+ SVN_JNI_ERR(intPath.error_occurred(), );
Path intUrl(url, subPool);
- SVN_JNI_ERR(intUrl.error_occured(), );
+ SVN_JNI_ERR(intUrl.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(message, subPool);
if (ctx == NULL)
@@ -570,7 +590,7 @@
SVN_JNI_ERR(svn_client_import4(intPath.c_str(), intUrl.c_str(), depth,
noIgnore, ignoreUnknownNodeTypes,
revprops.hash(subPool),
- CommitCallback::callback, callback,
+ CommitCallback::callback, commitCallback,
ctx, subPool.getPool()), );
}
@@ -593,21 +613,22 @@
void SVNClient::merge(const char *path1, Revision &revision1,
const char *path2, Revision &revision2,
- const char *localPath, bool force, svn_depth_t depth,
- bool ignoreAncestry, bool dryRun, bool recordOnly)
+ const char *localPath, bool forceDelete,
+ svn_depth_t depth, bool ignoreAncestry,
+ bool dryRun, bool recordOnly)
{
SVN::Pool subPool(pool);
SVN_JNI_NULL_PTR_EX(path1, "path1", );
SVN_JNI_NULL_PTR_EX(path2, "path2", );
SVN_JNI_NULL_PTR_EX(localPath, "localPath", );
Path intLocalPath(localPath, subPool);
- SVN_JNI_ERR(intLocalPath.error_occured(), );
+ SVN_JNI_ERR(intLocalPath.error_occurred(), );
Path srcPath1(path1, subPool);
- SVN_JNI_ERR(srcPath1.error_occured(), );
+ SVN_JNI_ERR(srcPath1.error_occurred(), );
Path srcPath2(path2, subPool);
- SVN_JNI_ERR(srcPath2.error_occured(), );
+ SVN_JNI_ERR(srcPath2.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
@@ -616,64 +637,42 @@
SVN_JNI_ERR(svn_client_merge4(srcPath1.c_str(), revision1.revision(),
srcPath2.c_str(), revision2.revision(),
intLocalPath.c_str(),
- depth,
- ignoreAncestry, force, recordOnly, dryRun,
+ depth, ignoreAncestry,
+ forceDelete, recordOnly, dryRun,
TRUE, NULL, ctx, subPool.getPool()), );
}
void SVNClient::merge(const char *path, Revision &pegRevision,
- std::vector<RevisionRange> &rangesToMerge,
- const char *localPath, bool force, svn_depth_t depth,
- bool ignoreAncestry, bool dryRun, bool recordOnly)
+ std::vector<RevisionRange> *rangesToMerge,
+ const char *localPath, bool forceDelete,
+ svn_depth_t depth, bool ignoreAncestry,
+ bool dryRun, bool recordOnly)
{
SVN::Pool subPool(pool);
SVN_JNI_NULL_PTR_EX(path, "path", );
SVN_JNI_NULL_PTR_EX(localPath, "localPath", );
Path intLocalPath(localPath, subPool);
- SVN_JNI_ERR(intLocalPath.error_occured(), );
+ SVN_JNI_ERR(intLocalPath.error_occurred(), );
Path srcPath(path, subPool);
- SVN_JNI_ERR(srcPath.error_occured(), );
+ SVN_JNI_ERR(srcPath.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
return;
apr_array_header_t *ranges =
- apr_array_make(subPool.getPool(), rangesToMerge.size(),
- sizeof(const svn_opt_revision_range_t *));
-
- std::vector<RevisionRange>::const_iterator it;
- for (it = rangesToMerge.begin(); it != rangesToMerge.end(); ++it)
- {
- if (it->toRange(subPool)->start.kind
- == svn_opt_revision_unspecified
- && it->toRange(subPool)->end.kind
- == svn_opt_revision_unspecified)
- {
- svn_opt_revision_range_t *range =
- (svn_opt_revision_range_t *)apr_pcalloc(subPool.getPool(),
- sizeof(*range));
- range->start.kind = svn_opt_revision_number;
- range->start.value.number = 1;
- range->end.kind = svn_opt_revision_head;
- APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) = range;
- }
- else
- {
- APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) =
- it->toRange(subPool);
- }
- if (JNIUtil::isExceptionThrown())
- return;
- }
+ (!rangesToMerge ? NULL
+ : rev_range_vector_to_apr_array(*rangesToMerge, subPool));
+ if (JNIUtil::isExceptionThrown())
+ return;
SVN_JNI_ERR(svn_client_merge_peg4(srcPath.c_str(),
ranges,
pegRevision.revision(),
intLocalPath.c_str(),
- depth,
- ignoreAncestry, force, recordOnly,
+ depth, ignoreAncestry,
+ forceDelete, recordOnly,
dryRun, TRUE, NULL, ctx,
subPool.getPool()), );
}
@@ -685,10 +684,10 @@
SVN_JNI_NULL_PTR_EX(path, "path", );
SVN_JNI_NULL_PTR_EX(localPath, "localPath", );
Path intLocalPath(localPath, subPool);
- SVN_JNI_ERR(intLocalPath.error_occured(), );
+ SVN_JNI_ERR(intLocalPath.error_occurred(), );
Path srcPath(path, subPool);
- SVN_JNI_ERR(srcPath.error_occured(), );
+ SVN_JNI_ERR(srcPath.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
@@ -713,7 +712,7 @@
svn_mergeinfo_t mergeinfo;
Path intLocalTarget(target, subPool);
- SVN_JNI_ERR(intLocalTarget.error_occured(), NULL);
+ SVN_JNI_ERR(intLocalTarget.error_occurred(), NULL);
SVN_JNI_ERR(svn_client_mergeinfo_get_merged(&mergeinfo,
intLocalTarget.c_str(),
pegRevision.revision(), ctx,
@@ -758,13 +757,13 @@
void *val;
apr_hash_this(hi, &path, NULL, &val);
- jstring jpath = JNIUtil::makeJString((const char *) path);
+ jstring jpath =
+ JNIUtil::makeJString(reinterpret_cast<const char *>(path));
jobject jranges =
CreateJ::RevisionRangeList((apr_array_header_t *) val);
env->CallVoidMethod(jmergeinfo, addRevisions, jpath, jranges);
- env->DeleteLocalRef(jranges);
env->DeleteLocalRef(jpath);
}
@@ -790,11 +789,11 @@
SVN_JNI_NULL_PTR_EX(pathOrURL, "path or url", );
Path urlPath(pathOrURL, subPool);
- SVN_JNI_ERR(urlPath.error_occured(), );
+ SVN_JNI_ERR(urlPath.error_occurred(), );
SVN_JNI_NULL_PTR_EX(mergeSourceURL, "merge source url", );
Path srcURL(mergeSourceURL, subPool);
- SVN_JNI_ERR(srcURL.error_occured(), );
+ SVN_JNI_ERR(srcURL.error_occurred(), );
SVN_JNI_ERR(svn_client_mergeinfo_log((type == 1),
urlPath.c_str(),
@@ -816,23 +815,24 @@
* Get a property.
*/
jbyteArray SVNClient::propertyGet(const char *path, const char *name,
- Revision &revision, Revision &pegRevision)
+ Revision &revision, Revision &pegRevision,
+ StringArray &changelists)
{
SVN::Pool subPool(pool);
SVN_JNI_NULL_PTR_EX(path, "path", NULL);
SVN_JNI_NULL_PTR_EX(name, "name", NULL);
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), NULL);
+ SVN_JNI_ERR(intPath.error_occurred(), NULL);
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
return NULL;
apr_hash_t *props;
- SVN_JNI_ERR(svn_client_propget3(&props, name,
+ SVN_JNI_ERR(svn_client_propget4(&props, name,
intPath.c_str(), pegRevision.revision(),
revision.revision(), NULL, svn_depth_empty,
- NULL, ctx, subPool.getPool()),
+ NULL, ctx, subPool.getPool(), subPool.getPool()),
NULL);
apr_hash_index_t *hi;
@@ -842,23 +842,23 @@
return NULL; // no property with this name
svn_string_t *propval;
- apr_hash_this(hi, NULL, NULL, (void**)&propval);
+ apr_hash_this(hi, NULL, NULL, reinterpret_cast<void**>(&propval));
if (propval == NULL)
return NULL;
- return JNIUtil::makeJByteArray((const signed char *)propval->data,
- propval->len);
+ return JNIUtil::makeJByteArray(propval);
}
void SVNClient::properties(const char *path, Revision &revision,
Revision &pegRevision, svn_depth_t depth,
- StringArray &changelists, ProplistCallback *callback)
+ StringArray &changelists,
+ ProplistCallback *callback)
{
SVN::Pool subPool(pool);
SVN_JNI_NULL_PTR_EX(path, "path", );
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), );
+ SVN_JNI_ERR(intPath.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
@@ -869,8 +869,6 @@
changelists.array(subPool),
ProplistCallback::callback, callback,
ctx, subPool.getPool()), );
-
- return;
}
void SVNClient::propertySetLocal(Targets &targets, const char *name,
@@ -884,8 +882,10 @@
if (value.isNull())
val = NULL;
else
- val = svn_string_ncreate((const char *)value.getBytes(), value.getLength(),
- subPool.getPool());
+ val = svn_string_ncreate
+ (reinterpret_cast<const char *>(value.getBytes()),
+ value.getLength(),
+ subPool.getPool());
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
@@ -912,11 +912,13 @@
if (value.isNull())
val = NULL;
else
- val = svn_string_ncreate((const char *)value.getBytes(), value.getLength(),
- subPool.getPool());
+ val = svn_string_ncreate
+ (reinterpret_cast<const char *>(value.getBytes()),
+ value.getLength(),
+ subPool.getPool());
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), );
+ SVN_JNI_ERR(intPath.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(message, subPool);
if (ctx == NULL)
@@ -942,6 +944,7 @@
const char *c_relToDir = relativeToDir ?
svn_dirent_canonicalize(relativeToDir, subPool.getPool()) :
relativeToDir;
+ bool noDiffAdded = false; /* ### Promote to argument */
SVN_JNI_NULL_PTR_EX(target1, "target", );
// target2 is ignored when pegRevision is provided.
@@ -954,7 +957,7 @@
return;
Path path1(target1, subPool);
- SVN_JNI_ERR(path1.error_occured(), );
+ SVN_JNI_ERR(path1.error_occurred(), );
apr_file_t *outfile = NULL;
apr_status_t rv =
@@ -998,7 +1001,7 @@
{
// "Regular" diff (without a peg revision).
Path path2(target2, subPool);
- err = path2.error_occured();
+ err = path2.error_occurred();
if (err)
{
if (outfile)
@@ -1081,9 +1084,9 @@
return;
Path path1(target1, subPool);
- SVN_JNI_ERR(path1.error_occured(), );
+ SVN_JNI_ERR(path1.error_occurred(), );
Path path2(target2, subPool);
- SVN_JNI_ERR(path2.error_occured(), );
+ SVN_JNI_ERR(path2.error_occurred(), );
SVN_JNI_ERR(svn_client_diff_summarize2(path1.c_str(), revision1.revision(),
path2.c_str(), revision2.revision(),
@@ -1110,7 +1113,7 @@
return;
Path path(target, subPool);
- SVN_JNI_ERR(path.error_occured(), );
+ SVN_JNI_ERR(path.error_occurred(), );
SVN_JNI_ERR(svn_client_diff_summarize_peg2(path.c_str(),
pegRevision.revision(),
@@ -1131,7 +1134,7 @@
SVN::Pool subPool(pool);
SVN_JNI_NULL_PTR_EX(path, "path", );
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), );
+ SVN_JNI_ERR(intPath.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
@@ -1150,7 +1153,7 @@
SVN_JNI_NULL_PTR_EX(path, "path", NULL);
SVN_JNI_NULL_PTR_EX(name, "name", NULL);
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), NULL);
+ SVN_JNI_ERR(intPath.error_occurred(), NULL);
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
@@ -1178,8 +1181,7 @@
if (propval == NULL)
return NULL;
- return JNIUtil::makeJByteArray((const signed char *)propval->data,
- propval->len);
+ return JNIUtil::makeJByteArray(propval);
}
void SVNClient::relocate(const char *from, const char *to, const char *path,
bool ignoreExternals)
@@ -1189,13 +1191,13 @@
SVN_JNI_NULL_PTR_EX(from, "from", );
SVN_JNI_NULL_PTR_EX(to, "to", );
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), );
+ SVN_JNI_ERR(intPath.error_occurred(), );
Path intFrom(from, subPool);
- SVN_JNI_ERR(intFrom.error_occured(), );
+ SVN_JNI_ERR(intFrom.error_occurred(), );
Path intTo(to, subPool);
- SVN_JNI_ERR(intTo.error_occured(), );
+ SVN_JNI_ERR(intTo.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
@@ -1213,21 +1215,19 @@
{
SVN::Pool subPool(pool);
SVN_JNI_NULL_PTR_EX(path, "path", );
- apr_pool_t *pool = subPool.getPool();
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), );
+ SVN_JNI_ERR(intPath.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
return;
- SVN_JNI_ERR(svn_client_blame5(intPath.c_str(), pegRevision.revision(),
- revisionStart.revision(),
- revisionEnd.revision(),
- svn_diff_file_options_create(pool),
- ignoreMimeType, includeMergedRevisions,
- BlameCallback::callback, callback, ctx,
- pool),
+ SVN_JNI_ERR(svn_client_blame5(
+ intPath.c_str(), pegRevision.revision(), revisionStart.revision(),
+ revisionEnd.revision(),
+ svn_diff_file_options_create(subPool.getPool()), ignoreMimeType,
+ includeMergedRevisions, BlameCallback::callback, callback, ctx,
+ subPool.getPool()),
);
}
@@ -1238,7 +1238,7 @@
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
const apr_array_header_t *srcs = srcPaths.array(subPool);
- SVN_JNI_ERR(srcPaths.error_occured(), );
+ SVN_JNI_ERR(srcPaths.error_occurred(), );
SVN_JNI_ERR(svn_client_add_to_changelist(srcs, changelist, depth,
changelists.array(subPool),
@@ -1252,7 +1252,7 @@
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
const apr_array_header_t *srcs = srcPaths.array(subPool);
- SVN_JNI_ERR(srcPaths.error_occured(), );
+ SVN_JNI_ERR(srcPaths.error_occurred(), );
SVN_JNI_ERR(svn_client_remove_from_changelists(srcs, depth,
changelists.array(subPool),
@@ -1278,7 +1278,7 @@
{
SVN::Pool subPool(pool);
const apr_array_header_t *targetsApr = targets.array(subPool);
- SVN_JNI_ERR(targets.error_occured(), );
+ SVN_JNI_ERR(targets.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
SVN_JNI_ERR(svn_client_lock(targetsApr, comment, force, ctx,
@@ -1290,10 +1290,10 @@
SVN::Pool subPool(pool);
const apr_array_header_t *targetsApr = targets.array(subPool);
- SVN_JNI_ERR(targets.error_occured(), );
+ SVN_JNI_ERR(targets.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
- SVN_JNI_ERR(svn_client_unlock((apr_array_header_t*)targetsApr, force,
- ctx, subPool.getPool()), );
+ SVN_JNI_ERR(svn_client_unlock(
+ targetsApr, force, ctx, subPool.getPool()), );
}
void SVNClient::setRevProperty(const char *path,
const char *name, Revision &rev,
@@ -1304,7 +1304,7 @@
SVN_JNI_NULL_PTR_EX(path, "path", );
SVN_JNI_NULL_PTR_EX(name, "name", );
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), );
+ SVN_JNI_ERR(intPath.error_occurred(), );
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
if (ctx == NULL)
@@ -1342,7 +1342,7 @@
SVN_JNI_NULL_PTR_EX(path, "path", NULL);
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), NULL);
+ SVN_JNI_ERR(intPath.error_occurred(), NULL);
int wc_format;
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
@@ -1409,7 +1409,7 @@
return;
Path checkedPath(path, subPool);
- SVN_JNI_ERR(checkedPath.error_occured(), );
+ SVN_JNI_ERR(checkedPath.error_occurred(), );
SVN_JNI_ERR(svn_client_upgrade(path, ctx, subPool.getPool()), );
}
@@ -1420,7 +1420,7 @@
SVN::Pool subPool(pool);
SVN_JNI_NULL_PTR_EX(path, "path", NULL);
Path intPath(path, subPool);
- SVN_JNI_ERR(intPath.error_occured(), NULL);
+ SVN_JNI_ERR(intPath.error_occurred(), NULL);
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
const char *URL;
@@ -1459,7 +1459,7 @@
return;
Path checkedPath(path, subPool);
- SVN_JNI_ERR(checkedPath.error_occured(), );
+ SVN_JNI_ERR(checkedPath.error_occurred(), );
SVN_JNI_ERR(svn_client_info3(checkedPath.c_str(),
pegRevision.revision(),
@@ -1484,9 +1484,9 @@
return;
Path checkedPatchPath(patchPath, subPool);
- SVN_JNI_ERR(checkedPatchPath.error_occured(), );
+ SVN_JNI_ERR(checkedPatchPath.error_occurred(), );
Path checkedTargetPath(targetPath, subPool);
- SVN_JNI_ERR(checkedTargetPath.error_occured(), );
+ SVN_JNI_ERR(checkedTargetPath.error_occurred(), );
// Should parameterize the following, instead of defaulting to FALSE
SVN_JNI_ERR(svn_client_patch(checkedPatchPath.c_str(),
@@ -1497,6 +1497,77 @@
ctx, subPool.getPool()), );
}
+jobject
+SVNClient::openRemoteSession(const char* path, int retryAttempts)
+{
+ static const svn_opt_revision_t HEAD = { svn_opt_revision_head, {0}};
+ static const svn_opt_revision_t NONE = { svn_opt_revision_unspecified, {0}};
+
+ SVN_JNI_NULL_PTR_EX(path, "path", NULL);
+
+ SVN::Pool subPool(pool);
+ svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
+ if (ctx == NULL)
+ return NULL;
+
+ Path checkedPath(path, subPool);
+ SVN_JNI_ERR(checkedPath.error_occurred(), NULL);
+
+ struct PathInfo
+ {
+ std::string url;
+ std::string uuid;
+ static svn_error_t *callback(void *baton,
+ const char *,
+ const svn_client_info2_t *info,
+ apr_pool_t *)
+ {
+ PathInfo* const pi = static_cast<PathInfo*>(baton);
+ pi->url = info->URL;
+ pi->uuid = info->repos_UUID;
+ return SVN_NO_ERROR;
+ }
+ } path_info;
+
+ SVN_JNI_ERR(svn_client_info3(
+ checkedPath.c_str(), &NONE,
+ (svn_path_is_url(checkedPath.c_str()) ? &HEAD : &NONE),
+ svn_depth_empty, FALSE, TRUE, NULL,
+ PathInfo::callback, &path_info,
+ 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());
+ if (!prompter)
+ {
+ /* context.getSelf() created a new global reference. */
+ JNIUtil::getEnv()->DeleteGlobalRef(jctx);
+ JNIUtil::throwNullPointerException("allocating Prompter");
+ return NULL;
+ }
+
+ jobject jremoteSession = RemoteSession::open(
+ retryAttempts, path_info.url.c_str(), path_info.uuid.c_str(),
+ context.getConfigDirectory(),
+ context.getUsername(), context.getPassword(),
+ prompter, jctx);
+ if (JNIUtil::isJavaExceptionThrown())
+ {
+ /* context.getSelf() created a new global reference. */
+ JNIUtil::getEnv()->DeleteGlobalRef(jctx);
+ jremoteSession = NULL;
+ delete prompter;
+ }
+
+ return jremoteSession;
+}
+
ClientContext &
SVNClient::getClientContext()
{
diff --git a/subversion/bindings/javahl/native/SVNClient.h b/subversion/bindings/javahl/native/SVNClient.h
index 45ea79d..bbd6e2f 100644
--- a/subversion/bindings/javahl/native/SVNClient.h
+++ b/subversion/bindings/javahl/native/SVNClient.h
@@ -46,6 +46,7 @@
class InfoCallback;
class CommitCallback;
class ListCallback;
+class ImportFilterCallback;
class StatusCallback;
class OutputStream;
class PatchCallback;
@@ -53,6 +54,7 @@
class CommitMessage;
class StringArray;
class RevpropTable;
+class DiffOptions;
#include "svn_types.h"
#include "svn_client.h"
#include "SVNBase.h"
@@ -60,6 +62,7 @@
class SVNClient :public SVNBase
{
public:
+ jobject openRemoteSession(const char* path, int);
void patch(const char *patchPath, const char *targetPath, bool dryRun,
int stripCount, bool reverse, bool ignoreWhitespace,
bool removeTempfiles, PatchCallback *callback);
@@ -91,23 +94,28 @@
jobject getMergeinfo(const char *target, Revision &pegRevision);
void getMergeinfoLog(int type, const char *pathOrURL,
Revision &pegRevision, const char *mergeSourceURL,
- Revision &srcPegRevision, bool discoverChangedPaths,
+ Revision &srcPegRevision,
+ bool discoverChangedPaths,
svn_depth_t depth, StringArray &revProps,
LogMessageCallback *callback);
jobject suggestMergeSources(const char *path, Revision &pegRevision);
- void merge(const char *path1, Revision &revision1, const char *path2,
- Revision &revision2, const char *localPath, bool force,
- svn_depth_t depth, bool ignoreAncestry, bool dryRun,
- bool recordOnly);
+ void merge(const char *path1, Revision &revision1,
+ const char *path2, Revision &revision2,
+ const char *localPath, bool forceDelete, svn_depth_t depth,
+ bool ignoreAncestry,
+ bool dryRun, bool recordOnly);
void merge(const char *path, Revision &pegRevision,
- std::vector<RevisionRange> &rangesToMerge,
- const char *localPath, bool force, svn_depth_t depth,
- bool ignoreAncestry, bool dryRun, bool recordOnly);
+ std::vector<RevisionRange> *rangesToMerge,
+ const char *localPath, bool forceDelete, svn_depth_t depth,
+ bool ignoreAncestry,
+ bool dryRun, bool recordOnly);
void mergeReintegrate(const char *path, Revision &pegRevision,
const char *localPath, bool dryRun);
void doImport(const char *path, const char *url, CommitMessage *message,
- svn_depth_t depth, bool noIgnore, bool ignoreUnknownNodeTypes,
- RevpropTable &revprops, CommitCallback *callback);
+ svn_depth_t depth, bool noIgnore, bool noAutoProps,
+ bool ignoreUnknownNodeTypes,
+ RevpropTable &revprops, ImportFilterCallback *ifCallback,
+ CommitCallback *commitCallback);
jlong doSwitch(const char *path, const char *url, Revision &revision,
Revision &pegRevision, svn_depth_t depth,
bool depthIsSticky, bool ignoreExternals,
@@ -123,7 +131,8 @@
RevpropTable &revprops, CommitCallback *callback);
void move(Targets &srcPaths, const char *destPath,
CommitMessage *message, bool force, bool moveAsChild,
- bool makeParents, RevpropTable &revprops, CommitCallback *callback);
+ bool makeParents, bool metadataOnly, bool allowMixRev,
+ RevpropTable &revprops, CommitCallback *callback);
void copy(CopySources ©Sources, const char *destPath,
CommitMessage *message, bool copyAsChild, bool makeParents,
bool ignoreExternals, RevpropTable &revprops,
@@ -135,8 +144,8 @@
jlongArray update(Targets &targets, Revision &revision, svn_depth_t depth,
bool depthIsSticky, bool makeParents, bool ignoreExternals,
bool allowUnverObstructions);
- void add(const char *path, svn_depth_t depth, bool force, bool no_ignore,
- bool add_parents);
+ void add(const char *path, svn_depth_t depth, bool force,
+ bool no_ignore, bool no_autoprops, bool add_parents);
void revert(const char *path, svn_depth_t depth, StringArray &changelists);
void remove(Targets &targets, CommitMessage *message, bool force,
bool keep_local, RevpropTable &revprops,
@@ -149,6 +158,7 @@
bool discoverPaths, bool includeMergedRevisions,
StringArray &revProps,
long limit, LogMessageCallback *callback);
+ jobject getVersionExtended(bool verbose);
jstring getAdminDirectoryName();
jboolean isAdminDirectory(const char *name);
void addToChangelist(Targets &srcPaths, const char *changelist,
@@ -171,7 +181,8 @@
bool lastChanged);
void upgrade(const char *path);
jbyteArray propertyGet(const char *path, const char *name,
- Revision &revision, Revision &pegRevision);
+ Revision &revision, Revision &pegRevision,
+ StringArray &changelists);
void diff(const char *target1, Revision &revision1,
const char *target2, Revision &revision2,
const char *relativeToDir, const char *outfileName,
@@ -196,7 +207,7 @@
ClientContext &getClientContext();
const char *getLastPath();
- void dispose();
+ void dispose(jobject jthis);
static SVNClient *getCppObject(jobject jthis);
SVNClient(jobject jthis_in);
virtual ~SVNClient();
diff --git a/subversion/bindings/javahl/native/SVNRepos.cpp b/subversion/bindings/javahl/native/SVNRepos.cpp
index 079ad59..0f7e017 100644
--- a/subversion/bindings/javahl/native/SVNRepos.cpp
+++ b/subversion/bindings/javahl/native/SVNRepos.cpp
@@ -54,10 +54,10 @@
return (cppAddr == 0 ? NULL : reinterpret_cast<SVNRepos *>(cppAddr));
}
-void SVNRepos::dispose()
+void SVNRepos::dispose(jobject jthis)
{
static jfieldID fid = 0;
- SVNBase::dispose(&fid, JAVA_PACKAGE"/SVNRepos");
+ SVNBase::dispose(jthis, &fid, JAVA_PACKAGE"/SVNRepos");
}
void SVNRepos::cancelOperation()
@@ -68,7 +68,7 @@
svn_error_t *
SVNRepos::checkCancel(void *cancelBaton)
{
- SVNRepos *that = (SVNRepos *)cancelBaton;
+ SVNRepos *that = static_cast<SVNRepos *>(cancelBaton);
if (that->m_cancelOperation)
return svn_error_create(SVN_ERR_CANCELLED, NULL,
_("Operation cancelled"));
@@ -169,7 +169,7 @@
for (revision = start; revision <= end; ++revision)
{
revisionPool.clear();
- SVN_JNI_ERR(svn_fs_deltify_revision (fs, revision, revisionPool.getPool()),
+ SVN_JNI_ERR(svn_fs_deltify_revision(fs, revision, revisionPool.getPool()),
);
}
@@ -177,7 +177,7 @@
}
void SVNRepos::dump(File &path, OutputStream &dataOut,
- Revision &revsionStart, Revision &revisionEnd,
+ Revision &revisionStart, Revision &revisionEnd,
bool incremental, bool useDeltas,
ReposNotifyCallback *notifyCallback)
{
@@ -199,9 +199,9 @@
SVN_JNI_ERR(svn_fs_youngest_rev(&youngest, fs, requestPool.getPool()), );
/* ### We only handle revision numbers right now, not dates. */
- if (revsionStart.revision()->kind == svn_opt_revision_number)
- lower = revsionStart.revision()->value.number;
- else if (revsionStart.revision()->kind == svn_opt_revision_head)
+ if (revisionStart.revision()->kind == svn_opt_revision_number)
+ lower = revisionStart.revision()->value.number;
+ else if (revisionStart.revision()->kind == svn_opt_revision_head)
lower = youngest;
else
lower = SVN_INVALID_REVNUM;
@@ -248,7 +248,7 @@
}
void SVNRepos::hotcopy(File &path, File &targetPath,
- bool cleanLogs)
+ bool cleanLogs, bool incremental)
{
SVN::Pool requestPool;
@@ -270,7 +270,7 @@
}
static void
-list_dblogs (File &path, MessageReceiver &receiver, bool only_unused)
+list_dblogs(File &path, MessageReceiver &receiver, bool only_unused)
{
SVN::Pool requestPool;
apr_array_header_t *logfiles;
@@ -294,7 +294,7 @@
log_utf8 = svn_dirent_join(path.getInternalStyle(requestPool),
APR_ARRAY_IDX(logfiles, i, const char *),
requestPool.getPool());
- log_utf8 = svn_dirent_local_style (log_utf8, requestPool.getPool());
+ log_utf8 = svn_dirent_local_style(log_utf8, requestPool.getPool());
receiver.receiveMessage(log_utf8);
}
}
@@ -312,6 +312,8 @@
void SVNRepos::load(File &path,
InputStream &dataIn,
+ Revision &revisionStart,
+ Revision &revisionEnd,
bool ignoreUUID,
bool forceUUID,
bool usePreCommitHook,
@@ -321,6 +323,7 @@
{
SVN::Pool requestPool;
svn_repos_t *repos;
+ svn_revnum_t lower = SVN_INVALID_REVNUM, upper = SVN_INVALID_REVNUM;
enum svn_repos_load_uuid uuid_action = svn_repos_load_uuid_default;
if (ignoreUUID)
uuid_action = svn_repos_load_uuid_ignore;
@@ -333,6 +336,20 @@
return;
}
+ /* ### We only handle revision numbers right now, not dates. */
+ if (revisionStart.revision()->kind == svn_opt_revision_number)
+ lower = revisionStart.revision()->value.number;
+ if (revisionEnd.revision()->kind == svn_opt_revision_number)
+ upper = revisionEnd.revision()->value.number;
+ if (upper < lower
+ && lower != SVN_INVALID_REVNUM
+ && upper != SVN_INVALID_REVNUM)
+ {
+ SVN_JNI_ERR(svn_error_create
+ (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("First revision cannot be higher than second")), );
+ }
+
SVN_JNI_ERR(svn_repos_open2(&repos, path.getInternalStyle(requestPool),
NULL, requestPool.getPool()), );
@@ -362,13 +379,13 @@
SVN_JNI_ERR(svn_repos_open2(&repos, path.getInternalStyle(requestPool),
NULL, requestPool.getPool()), );
- fs = svn_repos_fs (repos);
+ fs = svn_repos_fs(repos);
SVN_JNI_ERR(svn_fs_list_transactions(&txns, fs, requestPool.getPool()), );
/* Loop, printing revisions. */
for (int i = 0; i < txns->nelts; ++i)
{
- messageReceiver.receiveMessage(APR_ARRAY_IDX (txns, i, const char *));
+ messageReceiver.receiveMessage(APR_ARRAY_IDX(txns, i, const char *));
}
@@ -399,7 +416,7 @@
* recovery actually worked. */
SVN_JNI_ERR(svn_repos_open2(&repos, path.getInternalStyle(requestPool),
NULL, requestPool.getPool()), -1);
- SVN_JNI_ERR(svn_fs_youngest_rev(&youngest_rev, svn_repos_fs (repos),
+ SVN_JNI_ERR(svn_fs_youngest_rev(&youngest_rev, svn_repos_fs(repos),
requestPool.getPool()),
-1);
return youngest_rev;
@@ -423,13 +440,13 @@
SVN_JNI_ERR(svn_repos_open2(&repos, path.getInternalStyle(requestPool),
NULL, requestPool.getPool()), );
- fs = svn_repos_fs (repos);
+ fs = svn_repos_fs(repos);
args = transactions.array(requestPool);
/* All the rest of the arguments are transaction names. */
for (i = 0; i < args->nelts; ++i)
{
- const char *txn_name = APR_ARRAY_IDX (args, i, const char *);
+ const char *txn_name = APR_ARRAY_IDX(args, i, const char *);
svn_error_t *err;
/* Try to open the txn. If that succeeds, try to abort it. */
@@ -443,7 +460,7 @@
* all. */
if (err && (err->apr_err == SVN_ERR_FS_TRANSACTION_DEAD))
{
- svn_error_clear (err);
+ svn_error_clear(err);
err = svn_fs_purge_txn(fs, txn_name, transactionPool.getPool());
}
@@ -497,7 +514,7 @@
}
else
{
- svn_fs_t *fs = svn_repos_fs (repos);
+ svn_fs_t *fs = svn_repos_fs(repos);
err = svn_fs_change_rev_prop2(fs, revision.revision()->value.number,
propName, NULL, propValStr,
requestPool.getPool());
@@ -554,7 +571,7 @@
* with no interest in the output. */
SVN_JNI_ERR(svn_repos_open2(&repos, path.getInternalStyle(requestPool),
NULL, requestPool.getPool()), );
- SVN_JNI_ERR(svn_fs_youngest_rev(&youngest, svn_repos_fs (repos),
+ SVN_JNI_ERR(svn_fs_youngest_rev(&youngest, svn_repos_fs(repos),
requestPool.getPool()), );
/* Find the revision numbers at which to start and end. */
@@ -658,13 +675,13 @@
std::vector<jobject> jlocks;
- for (hi = apr_hash_first (requestPool.getPool(), locks);
+ for (hi = apr_hash_first(requestPool.getPool(), locks);
hi;
- hi = apr_hash_next (hi))
+ hi = apr_hash_next(hi))
{
void *val;
- apr_hash_this (hi, NULL, NULL, &val);
- svn_lock_t *lock = (svn_lock_t *)val;
+ apr_hash_this(hi, NULL, NULL, &val);
+ svn_lock_t *lock = reinterpret_cast<svn_lock_t *>(val);
jobject jLock = CreateJ::Lock(lock);
jlocks.push_back(jLock);
@@ -691,8 +708,8 @@
SVN_JNI_ERR(svn_repos_open2(&repos, path.getInternalStyle(requestPool),
NULL, requestPool.getPool()), );
- fs = svn_repos_fs (repos);
- const char *username;
+ fs = svn_repos_fs(repos);
+ const char *username = NULL;
/* svn_fs_unlock() demands that some username be associated with the
* filesystem, so just use the UID of the person running 'svnadmin'.*/
@@ -704,7 +721,7 @@
apr_uid_name_get (&un, uid, pool) == APR_SUCCESS)
{
svn_error_t *err = svn_utf_cstring_to_utf8(&username, un, pool);
- svn_error_clear (err);
+ svn_error_clear(err);
if (err)
username = "administrator";
}
@@ -720,7 +737,7 @@
const apr_array_header_t *args = locks.array(requestPool);
for (int i = 0; i < args->nelts; ++i)
{
- const char *lock_path = APR_ARRAY_IDX (args, i, const char *);
+ const char *lock_path = APR_ARRAY_IDX(args, i, const char *);
svn_lock_t *lock;
/* Fetch the path's svn_lock_t. */
@@ -731,13 +748,13 @@
continue;
/* Now forcibly destroy the lock. */
- err = svn_fs_unlock (fs, lock_path,
- lock->token, 1 /* force */, subpool.getPool());
+ err = svn_fs_unlock(fs, lock_path,
+ lock->token, 1 /* force */, subpool.getPool());
if (err)
goto move_on;
move_on:
- svn_error_clear (err);
+ svn_error_clear(err);
subpool.clear();
}
diff --git a/subversion/bindings/javahl/native/SVNRepos.h b/subversion/bindings/javahl/native/SVNRepos.h
index 492b940..91f39c3 100644
--- a/subversion/bindings/javahl/native/SVNRepos.h
+++ b/subversion/bindings/javahl/native/SVNRepos.h
@@ -52,13 +52,15 @@
void rmtxns(File &path, StringArray &transactions);
jlong recover(File &path, ReposNotifyCallback *notifyCallback);
void lstxns(File &path, MessageReceiver &messageReceiver);
- void load(File &path, InputStream &dataIn, bool ignoreUUID, bool forceUUID,
+ void load(File &path, InputStream &dataIn,
+ Revision &revsionStart, Revision &revisionEnd,
+ bool ignoreUUID, bool forceUUID,
bool usePreCommitHook, bool usePostCommitHook,
const char *relativePath, ReposNotifyCallback *notifyCallback);
void listUnusedDBLogs(File &path,
MessageReceiver &messageReceiver);
void listDBLogs(File &path, MessageReceiver &messageReceiver);
- void hotcopy(File &path, File &targetPath, bool cleanLogs);
+ void hotcopy(File &path, File &targetPath, bool cleanLogs, bool incremental);
void dump(File &path, OutputStream &dataOut, Revision &revsionStart,
Revision &RevisionEnd, bool incremental, bool useDeltas,
ReposNotifyCallback *notifyCallback);
@@ -69,7 +71,7 @@
void pack(File &path, ReposNotifyCallback *callback);
SVNRepos();
virtual ~SVNRepos();
- void dispose();
+ void dispose(jobject jthis);
static SVNRepos *getCppObject(jobject jthis);
static svn_error_t *checkCancel(void *cancelBaton);
diff --git a/subversion/bindings/javahl/native/StatusCallback.cpp b/subversion/bindings/javahl/native/StatusCallback.cpp
index 49a8043..cc0d67a 100644
--- a/subversion/bindings/javahl/native/StatusCallback.cpp
+++ b/subversion/bindings/javahl/native/StatusCallback.cpp
@@ -55,7 +55,8 @@
apr_pool_t *pool)
{
if (baton)
- return ((StatusCallback *)baton)->doStatus(local_abspath, status, pool);
+ return static_cast<StatusCallback *>(baton)->doStatus(
+ local_abspath, status, pool);
return SVN_NO_ERROR;
}
@@ -93,7 +94,7 @@
jstring jPath = JNIUtil::makeJString(local_abspath);
if (JNIUtil::isJavaExceptionThrown())
- POP_AND_RETURN_NULL;
+ POP_AND_RETURN(SVN_NO_ERROR);
jobject jStatus = CreateJ::Status(wc_ctx, status, pool);
if (JNIUtil::isJavaExceptionThrown())
diff --git a/subversion/bindings/javahl/native/StringArray.cpp b/subversion/bindings/javahl/native/StringArray.cpp
index 03e7828..0438e44 100644
--- a/subversion/bindings/javahl/native/StringArray.cpp
+++ b/subversion/bindings/javahl/native/StringArray.cpp
@@ -39,7 +39,8 @@
const apr_array_header_t *StringArray::array(const SVN::Pool &pool)
{
apr_array_header_t *strings
- = apr_array_make(pool.getPool(), m_strings.size(), sizeof(char *));
+ = apr_array_make(pool.getPool(), static_cast<int>(m_strings.size()),
+ sizeof(char *));
std::vector<std::string>::const_iterator it;
for (it = m_strings.begin(); it < m_strings.end(); ++it)
@@ -69,7 +70,7 @@
if (JNIUtil::isExceptionThrown())
return;
- m_strings.push_back(std::string((const char *)str));
+ m_strings.push_back(std::string(static_cast<const char *>(str)));
}
}
diff --git a/subversion/bindings/javahl/native/Targets.cpp b/subversion/bindings/javahl/native/Targets.cpp
index 767caca..85ecc34 100644
--- a/subversion/bindings/javahl/native/Targets.cpp
+++ b/subversion/bindings/javahl/native/Targets.cpp
@@ -40,13 +40,13 @@
: m_subpool(in_pool)
{
m_strArray = NULL;
- m_targets.push_back (apr_pstrdup(m_subpool.getPool(), path));
- m_error_occured = NULL;
+ m_targets.push_back(apr_pstrdup(m_subpool.getPool(), path));
+ m_error_occurred = NULL;
}
void Targets::add(const char *path)
{
- m_targets.push_back (path);
+ m_targets.push_back(path);
}
const apr_array_header_t *Targets::array(const SVN::Pool &pool)
@@ -62,7 +62,7 @@
svn_error_t *err = JNIUtil::preprocessPath(tt, pool.getPool());
if (err != NULL)
{
- m_error_occured = err;
+ m_error_occurred = err;
break;
}
m_targets.push_back(tt);
@@ -72,9 +72,9 @@
std::vector<const char*>::const_iterator it;
apr_pool_t *apr_pool = pool.getPool();
- apr_array_header_t *apr_targets = apr_array_make (apr_pool,
- m_targets.size(),
- sizeof(const char *));
+ apr_array_header_t *apr_targets
+ = apr_array_make(apr_pool, static_cast<int>(m_targets.size()),
+ sizeof(const char *));
for (it = m_targets.begin(); it != m_targets.end(); ++it)
{
@@ -83,7 +83,7 @@
svn_error_t *err = JNIUtil::preprocessPath(target, pool.getPool());
if (err != NULL)
{
- m_error_occured = err;
+ m_error_occurred = err;
break;
}
APR_ARRAY_PUSH(apr_targets, const char *) = target;
@@ -96,10 +96,10 @@
: m_subpool(in_pool)
{
m_strArray = &strArray;
- m_error_occured = NULL;
+ m_error_occurred = NULL;
}
-svn_error_t *Targets::error_occured()
+svn_error_t *Targets::error_occurred()
{
- return m_error_occured;
+ return m_error_occurred;
}
diff --git a/subversion/bindings/javahl/native/Targets.h b/subversion/bindings/javahl/native/Targets.h
index 3743fd8..8d27a0d 100644
--- a/subversion/bindings/javahl/native/Targets.h
+++ b/subversion/bindings/javahl/native/Targets.h
@@ -43,14 +43,14 @@
SVN::Pool m_subpool;
std::vector<const char*> m_targets;
StringArray *m_strArray;
- svn_error_t *m_error_occured;
+ svn_error_t *m_error_occurred;
public:
Targets(StringArray &strArray, SVN::Pool &in_pool);
Targets(const char *path, SVN::Pool &in_pool);
void add(const char *path);
~Targets();
const apr_array_header_t *array(const SVN::Pool &pool);
- svn_error_t *error_occured();
+ svn_error_t *error_occurred();
};
#endif // TARGETS_H
diff --git a/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp b/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
index 6d66c99..e471a7a 100644
--- a/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
+++ b/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
@@ -75,7 +75,7 @@
JNIUtil::throwError(_("bad C++ this"));
return;
}
- cl->dispose();
+ cl->dispose(jthis);
}
JNIEXPORT void JNICALL
@@ -160,7 +160,8 @@
ListCallback callback(jcallback);
cl->list(url, revision, pegRevision, EnumMapper::toDepth(jdepth),
- (int)jdirentFields, jfetchLocks ? true : false, &callback);
+ static_cast<int>(jdirentFields), jfetchLocks ? true : false,
+ &callback);
}
JNIEXPORT void JNICALL
@@ -305,7 +306,7 @@
cl->logMessages(path, pegRevision, revisionRanges,
jstopOnCopy ? true: false, jdisoverPaths ? true : false,
jincludeMergedRevisions ? true : false,
- revProps, jlimit, &callback);
+ revProps, static_cast<long>(jlimit), &callback);
}
JNIEXPORT jlong JNICALL
@@ -401,7 +402,8 @@
JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_SVNClient_add
(JNIEnv *env, jobject jthis, jstring jpath, jobject jdepth,
- jboolean jforce, jboolean jnoIgnore, jboolean jaddParents)
+ jboolean jforce, jboolean jnoIgnore, jboolean jnoAutoProps,
+ jboolean jaddParents)
{
JNIEntry(SVNClient, add);
SVNClient *cl = SVNClient::getCppObject(jthis);
@@ -414,8 +416,11 @@
if (JNIUtil::isExceptionThrown())
return;
- cl->add(path, EnumMapper::toDepth(jdepth), jforce ? true : false,
- jnoIgnore ? true : false, jaddParents ? true : false);
+ cl->add(path, EnumMapper::toDepth(jdepth),
+ jforce ? true : false,
+ jnoIgnore ? true : false,
+ jnoAutoProps ? true : false,
+ jaddParents ? true : false);
}
JNIEXPORT jlongArray JNICALL
@@ -531,7 +536,8 @@
Java_org_apache_subversion_javahl_SVNClient_move
(JNIEnv *env, jobject jthis, jobject jsrcPaths, jstring jdestPath,
jboolean jforce, jboolean jmoveAsChild, jboolean jmakeParents,
- jobject jrevpropTable, jobject jmessage, jobject jcallback)
+ jboolean jmetadataOnly, jboolean jallowMixRev, jobject jrevpropTable,
+ jobject jmessage, jobject jcallback)
{
JNIEntry(SVNClient, move);
@@ -561,6 +567,7 @@
CommitCallback callback(jcallback);
cl->move(srcPaths, destPath, &message, jforce ? true : false,
jmoveAsChild ? true : false, jmakeParents ? true : false,
+ jmetadataOnly ? true: false, jallowMixRev ? true : false,
revprops, jcallback ? &callback : NULL);
}
@@ -711,8 +718,9 @@
JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_SVNClient_doImport
(JNIEnv *env, jobject jthis, jstring jpath, jstring jurl, jobject jdepth,
- jboolean jnoIgnore, jboolean jignoreUnknownNodeTypes, jobject jrevpropTable,
- jobject jmessage, jobject jcallback)
+ jboolean jnoIgnore, jboolean jnoAutoProps,
+ jboolean jignoreUnknownNodeTypes, jobject jrevpropTable,
+ jobject jimportFilterCallback, jobject jmessage, jobject jcommitCallback)
{
JNIEntry(SVNClient, doImport);
SVNClient *cl = SVNClient::getCppObject(jthis);
@@ -737,11 +745,13 @@
if (JNIUtil::isExceptionThrown())
return;
- CommitCallback callback(jcallback);
+ CommitCallback commitCallback(jcommitCallback);
+
cl->doImport(path, url, &message, EnumMapper::toDepth(jdepth),
- jnoIgnore ? true : false,
+ jnoIgnore ? true : false, jnoAutoProps ? true : false,
jignoreUnknownNodeTypes ? true : false, revprops,
- jcallback ? &callback : NULL);
+ NULL,
+ jcommitCallback ? &commitCallback : NULL);
}
JNIEXPORT jobject JNICALL
@@ -770,9 +780,9 @@
JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_SVNClient_merge__Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2ZLorg_apache_subversion_javahl_types_Depth_2ZZZ
(JNIEnv *env, jobject jthis, jstring jpath1, jobject jrevision1,
- jstring jpath2, jobject jrevision2, jstring jlocalPath, jboolean jforce,
- jobject jdepth, jboolean jignoreAncestry, jboolean jdryRun,
- jboolean jrecordOnly)
+ jstring jpath2, jobject jrevision2, jstring jlocalPath, jboolean jforceDelete,
+ jobject jdepth, jboolean jignoreAncestry,
+ jboolean jdryRun, jboolean jrecordOnly)
{
JNIEntry(SVNClient, merge);
SVNClient *cl = SVNClient::getCppObject(jthis);
@@ -802,16 +812,19 @@
return;
cl->merge(path1, revision1, path2, revision2, localPath,
- jforce ? true:false, EnumMapper::toDepth(jdepth),
- jignoreAncestry ? true:false, jdryRun ? true:false,
+ jforceDelete ? true:false,
+ EnumMapper::toDepth(jdepth),
+ jignoreAncestry ? true:false,
+ jdryRun ? true:false,
jrecordOnly ? true:false);
}
JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_SVNClient_merge__Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_util_List_2Ljava_lang_String_2ZLorg_apache_subversion_javahl_types_Depth_2ZZZ
(JNIEnv *env, jobject jthis, jstring jpath, jobject jpegRevision,
- jobject jranges, jstring jlocalPath, jboolean jforce, jobject jdepth,
- jboolean jignoreAncestry, jboolean jdryRun, jboolean jrecordOnly)
+ jobject jranges, jstring jlocalPath, jboolean jforceDelete, jobject jdepth,
+ jboolean jignoreAncestry,
+ jboolean jdryRun, jboolean jrecordOnly)
{
JNIEntry(SVNClient, merge);
SVNClient *cl = SVNClient::getCppObject(jthis);
@@ -833,27 +846,34 @@
if (JNIUtil::isExceptionThrown())
return;
+ std::vector<RevisionRange> *revisionRanges = NULL;
+ std::vector<RevisionRange> realRevisionRanges;
// Build the revision range vector from the Java array.
- Array ranges(jranges);
- if (JNIUtil::isExceptionThrown())
- return;
-
- std::vector<RevisionRange> revisionRanges;
- std::vector<jobject> rangeVec = ranges.vector();
-
- for (std::vector<jobject>::const_iterator it = rangeVec.begin();
- it < rangeVec.end(); ++it)
+ if (jranges)
{
- RevisionRange revisionRange(*it);
+ Array ranges(jranges);
if (JNIUtil::isExceptionThrown())
return;
- revisionRanges.push_back(revisionRange);
+ std::vector<jobject> rangeVec = ranges.vector();
+
+ for (std::vector<jobject>::const_iterator it = rangeVec.begin();
+ it < rangeVec.end(); ++it)
+ {
+ RevisionRange revisionRange(*it);
+ if (JNIUtil::isExceptionThrown())
+ return;
+
+ realRevisionRanges.push_back(revisionRange);
+ }
+ revisionRanges = &realRevisionRanges;
}
cl->merge(path, pegRevision, revisionRanges, localPath,
- jforce ? true:false, EnumMapper::toDepth(jdepth),
- jignoreAncestry ? true:false, jdryRun ? true:false,
+ jforceDelete ? true:false,
+ EnumMapper::toDepth(jdepth),
+ jignoreAncestry ? true:false,
+ jdryRun ? true:false,
jrecordOnly ? true:false);
}
@@ -886,13 +906,11 @@
jdryRun ? true:false);
}
-JNIEXPORT void JNICALL
-Java_org_apache_subversion_javahl_SVNClient_properties
+static void SVNClient_properties
(JNIEnv *env, jobject jthis, jstring jpath, jobject jrevision,
jobject jpegRevision, jobject jdepth, jobject jchangelists,
- jobject jproplistCallback)
+ jobject jproplistCallback, bool inherited)
{
- JNIEntry(SVNClient, properties);
SVNClient *cl = SVNClient::getCppObject(jthis);
if (cl == NULL)
{
@@ -915,11 +933,21 @@
if (JNIUtil::isExceptionThrown())
return;
- ProplistCallback callback(jproplistCallback);
+ ProplistCallback callback(jproplistCallback, inherited);
cl->properties(path, revision, pegRevision, EnumMapper::toDepth(jdepth),
changelists, &callback);
}
+JNIEXPORT void JNICALL Java_org_apache_subversion_javahl_SVNClient_properties
+(JNIEnv *env, jobject jthis, jstring jpath, jobject jrevision,
+ jobject jpegRevision, jobject jdepth, jobject jchangelists,
+ jobject jproplistCallback)
+{
+ JNIEntry(SVNClient, properties);
+ SVNClient_properties(env, jthis, jpath, jrevision, jpegRevision, jdepth,
+ jchangelists, jproplistCallback, false);
+}
+
JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_SVNClient_propertySetRemote
(JNIEnv *env, jobject jthis, jstring jpath, jlong jbaseRev, jstring jname,
@@ -954,8 +982,8 @@
return;
CommitCallback callback(jcallback);
- cl->propertySetRemote(path, jbaseRev, name, &message, value,
- jforce ? true:false,
+ cl->propertySetRemote(path, static_cast<svn_revnum_t>(jbaseRev),
+ name, &message, value, jforce ? true : false,
revprops, jcallback ? &callback : NULL);
}
@@ -1080,7 +1108,7 @@
JNIEXPORT jbyteArray JNICALL
Java_org_apache_subversion_javahl_SVNClient_propertyGet
(JNIEnv *env, jobject jthis, jstring jpath, jstring jname, jobject jrevision,
- jobject jpegRevision)
+ jobject jpegRevision, jobject jchangelists)
{
JNIEntry(SVNClient, propertyGet);
SVNClient *cl = SVNClient::getCppObject(jthis);
@@ -1105,7 +1133,11 @@
if (JNIUtil::isExceptionThrown())
return NULL;
- return cl->propertyGet(path, name, revision, pegRevision);
+ StringArray changelists(jchangelists);
+ if (JNIUtil::isExceptionThrown())
+ return NULL;
+
+ return cl->propertyGet(path, name, revision, pegRevision, changelists);
}
JNIEXPORT jobject JNICALL
@@ -1760,7 +1792,27 @@
return;
PatchCallback callback(jcallback);
- cl->patch(patchPath, targetPath, jdryRun ? true : false, (int) jstripCount,
+ cl->patch(patchPath, targetPath,
+ jdryRun ? true : false, static_cast<int>(jstripCount),
jreverse ? true : false, jignoreWhitespace ? true : false,
jremoveTempfiles ? true : false, &callback);
}
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_SVNClient_nativeOpenRemoteSession
+(JNIEnv *env, jobject jthis, jstring jpath, jint jretryAttempts)
+{
+ JNIEntry(SVNClient, openRemoteSession);
+ SVNClient *cl = SVNClient::getCppObject(jthis);
+ if (cl == NULL)
+ {
+ JNIUtil::throwError("bad C++ this");
+ return NULL;
+ }
+
+ JNIStringHolder path(jpath);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ return cl->openRemoteSession(path, jretryAttempts);
+}
diff --git a/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp b/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp
index b9ddbc6..b14b119 100644
--- a/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp
+++ b/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp
@@ -60,7 +60,7 @@
JNIUtil::throwError(_("bad C++ this"));
return;
}
- cl->dispose();
+ cl->dispose(jthis);
}
JNIEXPORT void JNICALL
@@ -170,7 +170,7 @@
JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_SVNRepos_hotcopy
(JNIEnv *env, jobject jthis, jobject jpath, jobject jtargetPath,
- jboolean jcleanLogs)
+ jboolean jcleanLogs, jboolean jincremental)
{
JNIEntry(SVNRepos, hotcopy);
SVNRepos *cl = SVNRepos::getCppObject(jthis);
@@ -188,7 +188,8 @@
if (JNIUtil::isExceptionThrown())
return;
- cl->hotcopy(path, targetPath, jcleanLogs ? true : false);
+ cl->hotcopy(path, targetPath, jcleanLogs ? true : false,
+ jincremental ? true : false);
}
JNIEXPORT void JNICALL
@@ -240,6 +241,7 @@
JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_SVNRepos_load
(JNIEnv *env, jobject jthis, jobject jpath, jobject jinputData,
+ jobject jrevisionStart, jobject jrevisionEnd,
jboolean jignoreUUID, jboolean jforceUUID, jboolean jusePreCommitHook,
jboolean jusePostCommitHook, jstring jrelativePath, jobject jnotifyCallback)
{
@@ -263,12 +265,23 @@
if (JNIUtil::isExceptionThrown())
return;
+ Revision revisionStart(jrevisionStart);
+ if (JNIUtil::isExceptionThrown())
+ return;
+
+ Revision revisionEnd(jrevisionEnd, true);
+ if (JNIUtil::isExceptionThrown())
+ return;
+
ReposNotifyCallback notifyCallback(jnotifyCallback);
- cl->load(path, inputData, jignoreUUID ? true : false,
- jforceUUID ? true : false, jusePreCommitHook ? true : false,
- jusePostCommitHook ? true : false, relativePath,
- jnotifyCallback != NULL ? ¬ifyCallback : NULL);
+ cl->load(path, inputData, revisionStart, revisionEnd,
+ jignoreUUID ? true : false,
+ jforceUUID ? true : false,
+ jusePreCommitHook ? true : false,
+ jusePostCommitHook ? true : false,
+ relativePath,
+ (jnotifyCallback != NULL ? ¬ifyCallback : NULL));
}
JNIEXPORT void JNICALL
diff --git a/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp b/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp
new file mode 100644
index 0000000..0a16131
--- /dev/null
+++ b/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteFactory.cpp
@@ -0,0 +1,58 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file org_apache_subversion_javahl_remote_RemoteFactory.cpp
+ * @brief Implementation of the native methods in the Java class RemoteFactory
+ */
+
+#include "../include/org_apache_subversion_javahl_remote_RemoteFactory.h"
+
+#include "JNIStackElement.h"
+#include "JNIUtil.h"
+#include "JNIStringHolder.h"
+
+#include "RemoteSession.h"
+
+#include "svn_private_config.h"
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteFactory_open(
+ JNIEnv *env, jclass jclass, jint jretryAttempts,
+ jstring jurl, jstring juuid,
+ jstring jconfigDirectory, jstring jusername, jstring jpassword,
+ jobject jprompter, jobject jprogress)
+{
+ //JNI macros need jthis but this is a static call
+ jobject jthis = NULL;
+ JNIEntry(Remotefactory, open);
+
+ /*
+ * Create RemoteSession C++ object and return its java wrapper to the caller
+ */
+ jobject jremoteSession = RemoteSession::open(
+ jretryAttempts, jurl, juuid, jconfigDirectory,
+ jusername, jpassword, jprompter, jprogress);
+ if (JNIUtil::isJavaExceptionThrown())
+ return NULL;
+
+ return jremoteSession;
+}
diff --git a/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp b/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
new file mode 100644
index 0000000..7dfdcf0
--- /dev/null
+++ b/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
@@ -0,0 +1,188 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file org_apache_subversion_javahl_remote_RemoteSession.cpp
+ * @brief Implementation of the native methods in the Java class RemoteSession
+ */
+
+#include "../include/org_apache_subversion_javahl_remote_RemoteSession.h"
+
+#include "JNIStackElement.h"
+#include "JNIUtil.h"
+#include "Prompter.h"
+#include "RemoteSession.h"
+#include "Revision.h"
+#include "EnumMapper.h"
+
+#include "svn_private_config.h"
+
+JNIEXPORT void JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_finalize(
+ JNIEnv *env, jobject jthis)
+{
+ JNIEntry(RemoteSession, finalize);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ if (ras != NULL)
+ ras->finalize();
+}
+
+JNIEXPORT void JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_nativeDispose(
+ JNIEnv *env, jobject jthis)
+{
+ JNIEntry(RemoteSession, dispose);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ if (ras != NULL)
+ ras->dispose(jthis);
+}
+
+JNIEXPORT void JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_cancelOperation(
+ JNIEnv *env, jobject jthis)
+{
+ JNIEntry(RemoteSession, cancelOperation);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, );
+
+ ras->cancelOperation();
+}
+
+JNIEXPORT void JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_reparent(
+ JNIEnv *env, jobject jthis, jstring jurl)
+{
+ JNIEntry(RemoteSession, getSessionUrl);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, );
+
+ ras->reparent(jurl);
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getSessionRelativePath(
+ JNIEnv *env, jobject jthis, jstring jurl)
+{
+ JNIEntry(RemoteSession, getSessionUrl);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, NULL);
+
+ return ras->getSessionRelativePath(jurl);
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getReposRelativePath(
+ JNIEnv *env, jobject jthis, jstring jurl)
+{
+ JNIEntry(RemoteSession, getSessionUrl);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, NULL);
+
+ return ras->getReposRelativePath(jurl);
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getSessionUrl(
+ JNIEnv *env, jobject jthis)
+{
+ JNIEntry(RemoteSession, getSessionUrl);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, NULL);
+
+ return ras->getSessionUrl();
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getReposUUID(
+ JNIEnv *env, jobject jthis)
+{
+ JNIEntry(RemoteSession, geRepostUUID);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, NULL);
+
+ return ras->getReposUUID();
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getReposRootUrl(
+ JNIEnv *env, jobject jthis)
+{
+ JNIEntry(RemoteSession, geRepostUUID);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, NULL);
+
+ return ras->getReposRootUrl();
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getLatestRevision(
+ JNIEnv *env, jobject jthis)
+{
+ JNIEntry(RemoteSession, getLatestRevision);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, SVN_INVALID_REVNUM);
+
+ return ras->getLatestRevision();
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getRevisionByTimestamp(
+ JNIEnv *env, jobject jthis, jlong timestamp)
+{
+ JNIEntry(RemoteSession, getDatedRevision);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, SVN_INVALID_REVNUM);
+
+ return ras->getRevisionByTimestamp(timestamp);
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_checkPath(
+ JNIEnv *env, jobject jthis, jstring jpath, jlong jrevision)
+{
+ JNIEntry(SVNReposAccess, checkPath);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, NULL);
+
+ return ras->checkPath(jpath, jrevision);
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_getLocks(
+ JNIEnv *env, jobject jthis, jstring jpath, jobject jdepth)
+{
+ JNIEntry(RemoteSession, getLocks);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, NULL);
+
+ return ras->getLocks(jpath, jdepth);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_apache_subversion_javahl_remote_RemoteSession_nativeHasCapability(
+ JNIEnv *env, jobject jthis, jstring jcapability)
+{
+ JNIEntry(RemoteSession, nativeHasCapability);
+ RemoteSession *ras = RemoteSession::getCppObject(jthis);
+ CPPADDR_NULL_PTR(ras, false);
+
+ return ras->hasCapability(jcapability);
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
index b1213c2..8a59e4d 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
@@ -544,7 +544,30 @@
failed_forbidden_by_server ("failed forbidden by server"),
/** Operation skipped the path because it was conflicted */
- skip_conflicted ("skipped conflicted path");
+ skip_conflicted ("skipped conflicted path"),
+
+ /** The lock on a file was removed during update */
+ update_broken_lock ("broken lock removed"),
+
+ /** Operation failed because a node is obstructed */
+ failed_obstructed ("failed by obstruction"),
+
+ /** Conflict resolver is starting. */
+ conflict_resolver_starting ("conflict resolver starting"),
+
+ /** Conflict resolver is done. */
+ conflict_resolver_done ("conflict resolver done"),
+
+ /** Operation left local modifications. */
+ left_local_modifications ("left local modifications"),
+
+ /** A copy from a foreign repository has started
+ * @since New in 1.8. */
+ foreign_copy_begin ("foreign copy begin"),
+
+ /** A move in the working copy has been broken
+ * @since New in 1.8. */
+ move_broken ("move broken");
/**
* The description of the action.
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItem.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItem.java
index 43dec0a..986faf6 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItem.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItem.java
@@ -70,6 +70,11 @@
long revision;
/**
+ * the source of the move
+ */
+ String movedFromPath;
+
+ /**
* This constructor will be only called from the jni code.
* @param p path to the commit item
* @param nk kind of node (see NodeKind)
@@ -77,8 +82,9 @@
* @param u url of the item
* @param cu copy source url
* @param r revision number
+ * @param mf move source abspath
*/
- public CommitItem(String p, NodeKind nk, int sf, String u, String cu, long r)
+ CommitItem(String p, NodeKind nk, int sf, String u, String cu, long r, String mf)
{
path = p;
nodeKind = nk;
@@ -86,6 +92,7 @@
url = u;
copyUrl = cu;
revision = r;
+ movedFromPath = mf;
}
/**
@@ -149,4 +156,13 @@
{
return revision;
}
+
+ /**
+ * @return the absolute path of the source of a move.
+ * @since 1.8
+ */
+ public String getMovedFromPath()
+ {
+ return movedFromPath;
+ }
}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItemStateFlags.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItemStateFlags.java
index 6ef0efb..6e8f593 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItemStateFlags.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItemStateFlags.java
@@ -53,4 +53,15 @@
* the item has been copied
*/
public static final int IsCopy=16;
+
+ /**
+ * the item has a lock token
+ */
+ public static final int LockToken = 32;
+
+ /**
+ * the item was moved to this location
+ * @since 1.8
+ */
+ public static int MovedHere = 64;
}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ConflictDescriptor.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ConflictDescriptor.java
index 75089c0..651dca1 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ConflictDescriptor.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ConflictDescriptor.java
@@ -244,6 +244,7 @@
/**
* Object is already added or schedule-add.
+ * @since 1.6
*/
added,
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
index b18ea2e..a527069 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
@@ -223,12 +223,30 @@
* ignore patterns
* @param addParents add any intermediate parents to the working copy
* @throws ClientException
+ * @note this method behaves like the 1.8 version with noAutoProps=false
*/
void add(String path, Depth depth, boolean force, boolean noIgnores,
boolean addParents)
throws ClientException;
/**
+ * Adds a file to the repository.
+ * @param path path to be added.
+ * @param depth the depth to recurse into subdirectories
+ * @param force if adding a directory and recurse true and path is a
+ * directory, all not already managed files are added.
+ * @param noIgnores if false, don't add files or directories matching
+ * ignore patterns
+ * @param noAutoProps if true, ignore any auto-props configuration
+ * @param addParents add any intermediate parents to the working copy
+ * @throws ClientException
+ * @since 1.8
+ */
+ void add(String path, Depth depth, boolean force,
+ boolean noIgnores, boolean noAutoProps, boolean addParents)
+ throws ClientException;
+
+ /**
* Updates the directories or files from repository
* @param path array of target files.
* @param revision the revision number to update.
@@ -298,12 +316,27 @@
* @param moveAsChild Whether to move <code>srcPaths</code> as
* children of <code>destPath</code>.
* @param makeParents Whether to create intermediate parents.
+ * @param metadataOnly Move just the metadata and not the working files/dirs
+ * @param allowMixRev If true use copy and delete without move tracking
+ * when a srcPath is mixed-revision, if false return
+ * an error when a srcPath is mixed-revision.
* @param revpropTable A string-to-string mapping of revision properties
* to values which will be set if this operation
* results in a commit.
* @param handler the commit message callback, may be <code>null</code>
* if <code>destPath</code> is not a URL
* @throws ClientException If the move operation fails.
+ * @since 1.8
+ */
+ void move(Set<String> srcPaths, String destPath, boolean force,
+ boolean moveAsChild, boolean makeParents, boolean metadataOnly,
+ boolean allowMixRev, Map<String, String> revpropTable,
+ CommitMessageCallback handler, CommitCallback callback)
+ throws ClientException;
+
+ /**
+ * @deprecated Provided for backward compatibility with 1.7. Passes
+ * metadataOnly false and allowMixRev true.
*/
void move(Set<String> srcPaths, String destPath, boolean force,
boolean moveAsChild, boolean makeParents,
@@ -400,8 +433,10 @@
* to values which will be set if this operation
* results in a commit.
* @param handler the commit message callback
+ * @param callback the commit status callback
* @throws ClientException
- *
+ * @note this method behaves like the 1.8 version with noAutoProps=false
+ * and without the filtering option.
*/
void doImport(String path, String url, Depth depth,
boolean noIgnore, boolean ignoreUnknownNodeTypes,
@@ -433,6 +468,8 @@
* @param dryRun do not change anything
* @param recordOnly record mergeinfo but do not run merge
* @throws ClientException
+ * @note Behaves like the 1.8 where ignoreAncestry maps to
+ * both ignoreMergeinfo and diffIgnoreAncestry
*/
void merge(String path1, Revision revision1, String path2,
Revision revision2, String localPath, boolean force, Depth depth,
@@ -443,7 +480,9 @@
* Merge set of revisions into a new local path.
* @param path path or url
* @param pegRevision revision to interpret path
- * @param revisions revisions to merge
+ * @param revisions revisions to merge;
+ * may be null, indicating that the optimal range
+ * should be determined automatcially (new in 1.8)
* @param localPath target local path
* @param force overwrite local changes
* @param depth how deep to traverse into subdirectories
@@ -451,7 +490,10 @@
* @param dryRun do not change anything
* @param recordOnly record mergeinfo but do not run merge
* @throws ClientException
+ * @note Behaves like the 1.8 where ignoreAncestry maps to
+ * both ignoreMergeinfo and diffIgnoreAncestry
*/
+ // FIXME: Broken
void merge(String path, Revision pegRevision, List<RevisionRange> revisions,
String localPath, boolean force, Depth depth,
boolean ignoreAncestry, boolean dryRun, boolean recordOnly)
@@ -472,6 +514,7 @@
* @param localPath target local path
* @param dryRun do not change anything
* @throws ClientException
+ * @deprecated Will be removed in a future release
*/
void mergeReintegrate(String path, Revision pegRevision,
String localPath, boolean dryRun)
@@ -521,6 +564,8 @@
* @param force diff even on binary files
* @param copiesAsAdds if set, copied files will be shown in their
* entirety, not as diffs from their sources
+ * @param ignoreProps don't show property diffs
+ * @param propsOnly show property changes only
* @throws ClientException
*/
void diff(String target1, Revision revision1, String target2,
@@ -545,6 +590,8 @@
* @param force diff even on binary files
* @param copiesAsAdds if set, copied files will be shown in their
* entirety, not as diffs from their sources
+ * @param ignoreProps don't show property diffs
+ * @param propsOnly show property changes only
* @throws ClientException
*/
void diff(String target, Revision pegRevision, Revision startRevision,
@@ -700,6 +747,10 @@
* @throws ClientException
*/
byte[] propertyGet(String path, String name, Revision revision,
+ Revision pegRevision, Collection<String> changelists)
+ throws ClientException;
+
+ byte[] propertyGet(String path, String name, Revision revision,
Revision pegRevision)
throws ClientException;
@@ -886,4 +937,36 @@
int stripCount, boolean reverse, boolean ignoreWhitespace,
boolean removeTempfiles, PatchCallback callback)
throws ClientException;
+
+ /**
+ * Open a persistent session to a repository.
+ * @param path A path in a working copy from which the
+ * session URL is derived.
+ * @throws remote.RetryOpenSession If the session URL was redirected
+ * @throws SubversionException If an URL redirect cycle was detected
+ * @throws ClientException
+ * @note The session object inherits the progress callback,
+ * configuration directory and authentication info.
+ * @since 1.9
+ */
+ ISVNRemote openRemoteSession(String path)
+ throws ClientException, SubversionException;
+
+ /**
+ * Open a persistent session to a repository.
+ * @param path A path in a working copy from which the
+ * session URL is derived.
+ * @param retryAttempts The number of times to retry the operation
+ * if the given URL is redirected.
+ * @throws IllegalArgumentException If <code>retryAttempts</code>
+ * is not positive
+ * @throws remote.RetryOpenSession If the session URL was redirected
+ * @throws SubversionException If an URL redirect cycle was detected
+ * @throws ClientException
+ * @note The session object inherits the progress callback,
+ * configuration directory and authentication info.
+ * @since 1.9
+ */
+ ISVNRemote openRemoteSession(String path, int retryAttempts)
+ throws ClientException, SubversionException;
}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNEditor.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNEditor.java
new file mode 100644
index 0000000..fd9d870
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNEditor.java
@@ -0,0 +1,327 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl;
+
+import org.apache.subversion.javahl.types.*;
+import org.apache.subversion.javahl.callback.*;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Editor interface (implements the EV2 abstraction).
+ * @see <a href="http://svn.apache.org/repos/asf/subversion/trunk/subversion/include/private/svn_editor.h"
+ * >svn_editor.h</a> for all restrictions on driving an editor.
+ * @since 1.9
+ */
+public interface ISVNEditor
+{
+ /**
+ * Release the native peer (should not depend on finalize),
+ * and abort the edit if it has not been completed yet.
+ */
+ void dispose();
+
+ /**
+ * Create a new directory at <code>relativePath</code>.
+ * The immediate parent of <code>relativePath</code> is expected to exist.
+ *
+ * For descriptions of <code>properties</code> and
+ * <code>replacesRevision</code>, see #addFile().
+ *
+ * A complete listing of the immediate children of
+ * <code>relativePath</code> that will be added subsequently is
+ * given in <code>children</code>. <code>children</code> is a
+ * collection of const strings, each giving the basename of an
+ * immediate child. It is an error to pass <code>null</code> for
+ * <code>children</code>; use an empty collection to indicate that
+ * the new directory will have no children.
+ *
+ * @throws ClientException
+ */
+ void addDirectory(String relativePath,
+ Iterable<String> children,
+ Map<String, byte[]> properties,
+ long replacesRevision)
+ throws ClientException;
+
+ /**
+ * Create a new file at <code>relativePath</code>.
+ * The immediate parent of <code>relativePath</code> is expected to exist.
+ *
+ * The file's contents are specified in <code>contents</code>
+ * which has a checksum matching <code>checksum</code>. Both
+ * values must be non-<code>null</code>.
+ *
+ * Set the properties of the new file to
+ * <code>properties</code>. If no properties are being set on the
+ * new file, <code>properties</code> must be empty. It is an error
+ * to pass <code>null</code> for <code>properties</code>.
+ *
+ * If this add is expected to replace a previously existing file,
+ * symlink or directory at <code>relativePath</code>, the revision
+ * number of the node to be replaced must be given in
+ * <code>replacesRevision</code>. Otherwise,
+ * <code>replacesRevision</code> must be
+ * Revision.SVN_INVALID_REVNUM.
+ *
+ * @note It is not allowed to call a "delete" followed by an "add" on the
+ * same path. Instead, an "add" with <code>replacesRevision</code>
+ * set accordingly MUST be used.
+ *
+ * @throws ClientException
+ */
+ void addFile(String relativePath,
+ Checksum checksum,
+ InputStream contents,
+ Map<String, byte[]> properties,
+ long replacesRevision)
+ throws ClientException;
+
+ /**
+ * Create a new symbolic link at <code>relativePath</code>, with a
+ * link target of <code>target</code>. The immediate parent of
+ * <code>relativePath</code> is expected to exist.
+ *
+ * For descriptions of <code>properties</code> and
+ * <code>replacesRevision</code>, see #addFile().
+ *
+ * @throws ClientException
+ */
+ void addSymlink(String relativePath,
+ String target,
+ Map<String, byte[]> properties,
+ long replacesRevision)
+ throws ClientException;
+
+ /**
+ * Create an "absent" node of kind <code>kind</code> at
+ * <code>relativePath</code>. The immediate parent of
+ * <code>relativePath</code> is expected to exist.
+ *
+ * For a description of <code>replacesRevision</code>, see #addFile().
+ *
+ * @throws ClientException
+ */
+ void addAbsent(String relativePath,
+ NodeKind kind,
+ long replacesRevision)
+ throws ClientException;
+
+ /**
+ * Alter the properties of the directory at <code>relativePath</code>.
+ *
+ * <code>revision</code> specifies the revision at which the
+ * receiver should expect to find this node. That is,
+ * <code>relativePath</code> at the start of the whole edit and
+ * <code>relativePath</code> at <code>revision</code> must lie
+ * within the same node-rev (aka location history segment). This
+ * information may be used to catch an attempt to alter and
+ * out-of-date directory. If the directory does not have a
+ * corresponding revision in the repository (e.g. it has not yet
+ * been committed), then <code>revision</code> should be
+ * Revision.SVN_INVALID_REVNUM.
+ *
+ * If any changes to the set of children will be made in the
+ * future of the edit drive, then <code>children</code>
+ * <em>must</em> specify the resulting set of children. See
+ * #addDirectory() for the format of <code>children</code>. If
+ * not changes will be made, then NULL may be specified.
+ *
+ * For a description of <code>properties</code>, see
+ * #addFile(). If no changes to the properties will be made
+ * (ie. only future changes to the set of children), then
+ * <code>properties</code> may be <code>null</code>.
+ *
+ * @throws ClientException
+ */
+ void alterDirectory(String relativePath,
+ long revision,
+ Iterable<String> children,
+ Map<String, byte[]> properties)
+ throws ClientException;
+
+ /**
+ * Alter the contents and/or the properties of the file at
+ * <code>relativePath</code> with <code>revision</code> as its
+ * expected revision. See #alterDirectory() for more information
+ * about <code>revision</code>.
+ *
+ * If <code>contents</code> is non-<code>null</code>, then the
+ * stream will be copied to the file, and its checksum must match
+ * <code>checksum</code> (which must also be
+ * non-<code>null</code>). If <code>contents</code> is
+ * <code>null</code>, then <code>checksum</code> must also be
+ * <code>null</code>, and no change will be applied to the file's
+ * contents.
+ *
+ * If <code>properties</code> is non-<code>null</code>, then the
+ * properties will be applied.
+ *
+ * For a description of <code>checksum</code> and
+ * <code>contents</code>, see #addFile().
+ *
+ * This function allows <code>properties</code> to be
+ * <code>null</code>, but the parameter is otherwise described by
+ * #addFile().
+ *
+ * @throws ClientException
+ */
+ void alterFile(String relativePath,
+ long revision,
+ Checksum checksum,
+ InputStream contents,
+ Map<String, byte[]> properties)
+ throws ClientException;
+
+ /**
+ * Alter the target and/or the properties of the symlink at
+ * <code>relativePath</code> with <code>revision</code> as its
+ * expected revision. See #alterDirectory() for more information
+ * about <code>revision</code>.
+ *
+ * If <code>target</code> is non-<code>null</code>, then the
+ * symlink's target will be updated.
+ *
+ * If <code>properties</code> is non-<code>null</code>, then the
+ * properties will be applied.
+ *
+ * The target and/or the properties must be changed. It is an
+ * error to pass <code>null</code> for both <code>target</code>
+ * and <code>properties</code>.
+ *
+ * This function allows <code>properties</code> to be
+ * <code>null</code>, but the parameter is otherwise described by
+ * #addFile().
+ *
+ * @throws ClientException
+ */
+ void alterSymlink(String relativePath,
+ long revision,
+ String target,
+ Map<String, byte[]> properties)
+ throws ClientException;
+
+ /**
+ * Delete the existing node at <code>relativePath</code>, expected
+ * to be identical to revision <code>revision</code> of that path.
+ *
+ * @throws ClientException
+ */
+ void delete(String relativePath,
+ long revision)
+ throws ClientException;
+
+ /**
+ * Move the node at <code>sourceRelativePath</code> to
+ * <code>destinationRelativePath</code>.
+ *
+ * For a description of <code>replacesRevision</code>, see #addFile().
+ *
+ * @note See the general instructions on paths for this API. Since
+ * the <code>sourceRelativePath</code> argument must generally be
+ * able to reference any node in the repository, the implication
+ * is that the editor's root must be the repository root.
+ *
+ * @throws ClientException
+ */
+ void copy(String sourceRelativePath,
+ long sourceRevision,
+ String destinationRelativePath,
+ long replacesRevision)
+ throws ClientException;
+
+ /**
+ * Move the node at <code>sourceRelativePath</code> to
+ * <code>destinationRelativePath</code>.
+ *
+ * <code>sourceRevision</code> specifies the revision at which the
+ * receiver should expect to find this node. That is,
+ * <code>sourceRelativePath</code> at the start of the whole edit
+ * and<code>sourceRelativePath</code> at
+ * <code>sourceRevision</code> must lie within the same node-rev
+ * (aka history-segment). This is just like the #delete() and
+ * #rotate().
+ *
+ * For a description of <code>replacesRevision</code>, see #addFile().
+ *
+ * @throws ClientException
+ */
+ void move(String sourceRelativePath,
+ long sourceRevision,
+ String destinationRelativePath,
+ long replacesRevision)
+ throws ClientException;
+ /**
+ * Perform a rotation among multiple nodes in the target tree.
+ *
+ * The <code>elements</code> list specifies the nodes in the tree
+ * which are located at a path and expected to be at a specific
+ * revision. These nodes are simultaneously moved in a rotation
+ * pattern. For example, the node at index 0
+ * <code>elements</code> will be moved to the relative path
+ * specified at index 1 of <code>elements</code>. The node at
+ * index 1 will be moved to the location at index 2. The node at
+ * index N-1 will be moved to the relative path specified at index 0.
+ *
+ * The simplest form of this operation is to swap nodes A and
+ * B. One may think to move A to a temporary location T, then move
+ * B to A, then move T to B. However, this last move violations
+ * the Once Rule by moving T (which had already by edited by the
+ * move from A). In order to keep the restrictions against
+ * multiple moves of a single node, the rotation operation is
+ * needed for certain types of tree edits.
+ *
+ * @throws ClientException
+ */
+ void rotate(List<RotatePair> elements) throws ClientException;
+
+ public static final class RotatePair
+ {
+ public RotatePair(String relativePath, long revision)
+ {
+ this.relativePath = relativePath;
+ this.revision = revision;
+ }
+ public final String relativePath;
+ public final long revision;
+ }
+
+ /**
+ * Signal that the edit has been completed successfully.
+ * After this method is called, the editor is considered closed.
+ *
+ * @throws ClientException
+ */
+ void complete() throws ClientException;
+
+ /**
+ * Signal that the edit transmission was not successful.
+ * After this method is called, the editor is considered closed.
+ *
+ * @throws ClientException
+ */
+ void abort() throws ClientException;
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java
new file mode 100644
index 0000000..522199f
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java
@@ -0,0 +1,222 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl;
+
+import org.apache.subversion.javahl.types.*;
+import org.apache.subversion.javahl.callback.*;
+
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * Encapsulates an RA session object and related operations.
+ * @see subversion/include/svn_ra.h#svn_ra_open
+ * @since 1.9
+ */
+public interface ISVNRemote
+{
+ /**
+ * Release the native peer (should not depend on finalize).
+ * Also invalidates any existing editors related to this session.
+ */
+ void dispose();
+
+ /**
+ * Cancel the active operation.
+ * @throws ClientException
+ */
+ void cancelOperation() throws ClientException;
+
+ /** Change the URL of the session to point to a new path in the
+ * same repository.
+ * @throws ClientException
+ * @note The operation fails if the URL has a different repository
+ * root than the current session URL.
+ */
+ void reparent(String url) throws ClientException;
+
+ /**
+ * Get the current session URL.
+ * @throws ClientException
+ */
+ String getSessionUrl() throws ClientException;
+
+ /**
+ * Return a path relative to the current session URL.
+ * @param url Must be a child of the current session URL.
+ * @throws ClientException
+ */
+ String getSessionRelativePath(String url) throws ClientException;
+
+ /**
+ * Return a path relative to the repository root URL associated with
+ * current session URL.
+ * @param url Must be a child of the repository root URL.
+ * @throws ClientException
+ */
+ String getReposRelativePath(String url) throws ClientException;
+
+ /**
+ * Get the UUID of the session's repository.
+ * @throws ClientException
+ */
+ String getReposUUID() throws ClientException;
+
+ /**
+ * Get the root URL of the session's repository.
+ * @throws ClientException
+ */
+ String getReposRootUrl() throws ClientException;
+
+ /**
+ * Get the latest revision number from the session's repository.
+ * @throws ClientException
+ */
+ long getLatestRevision() throws ClientException;
+
+ /**
+ * Get the latest revision number at the given time
+ * from the session's repository.
+ * @throws ClientException
+ */
+ long getRevisionByDate(Date date) throws ClientException;
+
+ /**
+ * Get the latest revision number at the given time, expressed as
+ * the number of milliseconds since the epoch, from the session's
+ * repository.
+ * @throws ClientException
+ */
+ long getRevisionByTimestamp(long timestamp) throws ClientException;
+
+ /**
+ * Return the kind of the node in path at revision.
+ * @param path A path relative to the sessionn URL
+ * @throws ClientException
+ */
+ NodeKind checkPath(String path, long revision)
+ throws ClientException;
+
+ /**
+ * Return a dictionary containing all locks on or below the given path.
+ * @param path A path relative to the sessionn URL
+ * @param depth The recursion depth
+ * @note It is not considered an error for the path to not exist in HEAD.
+ * Such a search will simply return no locks.
+ * @note This functionality is not available in pre-1.2 servers.
+ * @throws ClientException
+ */
+ Map<String, Lock> getLocks(String path, Depth depth)
+ throws ClientException;
+
+ /**
+ * Create a commit editor instance, rooted at the current session URL.
+ * @throws ClientException
+ */
+ ISVNEditor getCommitEditor() throws ClientException;
+
+ /**
+ * Enumeration of known capabilities of the repository and server.
+ */
+ public enum Capability
+ {
+ /**
+ * The capability of understanding operation depth.
+ * @since 1.5
+ */
+ depth ("depth"),
+
+ /**
+ * The capability of doing the right thing with merge-tracking
+ * information.
+ * @since 1.5
+ */
+ mergeinfo ("mergeinfo"),
+
+ /**
+ * The capability of retrieving arbitrary revprops in #getLog().
+ * @since 1.5
+ */
+ log_revprops ("log-revprops"),
+
+ /**
+ * The capability of replaying a directory in the
+ * repository (partial replay).
+ * @since 1.5
+ */
+ partial_replay ("partial-replay"),
+
+ /**
+ * The capability of including revision properties in a commit.
+ * @since 1.5
+ */
+ commit_revprops ("commit-revprops"),
+
+ /**
+ * The capability of specifying (and atomically verifying) expected
+ * preexisting values when modifying revprops.
+ * @since 1.7
+ */
+ atomic_revprops ("atomic-revprops"),
+
+ /**
+ * The capability to get inherited properties.
+ * @since 1.8
+ */
+ inherited_props ("inherited-props"),
+
+ /**
+ * The capability of a server to automatically ephemeral
+ * transaction properties.
+ * @since 1.8
+ */
+ ephemeral_txnprops ("ephemeral-txnprops"),
+
+ /**
+ * The capability of a server to walk revisions backwards in
+ * #getFileRevisions().
+ * @since 1.8
+ */
+ get_file_revs_reversed ("get-file-revs-reversed");
+
+ private Capability(String token)
+ {
+ this.token = token;
+ }
+
+ public String toString()
+ {
+ return token;
+ }
+
+ private String token;
+ }
+
+ /**
+ * Check if the server associated with this session has
+ * the given <code>capability</code>.
+ * @throws ClientException
+ */
+ boolean hasCapability(Capability capability) throws ClientException;
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java
index 318fb07..3a907e7 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java
@@ -113,6 +113,9 @@
* @throws ClientException throw in case of problem
*/
public abstract void hotcopy(File path, File targetPath,
+ boolean cleanLogs, boolean incremental) throws ClientException;
+
+ public abstract void hotcopy(File path, File targetPath,
boolean cleanLogs) throws ClientException;
/**
@@ -133,8 +136,35 @@
public abstract void listUnusedDBLogs(File path, MessageReceiver receiver)
throws ClientException;
+
/**
- * load the data of a dump into a repository,
+ * load the data of a dump into a repository
+ * @param path the path to the repository
+ * @param dataInput the data input source
+ * @param start the first revision to load
+ * @param end the last revision to load
+ * @param ignoreUUID ignore any UUID found in the input stream
+ * @param forceUUID set the repository UUID to any found in the
+ * stream
+ * @param usePreCommitHook use the pre-commit hook when processing commits
+ * @param usePostCommitHook use the post-commit hook when processing commits
+ * @param relativePath the directory in the repository, where the data
+ * in put optional.
+ * @param callback the target for processing messages
+ * @throws ClientException throw in case of problem
+ * @since 1.8
+ */
+ public abstract void load(File path, InputStream dataInput,
+ Revision start, Revision end,
+ boolean ignoreUUID, boolean forceUUID,
+ boolean usePreCommitHook,
+ boolean usePostCommitHook,
+ String relativePath,
+ ReposNotifyCallback callback)
+ throws ClientException;
+
+ /**
+ * load the data of a dump into a repository
* @param path the path to the repository
* @param dataInput the data input source
* @param ignoreUUID ignore any UUID found in the input stream
@@ -146,6 +176,8 @@
* in put optional.
* @param callback the target for processing messages
* @throws ClientException throw in case of problem
+ * @note behaves like the 1.8 vesion with the revision
+ * parameters set to Revision.START and Revision.HEAD.
*/
public abstract void load(File path, InputStream dataInput,
boolean ignoreUUID, boolean forceUUID, boolean usePreCommitHook,
@@ -163,8 +195,9 @@
throws ClientException;
/**
- * recover the berkeley db of a repository, returns youngest revision
+ * recover the filesystem backend of a repository
* @param path the path to the repository
+ * @return youngest revision
* @throws ClientException throw in case of problem
*/
public abstract long recover(File path, ReposNotifyCallback callback)
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/JNIObject.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/JNIObject.java
new file mode 100644
index 0000000..7c55510
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/JNIObject.java
@@ -0,0 +1,42 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl;
+
+/**
+ * This class is used internally by the JavaHL implementation and not considered
+ * part part of the public API.
+ */
+public abstract class JNIObject
+{
+ /**
+ * slot for the address of the native peer. The JNI code controls this
+ * field. If it is set to 0 then underlying JNI object has been freed
+ */
+ protected final long cppAddr;
+
+ protected JNIObject(long cppAddr)
+ {
+ this.cppAddr = cppAddr;
+ }
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/OperationContext.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/OperationContext.java
new file mode 100644
index 0000000..ad56e12
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/OperationContext.java
@@ -0,0 +1,46 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl;
+
+import org.apache.subversion.javahl.callback.ProgressCallback;
+
+/**
+ * A private class to hold the contextual information required to
+ * persist in this object, such as notification handlers.
+ */
+public class OperationContext implements ProgressCallback
+{
+ private ProgressCallback progress = null;
+
+ public void onProgress(ProgressEvent event)
+ {
+ if (progress != null)
+ progress.onProgress(event);
+ }
+
+ public void setProgressCallback(ProgressCallback progress)
+ {
+ this.progress = progress;
+ }
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java
index 8a90dca..7594d6c 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java
@@ -188,7 +188,19 @@
recover_start,
/** Upgrade has started. */
- upgrade_start;
+ upgrade_start,
+
+ /**
+ * A revision was skipped during loading.
+ * @since 1.8
+ */
+ load_skipped_rev,
+
+ /**
+ * The structure of a revision is being verified.
+ * @since 1.8
+ */
+ verify_rev_structure;
}
public enum NodeAction
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
index 8af71f3..09d3048 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
@@ -147,14 +147,14 @@
clientContext.notify = notify;
}
- public void setConflictResolver(ConflictResolverCallback listener)
+ public void setConflictResolver(ConflictResolverCallback resolver)
{
- clientContext.resolver = listener;
+ clientContext.resolver = resolver;
}
- public void setProgressCallback(ProgressCallback listener)
+ public void setProgressCallback(ProgressCallback progress)
{
- clientContext.listener = listener;
+ clientContext.setProgressCallback(progress);
}
public native void remove(Set<String> paths, boolean force,
@@ -168,9 +168,17 @@
throws ClientException;
public native void add(String path, Depth depth, boolean force,
- boolean noIgnores, boolean addParents)
+ boolean noIgnores, boolean noAutoProps,
+ boolean addParents)
throws ClientException;
+ public void add(String path, Depth depth, boolean force,
+ boolean noIgnores, boolean addParents)
+ throws ClientException
+ {
+ add(path, depth, force, noIgnores, false, addParents);
+ }
+
public native long[] update(Set<String> paths, Revision revision,
Depth depth, boolean depthIsSticky,
boolean makeParents,
@@ -194,11 +202,24 @@
public native void move(Set<String> srcPaths, String destPath,
boolean force, boolean moveAsChild,
- boolean makeParents,
+ boolean makeParents, boolean metadataOnly,
+ boolean allowMixRev,
Map<String, String> revpropTable,
CommitMessageCallback handler, CommitCallback callback)
throws ClientException;
+ /** @deprecated */
+ public void move(Set<String> srcPaths, String destPath,
+ boolean force, boolean moveAsChild,
+ boolean makeParents,
+ Map<String, String> revpropTable,
+ CommitMessageCallback handler, CommitCallback callback)
+ throws ClientException
+ {
+ move(srcPaths, destPath, force, moveAsChild, makeParents, false, true,
+ revpropTable, handler, callback);
+ }
+
public native void mkdir(Set<String> paths, boolean makeParents,
Map<String, String> revpropTable,
CommitMessageCallback handler, CommitCallback callback)
@@ -224,22 +245,34 @@
boolean ignoreAncestry)
throws ClientException;
- public native void doImport(String path, String url, Depth depth,
- boolean noIgnore,
+ private native void doImport(String path, String url, Depth depth,
+ boolean noIgnore, boolean noAutoProps,
boolean ignoreUnknownNodeTypes,
Map<String, String> revpropTable,
- CommitMessageCallback handler, CommitCallback callback)
+ Object importFilterCallback,
+ CommitMessageCallback handler,
+ CommitCallback commitCallback)
throws ClientException;
+ public void doImport(String path, String url, Depth depth, boolean noIgnore,
+ boolean ignoreUnknownNodeTypes,
+ Map<String, String> revpropTable,
+ CommitMessageCallback handler,
+ CommitCallback callback)
+ throws ClientException
+ {
+ doImport(path, url, depth, noIgnore, false, ignoreUnknownNodeTypes,
+ revpropTable, null, handler, callback);
+ }
+
public native Set<String> suggestMergeSources(String path,
Revision pegRevision)
throws SubversionException;
public native void merge(String path1, Revision revision1, String path2,
Revision revision2, String localPath,
- boolean force, Depth depth,
- boolean ignoreAncestry, boolean dryRun,
- boolean recordOnly)
+ boolean force, Depth depth, boolean ignoreAncestry,
+ boolean dryRun, boolean recordOnly)
throws ClientException;
public native void merge(String path, Revision pegRevision,
@@ -248,6 +281,8 @@
boolean dryRun, boolean recordOnly)
throws ClientException;
+
+ /** @deprecated */
public native void mergeReintegrate(String path, Revision pegRevision,
String localPath, boolean dryRun)
throws ClientException;
@@ -264,6 +299,7 @@
LogMessageCallback callback)
throws ClientException;
+
public native void diff(String target1, Revision revision1, String target2,
Revision revision2, String relativeToDir,
String outFileName, Depth depth,
@@ -326,8 +362,16 @@
boolean force)
throws ClientException;
+ public byte[] propertyGet(String path, String name,
+ Revision revision, Revision pegRevision)
+ throws ClientException
+ {
+ return propertyGet(path, name, revision, pegRevision, null);
+ }
+
public native byte[] propertyGet(String path, String name,
- Revision revision, Revision pegRevision)
+ Revision revision, Revision pegRevision,
+ Collection<String> changelists)
throws ClientException;
public byte[] fileContent(String path, Revision revision,
@@ -458,16 +502,33 @@
PatchCallback callback)
throws ClientException;
+ public ISVNRemote openRemoteSession(String path)
+ throws ClientException, SubversionException
+ {
+ return nativeOpenRemoteSession(path, 1);
+ }
+
+ public ISVNRemote openRemoteSession(String path, int retryAttempts)
+ throws ClientException, SubversionException
+ {
+ if (retryAttempts <= 0)
+ throw new IllegalArgumentException(
+ "retryAttempts must be positive");
+ return nativeOpenRemoteSession(path, retryAttempts);
+ }
+
+ private native ISVNRemote nativeOpenRemoteSession(
+ String path, int retryAttempts)
+ throws ClientException, SubversionException;
+
/**
* A private class to hold the contextual information required to
* persist in this object, such as notification handlers.
*/
- private class ClientContext
- implements ClientNotifyCallback, ProgressCallback,
- ConflictResolverCallback
+ private class ClientContext extends OperationContext
+ implements ClientNotifyCallback, ConflictResolverCallback
{
public ClientNotifyCallback notify = null;
- public ProgressCallback listener = null;
public ConflictResolverCallback resolver = null;
public void onNotify(ClientNotifyInformation notifyInfo)
@@ -476,12 +537,6 @@
notify.onNotify(notifyInfo);
}
- public void onProgress(ProgressEvent event)
- {
- if (listener != null)
- listener.onProgress(event);
- }
-
public ConflictResult resolve(ConflictDescriptor conflict)
throws SubversionException
{
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java
index 98b611f..1cd5d99 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java
@@ -130,7 +130,14 @@
* @throws ClientException throw in case of problem
*/
public native void hotcopy(File path, File targetPath,
- boolean cleanLogs) throws ClientException;
+ boolean cleanLogs, boolean incremental)
+ throws ClientException;
+
+ public void hotcopy(File path, File targetPath,
+ boolean cleanLogs) throws ClientException
+ {
+ hotcopy(path, targetPath, cleanLogs, false);
+ }
/**
* list all logfiles (BDB) in use or not)
@@ -150,7 +157,19 @@
public native void listUnusedDBLogs(File path, ISVNRepos.MessageReceiver receiver)
throws ClientException;
+ public void load(File path, InputStream dataInput,
+ boolean ignoreUUID, boolean forceUUID,
+ boolean usePreCommitHook, boolean usePostCommitHook,
+ String relativePath, ReposNotifyCallback callback)
+ throws ClientException
+ {
+ load(path, dataInput, Revision.START, Revision.HEAD,
+ ignoreUUID, forceUUID, usePreCommitHook, usePostCommitHook,
+ relativePath, callback);
+ }
+
public native void load(File path, InputStream dataInput,
+ Revision start, Revision end,
boolean ignoreUUID, boolean forceUUID,
boolean usePreCommitHook, boolean usePostCommitHook,
String relativePath, ReposNotifyCallback callback)
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListCallback.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListCallback.java
index 4da1506..61ff0ca 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListCallback.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListCallback.java
@@ -29,7 +29,7 @@
/**
* This interface is used to receive every single line for a file on a
- * the {@link ISVNClient#blame} call.
+ * the {@link ISVNClient#list} call.
*/
public interface ListCallback
{
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ProplistCallback.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ProplistCallback.java
index 98f73fd..5c6b0e7 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ProplistCallback.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ProplistCallback.java
@@ -33,7 +33,7 @@
public interface ProplistCallback
{
/**
- * the method will be called for every line in a file.
+ * the method will be called once for every file.
* @param path the path.
* @param properties the properties on the path.
*/
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/CommitEditor.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/CommitEditor.java
new file mode 100644
index 0000000..3b546d2
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/CommitEditor.java
@@ -0,0 +1,171 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.remote;
+
+import org.apache.subversion.javahl.types.*;
+import org.apache.subversion.javahl.callback.*;
+
+import org.apache.subversion.javahl.ISVNEditor;
+import org.apache.subversion.javahl.JNIObject;
+import org.apache.subversion.javahl.ClientException;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implementation of ISVNEditor that drives commits.
+ * @since 1.9
+ */
+public class CommitEditor extends JNIObject implements ISVNEditor
+{
+ public void dispose() {/* TODO */}
+
+ public void addDirectory(String relativePath,
+ Iterable<String> children,
+ Map<String, byte[]> properties,
+ long replacesRevision)
+ throws ClientException
+ {
+ notimplemented("addDirectory");
+ }
+
+ public void addFile(String relativePath,
+ Checksum checksum,
+ InputStream contents,
+ Map<String, byte[]> properties,
+ long replacesRevision)
+ throws ClientException
+ {
+ notimplemented("addFile");
+ }
+
+ public void addSymlink(String relativePath,
+ String target,
+ Map<String, byte[]> properties,
+ long replacesRevision)
+ throws ClientException
+ {
+ notimplemented("addSymlink");
+ }
+
+ public void addAbsent(String relativePath,
+ NodeKind kind,
+ long replacesRevision)
+ throws ClientException
+ {
+ notimplemented("addAbsent");
+ }
+
+ public void alterDirectory(String relativePath,
+ long revision,
+ Iterable<String> children,
+ Map<String, byte[]> properties)
+ throws ClientException
+ {
+ notimplemented("alterDirectory");
+ }
+
+ public void alterFile(String relativePath,
+ long revision,
+ Checksum checksum,
+ InputStream contents,
+ Map<String, byte[]> properties)
+ throws ClientException
+ {
+ notimplemented("alterFile");
+ }
+
+ public void alterSymlink(String relativePath,
+ long revision,
+ String target,
+ Map<String, byte[]> properties)
+ throws ClientException
+ {
+ notimplemented("alterSymlink");
+ }
+
+ public void delete(String relativePath,
+ long revision)
+ throws ClientException
+ {
+ notimplemented("delete");
+ }
+
+ public void copy(String sourceRelativePath,
+ long sourceRevision,
+ String destinationRelativePath,
+ long replacesRevision)
+ throws ClientException
+ {
+ notimplemented("copy");
+ }
+
+ public void move(String sourceRelativePath,
+ long sourceRevision,
+ String destinationRelativePath,
+ long replacesRevision)
+ throws ClientException
+ {
+ notimplemented("move");
+ }
+
+ public void rotate(List<RotatePair> elements) throws ClientException
+ {
+ notimplemented("rotate");
+ }
+
+ public void complete() throws ClientException
+ {
+ notimplemented("complete");
+ }
+
+ public void abort() throws ClientException
+ {
+ notimplemented("abort");
+ }
+
+ /**
+ * This factory method called from RemoteSession.getCommitEditor.
+ */
+ static final CommitEditor createInstance(RemoteSession owner)
+ throws ClientException
+ {
+ // FIXME: temporary implementation
+ return new CommitEditor(0L);
+ }
+
+ /**
+ * This constructor is called from JNI to get an instance.
+ */
+ protected CommitEditor(long cppAddr)
+ {
+ super(cppAddr);
+ }
+
+ private void notimplemented(String name)
+ {
+ throw new RuntimeException("Not implemented: " + name);
+ }
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java
new file mode 100644
index 0000000..e250496
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java
@@ -0,0 +1,226 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.remote;
+
+import org.apache.subversion.javahl.callback.*;
+import org.apache.subversion.javahl.types.*;
+
+import org.apache.subversion.javahl.ISVNRemote;
+import org.apache.subversion.javahl.NativeResources;
+import org.apache.subversion.javahl.ClientException;
+import org.apache.subversion.javahl.SubversionException;
+
+import java.util.HashSet;
+
+
+/**
+ * Factory class for creating ISVNRemote instances.
+ * @since 1.9
+ */
+public class RemoteFactory
+{
+ /**
+ * Default constructor.
+ */
+ public RemoteFactory() {}
+
+ /**
+ * Initializing constructor. Any or all of its arguments may be null.
+ */
+ public RemoteFactory(String configDirectory,
+ String username, String password,
+ UserPasswordCallback prompt,
+ ProgressCallback progress)
+ {
+ setConfigDirectory(configDirectory);
+ setUsername(username);
+ setPassword(password);
+ setPrompt(prompt);
+ setProgressCallback(progress);
+ }
+
+ /**
+ * Sets the username used for authentication.
+ * @param username The username; Set to the <code>null</code> to clear it.
+ * @throws IllegalArgumentException If <code>username</code> is empty.
+ * @see #password(String)
+ */
+ public void setUsername(String username)
+ {
+ if (username != null && username.isEmpty())
+ throw new IllegalArgumentException("username must not be empty");
+ this.username = username;
+ }
+
+ /**
+ * Sets the password used for authentication.
+ * @param password The passwordp Set <code>null</code> to clear it.
+ * @throws IllegalArgumentException If <code>password</code> is empty.
+ * @see #username(String)
+ */
+ public void setPassword(String password)
+ {
+ if (password != null && password.isEmpty())
+ throw new IllegalArgumentException("password must not be empty");
+ this.password = password;
+ }
+
+ /**
+ * Register callback interface to supply username and password on demand.
+ * This callback can also be used to provide theequivalent of the
+ * <code>--no-auth-cache</code> and <code>--non-interactive</code>
+ * arguments accepted by the command-line client.
+ * @param prompt the callback interface
+ */
+ public void setPrompt(UserPasswordCallback prompt)
+ {
+ this.prompt = prompt;
+ }
+
+ /**
+ * Set the progress callback for new sessions.
+ *
+ * @param progress The progress callback.
+ */
+ public void setProgressCallback(ProgressCallback progress)
+ {
+ this.progress = progress;
+ }
+
+ /**
+ * Set directory for the configuration information.
+ */
+ public void setConfigDirectory(String configDirectory)
+ {
+ this.configDirectory = configDirectory;
+ }
+
+
+ /**
+ * Open a persistent session to a repository.
+ * @param url The initial session root URL.
+ * @throws RetryOpenSession If the session URL was redirected
+ * @throws SubversionException If an URL redirect cycle was detected
+ * @throws ClientException
+ * @note The URL can point to a subtree of the repository.
+ * @note The session object inherits the progress callback,
+ * configuration directory and authentication info.
+ */
+ public ISVNRemote openRemoteSession(String url)
+ throws ClientException, SubversionException
+ {
+ return open(1, url, null,
+ configDirectory, username, password, prompt, progress);
+ }
+
+ /**
+ * Open a persistent session to a repository.
+ * @param url The initial session root URL.
+ * @param retryAttempts The number of times to retry the operation
+ * if the given URL is redirected.
+ * @throws IllegalArgumentException If <code>retryAttempts</code>
+ * is not positive
+ * @throws RetryOpenSession If the session URL was redirected
+ * @throws SubversionException If an URL redirect cycle was detected
+ * @throws ClientException
+ * @note The URL can point to a subtree of the repository.
+ * @note The session object inherits the progress callback,
+ * configuration directory and authentication info.
+ */
+ public ISVNRemote openRemoteSession(String url, int retryAttempts)
+ throws ClientException, SubversionException
+ {
+ if (retryAttempts <= 0)
+ throw new IllegalArgumentException(
+ "retryAttempts must be positive");
+ return open(retryAttempts, url, null,
+ configDirectory, username, password, prompt, progress);
+ }
+
+ /**
+ * Open a persistent session to a repository.
+ * @param url The initial session root URL.
+ * @param reposUUID The expected repository UUID; may not be null..
+ * @throws IllegalArgumentException If <code>reposUUID</code> is null.
+ * @throws RetryOpenSession If the session URL was redirected
+ * @throws SubversionException If an URL redirect cycle was detected
+ * @throws ClientException
+ * @note The URL can point to a subtree of the repository.
+ * @note If the UUID does not match the repository, this function fails.
+ * @note The session object inherits the progress callback,
+ * configuration directory and authentication info.
+ */
+ public ISVNRemote openRemoteSession(String url, String reposUUID)
+ throws ClientException, SubversionException
+ {
+ if (reposUUID == null)
+ throw new IllegalArgumentException("reposUUID may not be null");
+ return open(1, url, reposUUID,
+ configDirectory, username, password, prompt, progress);
+ }
+
+ /**
+ * Open a persistent session to a repository.
+ * @param url The initial session root URL.
+ * @param reposUUID The expected repository UUID; may not be null..
+ * @param retryAttempts The number of times to retry the operation
+ * if the given URL is redirected.
+ * @throws IllegalArgumentException If <code>reposUUID</code> is null
+ * or <code>retryAttempts</code> is not positive
+ * @throws RetryOpenSession If the session URL was redirected
+ * @throws SubversionException If an URL redirect cycle was detected
+ * @throws ClientException
+ * @note The URL can point to a subtree of the repository.
+ * @note If the UUID does not match the repository, this function fails.
+ * @note The session object inherits the progress callback,
+ * configuration directory and authentication info.
+ */
+ public ISVNRemote openRemoteSession(String url, String reposUUID,
+ int retryAttempts)
+ throws ClientException, SubversionException
+ {
+ if (reposUUID == null)
+ throw new IllegalArgumentException("reposUUID may not be null");
+ if (retryAttempts <= 0)
+ throw new IllegalArgumentException(
+ "retryAttempts must be positive");
+ return open(retryAttempts, url, reposUUID,
+ configDirectory, username, password, prompt, progress);
+ }
+
+ private String configDirectory;
+ private String username;
+ private String password;
+ private UserPasswordCallback prompt;
+ private ProgressCallback progress;
+
+ /* Native factory implementation. */
+ private static native ISVNRemote open(int retryAttempts,
+ String url, String reposUUID,
+ String configDirectory,
+ String username, String password,
+ UserPasswordCallback prompt,
+ ProgressCallback progress)
+ throws ClientException, SubversionException;
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java
new file mode 100644
index 0000000..aadc1f4
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java
@@ -0,0 +1,136 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.remote;
+
+import org.apache.subversion.javahl.types.*;
+import org.apache.subversion.javahl.callback.*;
+
+import org.apache.subversion.javahl.ISVNRemote;
+import org.apache.subversion.javahl.ISVNEditor;
+import org.apache.subversion.javahl.JNIObject;
+import org.apache.subversion.javahl.OperationContext;
+import org.apache.subversion.javahl.ClientException;
+
+import java.lang.ref.WeakReference;
+import java.util.HashSet;
+import java.util.Date;
+import java.util.Map;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+public class RemoteSession extends JNIObject implements ISVNRemote
+{
+ public void dispose()
+ {
+ if (editors != null)
+ {
+ // Deactivate all open editors
+ for (WeakReference<ISVNEditor> ref : editors)
+ {
+ ISVNEditor ed = ref.get();
+ if (ed == null)
+ continue;
+ ed.dispose();
+ ref.clear();
+ }
+ }
+ nativeDispose();
+ }
+
+ public native void cancelOperation() throws ClientException;
+
+ public native void reparent(String url) throws ClientException;
+
+ public native String getSessionUrl() throws ClientException;
+
+ public native String getSessionRelativePath(String url)
+ throws ClientException;
+
+ public native String getReposRelativePath(String url)
+ throws ClientException;
+
+ public native String getReposUUID() throws ClientException;
+
+ public native String getReposRootUrl() throws ClientException;
+
+ public native long getLatestRevision() throws ClientException;
+
+ public long getRevisionByDate(Date date) throws ClientException
+ {
+ long timestamp = NANOSECONDS.convert(date.getTime(), MILLISECONDS);
+ return getRevisionByTimestamp(timestamp);
+ }
+
+ public native long getRevisionByTimestamp(long timestamp)
+ throws ClientException;
+
+ public native NodeKind checkPath(String path, long revision)
+ throws ClientException;
+
+ public native Map<String, Lock> getLocks(String path, Depth depth)
+ throws ClientException;
+
+ public ISVNEditor getCommitEditor() throws ClientException
+ {
+ ISVNEditor ed = CommitEditor.createInstance(this);
+ if (editors == null)
+ editors = new HashSet<WeakReference<ISVNEditor>>();
+ editors.add(new WeakReference<ISVNEditor>(ed));
+ return ed;
+ }
+
+ public boolean hasCapability(Capability capability)
+ throws ClientException
+ {
+ return nativeHasCapability(capability.toString());
+ }
+
+ @Override
+ public native void finalize() throws Throwable;
+
+ /**
+ * This constructor is called from JNI to get an instance.
+ */
+ protected RemoteSession(long cppAddr)
+ {
+ super(cppAddr);
+ }
+
+ private native void nativeDispose();
+
+ private native boolean nativeHasCapability(String capability);
+
+ /*
+ * NOTE: This field is accessed from native code for callbacks.
+ */
+ private RemoteSessionContext sessionContext = new RemoteSessionContext();
+ private class RemoteSessionContext extends OperationContext {}
+
+ /*
+ * The set of open editors. We need this in order to dispose/abort
+ * the editors when the session is disposed.
+ */
+ private HashSet<WeakReference<ISVNEditor>> editors;
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RetryOpenSession.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RetryOpenSession.java
new file mode 100644
index 0000000..cc23256
--- /dev/null
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RetryOpenSession.java
@@ -0,0 +1,57 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+package org.apache.subversion.javahl.remote;
+
+import org.apache.subversion.javahl.SubversionException;
+
+/**
+ * This checked exception is thrown only from ISVNClient.openRemoteSession
+ * or RemoteFactory.openRemoteSession if a session could not be opened
+ * due to a redirect.
+ */
+public class RetryOpenSession extends SubversionException
+{
+ // Update the serialVersionUID when there is a incompatible change
+ // made to this class.
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * This constructor is only called from native code.
+ */
+ protected RetryOpenSession(String message, String correctedUrl)
+ {
+ super(message);
+ this.correctedUrl = correctedUrl;
+ }
+
+ /**
+ * @return the corrected URL for the session.
+ */
+ public String getCorrectedUrl()
+ {
+ return correctedUrl;
+ }
+
+ private final String correctedUrl;
+}
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ConflictVersion.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ConflictVersion.java
index 3c59726..3c37a89 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ConflictVersion.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ConflictVersion.java
@@ -31,16 +31,19 @@
public class ConflictVersion
{
private String reposURL;
+ private String reposUUID;
private long pegRevision;
private String pathInRepos;
private NodeKind nodeKind;
/** This constructor should only be called from JNI code. */
- public ConflictVersion(String reposURL, long pegRevision, String pathInRepos,
+ ConflictVersion(String reposURL, String reposUUID,
+ long pegRevision, String pathInRepos,
NodeKind nodeKind)
{
this.reposURL = reposURL;
+ this.reposUUID = reposUUID;
this.pegRevision = pegRevision;
this.pathInRepos = pathInRepos;
this.nodeKind = nodeKind;
@@ -51,6 +54,12 @@
return reposURL;
}
+ /** @since 1.8 */
+ public String getReposUUID()
+ {
+ return reposUUID;
+ }
+
public long getPegRevision()
{
return pegRevision;
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NodeKind.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NodeKind.java
index f81d49f..ccf39ab 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NodeKind.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NodeKind.java
@@ -28,17 +28,23 @@
*/
public enum NodeKind
{
- /* absent */
+ /** absent */
none ("none"),
- /* regular file */
+ /** regular file */
file ("file"),
- /* directory */
+ /** directory */
dir ("dir"),
- /* something's here, but we don't know what */
- unknown ("unknown");
+ /** something's here, but we don't know what */
+ unknown ("unknown"),
+
+ /**
+ * symbolic link
+ * @since: 1.8
+ */
+ symlink ("symlink");
/**
* The description of the node kind.
diff --git a/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Status.java b/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Status.java
index 8b26741..4e628c1 100644
--- a/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Status.java
+++ b/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Status.java
@@ -165,6 +165,10 @@
*/
private String changelist;
+ private String movedFromAbspath;
+
+ private String movedToAbspath;
+
/**
* this constructor should only called from JNI code
* @param path the file system path of item
@@ -203,6 +207,8 @@
* @param reposLastCmtAuthor the author of the last commit, if out of
* date
* @param changelist the changelist the item is a member of
+ * @param movedFromAbspath path moved from
+ * @param movedToAbspath path moved from
*/
public Status(String path, String url, NodeKind nodeKind, long revision,
long lastChangedRevision, long lastChangedDate,
@@ -212,7 +218,8 @@
boolean switched, boolean fileExternal, Lock localLock,
Lock reposLock, long reposLastCmtRevision,
long reposLastCmtDate, NodeKind reposKind,
- String reposLastCmtAuthor, String changelist)
+ String reposLastCmtAuthor, String changelist,
+ String movedFromAbspath, String movedToAbspath)
{
this.path = path;
this.url = url;
@@ -237,6 +244,8 @@
this.reposKind = reposKind;
this.reposLastCmtAuthor = reposLastCmtAuthor;
this.changelist = changelist;
+ this.movedFromAbspath = movedFromAbspath;
+ this.movedToAbspath = movedToAbspath;
}
/**
@@ -585,6 +594,16 @@
return isConflicted;
}
+ public String getMovedFromAbspath()
+ {
+ return movedFromAbspath;
+ }
+
+ public String getMovedToAbspath()
+ {
+ return movedToAbspath;
+ }
+
/**
* Converts microseconds since the epoch to a Date object.
*
diff --git a/subversion/bindings/javahl/src/org/tigris/subversion/javahl/ConflictDescriptor.java b/subversion/bindings/javahl/src/org/tigris/subversion/javahl/ConflictDescriptor.java
index 015f989..9c388c5 100644
--- a/subversion/bindings/javahl/src/org/tigris/subversion/javahl/ConflictDescriptor.java
+++ b/subversion/bindings/javahl/src/org/tigris/subversion/javahl/ConflictDescriptor.java
@@ -125,8 +125,12 @@
aDesc.getAction().ordinal(), aDesc.getReason().ordinal(),
aDesc.getOperation().ordinal(), aDesc.getBasePath(),
aDesc.getTheirPath(), aDesc.getMyPath(), aDesc.getMergedPath(),
- new ConflictVersion(aDesc.getSrcLeftVersion()),
- new ConflictVersion(aDesc.getSrcRightVersion()));
+ aDesc.getSrcLeftVersion() != null
+ ? new ConflictVersion(aDesc.getSrcLeftVersion())
+ : null,
+ aDesc.getSrcRightVersion() != null
+ ? new ConflictVersion(aDesc.getSrcRightVersion())
+ : null);
}
public String getPath()
diff --git a/subversion/bindings/javahl/src/org/tigris/subversion/javahl/SVNClient.java b/subversion/bindings/javahl/src/org/tigris/subversion/javahl/SVNClient.java
index 6343283..b8582c5 100644
--- a/subversion/bindings/javahl/src/org/tigris/subversion/javahl/SVNClient.java
+++ b/subversion/bindings/javahl/src/org/tigris/subversion/javahl/SVNClient.java
@@ -795,6 +795,7 @@
/**
* @since 1.5
*/
+ @SuppressWarnings("unchecked")
public void remove(String[] paths, String message, boolean force,
boolean keepLocal, Map revpropTable)
throws ClientException
@@ -964,6 +965,7 @@
/**
* @since 1.5
*/
+ @SuppressWarnings("unchecked")
public long commit(String[] paths, String message, int depth,
boolean noUnlock, boolean keepChangelist,
String[] changelists, Map revpropTable)
@@ -998,6 +1000,7 @@
/**
* @since 1.7
*/
+ @SuppressWarnings("unchecked")
public void copy(CopySource[] sources, String destPath, String message,
boolean copyAsChild, boolean makeParents,
boolean ignoreExternals, Map revpropTable)
@@ -1031,6 +1034,7 @@
* boolean, boolean, Map)} instead.
* @since 1.5
*/
+ @SuppressWarnings("unchecked")
public void copy(CopySource[] sources, String destPath, String message,
boolean copyAsChild, boolean makeParents,
Map revpropTable)
@@ -1057,6 +1061,7 @@
/**
* @since 1.5
*/
+ @SuppressWarnings("unchecked")
public void move(String[] srcPaths, String destPath, String message,
boolean force, boolean moveAsChild,
boolean makeParents, Map revpropTable)
@@ -1106,6 +1111,7 @@
/**
* @since 1.5
*/
+ @SuppressWarnings("unchecked")
public void mkdir(String[] paths, String message,
boolean makeParents, Map revpropTable)
throws ClientException
@@ -1306,6 +1312,7 @@
/**
* @since 1.5
*/
+ @SuppressWarnings("unchecked")
public void doImport(String path, String url, String message,
int depth, boolean noIgnore,
boolean ignoreUnknownNodeTypes, Map revpropTable)
@@ -1888,6 +1895,7 @@
/**
* @since 1.5
*/
+ @SuppressWarnings("unchecked")
public void propertySet(String path, String name, String value, int depth,
String[] changelists, boolean force,
Map revpropTable)
diff --git a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
index 8de939c..8eac120 100644
--- a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
+++ b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
@@ -147,10 +147,10 @@
CommitItemStateFlags.Add);
Set<String> urls = new HashSet<String>(1);
urls.add(thisTest.getUrl() + "/Y");
- try
+ try
{
tempclient.mkdir(urls, false, null, new ConstMsg("log_msg"), null);
- }
+ }
catch(JNIError e)
{
return; // Test passes!
@@ -898,7 +898,7 @@
}
client.move(srcPaths,
new File(thisTest.getWorkingCopy(), "A/B/F").getPath(),
- false, true, false, null, null, null);
+ false, true, false, false, false, null, null, null);
// Commit the changes, and check the state of the WC.
checkCommitRevision(thisTest,
@@ -2352,222 +2352,222 @@
acquireMergeinfoAndAssertEquals(2, 4, 6, 6, targetPath, mergeSrc);
}
- /**
- * Test merge with automatic source and revision determination
- * (e.g. 'svn merge -g').
- * @throws Throwable
- * @since 1.5
- */
- public void testMergeUsingHistory() throws Throwable
- {
- OneTest thisTest = setupAndPerformMerge();
-
- // Test that getMergeinfo() returns null.
- assertNull(client.getMergeinfo(new File(thisTest.getWCPath(), "A")
- .toString(), Revision.HEAD));
-
- // Merge and commit some changes (r4).
- appendText(thisTest, "A/mu", "xxx", 4);
- checkCommitRevision(thisTest, "wrong revision number from commit", 4,
- thisTest.getWCPathSet(), "log msg", Depth.infinity,
- false, false, null, null);
-
- String branchPath = thisTest.getWCPath() + "/branches/A";
- String modUrl = thisTest.getUrl() + "/A";
- Revision unspec = new Revision(Revision.Kind.unspecified);
- List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
- ranges.add(new RevisionRange(unspec, unspec));
- client.merge(modUrl, Revision.HEAD, ranges,
- branchPath, true, Depth.infinity, false, false, false);
-
- // commit the changes so that we can verify merge
- addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
- "branches/A", NodeKind.dir,
- CommitItemStateFlags.PropMods);
- addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
- "branches/A/mu", NodeKind.file,
- CommitItemStateFlags.TextMods);
- checkCommitRevision(thisTest, "wrong revision number from commit", 5,
- thisTest.getWCPathSet(), "log msg", Depth.infinity,
- false, false, null, null);
- }
-
- /**
- * Test reintegrating a branch with trunk
- * (e.g. 'svn merge --reintegrate').
- * @throws Throwable
- * @since 1.5
- */
- public void testMergeReintegrate() throws Throwable
- {
- OneTest thisTest = setupAndPerformMerge();
-
- // Test that getMergeinfo() returns null.
- assertNull(client.getMergeinfo(new File(thisTest.getWCPath(), "A")
- .toString(), Revision.HEAD));
-
- // Merge and commit some changes to main (r4).
- appendText(thisTest, "A/mu", "xxx", 4);
- checkCommitRevision(thisTest,
- "wrong revision number from main commit", 4,
- thisTest.getWCPathSet(), "log msg", Depth.infinity,
- false, false, null, null);
- // Merge and commit some changes to branch (r5).
- appendText(thisTest, "branches/A/D/G/rho", "yyy", -1);
- checkCommitRevision(thisTest,
- "wrong revision number from branch commit", 5,
- thisTest.getWCPathSet(), "log msg", Depth.infinity,
- false, false, null, null);
-
- // update the branch WC (to r5) before merge
- update(thisTest, "/branches");
-
- String branchPath = thisTest.getWCPath() + "/branches/A";
- String modUrl = thisTest.getUrl() + "/A";
- Revision unspec = new Revision(Revision.Kind.unspecified);
- List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
- ranges.add(new RevisionRange(unspec, unspec));
- client.merge(modUrl, Revision.HEAD, ranges,
- branchPath, true, Depth.infinity, false, false, false);
-
- // commit the changes so that we can verify merge
- addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
- "branches/A", NodeKind.dir,
- CommitItemStateFlags.PropMods);
- addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
- "branches/A/mu", NodeKind.file,
- CommitItemStateFlags.TextMods);
- checkCommitRevision(thisTest, "wrong revision number from commit", 6,
- thisTest.getWCPathSet(), "log msg", Depth.infinity,
- false, false, null, null);
-
- // now we --reintegrate the branch with main
- String branchUrl = thisTest.getUrl() + "/branches/A";
- try
- {
- client.mergeReintegrate(branchUrl, Revision.HEAD,
- thisTest.getWCPath() + "/A", false);
- fail("reintegrate merged into a mixed-revision WC");
- }
- catch(ClientException e)
- {
- // update the WC (to r6) and try again
- update(thisTest);
- client.mergeReintegrate(branchUrl, Revision.HEAD,
- thisTest.getWCPath() + "/A", false);
- }
- // commit the changes so that we can verify merge
- addExpectedCommitItem(thisTest.getWCPath(),
- thisTest.getUrl().toString(), "A", NodeKind.dir,
- CommitItemStateFlags.PropMods);
- addExpectedCommitItem(thisTest.getWCPath(),
- thisTest.getUrl().toString(), "A/D/G/rho",
- NodeKind.file, CommitItemStateFlags.TextMods);
- checkCommitRevision(thisTest, "wrong revision number from commit", 7,
- thisTest.getWCPathSet(), "log msg", Depth.infinity,
- false, false, null, null);
-
- }
-
- /**
- * Test automatic merge conflict resolution.
- * @throws Throwable
- * @since 1.5
- */
- public void testMergeConflictResolution() throws Throwable
- {
- // Add a conflict resolution callback which always chooses the
- // user's version of a conflicted file.
- client.setConflictResolver(new ConflictResolverCallback()
- {
- public ConflictResult resolve(ConflictDescriptor descrip)
- {
- return new ConflictResult(ConflictResult.Choice.chooseTheirsConflict,
- null);
- }
- });
-
- OneTest thisTest = new OneTest();
- String originalContents = thisTest.getWc().getItemContent("A/mu");
- String expectedContents = originalContents + "xxx";
-
- // Merge and commit a change (r2).
- File mu = appendText(thisTest, "A/mu", "xxx", 2);
- checkCommitRevision(thisTest, "wrong revision number from commit", 2,
- thisTest.getWCPathSet(), "log msg", Depth.infinity,
- false, false, null, null);
-
- // Backdate the WC to the previous revision (r1).
- client.update(thisTest.getWCPathSet(), Revision.getInstance(1),
- Depth.unknown, false, false, false, false);
-
- // Prep for a merge conflict by changing A/mu in a different
- // way.
- mu = appendText(thisTest, "A/mu", "yyy", 1);
-
- // Merge in the previous changes to A/mu (from r2).
- List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
- ranges.add(new RevisionRange(new Revision.Number(1),
- new Revision.Number(2)));
- client.merge(thisTest.getUrl().toString(), Revision.HEAD, ranges,
- thisTest.getWCPath(), false, Depth.infinity, false,
- false, false);
-
- assertFileContentsEquals("Unexpected conflict resolution",
- expectedContents, mu);
- }
-
- /**
- * Test merge --record-only
- * @throws Throwable
- * @since 1.5
- */
- public void testRecordOnlyMerge() throws Throwable
- {
- OneTest thisTest = setupAndPerformMerge();
-
- // Verify that there are now potential merge sources.
- Set<String> suggestedSrcs =
- client.suggestMergeSources(thisTest.getWCPath() + "/branches/A",
- Revision.WORKING);
- assertNotNull(suggestedSrcs);
- assertEquals(1, suggestedSrcs.size());
-
- // Test that getMergeinfo() returns null.
- assertNull(client.getMergeinfo(new File(thisTest.getWCPath(), "A")
- .toString(), Revision.HEAD));
-
- // Merge and commit some changes (r4).
- appendText(thisTest, "A/mu", "xxx", 4);
- appendText(thisTest, "A/D/G/rho", "yyy", 4);
- checkCommitRevision(thisTest, "wrong revision number from commit", 4,
- thisTest.getWCPathSet(), "log msg", Depth.infinity,
- false, false, null, null);
-
- // --record-only merge changes in A to branches/A
- String branchPath = thisTest.getWCPath() + "/branches/A";
- String modUrl = thisTest.getUrl() + "/A";
-
- List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
- ranges.add(new RevisionRange(new Revision.Number(2),
- new Revision.Number(4)));
- client.merge(modUrl, Revision.HEAD, ranges,
- branchPath, true, Depth.infinity, false, false, true);
-
- // commit the changes so that we can verify merge
- addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
- "branches/A", NodeKind.dir,
- CommitItemStateFlags.PropMods);
- checkCommitRevision(thisTest, "wrong revision number from commit", 5,
- thisTest.getWCPathSet(), "log msg", Depth.infinity,
- false, false, null, null);
-
- // Test retrieval of mergeinfo from a WC path.
- String targetPath =
- new File(thisTest.getWCPath(), "branches/A").getPath();
- final String mergeSrc = thisTest.getUrl() + "/A";
- acquireMergeinfoAndAssertEquals(2, 4, 0, 0, targetPath, mergeSrc);
- }
+//FIXME: /**
+//FIXME: * Test merge with automatic source and revision determination
+//FIXME: * (e.g. 'svn merge -g').
+//FIXME: * @throws Throwable
+//FIXME: * @since 1.5
+//FIXME: */
+//FIXME: public void testMergeUsingHistory() throws Throwable
+//FIXME: {
+//FIXME: OneTest thisTest = setupAndPerformMerge();
+//FIXME:
+//FIXME: // Test that getMergeinfo() returns null.
+//FIXME: assertNull(client.getMergeinfo(new File(thisTest.getWCPath(), "A")
+//FIXME: .toString(), Revision.HEAD));
+//FIXME:
+//FIXME: // Merge and commit some changes (r4).
+//FIXME: appendText(thisTest, "A/mu", "xxx", 4);
+//FIXME: checkCommitRevision(thisTest, "wrong revision number from commit", 4,
+//FIXME: thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME: false, false, null, null);
+//FIXME:
+//FIXME: String branchPath = thisTest.getWCPath() + "/branches/A";
+//FIXME: String modUrl = thisTest.getUrl() + "/A";
+//FIXME: Revision unspec = new Revision(Revision.Kind.unspecified);
+//FIXME: List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
+//FIXME: ranges.add(new RevisionRange(unspec, unspec));
+//FIXME: client.merge(modUrl, Revision.HEAD, ranges,
+//FIXME: branchPath, true, Depth.infinity, false, false, false);
+//FIXME:
+//FIXME: // commit the changes so that we can verify merge
+//FIXME: addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
+//FIXME: "branches/A", NodeKind.dir,
+//FIXME: CommitItemStateFlags.PropMods);
+//FIXME: addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
+//FIXME: "branches/A/mu", NodeKind.file,
+//FIXME: CommitItemStateFlags.TextMods);
+//FIXME: checkCommitRevision(thisTest, "wrong revision number from commit", 5,
+//FIXME: thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME: false, false, null, null);
+//FIXME: }
+//FIXME:
+//FIXME: /**
+//FIXME: * Test reintegrating a branch with trunk
+//FIXME: * (e.g. 'svn merge --reintegrate').
+//FIXME: * @throws Throwable
+//FIXME: * @since 1.5
+//FIXME: */
+//FIXME: public void testMergeReintegrate() throws Throwable
+//FIXME: {
+//FIXME: OneTest thisTest = setupAndPerformMerge();
+//FIXME:
+//FIXME: // Test that getMergeinfo() returns null.
+//FIXME: assertNull(client.getMergeinfo(new File(thisTest.getWCPath(), "A")
+//FIXME: .toString(), Revision.HEAD));
+//FIXME:
+//FIXME: // Merge and commit some changes to main (r4).
+//FIXME: appendText(thisTest, "A/mu", "xxx", 4);
+//FIXME: checkCommitRevision(thisTest,
+//FIXME: "wrong revision number from main commit", 4,
+//FIXME: thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME: false, false, null, null);
+//FIXME: // Merge and commit some changes to branch (r5).
+//FIXME: appendText(thisTest, "branches/A/D/G/rho", "yyy", -1);
+//FIXME: checkCommitRevision(thisTest,
+//FIXME: "wrong revision number from branch commit", 5,
+//FIXME: thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME: false, false, null, null);
+//FIXME:
+//FIXME: // update the branch WC (to r5) before merge
+//FIXME: update(thisTest, "/branches");
+//FIXME:
+//FIXME: String branchPath = thisTest.getWCPath() + "/branches/A";
+//FIXME: String modUrl = thisTest.getUrl() + "/A";
+//FIXME: Revision unspec = new Revision(Revision.Kind.unspecified);
+//FIXME: List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
+//FIXME: ranges.add(new RevisionRange(unspec, unspec));
+//FIXME: client.merge(modUrl, Revision.HEAD, ranges,
+//FIXME: branchPath, true, Depth.infinity, false, false, false);
+//FIXME:
+//FIXME: // commit the changes so that we can verify merge
+//FIXME: addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
+//FIXME: "branches/A", NodeKind.dir,
+//FIXME: CommitItemStateFlags.PropMods);
+//FIXME: addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
+//FIXME: "branches/A/mu", NodeKind.file,
+//FIXME: CommitItemStateFlags.TextMods);
+//FIXME: checkCommitRevision(thisTest, "wrong revision number from commit", 6,
+//FIXME: thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME: false, false, null, null);
+//FIXME:
+//FIXME: // now we --reintegrate the branch with main
+//FIXME: String branchUrl = thisTest.getUrl() + "/branches/A";
+//FIXME: try
+//FIXME: {
+//FIXME: client.mergeReintegrate(branchUrl, Revision.HEAD,
+//FIXME: thisTest.getWCPath() + "/A", false);
+//FIXME: fail("reintegrate merged into a mixed-revision WC");
+//FIXME: }
+//FIXME: catch(ClientException e)
+//FIXME: {
+//FIXME: // update the WC (to r6) and try again
+//FIXME: update(thisTest);
+//FIXME: client.mergeReintegrate(branchUrl, Revision.HEAD,
+//FIXME: thisTest.getWCPath() + "/A", false);
+//FIXME: }
+//FIXME: // commit the changes so that we can verify merge
+//FIXME: addExpectedCommitItem(thisTest.getWCPath(),
+//FIXME: thisTest.getUrl().toString(), "A", NodeKind.dir,
+//FIXME: CommitItemStateFlags.PropMods);
+//FIXME: addExpectedCommitItem(thisTest.getWCPath(),
+//FIXME: thisTest.getUrl().toString(), "A/D/G/rho",
+//FIXME: NodeKind.file, CommitItemStateFlags.TextMods);
+//FIXME: checkCommitRevision(thisTest, "wrong revision number from commit", 7,
+//FIXME: thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME: false, false, null, null);
+//FIXME:
+//FIXME: }
+//FIXME:
+//FIXME: /**
+//FIXME: * Test automatic merge conflict resolution.
+//FIXME: * @throws Throwable
+//FIXME: * @since 1.5
+//FIXME: */
+//FIXME: public void testMergeConflictResolution() throws Throwable
+//FIXME: {
+//FIXME: // Add a conflict resolution callback which always chooses the
+//FIXME: // user's version of a conflicted file.
+//FIXME: client.setConflictResolver(new ConflictResolverCallback()
+//FIXME: {
+//FIXME: public ConflictResult resolve(ConflictDescriptor descrip)
+//FIXME: {
+//FIXME: return new ConflictResult(ConflictResult.Choice.chooseTheirsConflict,
+//FIXME: null);
+//FIXME: }
+//FIXME: });
+//FIXME:
+//FIXME: OneTest thisTest = new OneTest();
+//FIXME: String originalContents = thisTest.getWc().getItemContent("A/mu");
+//FIXME: String expectedContents = originalContents + "xxx";
+//FIXME:
+//FIXME: // Merge and commit a change (r2).
+//FIXME: File mu = appendText(thisTest, "A/mu", "xxx", 2);
+//FIXME: checkCommitRevision(thisTest, "wrong revision number from commit", 2,
+//FIXME: thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME: false, false, null, null);
+//FIXME:
+//FIXME: // Backdate the WC to the previous revision (r1).
+//FIXME: client.update(thisTest.getWCPathSet(), Revision.getInstance(1),
+//FIXME: Depth.unknown, false, false, false, false);
+//FIXME:
+//FIXME: // Prep for a merge conflict by changing A/mu in a different
+//FIXME: // way.
+//FIXME: mu = appendText(thisTest, "A/mu", "yyy", 1);
+//FIXME:
+//FIXME: // Merge in the previous changes to A/mu (from r2).
+//FIXME: List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
+//FIXME: ranges.add(new RevisionRange(new Revision.Number(1),
+//FIXME: new Revision.Number(2)));
+//FIXME: client.merge(thisTest.getUrl().toString(), Revision.HEAD, ranges,
+//FIXME: thisTest.getWCPath(), false, Depth.infinity, false,
+//FIXME: false, false);
+//FIXME:
+//FIXME: assertFileContentsEquals("Unexpected conflict resolution",
+//FIXME: expectedContents, mu);
+//FIXME: }
+//FIXME:
+//FIXME: /**
+//FIXME: * Test merge --record-only
+//FIXME: * @throws Throwable
+//FIXME: * @since 1.5
+//FIXME: */
+//FIXME: public void testRecordOnlyMerge() throws Throwable
+//FIXME: {
+//FIXME: OneTest thisTest = setupAndPerformMerge();
+//FIXME:
+//FIXME: // Verify that there are now potential merge sources.
+//FIXME: Set<String> suggestedSrcs =
+//FIXME: client.suggestMergeSources(thisTest.getWCPath() + "/branches/A",
+//FIXME: Revision.WORKING);
+//FIXME: assertNotNull(suggestedSrcs);
+//FIXME: assertEquals(1, suggestedSrcs.size());
+//FIXME:
+//FIXME: // Test that getMergeinfo() returns null.
+//FIXME: assertNull(client.getMergeinfo(new File(thisTest.getWCPath(), "A")
+//FIXME: .toString(), Revision.HEAD));
+//FIXME:
+//FIXME: // Merge and commit some changes (r4).
+//FIXME: appendText(thisTest, "A/mu", "xxx", 4);
+//FIXME: appendText(thisTest, "A/D/G/rho", "yyy", 4);
+//FIXME: checkCommitRevision(thisTest, "wrong revision number from commit", 4,
+//FIXME: thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME: false, false, null, null);
+//FIXME:
+//FIXME: // --record-only merge changes in A to branches/A
+//FIXME: String branchPath = thisTest.getWCPath() + "/branches/A";
+//FIXME: String modUrl = thisTest.getUrl() + "/A";
+//FIXME:
+//FIXME: List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
+//FIXME: ranges.add(new RevisionRange(new Revision.Number(2),
+//FIXME: new Revision.Number(4)));
+//FIXME: client.merge(modUrl, Revision.HEAD, ranges,
+//FIXME: branchPath, true, Depth.infinity, false, false, true);
+//FIXME:
+//FIXME: // commit the changes so that we can verify merge
+//FIXME: addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
+//FIXME: "branches/A", NodeKind.dir,
+//FIXME: CommitItemStateFlags.PropMods);
+//FIXME: checkCommitRevision(thisTest, "wrong revision number from commit", 5,
+//FIXME: thisTest.getWCPathSet(), "log msg", Depth.infinity,
+//FIXME: false, false, null, null);
+//FIXME:
+//FIXME: // Test retrieval of mergeinfo from a WC path.
+//FIXME: String targetPath =
+//FIXME: new File(thisTest.getWCPath(), "branches/A").getPath();
+//FIXME: final String mergeSrc = thisTest.getUrl() + "/A";
+//FIXME: acquireMergeinfoAndAssertEquals(2, 4, 0, 0, targetPath, mergeSrc);
+//FIXME: }
/**
* Setup a test with a WC. In the repository, create a
@@ -2648,7 +2648,7 @@
}
/**
- * Test the {@link SVNClientInterface.diff()} APIs.
+ * Test the {@link ISVNClient.diff()} APIs.
* @since 1.5
*/
public void testDiff()
@@ -3061,7 +3061,7 @@
}
client.move(srcPaths,
new File(thisTest.getWorkingCopy(), "A/B/F").getPath(),
- false, true, false, null, null, null);
+ false, true, false, false, false, null, null, null);
// Commit the changes, and check the state of the WC.
checkCommitRevision(thisTest,
@@ -3102,16 +3102,21 @@
ConflictDescriptor conflict = conflicts.iterator().next();
assertNotNull("Conflict should not be null", conflict);
+ // 1.8 assertNotNull("Repository UUID must be set", conflict.getSrcLeftVersion().getReposUUID());
assertEquals(conflict.getSrcLeftVersion().getNodeKind(), NodeKind.file);
assertEquals(conflict.getSrcLeftVersion().getReposURL() + "/" +
conflict.getSrcLeftVersion().getPathInRepos(), tcTest.getUrl() + "/A/B/E/alpha");
assertEquals(conflict.getSrcLeftVersion().getPegRevision(), 1L);
- assertEquals(conflict.getSrcRightVersion().getNodeKind(), NodeKind.none);
- assertEquals(conflict.getSrcRightVersion().getReposURL(), tcTest.getUrl().toString());
- assertEquals(conflict.getSrcRightVersion().getPegRevision(), 2L);
-
+ if (conflict.getSrcRightVersion() != null)
+ {
+ assertEquals(conflict.getSrcLeftVersion().getReposUUID(),
+ conflict.getSrcRightVersion().getReposUUID());
+ assertEquals(conflict.getSrcRightVersion().getNodeKind(), NodeKind.none);
+ assertEquals(conflict.getSrcRightVersion().getReposURL(), tcTest.getUrl().toString());
+ assertEquals(conflict.getSrcRightVersion().getPegRevision(), 2L);
+ }
}
/**
@@ -3146,12 +3151,12 @@
// check the status of the working copy
thisTest.checkStatus();
-
+
// now edit the propval directly in the repository
long baseRev = 2L;
client.propertySetRemote(thisTest.getUrl()+"/A/D/G/rho", baseRev, PROP, NEWVALUE,
new ConstMsg("edit prop"), false, null, null);
-
+
// update the WC and verify that the property was changed
client.update(thisTest.getWCPathSet(), Revision.HEAD, Depth.infinity, false, false,
false, false);
diff --git a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java
index 7779a60..0d01e8b 100644
--- a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java
+++ b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java
@@ -92,6 +92,7 @@
{
// Add default test suites.
suite.addTestSuite(SVNReposTests.class);
+ suite.addTestSuite(SVNRemoteTests.class);
suite.addTestSuite(BasicTests.class);
}
else
diff --git a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
new file mode 100644
index 0000000..509baad
--- /dev/null
+++ b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
@@ -0,0 +1,251 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+package org.apache.subversion.javahl;
+
+import org.apache.subversion.javahl.*;
+import org.apache.subversion.javahl.remote.*;
+import org.apache.subversion.javahl.types.*;
+
+import java.util.Date;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashSet;
+import java.io.IOException;
+
+/**
+ * This class is used for testing the SVNReposAccess class
+ *
+ * More methodes for testing are still needed
+ */
+public class SVNRemoteTests extends SVNTests
+{
+ protected OneTest thisTest;
+
+ public SVNRemoteTests()
+ {
+ }
+
+ public SVNRemoteTests(String name)
+ {
+ super(name);
+ }
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ thisTest = new OneTest();
+ }
+
+ public static ISVNRemote getSession(String url, String configDirectory)
+ {
+ try
+ {
+ RemoteFactory factory = new RemoteFactory();
+ factory.setConfigDirectory(configDirectory);
+ factory.setUsername(USERNAME);
+ factory.setPassword(PASSWORD);
+ factory.setPrompt(new DefaultPromptUserPassword());
+
+ ISVNRemote raSession = factory.openRemoteSession(url);
+ assertNotNull("Null session was returned by factory", raSession);
+ return raSession;
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private ISVNRemote getSession()
+ {
+ return getSession(getTestRepoUrl(), super.conf.getAbsolutePath());
+ }
+
+ /**
+ * Test the basic SVNAdmin.create functionality
+ * @throws SubversionException
+ */
+ public void testCreate()
+ throws SubversionException, IOException
+ {
+ assertTrue("repository exists", thisTest.getRepository().exists());
+ }
+
+ public void testGetSession_ConfigConstructor() throws Exception
+ {
+ ISVNRemote session;
+ try
+ {
+ session = new RemoteFactory(
+ super.conf.getAbsolutePath(),
+ USERNAME, PASSWORD,
+ new DefaultPromptUserPassword(), null)
+ .openRemoteSession(getTestRepoUrl());
+ }
+ catch (ClientException ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ assertNotNull("Null session was returned by factory", session);
+ assertEquals(getTestRepoUrl(), session.getSessionUrl());
+ }
+
+ public void testDispose() throws Exception
+ {
+ ISVNRemote session = getSession();
+ session.dispose();
+ }
+
+ public void testDatedRev() throws Exception
+ {
+ ISVNRemote session = getSession();
+
+ long revision = session.getRevisionByDate(new Date());
+ assertEquals(revision, 1);
+ }
+
+ public void testGetLocks() throws Exception
+ {
+ ISVNRemote session = getSession();
+
+ Set<String> iotaPathSet = new HashSet<String>(1);
+ String iotaPath = thisTest.getWCPath() + "/iota";
+ iotaPathSet.add(iotaPath);
+
+ client.lock(iotaPathSet, "foo", false);
+
+ Map<String, Lock> locks = session.getLocks("iota", Depth.infinity);
+
+ assertEquals(locks.size(), 1);
+ Lock lock = locks.get("/iota");
+ assertNotNull(lock);
+ assertEquals(lock.getOwner(), "jrandom");
+ }
+
+ public void testCheckPath() throws Exception
+ {
+ ISVNRemote session = getSession();
+
+ NodeKind kind = session.checkPath("iota", 1);
+ assertEquals(NodeKind.file, kind);
+
+ kind = session.checkPath("iota", 0);
+ assertEquals(NodeKind.none, kind);
+
+ kind = session.checkPath("A", 1);
+ assertEquals(NodeKind.dir, kind);
+ }
+
+ private String getTestRepoUrl()
+ {
+ return thisTest.getUrl().toASCIIString();
+ }
+
+ public void testGetLatestRevision() throws Exception
+ {
+ ISVNRemote session = getSession();
+ long revision = session.getLatestRevision();
+ assertEquals(revision, 1);
+ }
+
+ public void testGetUUID() throws Exception
+ {
+ ISVNRemote session = getSession();
+
+ /*
+ * Test UUID
+ * TODO: Test for actual UUID once test dump file has
+ * fixed UUID
+ */
+ assertNotNull(session.getReposUUID());
+ }
+
+ public void testGetUrl() throws Exception
+ {
+ ISVNRemote session = getSession();
+
+ assertEquals(getTestRepoUrl(), session.getSessionUrl());
+ }
+
+ public void testGetRootUrl() throws Exception
+ {
+ ISVNRemote session = getSession();
+ session.reparent(session.getSessionUrl() + "/A/B/E");
+ assertEquals(getTestRepoUrl(), session.getReposRootUrl());
+ }
+
+ public void testGetUrl_viaSVNClient() throws Exception
+ {
+ ISVNRemote session = client.openRemoteSession(getTestRepoUrl());
+
+ assertEquals(getTestRepoUrl(), session.getSessionUrl());
+ }
+
+ public void testGetUrl_viaSVNClientWorkingCopy() throws Exception
+ {
+ ISVNRemote session = client.openRemoteSession(thisTest.getWCPath());
+
+ assertEquals(getTestRepoUrl(), session.getSessionUrl());
+ }
+
+ public void testReparent() throws Exception
+ {
+ ISVNRemote session = getSession();
+ String newUrl = session.getSessionUrl() + "/A/B/E";
+ session.reparent(newUrl);
+ assertEquals(newUrl, session.getSessionUrl());
+ }
+
+ public void testGetRelativePath() throws Exception
+ {
+ ISVNRemote session = getSession();
+ String baseUrl = session.getSessionUrl() + "/A/B/E";
+ session.reparent(baseUrl);
+
+ String relPath = session.getSessionRelativePath(baseUrl + "/alpha");
+ assertEquals("alpha", relPath);
+
+ relPath = session.getReposRelativePath(baseUrl + "/beta");
+ assertEquals("A/B/E/beta", relPath);
+ }
+
+ public void testGetCommitEditor() throws Exception
+ {
+ ISVNRemote session = getSession();
+ session.getCommitEditor();
+ }
+
+ public void testDisposeCommitEditor() throws Exception
+ {
+ ISVNRemote session = getSession();
+ session.getCommitEditor();
+ session.dispose();
+ }
+
+ public void testHasCapability() throws Exception
+ {
+ ISVNRemote session = getSession();
+ assert(session.hasCapability(ISVNRemote.Capability.depth));
+ }
+}
diff --git a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNReposTests.java b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNReposTests.java
index eaa1ebd..ed3a2a6 100644
--- a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNReposTests.java
+++ b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNReposTests.java
@@ -34,7 +34,7 @@
import java.util.Map;
/**
- * This class is used for testing the SVNAdmin class
+ * This class is used for testing the ISVNRepos interface
*
* More methodes for testing are still needed
*/
@@ -50,7 +50,7 @@
}
/**
- * Test the basic SVNAdmin.create functionality
+ * Test the basic ISVNRepos.create functionality
* @throws SubversionException
*/
public void testCreate()
@@ -103,7 +103,7 @@
public void testLoadRepo()
throws SubversionException, IOException
{
- /* Make sure SVNAdmin.load() works, with a repo dump file known
+ /* Make sure ISVNRepos.load() works, with a repo dump file known
* to provoke bug 2979
*/
// makes repos with nothing in it
diff --git a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java
index 5e4f32e..dd79925 100644
--- a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java
+++ b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java
@@ -145,6 +145,16 @@
protected static String rootUrl;
/**
+ * Username to use in tests
+ */
+ protected final static String USERNAME = "jrandom";
+
+ /**
+ * Password to use in tests
+ */
+ protected final static String PASSWORD = "rayjandom";
+
+ /**
* Create a JUnit <code>TestCase</code> instance.
*/
protected SVNTests()
@@ -276,7 +286,7 @@
this.client = new SVNClient();
this.client.notification2(new MyNotifier());
this.client.setPrompt(new DefaultPromptUserPassword());
- this.client.username("jrandom");
+ this.client.username(USERNAME);
this.client.setProgressCallback(new DefaultProgressListener());
this.client.setConfigDirectory(this.conf.getAbsolutePath());
this.expectedCommitItems = new HashMap<String, MyCommitItem>();
@@ -284,7 +294,7 @@
/**
* the default prompt : never prompts the user, provides defaults answers
*/
- private static class DefaultPromptUserPassword implements UserPasswordCallback
+ protected static class DefaultPromptUserPassword implements UserPasswordCallback
{
public int askTrustSSLServer(String info, boolean allowPermanently)
@@ -304,12 +314,12 @@
public String getPassword()
{
- return "rayjandom";
+ return PASSWORD;
}
public String getUsername()
{
- return "jrandom";
+ return USERNAME;
}
public boolean prompt(String realm, String username)
diff --git a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java
index 852e087..3407b96 100644
--- a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java
+++ b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java
@@ -2176,6 +2176,7 @@
* are no revisions to return.
* @since 1.5
*/
+ @SuppressWarnings("unchecked")
private long[] getMergeinfoRevisions(int kind, String pathOrUrl,
Revision pegRevision,
String mergeSourceUrl,
@@ -3039,10 +3040,12 @@
conflict.getSrcLeftVersion().getPathInRepos(), tcTest.getUrl() + "/A/B/E/alpha");
assertEquals(conflict.getSrcLeftVersion().getPegRevision(), 1L);
- assertEquals(conflict.getSrcRightVersion().getNodeKind(), NodeKind.none);
- assertEquals(conflict.getSrcRightVersion().getReposURL(), tcTest.getUrl());
- assertEquals(conflict.getSrcRightVersion().getPegRevision(), 2L);
-
+ if (conflict.getSrcRightVersion() != null)
+ {
+ assertEquals(conflict.getSrcRightVersion().getNodeKind(), NodeKind.none);
+ assertEquals(conflict.getSrcRightVersion().getReposURL(), tcTest.getUrl());
+ assertEquals(conflict.getSrcRightVersion().getPegRevision(), 2L);
+ }
}
/**
@@ -3240,6 +3243,7 @@
* @throws Throwable
* @since 1.5
*/
+ @SuppressWarnings("unchecked")
public void testCommitRevprops() throws Throwable
{
@@ -3346,6 +3350,7 @@
// change made to this class.
private static final long serialVersionUID = 1L;
+ @SuppressWarnings("unchecked")
public void onSummary(DiffSummary descriptor)
{
super.put(descriptor.getPath(), descriptor);
@@ -3355,6 +3360,7 @@
private class MyChangelistCallback extends HashMap
implements ChangelistCallback
{
+ @SuppressWarnings("unchecked")
public void doChangelist(String path, String changelist)
{
if (super.containsKey(path))
diff --git a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/RunTests.java b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/RunTests.java
index 779b782..606142c 100644
--- a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/RunTests.java
+++ b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/RunTests.java
@@ -47,6 +47,7 @@
*
* @return The complete test suite.
*/
+ @SuppressWarnings("unchecked")
public static TestSuite suite()
{
TestSuite suite = new SVNTestSuite();
@@ -75,9 +76,8 @@
Constructor ctor =
clazz.getDeclaredConstructor(argTypes);
methodName = methodName.substring(i + 1);
- String[] args = { methodName };
testCases[testCaseIndex++] =
- (TestCase) ctor.newInstance(args);
+ (TestCase) ctor.newInstance(methodName);
}
catch (Exception e)
{
diff --git a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/SVNTests.java b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/SVNTests.java
index 8b7d6ff..1e858c8 100644
--- a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/SVNTests.java
+++ b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/SVNTests.java
@@ -438,6 +438,7 @@
* @param stateFlags expected commit state flags
* (see CommitItemStateFlags)
*/
+ @SuppressWarnings("unchecked")
protected void addExpectedCommitItem(String workingCopyPath,
String baseUrl,
String itemPath,
diff --git a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/WC.java b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/WC.java
index 4f1f389..6f68ae9 100644
--- a/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/WC.java
+++ b/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/WC.java
@@ -627,6 +627,7 @@
* @param path the path of the item.
* @param content the content of the item. A null signals a directory.
*/
+ @SuppressWarnings("unchecked")
private Item(String path, String content)
{
myPath = path;
@@ -639,6 +640,7 @@
* @param source the copy source.
* @param owner the WC of the copy
*/
+ @SuppressWarnings("unchecked")
private Item(Item source, WC owner)
{
myPath = source.myPath;