~svn/ubuntu/raring/subversion/ppa

« back to all changes in this revision

Viewing changes to subversion/bindings/java/javahl/native/SVNAdmin.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-12-05 01:26:14 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051205012614-qom4xfypgtsqc2xq
Tags: 1.2.3dfsg1-3ubuntu1
Merge with the final Debian release of 1.2.3dfsg1-3, bringing in
fixes to the clean target, better documentation of the libdb4.3
upgrade and build fixes to work with swig1.3_1.3.27.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @copyright
 
3
 * ====================================================================
 
4
 * Copyright (c) 2003-2004 CollabNet.  All rights reserved.
 
5
 *
 
6
 * This software is licensed as described in the file COPYING, which
 
7
 * you should have received as part of this distribution.  The terms
 
8
 * are also available at http://subversion.tigris.org/license-1.html.
 
9
 * If newer versions of this license are posted there, you may use a
 
10
 * newer version instead, at your option.
 
11
 *
 
12
 * This software consists of voluntary contributions made by many
 
13
 * individuals.  For exact contribution history, see the revision
 
14
 * history and logs, available at http://subversion.tigris.org/.
 
15
 * ====================================================================
 
16
 * @endcopyright
 
17
 *
 
18
 * @file SVNAdmin.cpp
 
19
 * @brief Implementation of the class SVNAdmin
 
20
 */
 
21
 
 
22
#include "SVNAdmin.h"
 
23
#include "SVNClient.h"
 
24
#include "JNIUtil.h"
 
25
#include "svn_repos.h"
 
26
#include "svn_config.h"
 
27
#include "svn_pools.h"
 
28
#include "svn_path.h"
 
29
#include "svn_utf.h"
 
30
#include "svn_private_config.h"
 
31
//////////////////////////////////////////////////////////////////////
 
32
// Construction/Destruction
 
33
//////////////////////////////////////////////////////////////////////
 
34
 
 
35
SVNAdmin::SVNAdmin()
 
36
{
 
37
 
 
38
}
 
39
 
 
40
SVNAdmin::~SVNAdmin()
 
41
{
 
42
 
 
43
}
 
44
jlong SVNAdmin::getCppAddr()
 
45
{
 
46
    return reinterpret_cast<jlong>(this);
 
47
}
 
48
SVNAdmin * SVNAdmin::getCppObject(jobject jthis)
 
49
{
 
50
    static jfieldID fid = 0;
 
51
    JNIEnv *env = JNIUtil::getEnv();
 
52
    if(fid == 0)
 
53
    {
 
54
        jclass clazz = env->FindClass(JAVA_PACKAGE"/SVNAdmin");
 
55
        if(JNIUtil::isJavaExceptionThrown())
 
56
        {
 
57
            return NULL;
 
58
        }
 
59
        fid = env->GetFieldID(clazz, "cppAddr", "J");
 
60
        if(JNIUtil::isJavaExceptionThrown())
 
61
        {
 
62
            return NULL;
 
63
        }
 
64
    }
 
65
 
 
66
    jlong cppAddr = env->GetLongField(jthis, fid);
 
67
    if(JNIUtil::isJavaExceptionThrown())
 
68
    {
 
69
        return NULL;
 
70
    }
 
71
    return reinterpret_cast<SVNAdmin*>(cppAddr);
 
72
 
 
73
}
 
74
 
 
75
void SVNAdmin::dispose(jobject jthis)
 
76
{
 
77
    delete this;
 
78
    static jfieldID fid = 0;
 
79
    JNIEnv *env = JNIUtil::getEnv();
 
80
    if(fid == 0)
 
81
    {
 
82
        jclass clazz = env->FindClass(JAVA_PACKAGE"/SVNAdmin");
 
83
        if(JNIUtil::isJavaExceptionThrown())
 
84
        {
 
85
            return;
 
86
        }
 
87
        fid = env->GetFieldID(clazz, "cppAddr", "J");
 
88
        if(JNIUtil::isJavaExceptionThrown())
 
89
        {
 
90
            return;
 
91
        }
 
92
    }
 
93
 
 
94
    env->SetLongField(jthis, fid, 0);
 
95
    if(JNIUtil::isJavaExceptionThrown())
 
96
    {
 
97
        return;
 
98
    }
 
99
}
 
100
 
 
101
void SVNAdmin::finalize()
 
102
{
 
103
    JNIUtil::putFinalizedClient(this);
 
104
}
 
105
 
 
106
void SVNAdmin::create(const char *path, bool disableFsyncCommits,
 
107
                      bool keepLogs, const char *configPath,
 
108
                      const char *fstype)
 
109
{
 
110
    Pool requestPool;
 
111
    if(path == NULL)
 
112
    {
 
113
        JNIUtil::throwNullPointerException("path");
 
114
        return;
 
115
    }
 
116
    path = svn_path_internal_style(path, requestPool.pool());
 
117
    if(configPath != NULL)
 
118
        configPath = svn_path_internal_style(configPath, requestPool.pool());
 
119
    svn_repos_t *repos;
 
120
    apr_hash_t *config;
 
121
    apr_hash_t *fs_config = apr_hash_make (requestPool.pool());;
 
122
 
 
123
    apr_hash_set (fs_config, SVN_FS_CONFIG_BDB_TXN_NOSYNC,
 
124
                  APR_HASH_KEY_STRING,
 
125
                  (disableFsyncCommits? "1" : "0"));
 
126
 
 
127
    apr_hash_set (fs_config, SVN_FS_CONFIG_BDB_LOG_AUTOREMOVE,
 
128
                  APR_HASH_KEY_STRING,
 
129
                  (keepLogs ? "0" : "1"));
 
130
    apr_hash_set (fs_config, SVN_FS_CONFIG_FS_TYPE,
 
131
                  APR_HASH_KEY_STRING,
 
132
                  fstype);
 
133
 
 
134
    svn_error_t *err = 
 
135
        svn_config_get_config (&config, configPath, requestPool.pool());
 
136
    if(err != SVN_NO_ERROR)
 
137
    {
 
138
        JNIUtil::handleSVNError(err);
 
139
        return;
 
140
    }
 
141
    err = svn_repos_create (&repos, path,
 
142
                            NULL, NULL,
 
143
                            config, fs_config, requestPool.pool());
 
144
 
 
145
    if(err != SVN_NO_ERROR)
 
146
    {
 
147
        JNIUtil::handleSVNError(err);
 
148
        return;
 
149
    }
 
150
}
 
151
 
 
152
void SVNAdmin::deltify(const char *path, Revision &revStart, Revision &revEnd)
 
153
{
 
154
    Pool requestPool;
 
155
    if(path == NULL)
 
156
    {
 
157
        JNIUtil::throwNullPointerException("path");
 
158
        return;
 
159
    }
 
160
    path = svn_path_internal_style(path, requestPool.pool());
 
161
    svn_repos_t *repos;
 
162
    svn_fs_t *fs;
 
163
    svn_revnum_t start = SVN_INVALID_REVNUM, end = SVN_INVALID_REVNUM;
 
164
    svn_revnum_t youngest, revision;
 
165
    apr_pool_t *revisionPool = svn_pool_create (requestPool.pool());
 
166
 
 
167
    svn_error_t *err = svn_repos_open (&repos, path, requestPool.pool());
 
168
    if(err != SVN_NO_ERROR)
 
169
    {
 
170
        JNIUtil::handleSVNError(err);
 
171
        return;
 
172
    }
 
173
    fs = svn_repos_fs (repos);
 
174
    err = svn_fs_youngest_rev (&youngest, fs, requestPool.pool());
 
175
    if(err != SVN_NO_ERROR)
 
176
    {
 
177
        JNIUtil::handleSVNError(err);
 
178
        return;
 
179
    }
 
180
 
 
181
    if(revStart.revision()->kind == svn_opt_revision_number)
 
182
    /* ### We only handle revision numbers right now, not dates. */
 
183
        start = revStart.revision()->value.number;
 
184
    else if (revStart.revision()->kind == svn_opt_revision_head)
 
185
        start = youngest;
 
186
    else
 
187
        start = SVN_INVALID_REVNUM;
 
188
 
 
189
    if (revEnd.revision()->kind == svn_opt_revision_number)
 
190
        end = revEnd.revision()->value.number;
 
191
    else if (revEnd.revision()->kind == svn_opt_revision_head)
 
192
        end = youngest;
 
193
    else
 
194
        end = SVN_INVALID_REVNUM;
 
195
 
 
196
    /* Fill in implied revisions if necessary. */
 
197
    if (start == SVN_INVALID_REVNUM)
 
198
        start = youngest;
 
199
    if (end == SVN_INVALID_REVNUM)
 
200
        end = start;
 
201
 
 
202
    if (start > end)
 
203
    {
 
204
        JNIUtil::handleSVNError( svn_error_create
 
205
           (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
 
206
           _("First revision cannot be higher than second")));
 
207
        return;
 
208
    }
 
209
    if ((start > youngest) || (end > youngest))
 
210
    {
 
211
        JNIUtil::handleSVNError(svn_error_createf
 
212
           (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
 
213
           _("Revisions must not be greater than the youngest revision (%"
 
214
           SVN_REVNUM_T_FMT ")"), youngest));
 
215
        return;
 
216
    }
 
217
 
 
218
    /* Loop over the requested revision range, performing the
 
219
       predecessor deltification on paths changed in each. */
 
220
    for (revision = start; revision <= end; revision++)
 
221
    {
 
222
        svn_pool_clear (revisionPool);
 
223
        err = svn_fs_deltify_revision (fs, revision, revisionPool);
 
224
        if(err != SVN_NO_ERROR)
 
225
        {
 
226
            JNIUtil::handleSVNError(err);
 
227
            return;
 
228
        }
 
229
    }
 
230
    svn_pool_destroy (revisionPool);
 
231
 
 
232
    return;
 
233
}
 
234
 
 
235
void SVNAdmin::dump(const char *path, Outputer &dataOut, Outputer &messageOut, 
 
236
                    Revision &revsionStart, Revision &revisionEnd, 
 
237
                    bool incremental)
 
238
{
 
239
    Pool requestPool;
 
240
    if(path == NULL)
 
241
    {
 
242
        JNIUtil::throwNullPointerException("path");
 
243
        return;
 
244
    }
 
245
    path = svn_path_internal_style(path, requestPool.pool());
 
246
    svn_repos_t *repos;
 
247
    svn_fs_t *fs;
 
248
    svn_revnum_t lower = SVN_INVALID_REVNUM, upper = SVN_INVALID_REVNUM;
 
249
    svn_revnum_t youngest;
 
250
 
 
251
    svn_error_t *err = svn_repos_open (&repos, path, requestPool.pool());
 
252
    if(err != SVN_NO_ERROR)
 
253
    {
 
254
        JNIUtil::handleSVNError(err);
 
255
        return;
 
256
    }
 
257
    fs = svn_repos_fs (repos);
 
258
    err = svn_fs_youngest_rev (&youngest, fs, requestPool.pool());
 
259
    if(err != SVN_NO_ERROR)
 
260
    {
 
261
        JNIUtil::handleSVNError(err);
 
262
        return;
 
263
    }
 
264
 
 
265
    /* ### We only handle revision numbers right now, not dates. */
 
266
    if (revsionStart.revision()->kind == svn_opt_revision_number)
 
267
        lower = revsionStart.revision()->value.number;
 
268
    else if (revsionStart.revision()->kind == svn_opt_revision_head)
 
269
        lower = youngest;
 
270
    else
 
271
        lower = SVN_INVALID_REVNUM;
 
272
 
 
273
    if (revisionEnd.revision()->kind == svn_opt_revision_number)
 
274
        upper = revisionEnd.revision()->value.number;
 
275
    else if (revisionEnd.revision()->kind == svn_opt_revision_head)
 
276
        upper = youngest;
 
277
    else
 
278
        upper = SVN_INVALID_REVNUM;
 
279
 
 
280
    /* Fill in implied revisions if necessary. */
 
281
    if (lower == SVN_INVALID_REVNUM)
 
282
    {
 
283
        lower = 0;
 
284
        upper = youngest;
 
285
    }
 
286
    else if (upper == SVN_INVALID_REVNUM)
 
287
    {
 
288
        upper = lower;
 
289
    }
 
290
 
 
291
    if (lower > upper)
 
292
    {
 
293
        JNIUtil::handleSVNError(svn_error_create
 
294
          (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
 
295
          _("First revision cannot be higher than second")));
 
296
        return;
 
297
    }
 
298
    if ((lower > youngest) || (upper > youngest))
 
299
    {
 
300
        JNIUtil::handleSVNError(svn_error_createf
 
301
          (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
 
302
          _("Revisions must not be greater than the youngest revision (%"
 
303
            SVN_REVNUM_T_FMT ")"), youngest));
 
304
        return;
 
305
    }
 
306
 
 
307
    err= svn_repos_dump_fs (repos, dataOut.getStream(requestPool),
 
308
                            messageOut.getStream(requestPool),
 
309
                            lower, upper, incremental,
 
310
                            NULL, NULL, requestPool.pool());
 
311
    if(err != SVN_NO_ERROR)
 
312
    {
 
313
        JNIUtil::handleSVNError(err);
 
314
        return;
 
315
    }
 
316
 
 
317
}
 
318
 
 
319
void SVNAdmin::hotcopy(const char *path, const char *targetPath, 
 
320
                       bool cleanLogs)
 
321
{
 
322
    Pool requestPool;
 
323
    if(path == NULL)
 
324
    {
 
325
        JNIUtil::throwNullPointerException("path");
 
326
        return;
 
327
    }
 
328
    if(targetPath == NULL)
 
329
    {
 
330
        JNIUtil::throwNullPointerException("targetPath");
 
331
        return;
 
332
    }
 
333
    path = svn_path_internal_style(path, requestPool.pool());
 
334
    targetPath = svn_path_internal_style(targetPath, requestPool.pool());
 
335
    svn_error_t *err = svn_repos_hotcopy (path,
 
336
                                          targetPath,
 
337
                                          cleanLogs,
 
338
                                          requestPool.pool());
 
339
    if(err != SVN_NO_ERROR)
 
340
    {
 
341
        JNIUtil::handleSVNError(err);
 
342
        return;
 
343
    }
 
344
 
 
345
}
 
346
static void
 
347
list_dblogs (const char *path, MessageReceiver &receiver, bool only_unused)
 
348
{
 
349
    Pool requestPool;
 
350
    if(path == NULL)
 
351
    {
 
352
        JNIUtil::throwNullPointerException("path");
 
353
        return;
 
354
    }
 
355
    path = svn_path_internal_style(path, requestPool.pool());
 
356
    apr_array_header_t *logfiles;
 
357
    int i;
 
358
    svn_error_t *err = svn_repos_db_logfiles (&logfiles,
 
359
                                              path,
 
360
                                              only_unused,
 
361
                                              requestPool.pool());
 
362
    if(err != SVN_NO_ERROR)
 
363
    {
 
364
        JNIUtil::handleSVNError(err);
 
365
        return;
 
366
    }
 
367
 
 
368
    /* Loop, printing log files.  We append the log paths to the
 
369
       repository path, making sure to return everything to the native
 
370
       style and encoding before printing. */
 
371
    for (i = 0; i < logfiles->nelts; i++)
 
372
    {
 
373
        const char *log_utf8;
 
374
        log_utf8 = svn_path_join (path,
 
375
                                  APR_ARRAY_IDX (logfiles, i, const char *),
 
376
                                  requestPool.pool());
 
377
        log_utf8 = svn_path_local_style (log_utf8, requestPool.pool());
 
378
        receiver.receiveMessage(log_utf8);
 
379
    }
 
380
}
 
381
 
 
382
void SVNAdmin::listDBLogs(const char *path, MessageReceiver &messageReceiver)
 
383
{
 
384
    list_dblogs(path, messageReceiver, false);
 
385
}
 
386
 
 
387
void SVNAdmin::listUnusedDBLogs(const char *path, MessageReceiver &messageReceiver)
 
388
{
 
389
    list_dblogs(path, messageReceiver, true);
 
390
}
 
391
 
 
392
void SVNAdmin::load(const char *path, Inputer &dataIn, Outputer &messageOut, bool ignoreUUID, bool forceUUID, const char *relativePath)
 
393
{
 
394
    Pool requestPool;
 
395
    if(path == NULL)
 
396
    {
 
397
        JNIUtil::throwNullPointerException("path");
 
398
        return;
 
399
    }
 
400
    path = svn_path_internal_style(path, requestPool.pool());
 
401
    svn_repos_t *repos;
 
402
    enum svn_repos_load_uuid uuid_action;
 
403
    if(ignoreUUID)
 
404
        uuid_action = svn_repos_load_uuid_ignore;
 
405
    else if(forceUUID)
 
406
        uuid_action = svn_repos_load_uuid_force;
 
407
    svn_error_t *err = svn_repos_open (&repos, path, requestPool.pool());
 
408
    if(err != SVN_NO_ERROR)
 
409
    {
 
410
        JNIUtil::handleSVNError(err);
 
411
        return;
 
412
    }
 
413
 
 
414
    err = svn_repos_load_fs (repos, dataIn.getStream(requestPool), 
 
415
                             messageOut.getStream(requestPool),
 
416
                             uuid_action, relativePath,
 
417
                             NULL, NULL, requestPool.pool());
 
418
 
 
419
    if(err != SVN_NO_ERROR)
 
420
    {
 
421
        JNIUtil::handleSVNError(err);
 
422
        return;
 
423
    }
 
424
 
 
425
}
 
426
 
 
427
void SVNAdmin::lstxns(const char *path, MessageReceiver &messageReceiver)
 
428
{
 
429
    Pool requestPool;
 
430
    if(path == NULL)
 
431
    {
 
432
        JNIUtil::throwNullPointerException("path");
 
433
        return;
 
434
    }
 
435
    path = svn_path_internal_style(path, requestPool.pool());
 
436
    svn_repos_t *repos;
 
437
    svn_fs_t *fs;
 
438
    apr_array_header_t *txns;
 
439
    int i;
 
440
 
 
441
    svn_error_t *err = svn_repos_open (&repos, path, requestPool.pool());
 
442
    if(err != SVN_NO_ERROR)
 
443
    {
 
444
        JNIUtil::handleSVNError(err);
 
445
        return;
 
446
    }
 
447
    fs = svn_repos_fs (repos);
 
448
    err = svn_fs_list_transactions (&txns, fs, requestPool.pool());
 
449
    if(err != SVN_NO_ERROR)
 
450
    {
 
451
        JNIUtil::handleSVNError(err);
 
452
        return;
 
453
    }
 
454
 
 
455
    /* Loop, printing revisions. */
 
456
    for (i = 0; i < txns->nelts; i++)
 
457
    {
 
458
        messageReceiver.receiveMessage(APR_ARRAY_IDX (txns, i, const char *));
 
459
    }
 
460
 
 
461
 
 
462
}
 
463
 
 
464
jlong SVNAdmin::recover(const char *path)
 
465
{
 
466
    Pool requestPool;
 
467
    if(path == NULL)
 
468
    {
 
469
        JNIUtil::throwNullPointerException("path");
 
470
        return -1;
 
471
    }
 
472
    path = svn_path_internal_style(path, requestPool.pool());
 
473
    svn_revnum_t youngest_rev;
 
474
    svn_repos_t *repos;
 
475
 
 
476
    svn_error_t *err = svn_repos_recover2 (path, FALSE, NULL, NULL,
 
477
                                           requestPool.pool());
 
478
    if(err != SVN_NO_ERROR)
 
479
    {
 
480
        JNIUtil::handleSVNError(err);
 
481
        return -1;
 
482
    }
 
483
 
 
484
    /* Since db transactions may have been replayed, it's nice to tell
 
485
       people what the latest revision is.  It also proves that the
 
486
       recovery actually worked. */
 
487
    err = svn_repos_open (&repos, path, requestPool.pool());
 
488
    if(err != SVN_NO_ERROR)
 
489
    {
 
490
        JNIUtil::handleSVNError(err);
 
491
        return -1;
 
492
    }
 
493
    err = svn_fs_youngest_rev (&youngest_rev, svn_repos_fs (repos), 
 
494
                               requestPool.pool());
 
495
    if(err != SVN_NO_ERROR)
 
496
    {
 
497
        JNIUtil::handleSVNError(err);
 
498
        return -1;
 
499
    }
 
500
    return youngest_rev;
 
501
}
 
502
 
 
503
void SVNAdmin::rmtxns(const char *path, Targets &transactions)
 
504
{
 
505
    Pool requestPool;
 
506
    if(path == NULL)
 
507
    {
 
508
        JNIUtil::throwNullPointerException("path");
 
509
        return;
 
510
    }
 
511
    path = svn_path_internal_style(path, requestPool.pool());
 
512
    svn_repos_t *repos;
 
513
    svn_fs_t *fs;
 
514
    svn_fs_txn_t *txn;
 
515
    const apr_array_header_t *args;
 
516
    int i;
 
517
    apr_pool_t *transactionPool = svn_pool_create (requestPool.pool());
 
518
 
 
519
    svn_error_t *err = svn_repos_open (&repos, path, requestPool.pool());
 
520
    if(err != SVN_NO_ERROR)
 
521
    {
 
522
        JNIUtil::handleSVNError(err);
 
523
        return;
 
524
    }
 
525
    fs = svn_repos_fs (repos);
 
526
 
 
527
    args = transactions.array(requestPool);
 
528
    /* All the rest of the arguments are transaction names. */
 
529
    for (i = 0; i < args->nelts; i++)
 
530
    {
 
531
        const char *txn_name = APR_ARRAY_IDX (args, i, const char *);
 
532
 
 
533
        /* Try to open the txn.  If that succeeds, try to abort it. */
 
534
        err = svn_fs_open_txn (&txn, fs, txn_name, transactionPool);
 
535
        if (! err)
 
536
            err = svn_fs_abort_txn (txn, transactionPool);
 
537
 
 
538
        /* If either the open or the abort of the txn fails because that
 
539
           transaction is dead, just try to purge the thing.  Else,
 
540
           there was either an error worth reporting, or not error at
 
541
           all.  */
 
542
        if (err && (err->apr_err == SVN_ERR_FS_TRANSACTION_DEAD))
 
543
        {
 
544
            svn_error_clear (err);
 
545
            err = svn_fs_purge_txn (fs, txn_name, transactionPool);
 
546
        }
 
547
 
 
548
        /* If we had a real from the txn open, abort, or purge, we clear
 
549
           that error and just report to the user that we had an issue
 
550
           with this particular txn. */
 
551
        if (err)
 
552
        {
 
553
            JNIUtil::handleSVNError(err);
 
554
            return;
 
555
        }
 
556
        svn_pool_clear (transactionPool);
 
557
    }
 
558
 
 
559
}
 
560
 
 
561
void SVNAdmin::setLog(const char *path, Revision &revision, 
 
562
                      const char *message, bool bypassHooks)
 
563
{
 
564
    Pool requestPool;
 
565
    if(path == NULL)
 
566
    {
 
567
        JNIUtil::throwNullPointerException("path");
 
568
        return;
 
569
    }
 
570
    if(message == NULL)
 
571
    {
 
572
        JNIUtil::throwNullPointerException("message");
 
573
        return;
 
574
    }
 
575
    path = svn_path_internal_style(path, requestPool.pool());
 
576
    svn_repos_t *repos;
 
577
    svn_string_t *log_contents = svn_string_create (message, 
 
578
                                                    requestPool.pool());
 
579
 
 
580
    if (revision.revision()->kind != svn_opt_revision_number)
 
581
    {
 
582
        JNIUtil::handleSVNError(
 
583
            svn_error_createf (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
 
584
                              _("Missing revision")));
 
585
        return;
 
586
    }
 
587
    else if (revision.revision()->kind != svn_opt_revision_unspecified)
 
588
    { 
 
589
        JNIUtil::handleSVNError(
 
590
            svn_error_createf (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
 
591
                              _("Only one revision allowed")));
 
592
      return;
 
593
    }
 
594
    /* Open the filesystem  */
 
595
    svn_error_t *err = svn_repos_open (&repos, path, requestPool.pool());
 
596
    if(err != SVN_NO_ERROR)
 
597
    {
 
598
        JNIUtil::handleSVNError(err);
 
599
        return;
 
600
    }
 
601
 
 
602
    /* If we are bypassing the hooks system, we just hit the filesystem
 
603
       directly. */
 
604
    if (bypassHooks)
 
605
    {
 
606
        svn_fs_t *fs = svn_repos_fs (repos);
 
607
        err = svn_fs_change_rev_prop
 
608
               (fs, revision.revision()->value.number,
 
609
                SVN_PROP_REVISION_LOG, log_contents, requestPool.pool());
 
610
    }
 
611
    else
 
612
    {
 
613
        err = svn_repos_fs_change_rev_prop
 
614
               (repos, revision.revision()->value.number,
 
615
                NULL, SVN_PROP_REVISION_LOG, log_contents, requestPool.pool());
 
616
    }
 
617
    if(err != SVN_NO_ERROR)
 
618
    {
 
619
        JNIUtil::handleSVNError(err);
 
620
        return;
 
621
    }
 
622
}
 
623
 
 
624
void SVNAdmin::verify(const char *path, Outputer &messageOut, 
 
625
                      Revision &revisionStart, Revision &revisionEnd)
 
626
{
 
627
    Pool requestPool;
 
628
    if(path == NULL)
 
629
    {
 
630
        JNIUtil::throwNullPointerException("path");
 
631
        return;
 
632
    }
 
633
    path = svn_path_internal_style(path, requestPool.pool());
 
634
    svn_repos_t *repos;
 
635
    svn_revnum_t youngest;
 
636
 
 
637
    /* This whole process is basically just a dump of the repository
 
638
       with no interest in the output. */
 
639
    svn_error_t *err = svn_repos_open (&repos, path, requestPool.pool());
 
640
    if(err != SVN_NO_ERROR)
 
641
    {
 
642
        JNIUtil::handleSVNError(err);
 
643
        return;
 
644
    }
 
645
    err = svn_fs_youngest_rev (&youngest, svn_repos_fs (repos), 
 
646
                               requestPool.pool());
 
647
    if(err != SVN_NO_ERROR)
 
648
    { 
 
649
        JNIUtil::handleSVNError(err);
 
650
        return;
 
651
    }
 
652
    err = svn_repos_dump_fs (repos, NULL, messageOut.getStream(requestPool),
 
653
                             0, youngest, FALSE, NULL, NULL, 
 
654
                             requestPool.pool());
 
655
    if(err != SVN_NO_ERROR)
 
656
    {
 
657
        JNIUtil::handleSVNError(err);
 
658
        return;
 
659
    }
 
660
}
 
661
 
 
662
jobjectArray SVNAdmin::lslocks(const char *path)
 
663
{
 
664
    Pool requestPool;
 
665
    if(path == NULL)
 
666
    {
 
667
        JNIUtil::throwNullPointerException("path");
 
668
        return NULL;
 
669
    }
 
670
    path = svn_path_internal_style(path, requestPool.pool());
 
671
    svn_repos_t *repos;
 
672
    svn_fs_t *fs;
 
673
    apr_hash_t *locks;
 
674
    apr_hash_index_t *hi;
 
675
 
 
676
    svn_error_t *err = svn_repos_open (&repos, path, requestPool.pool());
 
677
    if(err != SVN_NO_ERROR)
 
678
    {
 
679
        JNIUtil::handleSVNError(err);
 
680
        return NULL;
 
681
    }
 
682
    fs = svn_repos_fs (repos);
 
683
    /* Fetch all locks on or below the root directory. */
 
684
    err = svn_repos_fs_get_locks (&locks, repos, "/", NULL, NULL, 
 
685
        requestPool.pool());
 
686
    if(err != SVN_NO_ERROR)
 
687
    {
 
688
        JNIUtil::handleSVNError(err);
 
689
        return NULL;
 
690
    }
 
691
 
 
692
    int count = apr_hash_count (locks);
 
693
 
 
694
    JNIEnv *env = JNIUtil::getEnv();
 
695
    jclass clazz = env->FindClass(JAVA_PACKAGE"/Lock");
 
696
    if(JNIUtil::isJavaExceptionThrown())
 
697
    {
 
698
        return NULL;
 
699
    }
 
700
    jobjectArray ret = env->NewObjectArray(count, clazz, NULL);
 
701
    if(JNIUtil::isJavaExceptionThrown())
 
702
    {
 
703
        return NULL;
 
704
    }
 
705
    env->DeleteLocalRef(clazz);
 
706
    if(JNIUtil::isJavaExceptionThrown())
 
707
    {
 
708
        return NULL;
 
709
    }
 
710
    
 
711
    int i = 0;
 
712
    for (hi = apr_hash_first (requestPool.pool(), locks); hi; 
 
713
            hi = apr_hash_next (hi),i++)
 
714
    {
 
715
        const void *key;
 
716
        void *val;
 
717
        apr_hash_this (hi, &key, NULL, &val);
 
718
        svn_lock_t *lock = (svn_lock_t *)val;
 
719
        jobject jLock = SVNClient::createJavaLock(lock);
 
720
        env->SetObjectArrayElement(ret, i, jLock);
 
721
        if(JNIUtil::isJavaExceptionThrown())
 
722
        {
 
723
            return NULL;
 
724
        }
 
725
        env->DeleteLocalRef(jLock);
 
726
        if(JNIUtil::isJavaExceptionThrown())
 
727
        {
 
728
            return NULL;
 
729
        }
 
730
    }
 
731
  
 
732
    return ret;
 
733
}
 
734
void SVNAdmin::rmlocks(const char *path, Targets &locks)
 
735
{
 
736
    Pool requestPool;
 
737
    apr_pool_t *pool = requestPool.pool();
 
738
    if(path == NULL)
 
739
    {
 
740
        JNIUtil::throwNullPointerException("path");
 
741
        return;
 
742
    }
 
743
    path = svn_path_internal_style(path, requestPool.pool());
 
744
    svn_repos_t *repos;
 
745
    svn_fs_t *fs;
 
746
    svn_fs_access_t *access;
 
747
 
 
748
    svn_error_t *err = svn_repos_open (&repos, path, requestPool.pool());
 
749
    if(err != SVN_NO_ERROR)
 
750
    {
 
751
        JNIUtil::handleSVNError(err);
 
752
        return;
 
753
    }
 
754
    fs = svn_repos_fs (repos);
 
755
    const char *username;
 
756
  
 
757
    /* svn_fs_unlock() demands that some username be associated with the
 
758
       filesystem, so just use the UID of the person running 'svnadmin'.*/
 
759
    {
 
760
        apr_uid_t uid;
 
761
        apr_gid_t gid;
 
762
        char *un;
 
763
        if (apr_uid_current (&uid, &gid, pool) == APR_SUCCESS &&
 
764
            apr_uid_name_get (&un, uid, pool) == APR_SUCCESS)
 
765
        {
 
766
            err = svn_utf_cstring_to_utf8 (&username, un, pool);
 
767
            svn_error_clear (err);
 
768
            if (err)
 
769
                username = "administrator";
 
770
        }
 
771
    }
 
772
 
 
773
    /* Create an access context describing the current user. */
 
774
    err = svn_fs_create_access (&access, username, pool);
 
775
    if(err != SVN_NO_ERROR)
 
776
    {
 
777
        JNIUtil::handleSVNError(err);
 
778
        return;
 
779
    }
 
780
 
 
781
    /* Attach the access context to the filesystem. */
 
782
    err = svn_fs_set_access (fs, access);
 
783
    if(err != SVN_NO_ERROR)
 
784
    {
 
785
        JNIUtil::handleSVNError(err);
 
786
        return;
 
787
    }
 
788
 
 
789
    apr_pool_t *subpool = svn_pool_create (pool);
 
790
    const apr_array_header_t *args = locks.array(requestPool);
 
791
    for (int i = 0; i < args->nelts; i++)
 
792
    {
 
793
        const char *lock_path = APR_ARRAY_IDX (args, i, const char *);
 
794
        svn_lock_t *lock;
 
795
      
 
796
        /* Fetch the path's svn_lock_t. */
 
797
        err = svn_fs_get_lock (&lock, fs, lock_path, subpool);
 
798
        if (err)
 
799
            goto move_on;
 
800
        if (! lock)
 
801
        {
 
802
            continue;
 
803
        }
 
804
      
 
805
        /* Now forcibly destroy the lock. */
 
806
        err = svn_fs_unlock (fs, lock_path,
 
807
                             lock->token, 1 /* force */, subpool);
 
808
        if (err)
 
809
            goto move_on;
 
810
      
 
811
    move_on:      
 
812
        if (err)
 
813
        {
 
814
            svn_error_clear (err);
 
815
        }
 
816
            
 
817
        svn_pool_clear (subpool);
 
818
    }
 
819
 
 
820
    return;
 
821
}