62
70
#include "svn_diff.h"
63
71
#include "svn_config.h"
64
72
#include "svn_io.h"
65
74
#include "svn_dirent_uri.h"
66
75
#include "svn_path.h"
67
76
#include "svn_utf.h"
77
#include "private/svn_subr_private.h"
68
78
#include "svn_private_config.h"
69
#include "JNIStringHolder.h"
80
#include "ExternalItem.hpp"
81
#include "jniwrapper/jni_list.hpp"
82
#include "jniwrapper/jni_stack.hpp"
83
#include "jniwrapper/jni_string_map.hpp"
75
86
SVNClient::SVNClient(jobject jthis_in)
86
97
static jfieldID fid = 0;
87
98
jlong cppAddr = SVNBase::findCppAddrForJObject(jthis, &fid,
88
JAVA_PACKAGE"/SVNClient");
99
JAVAHL_CLASS("/SVNClient"));
89
100
return (cppAddr == 0 ? NULL : reinterpret_cast<SVNClient *>(cppAddr));
92
103
void SVNClient::dispose(jobject jthis)
94
105
static jfieldID fid = 0;
95
SVNBase::dispose(jthis, &fid, JAVA_PACKAGE"/SVNClient");
106
SVNBase::dispose(jthis, &fid, JAVAHL_CLASS("/SVNClient"));
98
109
jobject SVNClient::getVersionExtended(bool verbose)
100
111
JNIEnv *const env = JNIUtil::getEnv();
102
jclass clazz = env->FindClass(JAVA_PACKAGE"/types/VersionExtended");
113
jclass clazz = env->FindClass(JAVAHL_CLASS("/types/VersionExtended"));
103
114
if (JNIUtil::isJavaExceptionThrown())
186
197
SVNClient::status(const char *path, svn_depth_t depth,
187
bool onServer, bool getAll, bool noIgnore,
188
bool ignoreExternals, StringArray &changelists,
198
bool onServer, bool onDisk, bool getAll,
199
bool noIgnore, bool ignoreExternals,
200
bool depthAsSticky, StringArray &changelists,
189
201
StatusCallback *callback)
191
203
SVN::Pool subPool(pool);
205
217
rev.kind = svn_opt_revision_unspecified;
207
SVN_JNI_ERR(svn_client_status5(&youngest, ctx, checkedPath.c_str(),
210
getAll, onServer, noIgnore, ignoreExternals,
219
SVN_JNI_ERR(svn_client_status6(&youngest, ctx, checkedPath.c_str(),
221
getAll, onServer, onDisk,
222
noIgnore, ignoreExternals, depthAsSticky,
212
223
changelists.array(subPool),
213
224
StatusCallback::callback, callback,
214
225
subPool.getPool()), );
227
238
std::vector<RevisionRange>::const_iterator it;
228
239
for (it = revRanges.begin(); it != revRanges.end(); ++it)
230
if (it->toRange(subPool)->start.kind
231
== svn_opt_revision_unspecified
232
&& it->toRange(subPool)->end.kind
233
== svn_opt_revision_unspecified)
241
const svn_opt_revision_range_t *range = it->toRange(subPool);
243
if (range->start.kind == svn_opt_revision_unspecified
244
&& range->end.kind == svn_opt_revision_unspecified)
235
svn_opt_revision_range_t *range =
246
svn_opt_revision_range_t *full =
236
247
reinterpret_cast<svn_opt_revision_range_t *>
237
248
(apr_pcalloc(subPool.getPool(), sizeof(*range)));
238
range->start.kind = svn_opt_revision_number;
239
range->start.value.number = 1;
240
range->end.kind = svn_opt_revision_head;
249
full->start.kind = svn_opt_revision_number;
250
full->start.value.number = 1;
251
full->end.kind = svn_opt_revision_head;
252
full->end.value.number = 0;
253
APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) = full;
241
257
APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) = range;
245
APR_ARRAY_PUSH(ranges, const svn_opt_revision_range_t *) =
246
it->toRange(subPool);
248
259
if (JNIUtil::isExceptionThrown())
255
266
std::vector<RevisionRange> &logRanges,
256
267
bool stopOnCopy, bool discoverPaths,
257
268
bool includeMergedRevisions, StringArray &revProps,
258
long limit, LogMessageCallback *callback)
269
int limit, LogMessageCallback *callback)
260
271
SVN::Pool subPool(pool);
334
345
ctx, subPool.getPool()), );
337
void SVNClient::revert(const char *path, svn_depth_t depth,
338
StringArray &changelists)
348
void SVNClient::revert(StringArray &paths, svn_depth_t depth,
349
StringArray &changelists,
350
bool clear_changelists,
340
353
SVN::Pool subPool(pool);
342
SVN_JNI_NULL_PTR_EX(path, "path", );
344
355
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
348
Targets target(path, subPool);
349
const apr_array_header_t *targets = target.array(subPool);
350
SVN_JNI_ERR(target.error_occurred(), );
351
SVN_JNI_ERR(svn_client_revert2(targets, depth,
352
changelists.array(subPool), ctx,
353
subPool.getPool()), );
359
Targets targets(paths, subPool);
360
SVN_JNI_ERR(targets.error_occurred(), );
361
SVN_JNI_ERR(svn_client_revert3(targets.array(subPool), depth,
362
changelists.array(subPool),
365
ctx, subPool.getPool()), );
356
368
void SVNClient::add(const char *path,
418
430
void SVNClient::commit(Targets &targets, CommitMessage *message,
419
431
svn_depth_t depth, bool noUnlock, bool keepChangelist,
420
StringArray &changelists, RevpropTable &revprops,
432
StringArray &changelists, PropertyTable &revprops,
421
433
CommitCallback *callback)
423
435
SVN::Pool subPool(pool);
456
typedef Java::ImmutableList<JavaHL::ExternalItem> PinList;
457
typedef Java::ImmutableMap<PinList> PinMap;
459
struct PinListFunctor
461
explicit PinListFunctor(const Java::Env& env, SVN::Pool& pool, int refs_len)
463
m_refs(apr_array_make(pool.getPool(), refs_len,
464
sizeof(svn_wc_external_item2_t*)))
467
void operator()(const JavaHL::ExternalItem& item)
469
APR_ARRAY_PUSH(m_refs, svn_wc_external_item2_t*) =
470
item.get_external_item(m_pool);
474
apr_array_header_t *m_refs;
479
explicit PinMapFunctor(const Java::Env& env, SVN::Pool& pool)
482
m_pin_set(svn_hash__make(pool.getPool()))
485
void operator()(const std::string& path, const PinList& refs)
487
PinListFunctor lf(m_env, m_pool, refs.length());
489
const char* key = static_cast<const char*>(
490
apr_pmemdup(m_pool.getPool(), path.c_str(), path.size() + 1));
491
svn_hash_sets(m_pin_set, key, lf.m_refs);
494
const Java::Env& m_env;
496
apr_hash_t *m_pin_set;
499
apr_hash_t *get_externals_to_pin(jobject jexternalsToPin, SVN::Pool& pool)
501
if (!jexternalsToPin)
505
JNIEnv *jenv = env.get();
509
PinMap pin_map(env, jexternalsToPin);
510
PinMapFunctor mf(env, pool);
511
pin_map.for_each(mf);
514
SVN_JAVAHL_JNI_CATCH;
517
} // anonymous namespace
442
519
void SVNClient::copy(CopySources ©Sources, const char *destPath,
443
520
CommitMessage *message, bool copyAsChild,
444
521
bool makeParents, bool ignoreExternals,
445
RevpropTable &revprops, CommitCallback *callback)
523
bool pinExternals, jobject jexternalsToPin,
524
PropertyTable &revprops, CommitCallback *callback)
447
526
SVN::Pool subPool(pool);
449
528
apr_array_header_t *srcs = copySources.array(subPool);
452
JNIUtil::throwNativeException(JAVA_PACKAGE "/ClientException",
453
"Invalid copy sources");
529
SVN_JNI_NULL_PTR_EX(srcs, "sources", );
456
530
SVN_JNI_NULL_PTR_EX(destPath, "destPath", );
457
531
Path destinationPath(destPath, subPool);
458
532
SVN_JNI_ERR(destinationPath.error_occurred(), );
464
SVN_JNI_ERR(svn_client_copy6(srcs, destinationPath.c_str(),
465
copyAsChild, makeParents, ignoreExternals,
466
revprops.hash(subPool),
467
CommitCallback::callback, callback,
538
apr_hash_t *pin_set = get_externals_to_pin(jexternalsToPin, subPool);
539
if (!JNIUtil::isJavaExceptionThrown())
540
SVN_JNI_ERR(svn_client_copy7(srcs, destinationPath.c_str(),
541
copyAsChild, makeParents, ignoreExternals,
543
pinExternals, pin_set,
544
revprops.hash(subPool),
545
CommitCallback::callback, callback,
468
546
ctx, subPool.getPool()), );
471
549
void SVNClient::move(Targets &srcPaths, const char *destPath,
472
550
CommitMessage *message, bool force, bool moveAsChild,
473
551
bool makeParents, bool metadataOnly, bool allowMixRev,
474
RevpropTable &revprops, CommitCallback *callback)
552
PropertyTable &revprops, CommitCallback *callback)
476
554
SVN::Pool subPool(pool);
513
591
ctx, subPool.getPool()), );
516
void SVNClient::cleanup(const char *path)
594
void SVNClient::cleanup(const char *path,
596
bool fix_recorded_timestamps,
597
bool clear_dav_cache,
598
bool remove_unused_pristines,
599
bool include_externals)
518
601
SVN::Pool subPool(pool);
519
602
SVN_JNI_NULL_PTR_EX(path, "path", );
658
748
const char *path2, Revision &revision2,
659
749
const char *localPath, bool forceDelete, svn_depth_t depth,
660
750
bool ignoreMergeinfo, bool diffIgnoreAncestry,
661
bool dryRun, bool recordOnly)
751
bool dryRun, bool allowMixedRev, bool recordOnly)
663
753
SVN::Pool subPool(pool);
664
754
SVN_JNI_NULL_PTR_EX(path1, "path1", );
684
774
ignoreMergeinfo, diffIgnoreAncestry,
685
775
forceDelete, recordOnly, dryRun,
686
TRUE, NULL, ctx, subPool.getPool()), );
776
allowMixedRev, NULL, ctx,
777
subPool.getPool()), );
689
780
void SVNClient::merge(const char *path, Revision &pegRevision,
690
781
std::vector<RevisionRange> *rangesToMerge,
691
782
const char *localPath, bool forceDelete, svn_depth_t depth,
692
783
bool ignoreMergeinfo, bool diffIgnoreAncestry,
693
bool dryRun, bool recordOnly)
784
bool dryRun, bool allowMixedRev, bool recordOnly)
695
786
SVN::Pool subPool(pool);
696
787
SVN_JNI_NULL_PTR_EX(path, "path", );
719
810
ignoreMergeinfo, diffIgnoreAncestry,
720
811
forceDelete, recordOnly,
721
dryRun, TRUE, NULL, ctx,
812
dryRun, allowMixedRev, NULL, ctx,
722
813
subPool.getPool()), );
725
void SVNClient::mergeReintegrate(const char *path, Revision &pegRevision,
726
const char *localPath, bool dryRun)
728
SVN::Pool subPool(pool);
729
SVN_JNI_NULL_PTR_EX(path, "path", );
730
SVN_JNI_NULL_PTR_EX(localPath, "localPath", );
731
Path intLocalPath(localPath, subPool);
732
SVN_JNI_ERR(intLocalPath.error_occurred(), );
734
Path srcPath(path, subPool);
735
SVN_JNI_ERR(srcPath.error_occurred(), );
737
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
741
SVN_JNI_ERR(svn_client_merge_reintegrate(srcPath.c_str(),
742
pegRevision.revision(),
743
intLocalPath.c_str(),
745
subPool.getPool()), );
816
/* SVNClient::mergeReintegrate is implemented in deprecated.cpp. */
749
819
SVNClient::getMergeinfo(const char *target, Revision &pegRevision)
751
821
SVN::Pool subPool(pool);
752
JNIEnv *env = JNIUtil::getEnv();
754
822
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
766
834
if (mergeinfo == NULL)
769
// Transform mergeinfo into Java Mergeinfo object.
770
jclass clazz = env->FindClass(JAVA_PACKAGE "/types/Mergeinfo");
771
if (JNIUtil::isJavaExceptionThrown())
774
static jmethodID ctor = 0;
777
ctor = env->GetMethodID(clazz, "<init>", "()V");
778
if (JNIUtil::isJavaExceptionThrown())
782
static jmethodID addRevisions = 0;
783
if (addRevisions == 0)
785
addRevisions = env->GetMethodID(clazz, "addRevisions",
786
"(Ljava/lang/String;"
787
"Ljava/util/List;)V");
788
if (JNIUtil::isJavaExceptionThrown())
792
jobject jmergeinfo = env->NewObject(clazz, ctor);
793
if (JNIUtil::isJavaExceptionThrown())
796
apr_hash_index_t *hi;
797
for (hi = apr_hash_first(subPool.getPool(), mergeinfo);
799
hi = apr_hash_next(hi))
803
apr_hash_this(hi, &path, NULL, &val);
806
JNIUtil::makeJString(reinterpret_cast<const char *>(path));
808
CreateJ::RevisionRangeList(reinterpret_cast<svn_rangelist_t *>(val));
810
env->CallVoidMethod(jmergeinfo, addRevisions, jpath, jranges);
812
env->DeleteLocalRef(jranges);
813
env->DeleteLocalRef(jpath);
816
env->DeleteLocalRef(clazz);
836
return CreateJ::Mergeinfo(mergeinfo, subPool.getPool());
821
839
void SVNClient::getMergeinfoLog(int type, const char *pathOrURL,
1155
1173
subPool.getPool()), );
1158
void SVNClient::streamFileContent(const char *path, Revision &revision,
1159
Revision &pegRevision,
1160
OutputStream &outputStream)
1176
apr_hash_t *SVNClient::streamFileContent(const char *path,
1178
Revision &pegRevision,
1179
bool expand_keywords,
1181
OutputStream &outputStream)
1162
1183
SVN::Pool subPool(pool);
1163
SVN_JNI_NULL_PTR_EX(path, "path", );
1184
SVN_JNI_NULL_PTR_EX(path, "path", NULL);
1164
1185
Path intPath(path, subPool);
1165
SVN_JNI_ERR(intPath.error_occurred(), );
1186
SVN_JNI_ERR(intPath.error_occurred(), NULL);
1167
1188
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
1168
1189
if (ctx == NULL)
1171
SVN_JNI_ERR(svn_client_cat2(outputStream.getStream(subPool),
1172
intPath.c_str(), pegRevision.revision(),
1173
revision.revision(), ctx, subPool.getPool()),
1192
apr_hash_t *props = NULL;
1193
SVN_JNI_ERR(svn_client_cat3((return_props ? &props : NULL),
1194
outputStream.getStream(subPool),
1196
pegRevision.revision(), revision.revision(),
1197
expand_keywords, ctx,
1198
subPool.getPool(), subPool.getPool()),
1177
1203
jbyteArray SVNClient::revProperty(const char *path,
1239
1265
void SVNClient::blame(const char *path, Revision &pegRevision,
1240
1266
Revision &revisionStart, Revision &revisionEnd,
1241
1267
bool ignoreMimeType, bool includeMergedRevisions,
1242
BlameCallback *callback)
1268
BlameCallback *callback, DiffOptions const& options)
1244
1270
SVN::Pool subPool(pool);
1245
1271
SVN_JNI_NULL_PTR_EX(path, "path", );
1253
1279
SVN_JNI_ERR(svn_client_blame5(
1254
1280
intPath.c_str(), pegRevision.revision(), revisionStart.revision(),
1255
1281
revisionEnd.revision(),
1256
svn_diff_file_options_create(subPool.getPool()), ignoreMimeType,
1282
options.fileOptions(subPool), ignoreMimeType,
1257
1283
includeMergedRevisions, BlameCallback::callback, callback, ctx,
1258
1284
subPool.getPool()),
1290
1316
void SVNClient::getChangelists(const char *rootPath,
1291
StringArray &changelists,
1317
StringArray *changelists,
1292
1318
svn_depth_t depth,
1293
1319
ChangelistCallback *callback)
1295
1321
SVN::Pool subPool(pool);
1296
1322
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
1298
SVN_JNI_ERR(svn_client_get_changelists(rootPath,
1299
changelists.array(subPool),
1324
const apr_array_header_t *cl_array = (!changelists ? NULL
1325
: changelists->array(subPool));
1327
SVN_JNI_ERR(svn_client_get_changelists(rootPath, cl_array,
1300
1328
depth, ChangelistCallback::callback,
1301
1329
callback, ctx, subPool.getPool()),
1395
char *message = JNIUtil::getFormatBuffer();
1396
apr_snprintf(message, JNIUtil::formatBufferSize,
1424
apr_snprintf(buffer, sizeof(buffer),
1397
1425
_("'%s' not versioned, and not exported\n"), path);
1398
return JNIUtil::makeJString(message);
1426
return JNIUtil::makeJString(buffer);
1465
1493
&set_rev, ctx, subPool.getPool()),
1468
return CreateJ::PropertyMap(props);
1496
return CreateJ::PropertyMap(props, subPool.getPool());
1473
std::vector<info_entry> infoVect;
1478
SVNClient::info2(const char *path, Revision &revision, Revision &pegRevision,
1479
svn_depth_t depth, StringArray &changelists,
1480
InfoCallback *callback)
1500
SVNClient::info(const char *path,
1501
Revision &revision, Revision &pegRevision, svn_depth_t depth,
1502
svn_boolean_t fetchExcluded, svn_boolean_t fetchActualOnly,
1503
svn_boolean_t includeExternals,
1504
StringArray &changelists, InfoCallback *callback)
1482
1506
SVN_JNI_NULL_PTR_EX(path, "path", );
1489
1513
Path checkedPath(path, subPool);
1490
1514
SVN_JNI_ERR(checkedPath.error_occurred(), );
1492
SVN_JNI_ERR(svn_client_info3(checkedPath.c_str(),
1516
SVN_JNI_ERR(svn_client_info4(checkedPath.c_str(),
1493
1517
pegRevision.revision(),
1494
revision.revision(),
1518
revision.revision(), depth,
1519
fetchExcluded, fetchActualOnly,
1496
1521
changelists.array(subPool),
1497
1522
InfoCallback::callback, callback,
1498
1523
ctx, subPool.getPool()), );
1525
1550
ctx, subPool.getPool()), );
1553
void SVNClient::vacuum(const char *path,
1554
bool remove_unversioned_items,
1555
bool remove_ignored_items,
1556
bool fix_recorded_timestamps,
1557
bool remove_unused_pristines,
1558
bool include_externals)
1560
SVN_JNI_NULL_PTR_EX(path, "path", );
1562
SVN::Pool subPool(pool);
1563
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
1567
SVN_JNI_ERR(svn_client_vacuum(path,
1568
remove_unversioned_items,
1569
remove_ignored_items,
1570
fix_recorded_timestamps,
1571
remove_unused_pristines,
1573
ctx, subPool.getPool()), );
1577
SVNClient::openRemoteSession(const char* path, int retryAttempts)
1579
static const svn_opt_revision_t HEAD = { svn_opt_revision_head, {0}};
1580
static const svn_opt_revision_t NONE = { svn_opt_revision_unspecified, {0}};
1582
SVN_JNI_NULL_PTR_EX(path, "path", NULL);
1584
SVN::Pool subPool(pool);
1585
svn_client_ctx_t *ctx = context.getContext(NULL, subPool);
1589
Path checkedPath(path, subPool);
1590
SVN_JNI_ERR(checkedPath.error_occurred(), NULL);
1596
static svn_error_t *callback(void *baton,
1598
const svn_client_info2_t *info,
1601
PathInfo* const pi = static_cast<PathInfo*>(baton);
1602
pi->url = info->URL;
1603
pi->uuid = info->repos_UUID;
1604
return SVN_NO_ERROR;
1608
SVN_JNI_ERR(svn_client_info4(
1609
checkedPath.c_str(), &NONE,
1610
(svn_path_is_url(checkedPath.c_str()) ? &HEAD : &NONE),
1611
svn_depth_empty, FALSE, TRUE, FALSE, NULL,
1612
PathInfo::callback, &path_info,
1613
ctx, subPool.getPool()),
1616
/* Decouple the RemoteSession's context from SVNClient's context
1617
by creating a copy of the prompter here. */
1619
jobject jremoteSession = RemoteSession::open(
1620
retryAttempts, path_info.url.c_str(), path_info.uuid.c_str(),
1621
context.getConfigDirectory(),
1622
context.getUsername(), context.getPassword(),
1623
context.clonePrompter(), context.getSelf(),
1624
context.getConfigEventHandler(), context.getTunnelCallback());
1625
if (JNIUtil::isJavaExceptionThrown())
1626
jremoteSession = NULL;
1628
return jremoteSession;
1528
1631
ClientContext &
1529
1632
SVNClient::getClientContext()