~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/libsvn_ra_local/ra_plugin.c

  • Committer: Package Import Robot
  • Author(s): James McCoy, Peter Samuelson, James McCoy
  • Date: 2014-01-12 19:48:33 UTC
  • mfrom: (0.2.10)
  • Revision ID: package-import@ubuntu.com-20140112194833-w3axfwksn296jn5x
Tags: 1.8.5-1
[ Peter Samuelson ]
* New upstream release.  (Closes: #725787) Rediff patches:
  - Remove apr-abi1 (applied upstream), rename apr-abi2 to apr-abi
  - Remove loosen-sqlite-version-check (shouldn't be needed)
  - Remove java-osgi-metadata (applied upstream)
  - svnmucc prompts for a changelog if none is provided. (Closes: #507430)
  - Remove fix-bdb-version-detection, upstream uses "apu-config --dbm-libs"
  - Remove ruby-test-wc (applied upstream)
  - Fix “svn diff -r N file” when file has svn:mime-type set.
    (Closes: #734163)
  - Support specifying an encoding for mod_dav_svn's environment in which
    hooks are run.  (Closes: #601544)
  - Fix ordering of “svnadmin dump” paths with certain APR versions.
    (Closes: #687291)
  - Provide a better error message when authentication fails with an
    svn+ssh:// URL.  (Closes: #273874)
  - Updated Polish translations.  (Closes: #690815)

[ James McCoy ]
* Remove all traces of libneon, replaced by libserf.
* patches/sqlite_3.8.x_workaround: Upstream fix for wc-queries-test test
  failurse.
* Run configure with --with-apache-libexecdir, which allows removing part of
  patches/rpath.
* Re-enable auth-test as upstream has fixed the problem of picking up
  libraries from the environment rather than the build tree.
  (Closes: #654172)
* Point LD_LIBRARY_PATH at the built auth libraries when running the svn
  command during the build.  (Closes: #678224)
* Add a NEWS entry describing how to configure mod_dav_svn to understand
  UTF-8.  (Closes: #566148)
* Remove ancient transitional package, libsvn-ruby.
* Enable compatibility with Sqlite3 versions back to Wheezy.
* Enable hardening flags.  (Closes: #734918)
* patches/build-fixes: Enable verbose build logs.
* Build against the default ruby version.  (Closes: #722393)

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 */
23
23
 
24
24
#include "ra_local.h"
 
25
#include "svn_hash.h"
25
26
#include "svn_ra.h"
26
27
#include "svn_fs.h"
27
28
#include "svn_delta.h"
40
41
#include "private/svn_repos_private.h"
41
42
#include "private/svn_fspath.h"
42
43
#include "private/svn_atomic.h"
 
44
#include "private/svn_subr_private.h"
43
45
 
44
46
#define APR_WANT_STRFUNC
45
47
#include <apr_want.h>
70
72
}
71
73
 
72
74
 
73
 
/* Fetch a username for use with SESS, and store it in SESS->username. */
 
75
/* Fetch a username for use with SESSION, and store it in SESSION->username.
 
76
 *
 
77
 * Allocate the username in SESSION->pool.  Use SCRATCH_POOL for temporary
 
78
 * allocations. */
74
79
static svn_error_t *
75
80
get_username(svn_ra_session_t *session,
76
 
             apr_pool_t *pool)
 
81
             apr_pool_t *scratch_pool)
77
82
{
78
83
  svn_ra_local__session_baton_t *sess = session->priv;
79
 
  svn_auth_iterstate_t *iterstate;
80
 
  svn_fs_access_t *access_ctx;
81
84
 
82
85
  /* If we've already found the username don't ask for it again. */
83
86
  if (! sess->username)
88
91
        {
89
92
          void *creds;
90
93
          svn_auth_cred_username_t *username_creds;
 
94
          svn_auth_iterstate_t *iterstate;
 
95
 
91
96
          SVN_ERR(svn_auth_first_credentials(&creds, &iterstate,
92
97
                                             SVN_AUTH_CRED_USERNAME,
93
98
                                             sess->uuid, /* realmstring */
94
99
                                             sess->callbacks->auth_baton,
95
 
                                             pool));
 
100
                                             scratch_pool));
96
101
 
97
102
          /* No point in calling next_creds(), since that assumes that the
98
103
             first_creds() somehow failed to authenticate.  But there's no
103
108
            {
104
109
              sess->username = apr_pstrdup(session->pool,
105
110
                                           username_creds->username);
106
 
              svn_error_clear(svn_auth_save_credentials(iterstate, pool));
 
111
              svn_error_clear(svn_auth_save_credentials(iterstate,
 
112
                                                        scratch_pool));
107
113
            }
108
114
          else
109
115
            sess->username = "";
118
124
  */
119
125
  if (*sess->username)
120
126
    {
 
127
      svn_fs_access_t *access_ctx;
 
128
 
121
129
      SVN_ERR(svn_fs_create_access(&access_ctx, sess->username,
122
130
                                   session->pool));
123
131
      SVN_ERR(svn_fs_set_access(sess->fs, access_ctx));
141
149
  const char *memory_cache_size_str;
142
150
 
143
151
  if (config_hash)
144
 
    config = apr_hash_get(config_hash, SVN_CONFIG_CATEGORY_CONFIG,
145
 
                          APR_HASH_KEY_STRING);
 
152
    config = svn_hash_gets(config_hash, SVN_CONFIG_CATEGORY_CONFIG);
146
153
  svn_config_get(config, &memory_cache_size_str, SVN_CONFIG_SECTION_MISCELLANY,
147
154
                 SVN_CONFIG_OPTION_MEMORY_CACHE_SIZE, NULL);
148
155
  if (memory_cache_size_str)
153
160
      SVN_ERR(svn_error_quick_wrap(svn_cstring_atoui64(&memory_cache_size,
154
161
                                                       memory_cache_size_str),
155
162
                                   _("memory-cache-size invalid")));
156
 
      settings.cache_size = 1024 * 1024 * memory_cache_size; 
 
163
      settings.cache_size = 1024 * 1024 * memory_cache_size;
157
164
      svn_cache_config_set(&settings);
158
165
    }
159
166
 
220
227
                   apr_pool_t *pool)
221
228
{
222
229
  reporter_baton_t *rbaton = reporter_baton;
223
 
  const char *fs_path = NULL;
224
230
  const char *repos_url = rbaton->sess->repos_url;
 
231
  const char *relpath = svn_uri_skip_ancestor(repos_url, url, pool);
 
232
  const char *fs_path;
225
233
 
226
 
  if (!svn_uri__is_ancestor(repos_url, url))
 
234
  if (!relpath)
227
235
    return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
228
236
                             _("'%s'\n"
229
237
                               "is not the same repository as\n"
230
238
                               "'%s'"), url, rbaton->sess->repos_url);
231
239
 
232
 
  /* Skip the repos_url, but keep the last '/' to create an fspath */
233
 
  fs_path = svn_uri_skip_ancestor(repos_url, url, pool);
234
 
  if (fs_path[0] == '\0')
 
240
  /* Convert the relpath to an fspath */
 
241
  if (relpath[0] == '\0')
235
242
    fs_path = "/";
236
243
  else
237
 
    fs_path = apr_pstrcat(pool, "/", fs_path, (char *)NULL);
 
244
    fs_path = apr_pstrcat(pool, "/", relpath, (char *)NULL);
238
245
 
239
246
  return svn_repos_link_path3(rbaton->report_baton, path, fs_path, revision,
240
247
                              depth, start_empty, lock_token, pool);
269
276
};
270
277
 
271
278
 
 
279
/* ...
 
280
 *
 
281
 * Wrap a cancellation editor using SESSION's cancellation function around
 
282
 * the supplied EDITOR.  ### Some callers (via svn_ra_do_update2() etc.)
 
283
 * don't appear to know that we do this, and are supplying an editor that
 
284
 * they have already wrapped with the same cancellation editor, so it ends
 
285
 * up double-wrapped.
 
286
 *
 
287
 * Allocate @a *reporter and @a *report_baton in @a result_pool.  Use
 
288
 * @a scratch_pool for temporary allocations.
 
289
 */
272
290
static svn_error_t *
273
291
make_reporter(svn_ra_session_t *session,
274
292
              const svn_ra_reporter3_t **reporter,
282
300
              svn_boolean_t ignore_ancestry,
283
301
              const svn_delta_editor_t *editor,
284
302
              void *edit_baton,
285
 
              apr_pool_t *pool)
 
303
              apr_pool_t *result_pool,
 
304
              apr_pool_t *scratch_pool)
286
305
{
287
306
  svn_ra_local__session_baton_t *sess = session->priv;
288
307
  void *rbaton;
290
309
 
291
310
  /* Get the HEAD revision if one is not supplied. */
292
311
  if (! SVN_IS_VALID_REVNUM(revision))
293
 
    SVN_ERR(svn_fs_youngest_rev(&revision, sess->fs, pool));
 
312
    SVN_ERR(svn_fs_youngest_rev(&revision, sess->fs, scratch_pool));
294
313
 
295
314
  /* If OTHER_URL was provided, validate it and convert it into a
296
315
     regular filesystem path. */
297
316
  if (other_url)
298
317
    {
299
318
      const char *other_relpath
300
 
        = svn_uri_skip_ancestor(sess->repos_url, other_url, pool);
 
319
        = svn_uri_skip_ancestor(sess->repos_url, other_url, scratch_pool);
301
320
 
302
321
      /* Sanity check:  the other_url better be in the same repository as
303
322
         the original session url! */
308
327
             "is not the same repository as\n"
309
328
             "'%s'"), other_url, sess->repos_url);
310
329
 
311
 
      other_fs_path = apr_pstrcat(pool, "/", other_relpath, (char *)NULL);
 
330
      other_fs_path = apr_pstrcat(scratch_pool, "/", other_relpath,
 
331
                                  (char *)NULL);
312
332
    }
313
333
 
314
334
  /* Pass back our reporter */
315
335
  *reporter = &ra_local_reporter;
316
336
 
317
 
  SVN_ERR(get_username(session, pool));
 
337
  SVN_ERR(get_username(session, scratch_pool));
318
338
 
319
339
  if (sess->callbacks)
320
340
    SVN_ERR(svn_delta_get_cancellation_editor(sess->callbacks->cancel_func,
323
343
                                              edit_baton,
324
344
                                              &editor,
325
345
                                              &edit_baton,
326
 
                                              pool));
 
346
                                              result_pool));
327
347
 
328
348
  /* Build a reporter baton. */
329
 
  SVN_ERR(svn_repos_begin_report2(&rbaton,
 
349
  SVN_ERR(svn_repos_begin_report3(&rbaton,
330
350
                                  revision,
331
351
                                  sess->repos,
332
352
                                  sess->fs_path->data,
340
360
                                  edit_baton,
341
361
                                  NULL,
342
362
                                  NULL,
343
 
                                  pool));
 
363
                                  1024 * 1024,  /* process-local transfers
 
364
                                                   should be fast */
 
365
                                  result_pool));
344
366
 
345
367
  /* Wrap the report baton given us by the repos layer with our own
346
368
     reporter baton. */
347
 
  *report_baton = make_reporter_baton(sess, rbaton, pool);
 
369
  *report_baton = make_reporter_baton(sess, rbaton, result_pool);
348
370
 
349
371
  return SVN_NO_ERROR;
350
372
}
358
380
{
359
381
  svn_fs_t *fs;                     /* the fs to deltify in */
360
382
  svn_repos_t *repos;               /* repos for unlocking */
361
 
  const char *fs_path;              /* fs-path part of split session URL */
 
383
  const char *fspath_base;          /* fs-path part of split session URL */
 
384
 
362
385
  apr_hash_t *lock_tokens;          /* tokens to unlock, if any */
363
 
  apr_pool_t *pool;                 /* pool for scratch work */
364
 
  svn_commit_callback2_t callback;  /* the original callback */
365
 
  void *callback_baton;             /* the original callback's baton */
 
386
 
 
387
  svn_commit_callback2_t commit_cb; /* the original callback */
 
388
  void *commit_baton;               /* the original callback's baton */
366
389
};
367
390
 
368
391
/* This implements 'svn_commit_callback_t'.  Its invokes the original
371
394
   BATON is 'struct deltify_etc_baton *'. */
372
395
static svn_error_t *
373
396
deltify_etc(const svn_commit_info_t *commit_info,
374
 
            void *baton, apr_pool_t *pool)
 
397
            void *baton,
 
398
            apr_pool_t *scratch_pool)
375
399
{
376
 
  struct deltify_etc_baton *db = baton;
 
400
  struct deltify_etc_baton *deb = baton;
377
401
  svn_error_t *err1 = SVN_NO_ERROR;
378
402
  svn_error_t *err2;
379
 
  apr_hash_index_t *hi;
380
 
  apr_pool_t *iterpool;
381
403
 
382
404
  /* Invoke the original callback first, in case someone's waiting to
383
405
     know the revision number so they can go off and annotate an
384
406
     issue or something. */
385
 
  if (db->callback)
386
 
    err1 = db->callback(commit_info, db->callback_baton, pool);
 
407
  if (deb->commit_cb)
 
408
    err1 = deb->commit_cb(commit_info, deb->commit_baton, scratch_pool);
387
409
 
388
410
  /* Maybe unlock the paths. */
389
 
  if (db->lock_tokens)
 
411
  if (deb->lock_tokens)
390
412
    {
391
 
      iterpool = svn_pool_create(db->pool);
392
 
      for (hi = apr_hash_first(db->pool, db->lock_tokens); hi;
 
413
      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
414
      apr_hash_index_t *hi;
 
415
 
 
416
      for (hi = apr_hash_first(scratch_pool, deb->lock_tokens); hi;
393
417
           hi = apr_hash_next(hi))
394
418
        {
395
 
          const void *rel_path;
396
 
          void *val;
397
 
          const char *abs_path, *token;
 
419
          const void *relpath = svn__apr_hash_index_key(hi);
 
420
          const char *token = svn__apr_hash_index_val(hi);
 
421
          const char *fspath;
398
422
 
399
423
          svn_pool_clear(iterpool);
400
 
          apr_hash_this(hi, &rel_path, NULL, &val);
401
 
          token = val;
402
 
          abs_path = svn_fspath__join(db->fs_path, rel_path, iterpool);
 
424
 
 
425
          fspath = svn_fspath__join(deb->fspath_base, relpath, iterpool);
 
426
 
403
427
          /* We may get errors here if the lock was broken or stolen
404
428
             after the commit succeeded.  This is fine and should be
405
429
             ignored. */
406
 
          svn_error_clear(svn_repos_fs_unlock(db->repos, abs_path, token,
 
430
          svn_error_clear(svn_repos_fs_unlock(deb->repos, fspath, token,
407
431
                                              FALSE, iterpool));
408
432
        }
 
433
 
409
434
      svn_pool_destroy(iterpool);
410
435
    }
411
436
 
412
437
  /* But, deltification shouldn't be stopped just because someone's
413
438
     random callback failed, so proceed unconditionally on to
414
439
     deltification. */
415
 
  err2 = svn_fs_deltify_revision(db->fs, commit_info->revision, db->pool);
416
 
 
417
 
  /* It's more interesting if the original callback failed, so let
418
 
     that one dominate. */
419
 
  if (err1)
 
440
  err2 = svn_fs_deltify_revision(deb->fs, commit_info->revision, scratch_pool);
 
441
 
 
442
  return svn_error_compose_create(err1, err2);
 
443
}
 
444
 
 
445
 
 
446
/* If LOCK_TOKENS is not NULL, then copy all tokens into the access context
 
447
   of FS. The tokens' paths will be prepended with FSPATH_BASE.
 
448
 
 
449
   ACCESS_POOL must match (or exceed) the lifetime of the access context
 
450
   that was associated with FS. Typically, this is the session pool.
 
451
 
 
452
   Temporary allocations are made in SCRATCH_POOL.  */
 
453
static svn_error_t *
 
454
apply_lock_tokens(svn_fs_t *fs,
 
455
                  const char *fspath_base,
 
456
                  apr_hash_t *lock_tokens,
 
457
                  apr_pool_t *access_pool,
 
458
                  apr_pool_t *scratch_pool)
 
459
{
 
460
  if (lock_tokens)
420
461
    {
421
 
      svn_error_clear(err2);
422
 
      return err1;
 
462
      svn_fs_access_t *access_ctx;
 
463
 
 
464
      SVN_ERR(svn_fs_get_access(&access_ctx, fs));
 
465
 
 
466
      /* If there is no access context, the filesystem will scream if a
 
467
         lock is needed.  */
 
468
      if (access_ctx)
 
469
        {
 
470
          apr_hash_index_t *hi;
 
471
 
 
472
          /* Note: we have no use for an iterpool here since the data
 
473
             within the loop is copied into ACCESS_POOL.  */
 
474
 
 
475
          for (hi = apr_hash_first(scratch_pool, lock_tokens); hi;
 
476
               hi = apr_hash_next(hi))
 
477
            {
 
478
              const void *relpath = svn__apr_hash_index_key(hi);
 
479
              const char *token = svn__apr_hash_index_val(hi);
 
480
              const char *fspath;
 
481
 
 
482
              /* The path needs to live as long as ACCESS_CTX.  */
 
483
              fspath = svn_fspath__join(fspath_base, relpath, access_pool);
 
484
 
 
485
              /* The token must live as long as ACCESS_CTX.  */
 
486
              token = apr_pstrdup(access_pool, token);
 
487
 
 
488
              SVN_ERR(svn_fs_access_add_lock_token2(access_ctx, fspath,
 
489
                                                    token));
 
490
            }
 
491
        }
423
492
    }
424
493
 
425
 
  return err2;
 
494
  return SVN_NO_ERROR;
426
495
}
427
496
 
 
497
 
428
498
/*----------------------------------------------------------------*/
429
499
 
430
500
/*** The RA vtable routines ***/
433
503
        N_("Module for accessing a repository on local disk.")
434
504
 
435
505
static const char *
436
 
svn_ra_local__get_description(void)
 
506
svn_ra_local__get_description(apr_pool_t *pool)
437
507
{
438
508
  return _(RA_LOCAL_DESCRIPTION);
439
509
}
532
602
                       apr_pool_t *pool)
533
603
{
534
604
  svn_ra_local__session_baton_t *sess = session->priv;
535
 
  const char *relpath = "";
 
605
  const char *relpath = svn_uri_skip_ancestor(sess->repos_url, url, pool);
536
606
 
537
607
  /* If the new URL isn't the same as our repository root URL, then
538
608
     let's ensure that it's some child of it. */
539
 
  if (strcmp(url, sess->repos_url) != 0)
540
 
    relpath = svn_uri__is_child(sess->repos_url, url, pool);
541
609
  if (! relpath)
542
610
    return svn_error_createf
543
611
      (SVN_ERR_RA_ILLEGAL_URL, NULL,
672
740
                                apr_pool_t *pool)
673
741
{
674
742
  svn_ra_local__session_baton_t *sess = session->priv;
675
 
  struct deltify_etc_baton *db = apr_palloc(pool, sizeof(*db));
676
 
  apr_hash_index_t *hi;
677
 
  svn_fs_access_t *fs_access;
 
743
  struct deltify_etc_baton *deb = apr_palloc(pool, sizeof(*deb));
678
744
 
679
 
  db->fs = sess->fs;
680
 
  db->repos = sess->repos;
681
 
  db->fs_path = sess->fs_path->data;
 
745
  /* Prepare the baton for deltify_etc()  */
 
746
  deb->fs = sess->fs;
 
747
  deb->repos = sess->repos;
 
748
  deb->fspath_base = sess->fs_path->data;
682
749
  if (! keep_locks)
683
 
    db->lock_tokens = lock_tokens;
 
750
    deb->lock_tokens = lock_tokens;
684
751
  else
685
 
    db->lock_tokens = NULL;
686
 
  db->pool = pool;
687
 
  db->callback = callback;
688
 
  db->callback_baton = callback_baton;
 
752
    deb->lock_tokens = NULL;
 
753
  deb->commit_cb = callback;
 
754
  deb->commit_baton = callback_baton;
689
755
 
690
756
  SVN_ERR(get_username(session, pool));
691
757
 
692
758
  /* If there are lock tokens to add, do so. */
693
 
  if (lock_tokens)
694
 
    {
695
 
      SVN_ERR(svn_fs_get_access(&fs_access, sess->fs));
696
 
 
697
 
      /* If there is no access context, the filesystem will scream if a
698
 
         lock is needed. */
699
 
      if (fs_access)
700
 
        {
701
 
          for (hi = apr_hash_first(pool, lock_tokens); hi;
702
 
               hi = apr_hash_next(hi))
703
 
            {
704
 
              void *val;
705
 
              const char *abs_path, *token;
706
 
              const void *key;
707
 
 
708
 
              apr_hash_this(hi, &key, NULL, &val);
709
 
              abs_path = svn_fspath__join(sess->fs_path->data, key, pool);
710
 
              token = val;
711
 
              SVN_ERR(svn_fs_access_add_lock_token2(fs_access,
712
 
                                                    abs_path, token));
713
 
            }
714
 
        }
715
 
    }
 
759
  SVN_ERR(apply_lock_tokens(sess->fs, sess->fs_path->data, lock_tokens,
 
760
                            session->pool, pool));
716
761
 
717
762
  /* Copy the revprops table so we can add the username. */
718
763
  revprop_table = apr_hash_copy(pool, revprop_table);
719
 
  apr_hash_set(revprop_table, SVN_PROP_REVISION_AUTHOR, APR_HASH_KEY_STRING,
720
 
               svn_string_create(sess->username, pool));
 
764
  svn_hash_sets(revprop_table, SVN_PROP_REVISION_AUTHOR,
 
765
                svn_string_create(sess->username, pool));
 
766
  svn_hash_sets(revprop_table, SVN_PROP_TXN_CLIENT_COMPAT_VERSION,
 
767
                svn_string_create(SVN_VER_NUMBER, pool));
721
768
 
722
769
  /* Get the repos commit-editor */
723
770
  return svn_repos_get_commit_editor5
724
771
         (editor, edit_baton, sess->repos, NULL,
725
772
          svn_path_uri_decode(sess->repos_url, pool), sess->fs_path->data,
726
 
          revprop_table, deltify_etc, db, NULL, NULL, pool);
 
773
          revprop_table, deltify_etc, deb, NULL, NULL, pool);
727
774
}
728
775
 
729
776
 
751
798
 
752
799
  SVN_ERR(svn_repos_fs_get_mergeinfo(&tmp_catalog, sess->repos, abs_paths,
753
800
                                     revision, inherit, include_descendants,
754
 
                                      NULL, NULL, pool));
 
801
                                     NULL, NULL, pool));
755
802
  if (apr_hash_count(tmp_catalog) > 0)
756
803
    SVN_ERR(svn_mergeinfo__remove_prefix_from_catalog(catalog,
757
804
                                                      tmp_catalog,
772
819
                        const char *update_target,
773
820
                        svn_depth_t depth,
774
821
                        svn_boolean_t send_copyfrom_args,
 
822
                        svn_boolean_t ignore_ancestry,
775
823
                        const svn_delta_editor_t *update_editor,
776
824
                        void *update_baton,
777
 
                        apr_pool_t *pool)
 
825
                        apr_pool_t *result_pool,
 
826
                        apr_pool_t *scratch_pool)
778
827
{
779
828
  return make_reporter(session,
780
829
                       reporter,
785
834
                       TRUE,
786
835
                       depth,
787
836
                       send_copyfrom_args,
788
 
                       FALSE,
 
837
                       ignore_ancestry,
789
838
                       update_editor,
790
839
                       update_baton,
791
 
                       pool);
 
840
                       result_pool, scratch_pool);
792
841
}
793
842
 
794
843
 
800
849
                        const char *update_target,
801
850
                        svn_depth_t depth,
802
851
                        const char *switch_url,
 
852
                        svn_boolean_t send_copyfrom_args,
 
853
                        svn_boolean_t ignore_ancestry,
803
854
                        const svn_delta_editor_t *update_editor,
804
855
                        void *update_baton,
805
 
                        apr_pool_t *pool)
 
856
                        apr_pool_t *result_pool,
 
857
                        apr_pool_t *scratch_pool)
806
858
{
807
859
  return make_reporter(session,
808
860
                       reporter,
810
862
                       update_revision,
811
863
                       update_target,
812
864
                       switch_url,
813
 
                       TRUE,
 
865
                       TRUE /* text_deltas */,
814
866
                       depth,
815
 
                       FALSE,   /* ### TODO(sussman): take new arg */
816
 
                       TRUE,
 
867
                       send_copyfrom_args,
 
868
                       ignore_ancestry,
817
869
                       update_editor,
818
870
                       update_baton,
819
 
                       pool);
 
871
                       result_pool, scratch_pool);
820
872
}
821
873
 
822
874
 
843
895
                       FALSE,
844
896
                       status_editor,
845
897
                       status_baton,
846
 
                       pool);
 
898
                       pool, pool);
847
899
}
848
900
 
849
901
 
873
925
                       ignore_ancestry,
874
926
                       update_editor,
875
927
                       update_baton,
876
 
                       pool);
 
928
                       pool, pool);
877
929
}
878
930
 
879
931
 
885
937
};
886
938
 
887
939
static svn_error_t *
888
 
cancellation_log_receiver(void *baton,
889
 
                          svn_log_entry_t *log_entry,
890
 
                          apr_pool_t *pool)
 
940
log_receiver_wrapper(void *baton,
 
941
                     svn_log_entry_t *log_entry,
 
942
                     apr_pool_t *pool)
891
943
{
892
944
  struct log_baton *b = baton;
893
945
  svn_ra_local__session_baton_t *sess = b->sess;
894
946
 
895
 
  SVN_ERR((sess->callbacks->cancel_func)(sess->callback_baton));
 
947
  if (sess->callbacks->cancel_func)
 
948
    SVN_ERR((sess->callbacks->cancel_func)(sess->callback_baton));
 
949
 
 
950
  /* For consistency with the other RA layers, replace an empty
 
951
     changed-paths hash with a NULL one.
 
952
 
 
953
     ### Should this be done by svn_ra_get_log2() instead, then? */
 
954
  if ((log_entry->changed_paths2)
 
955
      && (apr_hash_count(log_entry->changed_paths2) == 0))
 
956
    {
 
957
      log_entry->changed_paths = NULL;
 
958
      log_entry->changed_paths2 = NULL;
 
959
    }
896
960
 
897
961
  return b->real_cb(b->real_baton, log_entry, pool);
898
962
}
929
993
        }
930
994
    }
931
995
 
932
 
  if (sess->callbacks &&
933
 
      sess->callbacks->cancel_func)
934
 
    {
935
 
      lb.real_cb = receiver;
936
 
      lb.real_baton = receiver_baton;
937
 
      lb.sess = sess;
938
 
 
939
 
      receiver = cancellation_log_receiver;
940
 
      receiver_baton = &lb;
941
 
    }
 
996
  lb.real_cb = receiver;
 
997
  lb.real_baton = receiver_baton;
 
998
  lb.sess = sess;
 
999
  receiver = log_receiver_wrapper;
 
1000
  receiver_baton = &lb;
942
1001
 
943
1002
  return svn_repos_get_logs4(sess->repos,
944
1003
                             abs_paths,
997
1056
 
998
1057
static svn_error_t *
999
1058
get_node_props(apr_hash_t **props,
 
1059
               apr_array_header_t **inherited_props,
1000
1060
               svn_ra_local__session_baton_t *sess,
1001
1061
               svn_fs_root_t *root,
1002
1062
               const char *path,
1003
 
               apr_pool_t *pool)
 
1063
               apr_pool_t *result_pool,
 
1064
               apr_pool_t *scratch_pool)
1004
1065
{
1005
1066
  svn_revnum_t cmt_rev;
1006
1067
  const char *cmt_date, *cmt_author;
1007
1068
 
1008
1069
  /* Create a hash with props attached to the fs node. */
1009
 
  SVN_ERR(svn_fs_node_proplist(props, root, path, pool));
 
1070
  if (props)
 
1071
    {
 
1072
      SVN_ERR(svn_fs_node_proplist(props, root, path, result_pool));
 
1073
    }
 
1074
 
 
1075
  /* Get inherited properties if requested. */
 
1076
  if (inherited_props)
 
1077
    {
 
1078
      SVN_ERR(svn_repos_fs_get_inherited_props(inherited_props, root, path,
 
1079
                                               NULL, NULL, NULL,
 
1080
                                               result_pool, scratch_pool));
 
1081
    }
1010
1082
 
1011
1083
  /* Now add some non-tweakable metadata to the hash as well... */
1012
1084
 
1013
 
  /* The so-called 'entryprops' with info about CR & friends. */
1014
 
  SVN_ERR(svn_repos_get_committed_info(&cmt_rev, &cmt_date,
1015
 
                                       &cmt_author, root, path, pool));
1016
 
 
1017
 
  apr_hash_set(*props,
1018
 
               SVN_PROP_ENTRY_COMMITTED_REV,
1019
 
               APR_HASH_KEY_STRING,
1020
 
               svn_string_createf(pool, "%ld", cmt_rev));
1021
 
  apr_hash_set(*props,
1022
 
               SVN_PROP_ENTRY_COMMITTED_DATE,
1023
 
               APR_HASH_KEY_STRING,
1024
 
               cmt_date ? svn_string_create(cmt_date, pool) : NULL);
1025
 
  apr_hash_set(*props,
1026
 
               SVN_PROP_ENTRY_LAST_AUTHOR,
1027
 
               APR_HASH_KEY_STRING,
1028
 
               cmt_author ? svn_string_create(cmt_author, pool) : NULL);
1029
 
  apr_hash_set(*props,
1030
 
               SVN_PROP_ENTRY_UUID,
1031
 
               APR_HASH_KEY_STRING,
1032
 
               svn_string_create(sess->uuid, pool));
1033
 
 
1034
 
  /* We have no 'wcprops' in ra_local, but might someday. */
 
1085
  if (props)
 
1086
    {
 
1087
      /* The so-called 'entryprops' with info about CR & friends. */
 
1088
      SVN_ERR(svn_repos_get_committed_info(&cmt_rev, &cmt_date,
 
1089
                                           &cmt_author, root, path,
 
1090
                                           scratch_pool));
 
1091
 
 
1092
      svn_hash_sets(*props, SVN_PROP_ENTRY_COMMITTED_REV,
 
1093
                    svn_string_createf(result_pool, "%ld", cmt_rev));
 
1094
      svn_hash_sets(*props, SVN_PROP_ENTRY_COMMITTED_DATE, cmt_date ?
 
1095
                    svn_string_create(cmt_date, result_pool) :NULL);
 
1096
      svn_hash_sets(*props, SVN_PROP_ENTRY_LAST_AUTHOR, cmt_author ?
 
1097
                    svn_string_create(cmt_author, result_pool) :NULL);
 
1098
      svn_hash_sets(*props, SVN_PROP_ENTRY_UUID,
 
1099
                    svn_string_create(sess->uuid, result_pool));
 
1100
 
 
1101
      /* We have no 'wcprops' in ra_local, but might someday. */
 
1102
    }
1035
1103
 
1036
1104
  return SVN_NO_ERROR;
1037
1105
}
1103
1171
 
1104
1172
  /* Handle props if requested. */
1105
1173
  if (props)
1106
 
    SVN_ERR(get_node_props(props, sess, root, abs_path, pool));
 
1174
    SVN_ERR(get_node_props(props, NULL, sess, root, abs_path, pool, pool));
1107
1175
 
1108
1176
  return SVN_NO_ERROR;
1109
1177
}
1156
1224
          apr_hash_t *prophash;
1157
1225
          const char *datestring, *entryname, *fullpath;
1158
1226
          svn_fs_dirent_t *fs_entry;
1159
 
          svn_dirent_t *entry = apr_pcalloc(pool, sizeof(*entry));
 
1227
          svn_dirent_t *entry = svn_dirent_create(pool);
1160
1228
 
1161
1229
          svn_pool_clear(subpool);
1162
1230
 
1207
1275
            }
1208
1276
 
1209
1277
          /* Store. */
1210
 
          apr_hash_set(*dirents, entryname, APR_HASH_KEY_STRING, entry);
 
1278
          svn_hash_sets(*dirents, entryname, entry);
1211
1279
        }
1212
1280
      svn_pool_destroy(subpool);
1213
1281
    }
1214
1282
 
1215
1283
  /* Handle props if requested. */
1216
1284
  if (props)
1217
 
    SVN_ERR(get_node_props(props, sess, root, abs_path, pool));
 
1285
    SVN_ERR(get_node_props(props, NULL, sess, root, abs_path, pool, pool));
1218
1286
 
1219
1287
  return SVN_NO_ERROR;
1220
1288
}
1448
1516
      || strcmp(capability, SVN_RA_CAPABILITY_LOG_REVPROPS) == 0
1449
1517
      || strcmp(capability, SVN_RA_CAPABILITY_PARTIAL_REPLAY) == 0
1450
1518
      || strcmp(capability, SVN_RA_CAPABILITY_COMMIT_REVPROPS) == 0
1451
 
      || strcmp(capability, SVN_RA_CAPABILITY_ATOMIC_REVPROPS) == 0)
 
1519
      || strcmp(capability, SVN_RA_CAPABILITY_ATOMIC_REVPROPS) == 0
 
1520
      || strcmp(capability, SVN_RA_CAPABILITY_INHERITED_PROPS) == 0
 
1521
      || strcmp(capability, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS) == 0
 
1522
      || strcmp(capability, SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE) == 0
 
1523
      )
1452
1524
    {
1453
1525
      *has = TRUE;
1454
1526
    }
1491
1563
  return SVN_NO_ERROR;
1492
1564
}
1493
1565
 
 
1566
static svn_error_t *
 
1567
svn_ra_local__get_inherited_props(svn_ra_session_t *session,
 
1568
                                  apr_array_header_t **iprops,
 
1569
                                  const char *path,
 
1570
                                  svn_revnum_t revision,
 
1571
                                  apr_pool_t *result_pool,
 
1572
                                  apr_pool_t *scratch_pool)
 
1573
{
 
1574
  svn_fs_root_t *root;
 
1575
  svn_revnum_t youngest_rev;
 
1576
  svn_ra_local__session_baton_t *sess = session->priv;
 
1577
  const char *abs_path = svn_fspath__join(sess->fs_path->data, path,
 
1578
                                          scratch_pool);
 
1579
  svn_node_kind_t node_kind;
 
1580
 
 
1581
  /* Open the revision's root. */
 
1582
  if (! SVN_IS_VALID_REVNUM(revision))
 
1583
    {
 
1584
      SVN_ERR(svn_fs_youngest_rev(&youngest_rev, sess->fs, scratch_pool));
 
1585
      SVN_ERR(svn_fs_revision_root(&root, sess->fs, youngest_rev,
 
1586
                                   scratch_pool));
 
1587
    }
 
1588
  else
 
1589
    {
 
1590
      SVN_ERR(svn_fs_revision_root(&root, sess->fs, revision, scratch_pool));
 
1591
    }
 
1592
 
 
1593
  SVN_ERR(svn_fs_check_path(&node_kind, root, abs_path, scratch_pool));
 
1594
  if (node_kind == svn_node_none)
 
1595
    {
 
1596
      return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
 
1597
                               _("'%s' path not found"), abs_path);
 
1598
    }
 
1599
 
 
1600
  return svn_error_trace(get_node_props(NULL, iprops, sess, root, abs_path,
 
1601
                                        result_pool, scratch_pool));
 
1602
}
 
1603
 
 
1604
static svn_error_t *
 
1605
svn_ra_local__register_editor_shim_callbacks(svn_ra_session_t *session,
 
1606
                                    svn_delta_shim_callbacks_t *callbacks)
 
1607
{
 
1608
  /* This is currenly a no-op, since we don't provide our own editor, just
 
1609
     use the one the libsvn_repos hands back to us. */
 
1610
  return SVN_NO_ERROR;
 
1611
}
 
1612
 
 
1613
 
 
1614
static svn_error_t *
 
1615
svn_ra_local__get_commit_ev2(svn_editor_t **editor,
 
1616
                             svn_ra_session_t *session,
 
1617
                             apr_hash_t *revprops,
 
1618
                             svn_commit_callback2_t commit_cb,
 
1619
                             void *commit_baton,
 
1620
                             apr_hash_t *lock_tokens,
 
1621
                             svn_boolean_t keep_locks,
 
1622
                             svn_ra__provide_base_cb_t provide_base_cb,
 
1623
                             svn_ra__provide_props_cb_t provide_props_cb,
 
1624
                             svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
 
1625
                             void *cb_baton,
 
1626
                             svn_cancel_func_t cancel_func,
 
1627
                             void *cancel_baton,
 
1628
                             apr_pool_t *result_pool,
 
1629
                             apr_pool_t *scratch_pool)
 
1630
{
 
1631
  svn_ra_local__session_baton_t *sess = session->priv;
 
1632
  struct deltify_etc_baton *deb = apr_palloc(result_pool, sizeof(*deb));
 
1633
 
 
1634
  /* NOTE: the RA callbacks are ignored. We pass everything directly to
 
1635
     the REPOS editor.  */
 
1636
 
 
1637
  /* Prepare the baton for deltify_etc()  */
 
1638
  deb->fs = sess->fs;
 
1639
  deb->repos = sess->repos;
 
1640
  deb->fspath_base = sess->fs_path->data;
 
1641
  if (! keep_locks)
 
1642
    deb->lock_tokens = lock_tokens;
 
1643
  else
 
1644
    deb->lock_tokens = NULL;
 
1645
  deb->commit_cb = commit_cb;
 
1646
  deb->commit_baton = commit_baton;
 
1647
 
 
1648
  /* Ensure there is a username (and an FS access context) associated with
 
1649
     the session and its FS handle.  */
 
1650
  SVN_ERR(get_username(session, scratch_pool));
 
1651
 
 
1652
  /* If there are lock tokens to add, do so.  */
 
1653
  SVN_ERR(apply_lock_tokens(sess->fs, sess->fs_path->data, lock_tokens,
 
1654
                            session->pool, scratch_pool));
 
1655
 
 
1656
  /* Copy the REVPROPS and insert the author/username.  */
 
1657
  revprops = apr_hash_copy(scratch_pool, revprops);
 
1658
  svn_hash_sets(revprops, SVN_PROP_REVISION_AUTHOR,
 
1659
                svn_string_create(sess->username, scratch_pool));
 
1660
 
 
1661
  return svn_error_trace(svn_repos__get_commit_ev2(
 
1662
                           editor, sess->repos, NULL /* authz */,
 
1663
                           NULL /* authz_repos_name */, NULL /* authz_user */,
 
1664
                           revprops,
 
1665
                           deltify_etc, deb, cancel_func, cancel_baton,
 
1666
                           result_pool, scratch_pool));
 
1667
}
 
1668
 
1494
1669
/*----------------------------------------------------------------*/
1495
1670
 
1496
1671
static const svn_version_t *
1537
1712
  svn_ra_local__replay,
1538
1713
  svn_ra_local__has_capability,
1539
1714
  svn_ra_local__replay_range,
1540
 
  svn_ra_local__get_deleted_rev
 
1715
  svn_ra_local__get_deleted_rev,
 
1716
  svn_ra_local__register_editor_shim_callbacks,
 
1717
  svn_ra_local__get_inherited_props,
 
1718
  svn_ra_local__get_commit_ev2
1541
1719
};
1542
1720
 
1543
1721
 
1568
1746
                               "ra_local"),
1569
1747
                             loader_version->major);
1570
1748
 
1571
 
  SVN_ERR(svn_ver_check_list(ra_local_version(), checklist));
 
1749
  SVN_ERR(svn_ver_check_list2(ra_local_version(), checklist, svn_ver_equal));
1572
1750
 
1573
1751
#ifndef SVN_LIBSVN_CLIENT_LINKS_RA_LOCAL
1574
1752
  /* This assumes that POOL was the pool used to load the dso. */