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

« back to all changes in this revision

Viewing changes to subversion/libsvn_wc/entries.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:
45
45
#include "wc_db.h"
46
46
#include "wc-queries.h"  /* for STMT_*  */
47
47
 
 
48
#define SVN_WC__I_AM_WC_DB
 
49
 
48
50
#include "svn_private_config.h"
49
51
#include "private/svn_wc_private.h"
50
52
#include "private/svn_sqlite.h"
 
53
#include "token-map.h"
 
54
 
 
55
#include "wc_db_private.h"
51
56
 
52
57
#define MAYBE_ALLOC(x,p) ((x) ? (x) : apr_pcalloc((p), sizeof(*(x))))
53
58
 
213
218
                     svn_wc__db_lock_t **lock,
214
219
                     svn_wc__db_t *db,
215
220
                     const char *entry_abspath,
 
221
                     svn_wc__db_wcroot_t *wcroot,
 
222
                     const char *entry_relpath,
216
223
                     const svn_wc_entry_t *parent_entry,
217
224
                     svn_boolean_t have_base,
218
225
                     svn_boolean_t have_more_work,
221
228
{
222
229
  if (have_base && !have_more_work)
223
230
    {
 
231
      apr_int64_t repos_id;
224
232
      /* This is the delete of a BASE node */
225
 
      SVN_ERR(svn_wc__db_base_get_info(NULL, kind,
 
233
      SVN_ERR(svn_wc__db_base_get_info_internal(
 
234
                                       NULL, kind,
226
235
                                       &entry->revision,
227
236
                                       repos_relpath,
228
 
                                       &entry->repos,
229
 
                                       &entry->uuid,
 
237
                                       &repos_id,
230
238
                                       &entry->cmt_rev,
231
239
                                       &entry->cmt_date,
232
240
                                       &entry->cmt_author,
236
244
                                       lock,
237
245
                                       &entry->has_props, NULL,
238
246
                                       NULL,
239
 
                                       db,
240
 
                                       entry_abspath,
 
247
                                       wcroot, entry_relpath,
241
248
                                       result_pool,
242
249
                                       scratch_pool));
 
250
      SVN_ERR(svn_wc__db_fetch_repos_info(&entry->repos, &entry->uuid,
 
251
                                          wcroot, repos_id, result_pool));
243
252
    }
244
253
  else
245
254
    {
246
 
      const char *work_del_abspath;
 
255
      const char *work_del_relpath;
247
256
      const char *parent_repos_relpath;
248
 
      const char *parent_abspath;
 
257
      const char *parent_relpath;
 
258
      apr_int64_t repos_id;
249
259
 
250
260
      /* This is a deleted child of a copy/move-here,
251
261
         so we need to scan up the WORKING tree to find the root of
265
275
                                            scratch_pool));
266
276
      /* working_size and text_time unavailable */
267
277
 
268
 
     SVN_ERR(svn_wc__db_scan_deletion(NULL,
269
 
                                      NULL,
270
 
                                      &work_del_abspath, NULL,
271
 
                                      db, entry_abspath,
 
278
     SVN_ERR(svn_wc__db_scan_deletion_internal(
 
279
                                      NULL,
 
280
                                      NULL,
 
281
                                      &work_del_relpath, NULL,
 
282
                                      wcroot, entry_relpath,
272
283
                                      scratch_pool, scratch_pool));
273
284
 
274
 
      SVN_ERR_ASSERT(work_del_abspath != NULL);
275
 
      parent_abspath = svn_dirent_dirname(work_del_abspath, scratch_pool);
 
285
      SVN_ERR_ASSERT(work_del_relpath != NULL);
 
286
      parent_relpath = svn_relpath_dirname(work_del_relpath, scratch_pool);
276
287
 
277
288
      /* The parent directory of the delete root must be added, so we
278
289
         can find the required information there */
279
 
      SVN_ERR(svn_wc__db_scan_addition(NULL, NULL,
 
290
      SVN_ERR(svn_wc__db_scan_addition_internal(
 
291
                                       NULL, NULL,
280
292
                                       &parent_repos_relpath,
281
 
                                       &entry->repos,
282
 
                                       &entry->uuid,
283
 
                                       NULL, NULL, NULL, NULL,
284
 
                                       db, parent_abspath,
 
293
                                       &repos_id,
 
294
                                       NULL, NULL, NULL,
 
295
                                       wcroot, parent_relpath,
285
296
                                       result_pool, scratch_pool));
 
297
      SVN_ERR(svn_wc__db_fetch_repos_info(&entry->repos, &entry->uuid,
 
298
                                          wcroot, repos_id, result_pool));
286
299
 
287
300
      /* Now glue it all together */
288
301
      *repos_relpath = svn_relpath_join(parent_repos_relpath,
289
 
                                        svn_dirent_is_child(parent_abspath,
290
 
                                                            entry_abspath,
291
 
                                                            NULL),
 
302
                                        svn_relpath_skip_ancestor(
 
303
                                                            parent_relpath,
 
304
                                                            entry_relpath),
292
305
                                        result_pool);
293
306
 
294
307
 
297
310
      if (have_base)
298
311
        {
299
312
          svn_wc__db_status_t status;
300
 
          SVN_ERR(svn_wc__db_base_get_info(&status, NULL, &entry->revision,
 
313
          SVN_ERR(svn_wc__db_base_get_info_internal(
 
314
                                           &status, NULL, &entry->revision,
301
315
                                           NULL, NULL, NULL, NULL, NULL, NULL,
302
 
                                           NULL, NULL, NULL, lock, NULL, NULL,
 
316
                                           NULL, NULL, lock, NULL, NULL,
303
317
                                           NULL,
304
 
                                           db, entry_abspath,
 
318
                                           wcroot, entry_relpath,
305
319
                                           result_pool, scratch_pool));
306
320
 
307
321
          if (status == svn_wc__db_status_not_present)
346
360
    {
347
361
      svn_skel_t *c_skel;
348
362
 
349
 
      SVN_ERR(svn_wc__serialize_conflict(&c_skel, svn__apr_hash_index_val(hi),
 
363
      SVN_ERR(svn_wc__serialize_conflict(&c_skel, apr_hash_this_val(hi),
350
364
                                         pool, pool));
351
365
      svn_skel__prepend(c_skel, skel);
352
366
    }
369
383
   If this node is "this dir", then PARENT_ENTRY should be NULL. Otherwise,
370
384
   it should refer to the entry for the child's parent directory.
371
385
 
 
386
   ### All database read operations should really use wcroot, dir_relpath,
 
387
       as that restores obstruction compatibility with <= 1.6.0
 
388
       but that has been the case since the introduction of WC-NG in 1.7.0
 
389
 
372
390
   Temporary allocations are made in SCRATCH_POOL.  */
373
391
static svn_error_t *
374
392
read_one_entry(const svn_wc_entry_t **new_entry,
375
393
               svn_wc__db_t *db,
376
 
               apr_int64_t wc_id,
377
394
               const char *dir_abspath,
 
395
               svn_wc__db_wcroot_t *wcroot,
 
396
               const char *dir_relpath,
378
397
               const char *name,
379
398
               const svn_wc_entry_t *parent_entry,
380
399
               apr_pool_t *result_pool,
387
406
  const svn_checksum_t *checksum;
388
407
  svn_filesize_t translated_size;
389
408
  svn_wc_entry_t *entry = alloc_entry(result_pool);
 
409
  const char *entry_relpath;
390
410
  const char *entry_abspath;
 
411
  apr_int64_t repos_id;
 
412
  apr_int64_t original_repos_id;
391
413
  const char *original_repos_relpath;
392
414
  const char *original_root_url;
393
415
  svn_boolean_t conflicted;
394
416
  svn_boolean_t have_base;
395
417
  svn_boolean_t have_more_work;
396
 
 
397
 
  entry->name = name;
398
 
 
 
418
  svn_boolean_t op_root;
 
419
 
 
420
  entry->name = apr_pstrdup(result_pool, name);
 
421
 
 
422
  entry_relpath = svn_relpath_join(dir_relpath, entry->name, scratch_pool);
399
423
  entry_abspath = svn_dirent_join(dir_abspath, entry->name, scratch_pool);
400
424
 
401
 
  SVN_ERR(svn_wc__db_read_info(
 
425
  SVN_ERR(svn_wc__db_read_info_internal(
402
426
            &status,
403
427
            &kind,
404
428
            &entry->revision,
405
429
            &repos_relpath,
406
 
            &entry->repos,
407
 
            &entry->uuid,
 
430
            &repos_id,
408
431
            &entry->cmt_rev,
409
432
            &entry->cmt_date,
410
433
            &entry->cmt_author,
412
435
            &checksum,
413
436
            NULL,
414
437
            &original_repos_relpath,
415
 
            &original_root_url,
416
 
            NULL,
 
438
            &original_repos_id,
417
439
            &entry->copyfrom_rev,
418
440
            &lock,
419
441
            &translated_size,
420
442
            &entry->text_time,
421
443
            &entry->changelist,
422
444
            &conflicted,
423
 
            NULL /* op_root */,
 
445
            &op_root,
424
446
            &entry->has_props /* have_props */,
425
447
            &entry->has_prop_mods /* props_mod */,
426
448
            &have_base,
427
449
            &have_more_work,
428
450
            NULL /* have_work */,
429
 
            db,
430
 
            entry_abspath,
431
 
            result_pool,
432
 
            scratch_pool));
 
451
            wcroot, entry_relpath,
 
452
            result_pool, scratch_pool));
 
453
 
 
454
  SVN_ERR(svn_wc__db_fetch_repos_info(&entry->repos, &entry->uuid,
 
455
                                      wcroot, repos_id, result_pool));
 
456
  SVN_ERR(svn_wc__db_fetch_repos_info(&original_root_url, NULL,
 
457
                                      wcroot, original_repos_id,
 
458
                                      result_pool));
433
459
 
434
460
  if (entry->has_prop_mods)
435
461
    entry->has_props = TRUE;
457
483
          child_abspath = svn_dirent_join(dir_abspath, child_name,
458
484
                                          scratch_pool);
459
485
 
460
 
          SVN_ERR(svn_wc__read_conflicts(&child_conflicts,
 
486
          SVN_ERR(svn_wc__read_conflicts(&child_conflicts, NULL,
461
487
                                         db, child_abspath,
462
488
                                         FALSE /* create tempfiles */,
 
489
                                         TRUE /* tree_conflicts_only */,
463
490
                                         scratch_pool, scratch_pool));
464
491
 
465
492
          for (j = 0; j < child_conflicts->nelts; j++)
493
520
      /* Grab inherited repository information, if necessary. */
494
521
      if (repos_relpath == NULL)
495
522
        {
496
 
          SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath,
497
 
                                             &entry->repos,
498
 
                                             &entry->uuid,
499
 
                                             db,
500
 
                                             entry_abspath,
501
 
                                             result_pool,
502
 
                                             scratch_pool));
 
523
          SVN_ERR(svn_wc__db_base_get_info_internal(
 
524
                                           NULL, NULL, NULL, &repos_relpath,
 
525
                                           &repos_id, NULL, NULL, NULL,
 
526
                                           NULL, NULL, NULL, NULL, NULL, NULL,
 
527
                                           NULL,
 
528
                                           wcroot, entry_relpath,
 
529
                                           result_pool, scratch_pool));
 
530
          SVN_ERR(svn_wc__db_fetch_repos_info(&entry->repos, &entry->uuid,
 
531
                                              wcroot, repos_id, result_pool));
503
532
        }
504
533
 
505
534
      entry->incomplete = (status == svn_wc__db_status_incomplete);
519
548
        entry->copied = FALSE;
520
549
      else
521
550
        {
522
 
          const char *work_del_abspath;
523
 
          SVN_ERR(svn_wc__db_scan_deletion(NULL, NULL,
524
 
                                           &work_del_abspath, NULL,
525
 
                                           db, entry_abspath,
 
551
          const char *work_del_relpath;
 
552
          SVN_ERR(svn_wc__db_scan_deletion_internal(
 
553
                                           NULL, NULL,
 
554
                                           &work_del_relpath, NULL,
 
555
                                           wcroot, entry_relpath,
526
556
                                           scratch_pool, scratch_pool));
527
557
 
528
 
          if (work_del_abspath)
 
558
          if (work_del_relpath)
529
559
            entry->copied = TRUE;
530
560
        }
531
561
 
563
593
          /* ENTRY->REVISION is overloaded. When a node is schedule-add
564
594
             or -replace, then REVISION refers to the BASE node's revision
565
595
             that is being overwritten. We need to fetch it now.  */
566
 
          SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL,
 
596
          SVN_ERR(svn_wc__db_base_get_info_internal(
 
597
                                           &base_status, NULL,
567
598
                                           &entry->revision,
568
599
                                           NULL, NULL, NULL,
569
600
                                           NULL, NULL, NULL,
570
601
                                           NULL, NULL, NULL,
571
 
                                           NULL, NULL, NULL, NULL,
572
 
                                           db, entry_abspath,
 
602
                                           NULL, NULL, NULL,
 
603
                                           wcroot, entry_relpath,
573
604
                                           scratch_pool,
574
605
                                           scratch_pool));
575
606
 
603
634
         have important data. Set up stuff to kill that idea off,
604
635
         and finish up this entry.  */
605
636
        {
606
 
          SVN_ERR(svn_wc__db_scan_addition(&work_status,
607
 
                                           &op_root_abspath,
 
637
          const char *op_root_relpath;
 
638
          SVN_ERR(svn_wc__db_scan_addition_internal(
 
639
                                           &work_status,
 
640
                                           &op_root_relpath,
608
641
                                           &repos_relpath,
609
 
                                           &entry->repos,
610
 
                                           &entry->uuid,
 
642
                                           &repos_id,
611
643
                                           &scanned_original_relpath,
612
 
                                           NULL, NULL, /* original_root|uuid */
 
644
                                           NULL /* original_repos_id */,
613
645
                                           &original_revision,
614
 
                                           db,
615
 
                                           entry_abspath,
 
646
                                           wcroot, entry_relpath,
616
647
                                           result_pool, scratch_pool));
617
648
 
 
649
          SVN_ERR(svn_wc__db_fetch_repos_info(&entry->repos, &entry->uuid,
 
650
                                      wcroot, repos_id, result_pool));
 
651
 
 
652
          if (!op_root_relpath)
 
653
            op_root_abspath = NULL;
 
654
          else
 
655
            op_root_abspath = svn_dirent_join(wcroot->abspath, op_root_relpath,
 
656
                                              scratch_pool);
 
657
 
618
658
          /* In wc.db we want to keep the valid revision of the not-present
619
659
             BASE_REV, but when we used entries we set the revision to 0
620
660
             when adding a new node over a not present base node. */
633
673
          /* ### scan_addition may need to be updated to avoid returning
634
674
             ### status_copied in this case.  */
635
675
        }
636
 
      /* For backwards-compatiblity purposes we treat moves just like
 
676
      /* For backwards-compatibility purposes we treat moves just like
637
677
       * regular copies. */
638
678
      else if (work_status == svn_wc__db_status_copied ||
639
679
               work_status == svn_wc__db_status_moved_here)
675
715
             mixed-revision situation.  */
676
716
          if (!is_copied_child)
677
717
            {
678
 
              const char *parent_abspath;
 
718
              const char *parent_relpath;
679
719
              svn_error_t *err;
680
720
              const char *parent_repos_relpath;
681
721
              const char *parent_root_url;
 
722
              apr_int64_t parent_repos_id;
 
723
              const char *op_root_relpath;
682
724
 
683
725
              /* When we insert entries into the database, we will
684
726
                 construct additional copyfrom records for mixed-revision
705
747
                 Note that the parent could be added/copied/moved-here.
706
748
                 There is no way for it to be deleted/moved-away and
707
749
                 have *this* node appear as copied.  */
708
 
              parent_abspath = svn_dirent_dirname(entry_abspath,
709
 
                                                  scratch_pool);
710
 
              err = svn_wc__db_scan_addition(NULL,
711
 
                                             &op_root_abspath,
712
 
                                             NULL, NULL, NULL,
 
750
              parent_relpath = svn_relpath_dirname(entry_relpath,
 
751
                                                   scratch_pool);
 
752
              err = svn_wc__db_scan_addition_internal(
 
753
                                             NULL,
 
754
                                             &op_root_relpath,
 
755
                                             NULL, NULL,
713
756
                                             &parent_repos_relpath,
714
 
                                             &parent_root_url,
715
 
                                             NULL, NULL,
716
 
                                             db, parent_abspath,
 
757
                                             &parent_repos_id,
 
758
                                             NULL,
 
759
                                             wcroot, parent_relpath,
717
760
                                             scratch_pool,
718
761
                                             scratch_pool);
719
762
              if (err)
721
764
                  if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
722
765
                    return svn_error_trace(err);
723
766
                  svn_error_clear(err);
724
 
                }
725
 
              else if (parent_root_url != NULL
 
767
                  op_root_abspath = NULL;
 
768
                  parent_repos_relpath = NULL;
 
769
                  parent_root_url = NULL;
 
770
                }
 
771
              else
 
772
                {
 
773
                  SVN_ERR(svn_wc__db_fetch_repos_info(&parent_root_url, NULL,
 
774
                                                      wcroot, parent_repos_id,
 
775
                                                      scratch_pool));
 
776
                  op_root_abspath = svn_dirent_join(wcroot->abspath,
 
777
                                                    op_root_relpath,
 
778
                                                    scratch_pool);
 
779
                }
 
780
 
 
781
              if (parent_root_url != NULL
726
782
                       && strcmp(original_root_url, parent_root_url) == 0)
727
783
                {
 
784
                  
728
785
                  const char *relpath_to_entry = svn_dirent_is_child(
729
786
                    op_root_abspath, entry_abspath, NULL);
730
787
                  const char *entry_repos_relpath = svn_relpath_join(
827
884
                                   &checksum,
828
885
                                   &lock,
829
886
                                   db, entry_abspath,
 
887
                                   wcroot, entry_relpath,
830
888
                                   parent_entry,
831
889
                                   have_base, have_more_work,
832
890
                                   result_pool, scratch_pool));
869
927
      /* We got a SHA-1, get the corresponding MD-5. */
870
928
      if (checksum->kind != svn_checksum_md5)
871
929
        SVN_ERR(svn_wc__db_pristine_get_md5(&checksum, db,
872
 
                                            entry_abspath, checksum,
 
930
                                            dir_abspath, checksum,
873
931
                                            scratch_pool, scratch_pool));
874
932
 
875
933
      SVN_ERR_ASSERT(checksum->kind == svn_checksum_md5);
881
939
      svn_skel_t *conflict;
882
940
      svn_boolean_t text_conflicted;
883
941
      svn_boolean_t prop_conflicted;
884
 
      SVN_ERR(svn_wc__db_read_conflict(&conflict, db, entry_abspath,
885
 
                                       scratch_pool, scratch_pool));
 
942
      SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, NULL, NULL,
 
943
                                                wcroot, entry_relpath,
 
944
                                                scratch_pool, scratch_pool));
886
945
 
887
946
      SVN_ERR(svn_wc__conflict_read_info(NULL, NULL, &text_conflicted,
888
947
                                         &prop_conflicted, NULL,
955
1014
static svn_error_t *
956
1015
read_entries_new(apr_hash_t **result_entries,
957
1016
                 svn_wc__db_t *db,
958
 
                 const char *local_abspath,
 
1017
                 const char *dir_abspath,
 
1018
                 svn_wc__db_wcroot_t *wcroot,
 
1019
                 const char *dir_relpath,
959
1020
                 apr_pool_t *result_pool,
960
1021
                 apr_pool_t *scratch_pool)
961
1022
{
964
1025
  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
965
1026
  int i;
966
1027
  const svn_wc_entry_t *parent_entry;
967
 
  apr_int64_t wc_id = 1;  /* ### hacky. should remove.  */
968
1028
 
969
1029
  entries = apr_hash_make(result_pool);
970
1030
 
971
 
  SVN_ERR(read_one_entry(&parent_entry, db, wc_id, local_abspath,
 
1031
  SVN_ERR(read_one_entry(&parent_entry,
 
1032
                         db, dir_abspath,
 
1033
                         wcroot, dir_relpath,
972
1034
                         "" /* name */,
973
1035
                         NULL /* parent_entry */,
974
1036
                         result_pool, iterpool));
977
1039
  /* Use result_pool so that the child names (used by reference, rather
978
1040
     than copied) appear in result_pool.  */
979
1041
  SVN_ERR(svn_wc__db_read_children(&children, db,
980
 
                                   local_abspath,
981
 
                                   result_pool, iterpool));
 
1042
                                   dir_abspath,
 
1043
                                   scratch_pool, iterpool));
982
1044
  for (i = children->nelts; i--; )
983
1045
    {
984
1046
      const char *name = APR_ARRAY_IDX(children, i, const char *);
987
1049
      svn_pool_clear(iterpool);
988
1050
 
989
1051
      SVN_ERR(read_one_entry(&entry,
990
 
                             db, wc_id, local_abspath, name, parent_entry,
 
1052
                             db, dir_abspath, 
 
1053
                             wcroot, dir_relpath,
 
1054
                             name, parent_entry,
991
1055
                             result_pool, iterpool));
992
1056
      svn_hash_sets(entries, entry->name, entry);
993
1057
    }
1000
1064
}
1001
1065
 
1002
1066
 
1003
 
/* Read a pair of entries from wc_db in the directory DIR_ABSPATH. Return
1004
 
   the directory's entry in *PARENT_ENTRY and NAME's entry in *ENTRY. The
1005
 
   two returned pointers will be the same if NAME=="" ("this dir").
1006
 
 
1007
 
   The parent entry must exist.
1008
 
 
1009
 
   The requested entry MAY exist. If it does not, then NULL will be returned.
1010
 
 
1011
 
   The resulting entries are allocated in RESULT_POOL, and all temporary
1012
 
   allocations are made in SCRATCH_POOL.  */
1013
1067
static svn_error_t *
1014
 
read_entry_pair(const svn_wc_entry_t **parent_entry,
1015
 
                const svn_wc_entry_t **entry,
1016
 
                svn_wc__db_t *db,
1017
 
                const char *dir_abspath,
1018
 
                const char *name,
1019
 
                apr_pool_t *result_pool,
1020
 
                apr_pool_t *scratch_pool)
 
1068
read_entry_pair_txn(const svn_wc_entry_t **parent_entry,
 
1069
                    const svn_wc_entry_t **entry,
 
1070
                    svn_wc__db_t *db,
 
1071
                    const char *dir_abspath,
 
1072
                    svn_wc__db_wcroot_t *wcroot,
 
1073
                    const char *dir_relpath,
 
1074
                    const char *name,
 
1075
                    apr_pool_t *result_pool,
 
1076
                    apr_pool_t *scratch_pool)
1021
1077
{
1022
 
  apr_int64_t wc_id = 1;  /* ### hacky. should remove.  */
1023
 
 
1024
 
  SVN_ERR(read_one_entry(parent_entry, db, wc_id, dir_abspath,
 
1078
  SVN_ERR(read_one_entry(parent_entry,
 
1079
                         db, dir_abspath,
 
1080
                         wcroot, dir_relpath,
1025
1081
                         "" /* name */,
1026
1082
                         NULL /* parent_entry */,
1027
1083
                         result_pool, scratch_pool));
1073
1129
              svn_error_t *err;
1074
1130
 
1075
1131
              err = read_one_entry(entry,
1076
 
                                   db, wc_id, dir_abspath, name, *parent_entry,
 
1132
                                   db, dir_abspath,
 
1133
                                   wcroot, dir_relpath,
 
1134
                                   name, *parent_entry,
1077
1135
                                   result_pool, scratch_pool);
1078
1136
              if (err)
1079
1137
                {
1096
1154
  return SVN_NO_ERROR;
1097
1155
}
1098
1156
 
 
1157
/* Read a pair of entries from wc_db in the directory DIR_ABSPATH. Return
 
1158
   the directory's entry in *PARENT_ENTRY and NAME's entry in *ENTRY. The
 
1159
   two returned pointers will be the same if NAME=="" ("this dir").
 
1160
 
 
1161
   The parent entry must exist.
 
1162
 
 
1163
   The requested entry MAY exist. If it does not, then NULL will be returned.
 
1164
 
 
1165
   The resulting entries are allocated in RESULT_POOL, and all temporary
 
1166
   allocations are made in SCRATCH_POOL.  */
 
1167
static svn_error_t *
 
1168
read_entry_pair(const svn_wc_entry_t **parent_entry,
 
1169
                const svn_wc_entry_t **entry,
 
1170
                svn_wc__db_t *db,
 
1171
                const char *dir_abspath,
 
1172
                const char *name,
 
1173
                apr_pool_t *result_pool,
 
1174
                apr_pool_t *scratch_pool)
 
1175
{
 
1176
  svn_wc__db_wcroot_t *wcroot;
 
1177
  const char *dir_relpath;
 
1178
 
 
1179
  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &dir_relpath,
 
1180
                                                db, dir_abspath,
 
1181
                                                scratch_pool, scratch_pool));
 
1182
  VERIFY_USABLE_WCROOT(wcroot);
 
1183
 
 
1184
  SVN_WC__DB_WITH_TXN(read_entry_pair_txn(parent_entry, entry,
 
1185
                                          db, dir_abspath,
 
1186
                                          wcroot, dir_relpath,
 
1187
                                          name,
 
1188
                                          result_pool, scratch_pool),
 
1189
                      wcroot);
 
1190
 
 
1191
  return SVN_NO_ERROR;
 
1192
}
1099
1193
 
1100
1194
/* */
1101
1195
static svn_error_t *
1102
1196
read_entries(apr_hash_t **entries,
1103
1197
             svn_wc__db_t *db,
1104
 
             const char *wcroot_abspath,
 
1198
             const char *dir_abspath,
1105
1199
             apr_pool_t *result_pool,
1106
1200
             apr_pool_t *scratch_pool)
1107
1201
{
 
1202
  svn_wc__db_wcroot_t *wcroot;
 
1203
  const char *dir_relpath;
1108
1204
  int wc_format;
1109
1205
 
1110
 
  SVN_ERR(svn_wc__db_temp_get_format(&wc_format, db, wcroot_abspath,
 
1206
  SVN_ERR(svn_wc__db_temp_get_format(&wc_format, db, dir_abspath,
1111
1207
                                     scratch_pool));
1112
1208
 
1113
1209
  if (wc_format < SVN_WC__WC_NG_VERSION)
1114
1210
    return svn_error_trace(svn_wc__read_entries_old(entries,
1115
 
                                                    wcroot_abspath,
 
1211
                                                    dir_abspath,
1116
1212
                                                    result_pool,
1117
1213
                                                    scratch_pool));
1118
1214
 
1119
 
  return svn_error_trace(read_entries_new(entries, db, wcroot_abspath,
1120
 
                                          result_pool, scratch_pool));
 
1215
  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &dir_relpath,
 
1216
                                                db, dir_abspath,
 
1217
                                                scratch_pool, scratch_pool));
 
1218
  VERIFY_USABLE_WCROOT(wcroot);
 
1219
 
 
1220
  SVN_WC__DB_WITH_TXN(read_entries_new(entries,
 
1221
                                       db, dir_abspath,
 
1222
                                       wcroot, dir_relpath,
 
1223
                                       result_pool, scratch_pool),
 
1224
                      wcroot);
 
1225
 
 
1226
  return SVN_NO_ERROR;
1121
1227
}
1122
1228
 
1123
1229
 
1342
1448
      svn_boolean_t hidden;
1343
1449
 
1344
1450
      SVN_ERR(svn_wc__entry_is_hidden(&hidden,
1345
 
                                      svn__apr_hash_index_val(hi)));
 
1451
                                      apr_hash_this_val(hi)));
1346
1452
      if (hidden)
1347
1453
        break;
1348
1454
    }
1360
1466
       hi;
1361
1467
       hi = apr_hash_next(hi))
1362
1468
    {
1363
 
      const void *key = svn__apr_hash_index_key(hi);
1364
 
      const svn_wc_entry_t *entry = svn__apr_hash_index_val(hi);
 
1469
      const void *key = apr_hash_this_key(hi);
 
1470
      const svn_wc_entry_t *entry = apr_hash_this_val(hi);
1365
1471
      svn_boolean_t hidden;
1366
1472
 
1367
1473
      SVN_ERR(svn_wc__entry_is_hidden(&hidden, entry));
1372
1478
  return SVN_NO_ERROR;
1373
1479
}
1374
1480
 
1375
 
struct entries_read_baton_t
1376
 
{
1377
 
  apr_hash_t **new_entries;
1378
 
  svn_wc__db_t *db;
1379
 
  const char *local_abspath;
1380
 
  apr_pool_t *result_pool;
1381
 
};
1382
 
 
1383
 
static svn_error_t *
1384
 
entries_read_txn(void *baton, svn_sqlite__db_t *db, apr_pool_t *scratch_pool)
1385
 
{
1386
 
  struct entries_read_baton_t *erb = baton;
1387
 
 
1388
 
  SVN_ERR(read_entries(erb->new_entries, erb->db, erb->local_abspath,
1389
 
                       erb->result_pool, scratch_pool));
1390
 
 
1391
 
  return NULL;
1392
 
}
1393
 
 
1394
1481
svn_error_t *
1395
1482
svn_wc__entries_read_internal(apr_hash_t **entries,
1396
1483
                              svn_wc_adm_access_t *adm_access,
1405
1492
      svn_wc__db_t *db = svn_wc__adm_get_db(adm_access);
1406
1493
      const char *local_abspath = svn_wc__adm_access_abspath(adm_access);
1407
1494
      apr_pool_t *result_pool = svn_wc__adm_access_pool_internal(adm_access);
1408
 
      svn_sqlite__db_t *sdb;
1409
 
      struct entries_read_baton_t erb;
1410
 
 
1411
 
      /* ### Use the borrow DB api to handle all calls in a single read
1412
 
         ### transaction. This api is used extensively in our test suite
1413
 
         ### via the entries-read application. */
1414
 
 
1415
 
      SVN_ERR(svn_wc__db_temp_borrow_sdb(&sdb, db, local_abspath, pool));
1416
 
 
1417
 
      erb.db = db;
1418
 
      erb.local_abspath = local_abspath;
1419
 
      erb.new_entries = &new_entries;
1420
 
      erb.result_pool = result_pool;
1421
 
 
1422
 
      SVN_ERR(svn_sqlite__with_lock(sdb, entries_read_txn, &erb, pool));
 
1495
 
 
1496
      SVN_ERR(read_entries(&new_entries, db, local_abspath,
 
1497
                           result_pool, pool));
1423
1498
 
1424
1499
      svn_wc__adm_access_set_entries(adm_access, new_entries);
1425
1500
    }
1452
1527
            apr_pool_t *scratch_pool)
1453
1528
{
1454
1529
  svn_sqlite__stmt_t *stmt;
 
1530
  svn_boolean_t present = (node->presence == svn_wc__db_status_normal
 
1531
                           || node->presence == svn_wc__db_status_incomplete);
1455
1532
 
1456
1533
  SVN_ERR_ASSERT(node->op_depth > 0 || node->repos_relpath);
1457
1534
 
1458
1535
  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_NODE));
1459
 
  SVN_ERR(svn_sqlite__bindf(stmt, "isdsnnnnsnrisnnni",
 
1536
  SVN_ERR(svn_sqlite__bindf(stmt, "isdsnnnnsn",
1460
1537
                            node->wc_id,
1461
1538
                            node->local_relpath,
1462
1539
                            node->op_depth,
1463
1540
                            node->parent_relpath,
1464
1541
                            /* Setting depth for files? */
1465
 
                            svn_depth_to_word(node->depth),
1466
 
                            node->changed_rev,
1467
 
                            node->changed_date,
1468
 
                            node->changed_author,
1469
 
                            node->recorded_time));
1470
 
 
1471
 
  if (node->repos_relpath)
 
1542
                            (node->kind == svn_node_dir && present)
 
1543
                              ? svn_depth_to_word(node->depth)
 
1544
                              : NULL));
 
1545
 
 
1546
  if (present && node->repos_relpath)
 
1547
    {
 
1548
      SVN_ERR(svn_sqlite__bind_revnum(stmt, 11, node->changed_rev));
 
1549
      SVN_ERR(svn_sqlite__bind_int64(stmt, 12, node->changed_date));
 
1550
      SVN_ERR(svn_sqlite__bind_text(stmt, 13, node->changed_author));
 
1551
    }
 
1552
 
 
1553
  if (node->repos_relpath
 
1554
      && node->presence != svn_wc__db_status_base_deleted)
1472
1555
    {
1473
1556
      SVN_ERR(svn_sqlite__bind_int64(stmt, 5,
1474
1557
                                     node->repos_id));
1477
1560
      SVN_ERR(svn_sqlite__bind_revnum(stmt, 7, node->revision));
1478
1561
    }
1479
1562
 
1480
 
  if (node->presence == svn_wc__db_status_normal)
1481
 
    SVN_ERR(svn_sqlite__bind_text(stmt, 8, "normal"));
1482
 
  else if (node->presence == svn_wc__db_status_not_present)
1483
 
    SVN_ERR(svn_sqlite__bind_text(stmt, 8, "not-present"));
1484
 
  else if (node->presence == svn_wc__db_status_base_deleted)
1485
 
    SVN_ERR(svn_sqlite__bind_text(stmt, 8, "base-deleted"));
1486
 
  else if (node->presence == svn_wc__db_status_incomplete)
1487
 
    SVN_ERR(svn_sqlite__bind_text(stmt, 8, "incomplete"));
1488
 
  else if (node->presence == svn_wc__db_status_excluded)
1489
 
    SVN_ERR(svn_sqlite__bind_text(stmt, 8, "excluded"));
1490
 
  else if (node->presence == svn_wc__db_status_server_excluded)
1491
 
    SVN_ERR(svn_sqlite__bind_text(stmt, 8, "server-excluded"));
 
1563
  SVN_ERR(svn_sqlite__bind_token(stmt, 8, presence_map, node->presence));
1492
1564
 
1493
1565
  if (node->kind == svn_node_none)
1494
1566
    SVN_ERR(svn_sqlite__bind_text(stmt, 10, "unknown"));
1495
1567
  else
1496
 
    SVN_ERR(svn_sqlite__bind_text(stmt, 10,
1497
 
                                  svn_node_kind_to_word(node->kind)));
 
1568
    SVN_ERR(svn_sqlite__bind_token(stmt, 10, kind_map, node->kind));
1498
1569
 
1499
 
  if (node->kind == svn_node_file)
 
1570
  if (node->kind == svn_node_file && present)
1500
1571
    {
1501
1572
      if (!node->checksum
1502
1573
          && node->op_depth == 0
1510
1581
 
1511
1582
      SVN_ERR(svn_sqlite__bind_checksum(stmt, 14, node->checksum,
1512
1583
                                        scratch_pool));
 
1584
 
 
1585
      if (node->repos_relpath)
 
1586
        {
 
1587
          if (node->recorded_size != SVN_INVALID_FILESIZE)
 
1588
            SVN_ERR(svn_sqlite__bind_int64(stmt, 16, node->recorded_size));
 
1589
 
 
1590
          SVN_ERR(svn_sqlite__bind_int64(stmt, 17, node->recorded_time));
 
1591
        }
1513
1592
    }
1514
1593
 
1515
 
  if (node->properties) /* ### Never set, props done later */
 
1594
   /* ### Never set, props done later */
 
1595
  if (node->properties && present && node->repos_relpath)
1516
1596
    SVN_ERR(svn_sqlite__bind_properties(stmt, 15, node->properties,
1517
1597
                                        scratch_pool));
1518
1598
 
1519
 
  if (node->recorded_size != SVN_INVALID_FILESIZE)
1520
 
    SVN_ERR(svn_sqlite__bind_int64(stmt, 16, node->recorded_size));
1521
 
 
1522
1599
  if (node->file_external)
1523
1600
    SVN_ERR(svn_sqlite__bind_int(stmt, 20, 1));
1524
1601
 
1525
 
  if (node->inherited_props)
 
1602
  if (node->inherited_props && present)
1526
1603
    SVN_ERR(svn_sqlite__bind_iprops(stmt, 23, node->inherited_props,
1527
1604
                                    scratch_pool));
1528
1605
 
1801
1878
 
1802
1879
  if (entry->copied)
1803
1880
    {
 
1881
      db_node_t *work = parent_node->work
 
1882
                              ? parent_node->work
 
1883
                              : parent_node->below_work;
 
1884
 
1804
1885
      if (entry->copyfrom_url)
1805
1886
        {
1806
1887
          working_node->repos_id = repos_id;
1810
1891
          working_node->revision = entry->copyfrom_rev;
1811
1892
          working_node->op_depth
1812
1893
            = svn_wc__db_op_depth_for_upgrade(local_relpath);
 
1894
 
 
1895
          if (work && work->repos_relpath
 
1896
              && work->repos_id == repos_id
 
1897
              && work->revision == entry->copyfrom_rev)
 
1898
            {
 
1899
              const char *name;
 
1900
 
 
1901
              name = svn_relpath_skip_ancestor(work->repos_relpath,
 
1902
                                               working_node->repos_relpath);
 
1903
 
 
1904
              if (name
 
1905
                  && !strcmp(name, svn_relpath_basename(local_relpath, NULL)))
 
1906
                {
 
1907
                  working_node->op_depth = work->op_depth;
 
1908
                }
 
1909
            }
1813
1910
        }
1814
 
      else if (parent_node->work && parent_node->work->repos_relpath)
 
1911
      else if (work && work->repos_relpath)
1815
1912
        {
1816
1913
          working_node->repos_id = repos_id;
1817
1914
          working_node->repos_relpath
1818
 
            = svn_relpath_join(parent_node->work->repos_relpath,
 
1915
            = svn_relpath_join(work->repos_relpath,
1819
1916
                               svn_relpath_basename(local_relpath, NULL),
1820
1917
                               result_pool);
1821
 
          working_node->revision = parent_node->work->revision;
1822
 
          working_node->op_depth = parent_node->work->op_depth;
 
1918
          working_node->revision = work->revision;
 
1919
          working_node->op_depth = work->op_depth;
1823
1920
        }
1824
1921
      else if (parent_node->below_work
1825
1922
                && parent_node->below_work->repos_relpath)
1826
1923
        {
 
1924
          /* Parent deleted, this not-present or similar */
1827
1925
          working_node->repos_id = repos_id;
1828
1926
          working_node->repos_relpath
1829
1927
            = svn_relpath_join(parent_node->below_work->repos_relpath,
1837
1935
                                 _("No copyfrom URL for '%s'"),
1838
1936
                                 svn_dirent_local_style(local_relpath,
1839
1937
                                                        scratch_pool));
 
1938
 
 
1939
      if (work && work->op_depth != working_node->op_depth
 
1940
          && work->repos_relpath
 
1941
          && work->repos_id == working_node->repos_id
 
1942
          && work->presence == svn_wc__db_status_normal
 
1943
          && !below_working_node)
 
1944
        {
 
1945
          /* Introduce a not-present node! */
 
1946
          below_working_node = MAYBE_ALLOC(below_working_node, scratch_pool);
 
1947
 
 
1948
          below_working_node->wc_id = wc_id;
 
1949
          below_working_node->op_depth = work->op_depth;
 
1950
          below_working_node->local_relpath = local_relpath;
 
1951
          below_working_node->parent_relpath = parent_relpath;
 
1952
 
 
1953
          below_working_node->presence = svn_wc__db_status_not_present;
 
1954
          below_working_node->repos_id = repos_id;
 
1955
          below_working_node->repos_relpath = working_node->local_relpath;
 
1956
 
 
1957
          SVN_ERR(insert_node(sdb, below_working_node, scratch_pool));
 
1958
 
 
1959
          below_working_node = NULL; /* Don't write a present intermediate! */
 
1960
        }
1840
1961
    }
1841
1962
 
1842
1963
  if (entry->conflict_old)
1892
2013
                             scratch_pool);
1893
2014
      tree_conflicts = apr_hash_make(result_pool);
1894
2015
      skel = skel->children;
1895
 
      while(skel)
 
2016
      while (skel)
1896
2017
        {
1897
2018
          svn_wc_conflict_description2_t *conflict;
1898
2019
          svn_skel_t *new_skel;
1909
2030
 
1910
2031
          WRITE_ENTRY_ASSERT(conflict->kind == svn_wc_conflict_kind_tree);
1911
2032
 
1912
 
          /* Fix dubious data stored by old clients, local adds don't have
1913
 
             a repository URL. */
1914
 
          if (conflict->reason == svn_wc_conflict_reason_added)
1915
 
            conflict->src_left_version = NULL;
1916
 
 
1917
2033
          SVN_ERR(svn_wc__serialize_conflict(&new_skel, conflict,
1918
2034
                                             scratch_pool, scratch_pool));
1919
2035
 
2295
2411
        {
2296
2412
          working_node->op_depth = parent_node->work->op_depth;
2297
2413
        }
 
2414
      else if (working_node->presence == svn_wc__db_status_excluded
 
2415
               && parent_node->work)
 
2416
        {
 
2417
          working_node->op_depth = parent_node->work->op_depth;
 
2418
        }
2298
2419
      else if (!entry->copied)
2299
2420
        {
2300
2421
          working_node->op_depth
2358
2479
 
2359
2480
      actual_node = MAYBE_ALLOC(actual_node, scratch_pool);
2360
2481
      actual_node->wc_id = wc_id;
2361
 
      actual_node->local_relpath = svn__apr_hash_index_key(hi);
 
2482
      actual_node->local_relpath = apr_hash_this_key(hi);
2362
2483
      actual_node->parent_relpath = parent_relpath;
2363
 
      actual_node->tree_conflict_data = svn__apr_hash_index_val(hi);
 
2484
      actual_node->tree_conflict_data = apr_hash_this_val(hi);
2364
2485
 
2365
2486
      SVN_ERR(insert_actual_node(sdb, db, wri_abspath, actual_node,
2366
2487
                                 scratch_pool));
2418
2539
  for (hi = apr_hash_first(scratch_pool, entries); hi;
2419
2540
       hi = apr_hash_next(hi))
2420
2541
    {
2421
 
      const char *name = svn__apr_hash_index_key(hi);
2422
 
      const svn_wc_entry_t *this_entry = svn__apr_hash_index_val(hi);
 
2542
      const char *name = apr_hash_this_key(hi);
 
2543
      const svn_wc_entry_t *this_entry = apr_hash_this_val(hi);
2423
2544
      const char *child_abspath, *child_relpath;
2424
2545
      svn_wc__text_base_info_t *text_base_info
2425
2546
        = svn_hash_gets(text_bases_info, name);
2573
2694
  /* Loop over each of the other entries. */
2574
2695
  for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))
2575
2696
    {
2576
 
      const char *name = svn__apr_hash_index_key(hi);
2577
 
      const svn_wc_entry_t *current_entry = svn__apr_hash_index_val(hi);
 
2697
      const char *name = apr_hash_this_key(hi);
 
2698
      const svn_wc_entry_t *current_entry = apr_hash_this_val(hi);
2578
2699
      const char *entrypath;
2579
2700
      const char *entry_abspath;
2580
2701
      svn_boolean_t hidden;
2661
2782
  svn_wc__db_t *db = svn_wc__adm_get_db(adm_access);
2662
2783
  svn_error_t *err;
2663
2784
  svn_node_kind_t kind;
2664
 
  svn_depth_t depth;
 
2785
  svn_wc__db_status_t status;
2665
2786
 
2666
2787
  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
2667
 
  err = svn_wc__db_read_info(NULL, &kind, NULL, NULL, NULL, NULL,
2668
 
                             NULL, NULL, NULL, &depth, NULL, NULL,
 
2788
  err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
 
2789
                             NULL, NULL, NULL, NULL, NULL, NULL,
2669
2790
                             NULL, NULL, NULL, NULL, NULL, NULL,
2670
2791
                             NULL, NULL, NULL, NULL, NULL, NULL,
2671
2792
                             NULL, NULL, NULL,
2684
2805
        walk_baton, pool);
2685
2806
    }
2686
2807
 
2687
 
  if (kind == svn_node_file || depth == svn_depth_exclude)
 
2808
  if (kind == svn_node_file
 
2809
      || status == svn_wc__db_status_excluded
 
2810
      || status == svn_wc__db_status_server_excluded)
2688
2811
    {
2689
2812
      const svn_wc_entry_t *entry;
2690
2813
 
2693
2816
         ### we should not call handle_error for an error the *callback*
2694
2817
         ###   gave us. let it deal with the problem before returning.  */
2695
2818
 
2696
 
      if (!show_hidden)
 
2819
      if (!show_hidden
 
2820
          && (status == svn_wc__db_status_not_present
 
2821
              || status == svn_wc__db_status_excluded
 
2822
              || status == svn_wc__db_status_server_excluded))
2697
2823
        {
2698
 
          svn_boolean_t hidden;
2699
 
          SVN_ERR(svn_wc__db_node_hidden(&hidden, db, local_abspath, pool));
2700
 
 
2701
 
          if (hidden)
2702
 
            {
2703
 
              /* The fool asked to walk a "hidden" node. Report the node as
2704
 
                 unversioned.
2705
 
 
2706
 
                 ### this is incorrect behavior. see depth_test 36. the walk
2707
 
                 ### API will be revamped to avoid entry structures. we should
2708
 
                 ### be able to solve the problem with the new API. (since we
2709
 
                 ### shouldn't return a hidden entry here)  */
2710
 
              return walk_callbacks->handle_error(
2711
 
                               path, svn_error_createf(
2712
 
                                  SVN_ERR_UNVERSIONED_RESOURCE, NULL,
2713
 
                                  _("'%s' is not under version control"),
2714
 
                                  svn_dirent_local_style(local_abspath, pool)),
2715
 
                               walk_baton, pool);
2716
 
            }
 
2824
          /* The fool asked to walk a "hidden" node. Report the node as
 
2825
              unversioned.
 
2826
 
 
2827
              ### this is incorrect behavior. see depth_test 36. the walk
 
2828
              ### API will be revamped to avoid entry structures. we should
 
2829
              ### be able to solve the problem with the new API. (since we
 
2830
              ### shouldn't return a hidden entry here)  */
 
2831
          return walk_callbacks->handle_error(
 
2832
                            path, svn_error_createf(
 
2833
                              SVN_ERR_UNVERSIONED_RESOURCE, NULL,
 
2834
                              _("'%s' is not under version control"),
 
2835
                              svn_dirent_local_style(local_abspath, pool)),
 
2836
                            walk_baton, pool);
2717
2837
        }
2718
2838
 
2719
2839
      SVN_ERR(svn_wc__get_entry(&entry, db, local_abspath, FALSE,