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

« back to all changes in this revision

Viewing changes to subversion/libsvn_repos/load-fs-vtable.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2015-08-07 21:32:47 UTC
  • mfrom: (0.2.15) (4.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20150807213247-ozyewtmgsr6tkewl
Tags: 1.9.0-1
* Upload to unstable
* New upstream release.
  + Security fixes
    - CVE-2015-3184: Mixed anonymous/authenticated path-based authz with
      httpd 2.4
    - CVE-2015-3187: svn_repos_trace_node_locations() reveals paths hidden
      by authz
* Add >= 2.7 requirement for python-all-dev Build-Depends, needed to run
  tests.
* Remove Build-Conflicts against ruby-test-unit.  (Closes: #791844)
* Remove patches/apache_module_dependency in favor of expressing the
  dependencies in authz_svn.load/dav_svn.load.
* Build-Depend on apache2-dev (>= 2.4.16) to ensure ap_some_authn_required()
  is available when building mod_authz_svn and Depend on apache2-bin (>=
  2.4.16) for runtime support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#include "svn_string.h"
32
32
#include "svn_props.h"
33
33
#include "repos.h"
34
 
#include "svn_private_config.h"
35
34
#include "svn_mergeinfo.h"
36
35
#include "svn_checksum.h"
37
36
#include "svn_subst.h"
38
 
#include "svn_ctype.h"
39
37
#include "svn_dirent_uri.h"
40
38
 
41
39
#include <apr_lib.h>
42
40
 
43
 
#include "private/svn_repos_private.h"
44
41
#include "private/svn_fspath.h"
45
42
#include "private/svn_dep_compat.h"
46
43
#include "private/svn_mergeinfo_private.h"
 
44
#include "private/svn_repos_private.h"
47
45
 
48
46
/*----------------------------------------------------------------------*/
49
47
 
56
54
 
57
55
  svn_boolean_t use_history;
58
56
  svn_boolean_t validate_props;
 
57
  svn_boolean_t ignore_dates;
59
58
  svn_boolean_t use_pre_commit_hook;
60
59
  svn_boolean_t use_post_commit_hook;
61
60
  enum svn_repos_load_uuid uuid_action;
84
83
     SVN_INVALID_REVNUM. */
85
84
  svn_revnum_t last_rev_mapped;
86
85
 
87
 
  /* The oldest old revision loaded from the dump stream.  If no revisions
 
86
  /* The oldest revision loaded from the dump stream.  If no revisions
88
87
     have been loaded yet, this is set to SVN_INVALID_REVNUM. */
89
 
  svn_revnum_t oldest_old_rev;
 
88
  svn_revnum_t oldest_dumpstream_rev;
90
89
};
91
90
 
92
91
struct revision_baton
93
92
{
 
93
  /* rev num from dump file */
94
94
  svn_revnum_t rev;
95
95
  svn_fs_txn_t *txn;
96
96
  svn_fs_root_t *txn_root;
97
97
 
98
98
  const svn_string_t *datestamp;
99
99
 
 
100
  /* (rev num from dump file) minus (rev num to be committed) */
100
101
  apr_int32_t rev_offset;
101
102
  svn_boolean_t skipped;
102
103
 
 
104
  /* Array of svn_prop_t with revision properties. */
 
105
  apr_array_header_t *revprops;
 
106
 
103
107
  struct parse_baton *pb;
104
108
  apr_pool_t *pool;
105
109
};
189
193
 
190
194
/* Prepend the mergeinfo source paths in MERGEINFO_ORIG with PARENT_DIR, and
191
195
   return it in *MERGEINFO_VAL. */
192
 
/* ### FIXME:  Consider somehow sharing code with
193
 
   ### svnrdump/load_editor.c:prefix_mergeinfo_paths() */
194
196
static svn_error_t *
195
197
prefix_mergeinfo_paths(svn_string_t **mergeinfo_val,
196
198
                       const svn_string_t *mergeinfo_orig,
199
201
{
200
202
  apr_hash_t *prefixed_mergeinfo, *mergeinfo;
201
203
  apr_hash_index_t *hi;
202
 
  void *rangelist;
203
204
 
204
205
  SVN_ERR(svn_mergeinfo_parse(&mergeinfo, mergeinfo_orig->data, pool));
205
206
  prefixed_mergeinfo = apr_hash_make(pool);
206
207
  for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
207
208
    {
208
 
      const void *key;
209
 
      const char *path, *merge_source;
 
209
      const char *merge_source = apr_hash_this_key(hi);
 
210
      svn_rangelist_t *rangelist = apr_hash_this_val(hi);
 
211
      const char *path;
210
212
 
211
 
      apr_hash_this(hi, &key, NULL, &rangelist);
212
 
      merge_source = svn_relpath_canonicalize(key, pool);
 
213
      merge_source = svn_relpath_canonicalize(merge_source, pool);
213
214
 
214
215
      /* The svn:mergeinfo property syntax demands a repos abspath */
215
216
      path = svn_fspath__canonicalize(svn_relpath_join(parent_dir,
223
224
 
224
225
/* Examine the mergeinfo in INITIAL_VAL, renumber revisions in rangelists
225
226
   as appropriate, and return the (possibly new) mergeinfo in *FINAL_VAL
226
 
   (allocated from POOL). */
227
 
/* ### FIXME:  Consider somehow sharing code with
228
 
   ### svnrdump/load_editor.c:renumber_mergeinfo_revs() */
 
227
   (allocated from POOL).
 
228
 
 
229
   Adjust any mergeinfo revisions not older than OLDEST_DUMPSTREAM_REV by
 
230
   using REV_MAP which maps (svn_revnum_t) old rev to (svn_revnum_t) new rev.
 
231
 
 
232
   Adjust any mergeinfo revisions older than OLDEST_DUMPSTREAM_REV by
 
233
   (-OLDER_REVS_OFFSET), dropping any that become <= 0.
 
234
 */
229
235
static svn_error_t *
230
236
renumber_mergeinfo_revs(svn_string_t **final_val,
231
237
                        const svn_string_t *initial_val,
232
 
                        struct revision_baton *rb,
 
238
                        apr_hash_t *rev_map,
 
239
                        svn_revnum_t oldest_dumpstream_rev,
 
240
                        apr_int32_t older_revs_offset,
233
241
                        apr_pool_t *pool)
234
242
{
235
243
  apr_pool_t *subpool = svn_pool_create(pool);
244
252
     Remove mergeinfo older than the oldest revision in the dump stream
245
253
     and adjust its revisions by the difference between the head rev of
246
254
     the target repository and the current dump stream rev. */
247
 
  if (rb->pb->oldest_old_rev > 1)
 
255
  if (oldest_dumpstream_rev > 1)
248
256
    {
 
257
      /* predates_stream_mergeinfo := mergeinfo that refers to revs before
 
258
         oldest_dumpstream_rev */
249
259
      SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
250
260
        &predates_stream_mergeinfo, mergeinfo,
251
 
        rb->pb->oldest_old_rev - 1, 0,
 
261
        oldest_dumpstream_rev - 1, 0,
252
262
        TRUE, subpool, subpool));
 
263
      /* mergeinfo := mergeinfo that refers to revs >= oldest_dumpstream_rev */
253
264
      SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
254
265
        &mergeinfo, mergeinfo,
255
 
        rb->pb->oldest_old_rev - 1, 0,
 
266
        oldest_dumpstream_rev - 1, 0,
256
267
        FALSE, subpool, subpool));
257
268
      SVN_ERR(svn_mergeinfo__adjust_mergeinfo_rangelists(
258
269
        &predates_stream_mergeinfo, predates_stream_mergeinfo,
259
 
        -rb->rev_offset, subpool, subpool));
 
270
        -older_revs_offset, subpool, subpool));
260
271
    }
261
272
  else
262
273
    {
265
276
 
266
277
  for (hi = apr_hash_first(subpool, mergeinfo); hi; hi = apr_hash_next(hi))
267
278
    {
268
 
      const char *merge_source;
269
 
      svn_rangelist_t *rangelist;
270
 
      struct parse_baton *pb = rb->pb;
 
279
      const char *merge_source = apr_hash_this_key(hi);
 
280
      svn_rangelist_t *rangelist = apr_hash_this_val(hi);
271
281
      int i;
272
 
      const void *key;
273
 
      void *val;
274
 
 
275
 
      apr_hash_this(hi, &key, NULL, &val);
276
 
      merge_source = key;
277
 
      rangelist = val;
278
282
 
279
283
      /* Possibly renumber revisions in merge source's rangelist. */
280
284
      for (i = 0; i < rangelist->nelts; i++)
282
286
          svn_revnum_t rev_from_map;
283
287
          svn_merge_range_t *range = APR_ARRAY_IDX(rangelist, i,
284
288
                                                   svn_merge_range_t *);
285
 
          rev_from_map = get_revision_mapping(pb->rev_map, range->start);
 
289
          rev_from_map = get_revision_mapping(rev_map, range->start);
286
290
          if (SVN_IS_VALID_REVNUM(rev_from_map))
287
291
            {
288
292
              range->start = rev_from_map;
289
293
            }
290
 
          else if (range->start == pb->oldest_old_rev - 1)
 
294
          else if (range->start == oldest_dumpstream_rev - 1)
291
295
            {
292
296
              /* Since the start revision of svn_merge_range_t are not
293
297
                 inclusive there is one possible valid start revision that
294
 
                 won't be found in the PB->REV_MAP mapping of load stream
 
298
                 won't be found in the REV_MAP mapping of load stream
295
299
                 revsions to loaded revisions: The revision immediately
296
 
                 preceeding the oldest revision from the load stream.
 
300
                 preceding the oldest revision from the load stream.
297
301
                 This is a valid revision for mergeinfo, but not a valid
298
 
                 copy from revision (which PB->REV_MAP also maps for) so it
 
302
                 copy from revision (which REV_MAP also maps for) so it
299
303
                 will never be in the mapping.
300
304
 
301
305
                 If that is what we have here, then find the mapping for the
302
306
                 oldest rev from the load stream and subtract 1 to get the
303
307
                 renumbered, non-inclusive, start revision. */
304
 
              rev_from_map = get_revision_mapping(pb->rev_map,
305
 
                                                  pb->oldest_old_rev);
 
308
              rev_from_map = get_revision_mapping(rev_map,
 
309
                                                  oldest_dumpstream_rev);
306
310
              if (SVN_IS_VALID_REVNUM(rev_from_map))
307
311
                range->start = rev_from_map - 1;
308
312
            }
319
323
              continue;
320
324
            }
321
325
 
322
 
          rev_from_map = get_revision_mapping(pb->rev_map, range->end);
 
326
          rev_from_map = get_revision_mapping(rev_map, range->end);
323
327
          if (SVN_IS_VALID_REVNUM(rev_from_map))
324
328
            range->end = rev_from_map;
325
329
        }
327
331
    }
328
332
 
329
333
  if (predates_stream_mergeinfo)
 
334
    {
330
335
      SVN_ERR(svn_mergeinfo_merge2(final_mergeinfo, predates_stream_mergeinfo,
331
336
                                   subpool, subpool));
 
337
    }
332
338
 
333
339
  SVN_ERR(svn_mergeinfo__canonicalize_ranges(final_mergeinfo, subpool));
334
340
 
343
349
/** vtable for doing commits to a fs **/
344
350
 
345
351
 
 
352
/* Make a node baton, parsing the relevant HEADERS.
 
353
 *
 
354
 * If RB->pb->parent_dir:
 
355
 *   prefix it to NB->path
 
356
 *   prefix it to NB->copyfrom_path (if present)
 
357
 */
346
358
static svn_error_t *
347
359
make_node_baton(struct node_baton **node_baton_p,
348
360
                apr_hash_t *headers,
429
441
  return SVN_NO_ERROR;
430
442
}
431
443
 
 
444
/* Make a revision baton, parsing the relevant HEADERS.
 
445
 *
 
446
 * Set RB->skipped iff the revision number is outside the range given in PB.
 
447
 */
432
448
static struct revision_baton *
433
449
make_revision_baton(apr_hash_t *headers,
434
450
                    struct parse_baton *pb,
440
456
  rb->pb = pb;
441
457
  rb->pool = pool;
442
458
  rb->rev = SVN_INVALID_REVNUM;
 
459
  rb->revprops = apr_array_make(rb->pool, 8, sizeof(svn_prop_t));
443
460
 
444
461
  if ((val = svn_hash_gets(headers, SVN_REPOS_DUMPFILE_REVISION_NUMBER)))
445
462
    {
489
506
  if ((rb->rev > 0) && (! rb->skipped))
490
507
    {
491
508
      /* Create a new fs txn. */
492
 
      SVN_ERR(svn_fs_begin_txn2(&(rb->txn), pb->fs, head_rev, 0, pool));
 
509
      SVN_ERR(svn_fs_begin_txn2(&(rb->txn), pb->fs, head_rev,
 
510
                                SVN_FS_TXN_CLIENT_DATE, pool));
493
511
      SVN_ERR(svn_fs_txn_root(&(rb->txn_root), rb->txn, pool));
494
512
 
495
513
      if (pb->notify_func)
505
523
        }
506
524
 
507
525
      /* Stash the oldest "old" revision committed from the load stream. */
508
 
      if (!SVN_IS_VALID_REVNUM(pb->oldest_old_rev))
509
 
        pb->oldest_old_rev = rb->rev;
 
526
      if (!SVN_IS_VALID_REVNUM(pb->oldest_dumpstream_rev))
 
527
        pb->oldest_dumpstream_rev = rb->rev;
510
528
    }
511
529
 
512
530
  /* If we're skipping this revision, try to notify someone. */
522
540
      svn_pool_clear(pb->notify_pool);
523
541
    }
524
542
 
525
 
  /* If we're parsing revision 0, only the revision are (possibly)
 
543
  /* If we're parsing revision 0, only the revision props are (possibly)
526
544
     interesting to us: when loading the stream into an empty
527
545
     filesystem, then we want new filesystem's revision 0 to have the
528
546
     same props.  Otherwise, we just ignore revision 0 in the stream. */
533
551
 
534
552
 
535
553
 
536
 
/* Factorized helper func for new_node_record() */
 
554
/* Perform a copy or a plain add.
 
555
 *
 
556
 * For a copy, also adjust the copy-from rev, check any copy-source checksum,
 
557
 * and send a notification.
 
558
 */
537
559
static svn_error_t *
538
560
maybe_add_with_history(struct node_baton *nb,
539
561
                       struct revision_baton *rb,
702
724
                      const svn_string_t *value)
703
725
{
704
726
  struct revision_baton *rb = baton;
 
727
  struct parse_baton *pb = rb->pb;
 
728
  svn_boolean_t is_date = strcmp(name, SVN_PROP_REVISION_DATE) == 0;
 
729
  svn_prop_t *prop;
705
730
 
706
731
  /* If we're skipping this revision, we're done here. */
707
732
  if (rb->skipped)
708
733
    return SVN_NO_ERROR;
709
734
 
710
 
  if (rb->rev > 0)
711
 
    {
712
 
      if (rb->pb->validate_props)
713
 
        SVN_ERR(svn_repos_fs_change_txn_prop(rb->txn, name, value, rb->pool));
714
 
      else
715
 
        SVN_ERR(svn_fs_change_txn_prop(rb->txn, name, value, rb->pool));
716
 
 
717
 
      /* Remember any datestamp that passes through!  (See comment in
718
 
         close_revision() below.) */
719
 
      if (! strcmp(name, SVN_PROP_REVISION_DATE))
720
 
        rb->datestamp = svn_string_dup(value, rb->pool);
721
 
    }
722
 
  else if (rb->rev == 0)
723
 
    {
724
 
      /* Special case: set revision 0 properties when loading into an
725
 
         'empty' filesystem. */
726
 
      struct parse_baton *pb = rb->pb;
727
 
      svn_revnum_t youngest_rev;
728
 
 
729
 
      SVN_ERR(svn_fs_youngest_rev(&youngest_rev, pb->fs, rb->pool));
730
 
 
731
 
      if (youngest_rev == 0)
732
 
        SVN_ERR(change_rev_prop(pb->repos, 0, name, value,
733
 
                                pb->validate_props, rb->pool));
734
 
    }
 
735
  /* If we're ignoring dates, and this is one, we're done here. */
 
736
  if (is_date && pb->ignore_dates)
 
737
    return SVN_NO_ERROR;
 
738
 
 
739
  /* Collect property changes to apply them in one FS call in
 
740
     close_revision. */
 
741
  prop = &APR_ARRAY_PUSH(rb->revprops, svn_prop_t);
 
742
  prop->name = apr_pstrdup(rb->pool, name);
 
743
  prop->value = svn_string_dup(value, rb->pool);
 
744
 
 
745
  /* Remember any datestamp that passes through!  (See comment in
 
746
     close_revision() below.) */
 
747
  if (is_date)
 
748
    rb->datestamp = svn_string_dup(value, rb->pool);
735
749
 
736
750
  return SVN_NO_ERROR;
737
751
}
738
752
 
739
753
 
740
 
/* Adjust mergeinfo:
741
 
 *   - normalize line endings (if all CRLF, change to LF; but error if mixed);
742
 
 *   - adjust revision numbers (see renumber_mergeinfo_revs());
743
 
 *   - adjust paths (see prefix_mergeinfo_paths()).
744
 
 */
745
 
static svn_error_t *
746
 
adjust_mergeinfo_property(struct revision_baton *rb,
747
 
                          svn_string_t **new_value_p,
748
 
                          const svn_string_t *old_value,
749
 
                          apr_pool_t *result_pool)
 
754
svn_error_t *
 
755
svn_repos__adjust_mergeinfo_property(svn_string_t **new_value_p,
 
756
                                     const svn_string_t *old_value,
 
757
                                     const char *parent_dir,
 
758
                                     apr_hash_t *rev_map,
 
759
                                     svn_revnum_t oldest_dumpstream_rev,
 
760
                                     apr_int32_t older_revs_offset,
 
761
                                     svn_repos_notify_func_t notify_func,
 
762
                                     void *notify_baton,
 
763
                                     apr_pool_t *result_pool,
 
764
                                     apr_pool_t *scratch_pool)
750
765
{
751
 
  struct parse_baton *pb = rb->pb;
752
766
  svn_string_t prop_val = *old_value;
753
767
 
754
768
  /* Tolerate mergeinfo with "\r\n" line endings because some
755
769
     dumpstream sources might contain as much.  If so normalize
756
 
     the line endings to '\n' and make a notification to
757
 
     PARSE_BATON->FEEDBACK_STREAM that we have made this
 
770
     the line endings to '\n' and notify that we have made this
758
771
     correction. */
759
772
  if (strstr(prop_val.data, "\r"))
760
773
    {
770
783
      prop_val.data = prop_eol_normalized;
771
784
      prop_val.len = strlen(prop_eol_normalized);
772
785
 
773
 
      if (pb->notify_func)
 
786
      if (notify_func)
774
787
        {
775
 
          /* ### TODO: Use proper scratch pool instead of pb->notify_pool */
776
788
          svn_repos_notify_t *notify
777
789
                  = svn_repos_notify_create(
778
790
                                svn_repos_notify_load_normalized_mergeinfo,
779
 
                                pb->notify_pool);
 
791
                                scratch_pool);
780
792
 
781
 
          pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
782
 
          svn_pool_clear(pb->notify_pool);
 
793
          notify_func(notify_baton, notify, scratch_pool);
783
794
        }
784
795
    }
785
796
 
786
797
  /* Renumber mergeinfo as appropriate. */
787
 
  SVN_ERR(renumber_mergeinfo_revs(new_value_p, &prop_val, rb,
 
798
  SVN_ERR(renumber_mergeinfo_revs(new_value_p, &prop_val,
 
799
                                  rev_map, oldest_dumpstream_rev,
 
800
                                  older_revs_offset,
788
801
                                  result_pool));
789
 
  if (pb->parent_dir)
 
802
 
 
803
  if (parent_dir)
790
804
    {
791
 
      /* Prefix the merge source paths with PB->parent_dir. */
 
805
      /* Prefix the merge source paths with PARENT_DIR. */
792
806
      /* ASSUMPTION: All source paths are included in the dump stream. */
793
807
      SVN_ERR(prefix_mergeinfo_paths(new_value_p, *new_value_p,
794
 
                                     pb->parent_dir, result_pool));
 
808
                                     parent_dir, result_pool));
795
809
    }
796
810
 
797
811
  return SVN_NO_ERROR;
821
835
      svn_string_t *new_value;
822
836
      svn_error_t *err;
823
837
 
824
 
      err = adjust_mergeinfo_property(rb, &new_value, value, nb->pool);
 
838
      err = svn_repos__adjust_mergeinfo_property(&new_value, value,
 
839
                                                 pb->parent_dir,
 
840
                                                 pb->rev_map,
 
841
                                                 pb->oldest_dumpstream_rev,
 
842
                                                 rb->rev_offset,
 
843
                                                 pb->notify_func, pb->notify_baton,
 
844
                                                 nb->pool, pb->notify_pool);
 
845
      svn_pool_clear(pb->notify_pool);
825
846
      if (err)
826
847
        {
827
848
          if (pb->validate_props)
836
857
                = svn_repos_notify_create(svn_repos_notify_warning,
837
858
                                          pb->notify_pool);
838
859
 
839
 
              notify->warning = svn_repos__notify_warning_invalid_mergeinfo;
 
860
              notify->warning = svn_repos_notify_warning_invalid_mergeinfo;
840
861
              notify->warning_str = _("Invalid svn:mergeinfo value; "
841
862
                                      "leaving unchanged");
842
863
              pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
888
909
 
889
910
  for (hi = apr_hash_first(nb->pool, proplist); hi; hi = apr_hash_next(hi))
890
911
    {
891
 
      const void *key;
 
912
      const char *key = apr_hash_this_key(hi);
892
913
 
893
 
      apr_hash_this(hi, &key, NULL, NULL);
894
914
      SVN_ERR(change_node_prop(rb->txn_root, nb->path, key, NULL,
895
915
                               rb->pb->validate_props, nb->pool));
896
916
    }
983
1003
  const char *txn_name = NULL;
984
1004
  apr_hash_t *hooks_env;
985
1005
 
986
 
  /* If we're skipping this revision or it has an invalid revision
987
 
     number, we're done here. */
988
 
  if (rb->skipped || (rb->rev <= 0))
 
1006
  /* If we're skipping this revision we're done here. */
 
1007
  if (rb->skipped)
989
1008
    return SVN_NO_ERROR;
990
1009
 
 
1010
  if (rb->rev == 0)
 
1011
    {
 
1012
      /* Special case: set revision 0 properties when loading into an
 
1013
         'empty' filesystem. */
 
1014
      svn_revnum_t youngest_rev;
 
1015
 
 
1016
      SVN_ERR(svn_fs_youngest_rev(&youngest_rev, pb->fs, rb->pool));
 
1017
 
 
1018
      if (youngest_rev == 0)
 
1019
        {
 
1020
          apr_hash_t *orig_props;
 
1021
          apr_hash_t *new_props;
 
1022
          apr_array_header_t *diff;
 
1023
          int i;
 
1024
 
 
1025
          SVN_ERR(svn_fs_revision_proplist(&orig_props, pb->fs, 0, rb->pool));
 
1026
          new_props = svn_prop_array_to_hash(rb->revprops, rb->pool);
 
1027
          SVN_ERR(svn_prop_diffs(&diff, new_props, orig_props, rb->pool));
 
1028
 
 
1029
          for (i = 0; i < diff->nelts; i++)
 
1030
          {
 
1031
              const svn_prop_t *prop = &APR_ARRAY_IDX(diff, i, svn_prop_t);
 
1032
 
 
1033
              SVN_ERR(change_rev_prop(pb->repos, 0, prop->name, prop->value,
 
1034
                                      pb->validate_props, rb->pool));
 
1035
          }
 
1036
        }
 
1037
 
 
1038
      return SVN_NO_ERROR;
 
1039
    }
 
1040
 
 
1041
  /* If the dumpstream doesn't have an 'svn:date' property and we
 
1042
     aren't ignoring the dates in the dumpstream altogether, remove
 
1043
     any 'svn:date' revision property that was set by FS layer when
 
1044
     the TXN was created.  */
 
1045
  if (! (pb->ignore_dates || rb->datestamp))
 
1046
    {
 
1047
      svn_prop_t *prop = &APR_ARRAY_PUSH(rb->revprops, svn_prop_t);
 
1048
      prop->name = SVN_PROP_REVISION_DATE;
 
1049
      prop->value = NULL;
 
1050
    }
 
1051
 
 
1052
  /* Apply revision property changes. */
 
1053
  if (rb->pb->validate_props)
 
1054
    SVN_ERR(svn_repos_fs_change_txn_props(rb->txn, rb->revprops, rb->pool));
 
1055
  else
 
1056
    SVN_ERR(svn_fs_change_txn_props(rb->txn, rb->revprops, rb->pool));
 
1057
 
991
1058
  /* Get the txn name and hooks environment if they will be needed. */
992
1059
  if (pb->use_pre_commit_hook || pb->use_post_commit_hook)
993
1060
    {
1073
1140
  /* Deltify the predecessors of paths changed in this revision. */
1074
1141
  SVN_ERR(svn_fs_deltify_revision(pb->fs, committed_rev, rb->pool));
1075
1142
 
1076
 
  /* Grrr, svn_fs_commit_txn rewrites the datestamp property to the
1077
 
     current clock-time.  We don't want that, we want to preserve
1078
 
     history exactly.  Good thing revision props aren't versioned!
1079
 
     Note that if rb->datestamp is NULL, that's fine -- if the dump
1080
 
     data doesn't carry a datestamp, we want to preserve that fact in
1081
 
     the load. */
1082
 
  SVN_ERR(change_rev_prop(pb->repos, committed_rev, SVN_PROP_REVISION_DATE,
1083
 
                          rb->datestamp, pb->validate_props, rb->pool));
1084
 
 
1085
1143
  if (pb->notify_func)
1086
1144
    {
1087
1145
      /* ### TODO: Use proper scratch pool instead of pb->notify_pool */
1107
1165
 
1108
1166
 
1109
1167
svn_error_t *
1110
 
svn_repos_get_fs_build_parser4(const svn_repos_parse_fns3_t **callbacks,
 
1168
svn_repos_get_fs_build_parser5(const svn_repos_parse_fns3_t **callbacks,
1111
1169
                               void **parse_baton,
1112
1170
                               svn_repos_t *repos,
1113
1171
                               svn_revnum_t start_rev,
1116
1174
                               svn_boolean_t validate_props,
1117
1175
                               enum svn_repos_load_uuid uuid_action,
1118
1176
                               const char *parent_dir,
 
1177
                               svn_boolean_t use_pre_commit_hook,
 
1178
                               svn_boolean_t use_post_commit_hook,
 
1179
                               svn_boolean_t ignore_dates,
1119
1180
                               svn_repos_notify_func_t notify_func,
1120
1181
                               void *notify_baton,
1121
1182
                               apr_pool_t *pool)
1157
1218
  pb->pool = pool;
1158
1219
  pb->notify_pool = svn_pool_create(pool);
1159
1220
  pb->rev_map = apr_hash_make(pool);
1160
 
  pb->oldest_old_rev = SVN_INVALID_REVNUM;
 
1221
  pb->oldest_dumpstream_rev = SVN_INVALID_REVNUM;
1161
1222
  pb->last_rev_mapped = SVN_INVALID_REVNUM;
1162
1223
  pb->start_rev = start_rev;
1163
1224
  pb->end_rev = end_rev;
 
1225
  pb->use_pre_commit_hook = use_pre_commit_hook;
 
1226
  pb->use_post_commit_hook = use_post_commit_hook;
 
1227
  pb->ignore_dates = ignore_dates;
1164
1228
 
1165
1229
  *callbacks = parser;
1166
1230
  *parse_baton = pb;
1168
1232
}
1169
1233
 
1170
1234
 
1171
 
 
1172
1235
svn_error_t *
1173
 
svn_repos_load_fs4(svn_repos_t *repos,
 
1236
svn_repos_load_fs5(svn_repos_t *repos,
1174
1237
                   svn_stream_t *dumpstream,
1175
1238
                   svn_revnum_t start_rev,
1176
1239
                   svn_revnum_t end_rev,
1179
1242
                   svn_boolean_t use_pre_commit_hook,
1180
1243
                   svn_boolean_t use_post_commit_hook,
1181
1244
                   svn_boolean_t validate_props,
 
1245
                   svn_boolean_t ignore_dates,
1182
1246
                   svn_repos_notify_func_t notify_func,
1183
1247
                   void *notify_baton,
1184
1248
                   svn_cancel_func_t cancel_func,
1187
1251
{
1188
1252
  const svn_repos_parse_fns3_t *parser;
1189
1253
  void *parse_baton;
1190
 
  struct parse_baton *pb;
1191
1254
 
1192
1255
  /* This is really simple. */
1193
1256
 
1194
 
  SVN_ERR(svn_repos_get_fs_build_parser4(&parser, &parse_baton,
 
1257
  SVN_ERR(svn_repos_get_fs_build_parser5(&parser, &parse_baton,
1195
1258
                                         repos,
1196
1259
                                         start_rev, end_rev,
1197
1260
                                         TRUE, /* look for copyfrom revs */
1198
1261
                                         validate_props,
1199
1262
                                         uuid_action,
1200
1263
                                         parent_dir,
 
1264
                                         use_pre_commit_hook,
 
1265
                                         use_post_commit_hook,
 
1266
                                         ignore_dates,
1201
1267
                                         notify_func,
1202
1268
                                         notify_baton,
1203
1269
                                         pool));
1204
1270
 
1205
 
  /* Heh.  We know this is a parse_baton.  This file made it.  So
1206
 
     cast away, and set our hook booleans.  */
1207
 
  pb = parse_baton;
1208
 
  pb->use_pre_commit_hook = use_pre_commit_hook;
1209
 
  pb->use_post_commit_hook = use_post_commit_hook;
1210
 
 
1211
1271
  return svn_repos_parse_dumpstream3(dumpstream, parser, parse_baton, FALSE,
1212
1272
                                     cancel_func, cancel_baton, pool);
1213
1273
}