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

« back to all changes in this revision

Viewing changes to subversion/libsvn_wc/update_editor.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:
211
211
 
212
212
  /* If this is a 'switch' operation, the new relpath of target_abspath,
213
213
     else NULL. */
214
 
  const char *switch_relpath;
 
214
  const char *switch_repos_relpath;
215
215
 
216
216
  /* The URL to the root of the repository. */
217
217
  const char *repos_root;
258
258
  /* Absolute path of the working copy root or NULL if not initialized yet */
259
259
  const char *wcroot_abspath;
260
260
 
 
261
  /* After closing the root directory a copy of its edited value */
 
262
  svn_boolean_t edited;
 
263
 
261
264
  apr_pool_t *pool;
262
265
};
263
266
 
295
298
  const char *local_abspath;
296
299
 
297
300
  /* The repository relative path this directory will correspond to. */
298
 
  const char *new_relpath;
 
301
  const char *new_repos_relpath;
299
302
 
300
303
  /* The revision of the directory before updating */
301
304
  svn_revnum_t old_revision;
342
345
     and reinstall it. */
343
346
  apr_hash_t *deletion_conflicts;
344
347
 
345
 
  /* A hash of file names (only the hash key matters) seen by add_file
346
 
     and not yet added to the database by close_file. */
347
 
  apr_hash_t *not_present_files;
 
348
  /* A hash of file names (only the hash key matters) seen by add_file and
 
349
     add_directory and not yet added to the database, mapping to a const
 
350
     char * node kind (via svn_node_kind_to_word(). */
 
351
  apr_hash_t *not_present_nodes;
348
352
 
349
353
  /* Set if an unversioned dir of the same name already existed in
350
354
     this directory. */
398
402
  struct file_baton *fb;
399
403
 
400
404
  /* Where we are assembling the new file. */
401
 
  const char *new_text_base_tmp_abspath;
 
405
  svn_wc__db_install_data_t *install_data;
402
406
 
403
407
    /* The expected source checksum of the text source or NULL if no base
404
408
     checksum is available (MD5 if the server provides a checksum, SHA1 if
412
416
     provide a sha1, so we may not have to calculate both, but for the time
413
417
     being, that's the way it is. */
414
418
 
415
 
  /* The calculated checksum of the text source or NULL if the acual
 
419
  /* The calculated checksum of the text source or NULL if the actual
416
420
     checksum is not being calculated. The checksum kind is identical to the
417
421
     kind of expected_source_checksum. */
418
422
  svn_checksum_t *actual_source_checksum;
486
490
  return APR_SUCCESS;
487
491
}
488
492
 
 
493
/* Calculate the new repos_relpath for a directory or file */
 
494
static svn_error_t *
 
495
calculate_repos_relpath(const char **new_repos_relpath,
 
496
                        const char *local_abspath,
 
497
                        const char *old_repos_relpath,
 
498
                        struct edit_baton *eb,
 
499
                        struct dir_baton *pb,
 
500
                        apr_pool_t *result_pool,
 
501
                        apr_pool_t *scratch_pool)
 
502
{
 
503
  const char *name = svn_dirent_basename(local_abspath, NULL);
 
504
 
 
505
  /* Figure out the new_repos_relpath for this directory. */
 
506
  if (eb->switch_repos_relpath)
 
507
    {
 
508
      /* Handle switches... */
 
509
 
 
510
      if (pb == NULL)
 
511
        {
 
512
          if (*eb->target_basename == '\0')
 
513
            {
 
514
              /* No parent baton and target_basename=="" means that we are
 
515
                 the target of the switch. Thus, our new_repos_relpath will be
 
516
                 the switch_repos_relpath.  */
 
517
              *new_repos_relpath = eb->switch_repos_relpath;
 
518
            }
 
519
          else
 
520
            {
 
521
              /* This node is NOT the target of the switch (one of our
 
522
                 children is the target); therefore, it must already exist.
 
523
                 Get its old REPOS_RELPATH, as it won't be changing.  */
 
524
              *new_repos_relpath = apr_pstrdup(result_pool, old_repos_relpath);
 
525
            }
 
526
        }
 
527
      else
 
528
        {
 
529
          /* This directory is *not* the root (has a parent). If there is
 
530
             no grandparent, then we may have anchored at the parent,
 
531
             and self is the target. If we match the target, then set
 
532
             new_repos_relpath to the switch_repos_relpath.
 
533
 
 
534
             Otherwise, we simply extend new_repos_relpath from the parent.  */
 
535
 
 
536
          if (pb->parent_baton == NULL
 
537
              && strcmp(eb->target_basename, name) == 0)
 
538
            *new_repos_relpath = eb->switch_repos_relpath;
 
539
          else
 
540
            *new_repos_relpath = svn_relpath_join(pb->new_repos_relpath, name,
 
541
                                                  result_pool);
 
542
        }
 
543
    }
 
544
  else  /* must be an update */
 
545
    {
 
546
      /* If we are adding the node, then simply extend the parent's
 
547
         relpath for our own.  */
 
548
      if (old_repos_relpath == NULL)
 
549
        {
 
550
          SVN_ERR_ASSERT(pb != NULL);
 
551
          *new_repos_relpath = svn_relpath_join(pb->new_repos_relpath, name,
 
552
                                                result_pool);
 
553
        }
 
554
      else
 
555
        {
 
556
          *new_repos_relpath = apr_pstrdup(result_pool, old_repos_relpath);
 
557
        }
 
558
    }
 
559
 
 
560
  return SVN_NO_ERROR;
 
561
}
 
562
 
489
563
/* Make a new dir baton in a subpool of PB->pool. PB is the parent baton.
490
564
   If PATH and PB are NULL, this is the root directory of the edit; in this
491
565
   case, make the new dir baton in a subpool of EB->pool.
525
599
      d->local_abspath = eb->anchor_abspath;
526
600
    }
527
601
 
528
 
  /* Figure out the new_relpath for this directory. */
529
 
  if (eb->switch_relpath)
530
 
    {
531
 
      /* Handle switches... */
532
 
 
533
 
      if (pb == NULL)
534
 
        {
535
 
          if (*eb->target_basename == '\0')
536
 
            {
537
 
              /* No parent baton and target_basename=="" means that we are
538
 
                 the target of the switch. Thus, our NEW_RELPATH will be
539
 
                 the SWITCH_RELPATH.  */
540
 
              d->new_relpath = eb->switch_relpath;
541
 
            }
542
 
          else
543
 
            {
544
 
              /* This node is NOT the target of the switch (one of our
545
 
                 children is the target); therefore, it must already exist.
546
 
                 Get its old REPOS_RELPATH, as it won't be changing.  */
547
 
              SVN_ERR(svn_wc__db_scan_base_repos(&d->new_relpath, NULL, NULL,
548
 
                                                 eb->db, d->local_abspath,
549
 
                                                 dir_pool, scratch_pool));
550
 
            }
551
 
        }
552
 
      else
553
 
        {
554
 
          /* This directory is *not* the root (has a parent). If there is
555
 
             no grandparent, then we may have anchored at the parent,
556
 
             and self is the target. If we match the target, then set
557
 
             NEW_RELPATH to the SWITCH_RELPATH.
558
 
 
559
 
             Otherwise, we simply extend NEW_RELPATH from the parent.  */
560
 
          if (pb->parent_baton == NULL
561
 
              && strcmp(eb->target_basename, d->name) == 0)
562
 
            d->new_relpath = eb->switch_relpath;
563
 
          else
564
 
            d->new_relpath = svn_relpath_join(pb->new_relpath, d->name,
565
 
                                              dir_pool);
566
 
        }
567
 
    }
568
 
  else  /* must be an update */
569
 
    {
570
 
      /* If we are adding the node, then simply extend the parent's
571
 
         relpath for our own.  */
572
 
      if (adding)
573
 
        {
574
 
          SVN_ERR_ASSERT(pb != NULL);
575
 
          d->new_relpath = svn_relpath_join(pb->new_relpath, d->name,
576
 
                                            dir_pool);
577
 
        }
578
 
      else
579
 
        {
580
 
          SVN_ERR(svn_wc__db_scan_base_repos(&d->new_relpath, NULL, NULL,
581
 
                                             eb->db, d->local_abspath,
582
 
                                             dir_pool, scratch_pool));
583
 
          SVN_ERR_ASSERT(d->new_relpath);
584
 
        }
585
 
    }
586
 
 
587
602
  d->edit_baton   = eb;
588
603
  d->parent_baton = pb;
589
604
  d->pool         = dir_pool;
594
609
  d->old_revision = SVN_INVALID_REVNUM;
595
610
  d->adding_dir   = adding;
596
611
  d->changed_rev  = SVN_INVALID_REVNUM;
597
 
  d->not_present_files = apr_hash_make(dir_pool);
 
612
  d->not_present_nodes = apr_hash_make(dir_pool);
598
613
 
599
614
  /* Copy some flags from the parent baton */
600
615
  if (pb)
614
629
  return SVN_NO_ERROR;
615
630
}
616
631
 
617
 
 
618
632
/* Forward declarations. */
619
633
static svn_error_t *
620
634
already_in_a_tree_conflict(svn_boolean_t *conflicted,
680
694
  const char *local_abspath;
681
695
 
682
696
  /* The repository relative path this file will correspond to. */
683
 
  const char *new_relpath;
 
697
  const char *new_repos_relpath;
684
698
 
685
699
  /* The revision of the file before updating */
686
700
  svn_revnum_t old_revision;
764
778
                svn_boolean_t adding,
765
779
                apr_pool_t *scratch_pool)
766
780
{
767
 
  struct edit_baton *eb = pb->edit_baton;
768
781
  apr_pool_t *file_pool = svn_pool_create(pb->pool);
769
782
  struct file_baton *f = apr_pcalloc(file_pool, sizeof(*f));
770
783
 
776
789
  SVN_ERR(path_join_under_root(&f->local_abspath,
777
790
                               pb->local_abspath, f->name, file_pool));
778
791
 
779
 
  /* Figure out the new URL for this file. */
780
 
  if (eb->switch_relpath)
781
 
    {
782
 
      /* Handle switches... */
783
 
 
784
 
      /* This file has a parent directory. If there is
785
 
         no grandparent, then we may have anchored at the parent,
786
 
         and self is the target. If we match the target, then set
787
 
         NEW_RELPATH to the SWITCH_RELPATH.
788
 
 
789
 
         Otherwise, we simply extend NEW_RELPATH from the parent.  */
790
 
      if (pb->parent_baton == NULL
791
 
          && strcmp(eb->target_basename, f->name) == 0)
792
 
        f->new_relpath = eb->switch_relpath;
793
 
      else
794
 
        f->new_relpath = svn_relpath_join(pb->new_relpath, f->name,
795
 
                                          file_pool);
796
 
    }
797
 
  else  /* must be an update */
798
 
    {
799
 
      if (adding)
800
 
        f->new_relpath = svn_relpath_join(pb->new_relpath, f->name, file_pool);
801
 
      else
802
 
        {
803
 
          SVN_ERR(svn_wc__db_scan_base_repos(&f->new_relpath, NULL, NULL,
804
 
                                             eb->db, f->local_abspath,
805
 
                                             file_pool, scratch_pool));
806
 
          SVN_ERR_ASSERT(f->new_relpath);
807
 
        }
808
 
    }
809
 
 
810
792
  f->pool              = file_pool;
811
793
  f->edit_baton        = pb->edit_baton;
812
794
  f->propchanges       = apr_array_make(file_pool, 1, sizeof(svn_prop_t));
843
825
                  const char *new_repos_relpath,
844
826
                  svn_node_kind_t local_kind,
845
827
                  svn_node_kind_t target_kind,
 
828
                  const svn_skel_t *delete_conflict,
846
829
                  apr_pool_t *result_pool,
847
830
                  apr_pool_t *scratch_pool)
848
831
{
849
 
  svn_wc_conflict_version_t *original_version;
 
832
  const svn_wc_conflict_version_t *original_version = NULL;
850
833
  svn_wc_conflict_version_t *target_version;
851
834
  svn_boolean_t is_complete;
852
835
 
 
836
  SVN_ERR_ASSERT(new_repos_relpath);
 
837
 
853
838
  if (!conflict)
854
839
    return SVN_NO_ERROR; /* Not conflicted */
855
840
 
865
850
                                                       old_revision,
866
851
                                                       local_kind,
867
852
                                                       result_pool);
868
 
  else
869
 
    original_version = NULL;
870
 
 
871
 
  if (new_repos_relpath)
872
 
    target_version = svn_wc_conflict_version_create2(eb->repos_root,
873
 
                                                        eb->repos_uuid,
874
 
                                                        new_repos_relpath,
875
 
                                                        *eb->target_revision,
876
 
                                                        target_kind,
877
 
                                                        result_pool);
878
 
  else
879
 
    target_version = NULL;
880
 
 
881
 
  if (eb->switch_relpath)
 
853
  else if (delete_conflict)
 
854
    {
 
855
      const apr_array_header_t *locations;
 
856
 
 
857
      SVN_ERR(svn_wc__conflict_read_info(NULL, &locations, NULL, NULL, NULL,
 
858
                                         eb->db, local_abspath,
 
859
                                         delete_conflict,
 
860
                                         scratch_pool, scratch_pool));
 
861
 
 
862
      if (locations)
 
863
        {
 
864
          original_version = APR_ARRAY_IDX(locations, 0,
 
865
                                           const svn_wc_conflict_version_t *);
 
866
        }
 
867
    }
 
868
 
 
869
  target_version = svn_wc_conflict_version_create2(eb->repos_root,
 
870
                                                   eb->repos_uuid,
 
871
                                                   new_repos_relpath,
 
872
                                                   *eb->target_revision,
 
873
                                                   target_kind,
 
874
                                                   result_pool);
 
875
 
 
876
  if (eb->switch_repos_relpath)
882
877
    SVN_ERR(svn_wc__conflict_skel_set_op_switch(conflict,
883
878
                                                original_version,
884
879
                                                target_version,
913
908
      SVN_ERR(complete_conflict(db->edit_conflict, db->edit_baton,
914
909
                                db->local_abspath,
915
910
                                db->old_repos_relpath, db->old_revision,
916
 
                                db->new_relpath,
 
911
                                db->new_repos_relpath,
917
912
                                svn_node_dir, svn_node_dir,
 
913
                                NULL,
918
914
                                db->pool, scratch_pool));
919
915
      SVN_ERR(svn_wc__db_op_mark_conflict(db->edit_baton->db,
920
916
                                          db->local_abspath,
924
920
      do_notification(db->edit_baton, db->local_abspath, svn_node_dir,
925
921
                      svn_wc_notify_tree_conflict, scratch_pool);
926
922
      db->already_notified = TRUE;
927
 
 
928
923
    }
929
924
 
930
925
  return SVN_NO_ERROR;
948
943
 
949
944
      SVN_ERR(complete_conflict(fb->edit_conflict, fb->edit_baton,
950
945
                                fb->local_abspath, fb->old_repos_relpath,
951
 
                                fb->old_revision, fb->new_relpath,
 
946
                                fb->old_revision, fb->new_repos_relpath,
952
947
                                svn_node_file, svn_node_file,
 
948
                                NULL,
953
949
                                fb->pool, scratch_pool));
954
950
 
955
951
      SVN_ERR(svn_wc__db_op_mark_conflict(fb->edit_baton->db,
974
970
{
975
971
  struct handler_baton *hb = baton;
976
972
  struct file_baton *fb = hb->fb;
977
 
  svn_wc__db_t *db = fb->edit_baton->db;
978
973
  svn_error_t *err;
979
974
 
980
975
  /* Apply this window.  We may be done at that point.  */
1014
1009
    {
1015
1010
      /* We failed to apply the delta; clean up the temporary file if it
1016
1011
         already created by lazy_open_target(). */
1017
 
      if (hb->new_text_base_tmp_abspath)
 
1012
      if (hb->install_data)
1018
1013
        {
1019
 
          svn_error_clear(svn_io_remove_file2(hb->new_text_base_tmp_abspath,
1020
 
                                              TRUE, hb->pool));
 
1014
          svn_error_clear(svn_wc__db_pristine_install_abort(hb->install_data,
 
1015
                                                            hb->pool));
1021
1016
        }
1022
1017
    }
1023
1018
  else
1031
1026
      /* Store the new pristine text in the pristine store now.  Later, in a
1032
1027
         single transaction we will update the BASE_NODE to include a
1033
1028
         reference to this pristine text's checksum. */
1034
 
      SVN_ERR(svn_wc__db_pristine_install(db, hb->new_text_base_tmp_abspath,
 
1029
      SVN_ERR(svn_wc__db_pristine_install(hb->install_data,
1035
1030
                                          fb->new_text_base_sha1_checksum,
1036
1031
                                          fb->new_text_base_md5_checksum,
1037
1032
                                          hb->pool));
1154
1149
  return SVN_NO_ERROR;
1155
1150
}
1156
1151
 
1157
 
static svn_error_t *
1158
 
check_tree_conflict(svn_skel_t **pconflict,
1159
 
                    struct edit_baton *eb,
1160
 
                    const char *local_abspath,
1161
 
                    svn_wc__db_status_t working_status,
1162
 
                    svn_boolean_t exists_in_repos,
1163
 
                    svn_node_kind_t expected_kind,
1164
 
                    svn_wc_conflict_action_t action,
1165
 
                    apr_pool_t *result_pool,
1166
 
                    apr_pool_t *scratch_pool);
1167
 
 
1168
1152
/* An svn_delta_editor_t function. */
1169
1153
static svn_error_t *
1170
1154
open_root(void *edit_baton,
1228
1212
                               eb->db, db->local_abspath,
1229
1213
                               db->pool, pool));
1230
1214
 
 
1215
  if (have_work)
 
1216
    {
 
1217
      SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL,
 
1218
                                       &db->old_revision,
 
1219
                                       &db->old_repos_relpath, NULL, NULL,
 
1220
                                       &db->changed_rev, &db->changed_date,
 
1221
                                       &db->changed_author,
 
1222
                                       &db->ambient_depth,
 
1223
                                       NULL, NULL, NULL, NULL, NULL, NULL,
 
1224
                                       eb->db, db->local_abspath,
 
1225
                                       db->pool, pool));
 
1226
    }
 
1227
  else
 
1228
    base_status = status;
 
1229
 
 
1230
  SVN_ERR(calculate_repos_relpath(&db->new_repos_relpath, db->local_abspath,
 
1231
                                  db->old_repos_relpath, eb, NULL,
 
1232
                                  db->pool, pool));
 
1233
 
1231
1234
  if (conflict_ignored)
1232
 
    {
1233
 
      db->shadowed = TRUE;
1234
 
    }
 
1235
    db->shadowed = TRUE;
1235
1236
  else if (have_work)
1236
1237
    {
1237
1238
      const char *move_src_root_abspath;
1239
1240
      SVN_ERR(svn_wc__db_base_moved_to(NULL, NULL, &move_src_root_abspath,
1240
1241
                                       NULL, eb->db, db->local_abspath,
1241
1242
                                       pool, pool));
1242
 
      if (move_src_root_abspath || *eb->target_basename == '\0')
1243
 
        SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL,
1244
 
                                         &db->old_revision,
1245
 
                                         &db->old_repos_relpath, NULL, NULL,
1246
 
                                         &db->changed_rev, &db->changed_date,
1247
 
                                         &db->changed_author,
1248
 
                                         &db->ambient_depth,
1249
 
                                         NULL, NULL, NULL, NULL, NULL, NULL,
1250
 
                                         eb->db, db->local_abspath,
1251
 
                                         db->pool, pool));
1252
1243
 
1253
1244
      if (move_src_root_abspath)
1254
1245
        {
1271
1262
              SVN_ERR(complete_conflict(tree_conflict, eb,
1272
1263
                                        move_src_root_abspath,
1273
1264
                                        db->old_repos_relpath,
1274
 
                                        db->old_revision, db->new_relpath,
 
1265
                                        db->old_revision,
 
1266
                                        db->new_repos_relpath,
1275
1267
                                        svn_node_dir, svn_node_dir,
1276
 
                                        pool, pool));
 
1268
                                        NULL, pool, pool));
1277
1269
              SVN_ERR(svn_wc__db_op_mark_conflict(eb->db,
1278
1270
                                                  move_src_root_abspath,
1279
1271
                                                  tree_conflict,
1288
1280
      db->shadowed = TRUE; /* Needed for the close_directory() on the root, to
1289
1281
                              make sure it doesn't use the ACTUAL tree */
1290
1282
    }
1291
 
  else
1292
 
    base_status = status;
1293
1283
 
1294
1284
  if (*eb->target_basename == '\0')
1295
1285
    {
1308
1298
 
1309
1299
      SVN_ERR(svn_wc__db_temp_op_start_directory_update(eb->db,
1310
1300
                                                        db->local_abspath,
1311
 
                                                        db->new_relpath,
 
1301
                                                        db->new_repos_relpath,
1312
1302
                                                        *eb->target_revision,
1313
1303
                                                        pool));
1314
1304
    }
1320
1310
/* ===================================================================== */
1321
1311
/* Checking for local modifications. */
1322
1312
 
1323
 
/* A baton for use with modcheck_found_entry(). */
1324
 
typedef struct modcheck_baton_t {
1325
 
  svn_wc__db_t *db;         /* wc_db to access nodes */
1326
 
  svn_boolean_t found_mod;  /* whether a modification has been found */
1327
 
  svn_boolean_t found_not_delete;  /* Found a not-delete modification */
1328
 
} modcheck_baton_t;
1329
 
 
1330
 
/* An implementation of svn_wc_status_func4_t. */
1331
 
static svn_error_t *
1332
 
modcheck_callback(void *baton,
1333
 
                  const char *local_abspath,
1334
 
                  const svn_wc_status3_t *status,
1335
 
                  apr_pool_t *scratch_pool)
1336
 
{
1337
 
  modcheck_baton_t *mb = baton;
1338
 
 
1339
 
  switch (status->node_status)
1340
 
    {
1341
 
      case svn_wc_status_normal:
1342
 
      case svn_wc_status_incomplete:
1343
 
      case svn_wc_status_ignored:
1344
 
      case svn_wc_status_none:
1345
 
      case svn_wc_status_unversioned:
1346
 
      case svn_wc_status_external:
1347
 
        break;
1348
 
 
1349
 
      case svn_wc_status_deleted:
1350
 
        mb->found_mod = TRUE;
1351
 
        break;
1352
 
 
1353
 
      case svn_wc_status_missing:
1354
 
      case svn_wc_status_obstructed:
1355
 
        mb->found_mod = TRUE;
1356
 
        mb->found_not_delete = TRUE;
1357
 
        /* Exit from the status walker: We know what we want to know */
1358
 
        return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
1359
 
 
1360
 
      default:
1361
 
      case svn_wc_status_added:
1362
 
      case svn_wc_status_replaced:
1363
 
      case svn_wc_status_modified:
1364
 
        mb->found_mod = TRUE;
1365
 
        mb->found_not_delete = TRUE;
1366
 
        /* Exit from the status walker: We know what we want to know */
1367
 
        return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
1368
 
    }
1369
 
 
1370
 
  return SVN_NO_ERROR;
1371
 
}
1372
 
 
1373
 
 
1374
 
/* Set *MODIFIED to true iff there are any local modifications within the
1375
 
 * tree rooted at LOCAL_ABSPATH, using DB. If *MODIFIED
1376
 
 * is set to true and all the local modifications were deletes then set
1377
 
 * *ALL_EDITS_ARE_DELETES to true, set it to false otherwise.  LOCAL_ABSPATH
1378
 
 * may be a file or a directory. */
1379
 
svn_error_t *
1380
 
svn_wc__node_has_local_mods(svn_boolean_t *modified,
1381
 
                            svn_boolean_t *all_edits_are_deletes,
1382
 
                            svn_wc__db_t *db,
1383
 
                            const char *local_abspath,
1384
 
                            svn_cancel_func_t cancel_func,
1385
 
                            void *cancel_baton,
1386
 
                            apr_pool_t *scratch_pool)
1387
 
{
1388
 
  modcheck_baton_t modcheck_baton = { NULL, FALSE, FALSE };
1389
 
  svn_error_t *err;
1390
 
 
1391
 
  modcheck_baton.db = db;
1392
 
 
1393
 
  /* Walk the WC tree for status with depth infinity, looking for any local
1394
 
   * modifications. If it's a "sparse" directory, that's OK: there can be
1395
 
   * no local mods in the pieces that aren't present in the WC. */
1396
 
 
1397
 
  err = svn_wc__internal_walk_status(db, local_abspath,
1398
 
                                     svn_depth_infinity,
1399
 
                                     FALSE, FALSE, FALSE, NULL,
1400
 
                                     modcheck_callback, &modcheck_baton,
1401
 
                                     cancel_func, cancel_baton,
1402
 
                                     scratch_pool);
1403
 
 
1404
 
  if (err && err->apr_err == SVN_ERR_CEASE_INVOCATION)
1405
 
    svn_error_clear(err);
1406
 
  else
1407
 
    SVN_ERR(err);
1408
 
 
1409
 
  *modified = modcheck_baton.found_mod;
1410
 
  *all_edits_are_deletes = (modcheck_baton.found_mod
1411
 
                            && !modcheck_baton.found_not_delete);
1412
 
 
1413
 
  return SVN_NO_ERROR;
1414
 
}
1415
 
 
1416
1313
/* Indicates an unset svn_wc_conflict_reason_t. */
1417
1314
#define SVN_WC_CONFLICT_REASON_NONE (svn_wc_conflict_reason_t)(-1)
1418
1315
 
1447
1344
{
1448
1345
  svn_wc_conflict_reason_t reason = SVN_WC_CONFLICT_REASON_NONE;
1449
1346
  svn_boolean_t modified = FALSE;
1450
 
  svn_boolean_t all_mods_are_deletes = FALSE;
1451
1347
  const char *move_src_op_root_abspath = NULL;
1452
1348
 
1453
1349
  *pconflict = NULL;
1486
1382
          }
1487
1383
        else
1488
1384
          {
1489
 
            /* The node is locally replaced but could also be moved-away. */
1490
 
            SVN_ERR(svn_wc__db_base_moved_to(NULL, NULL, NULL,
1491
 
                                             &move_src_op_root_abspath,
1492
 
                                             eb->db, local_abspath,
1493
 
                                             scratch_pool, scratch_pool));
1494
 
            if (move_src_op_root_abspath)
1495
 
              reason = svn_wc_conflict_reason_moved_away;
1496
 
            else
1497
 
              reason = svn_wc_conflict_reason_replaced;
 
1385
            /* The node is locally replaced but could also be moved-away,
 
1386
               but we can't report that it is moved away and replaced.
 
1387
 
 
1388
               And we wouldn't be able to store that each of a dozen
 
1389
               descendants was moved to other locations...
 
1390
 
 
1391
               Replaced is what actually happened... */
 
1392
 
 
1393
            reason = svn_wc_conflict_reason_replaced;
1498
1394
          }
1499
1395
        break;
1500
1396
 
1557
1453
         * not visit the subdirectories of a directory that it wants to delete.
1558
1454
         * Therefore, we need to start a separate crawl here. */
1559
1455
 
1560
 
        SVN_ERR(svn_wc__node_has_local_mods(&modified, &all_mods_are_deletes,
1561
 
                                            eb->db, local_abspath,
 
1456
        SVN_ERR(svn_wc__node_has_local_mods(&modified, NULL,
 
1457
                                            eb->db, local_abspath, FALSE,
1562
1458
                                            eb->cancel_func, eb->cancel_baton,
1563
1459
                                            scratch_pool));
1564
1460
 
1565
1461
        if (modified)
1566
1462
          {
1567
 
            if (all_mods_are_deletes)
 
1463
            if (working_status == svn_wc__db_status_deleted)
1568
1464
              reason = svn_wc_conflict_reason_deleted;
1569
1465
            else
1570
1466
              reason = svn_wc_conflict_reason_edited;
1711
1607
  const char *base = svn_relpath_basename(path, NULL);
1712
1608
  const char *local_abspath;
1713
1609
  const char *repos_relpath;
1714
 
  svn_node_kind_t kind, base_kind;
 
1610
  const char *deleted_repos_relpath;
 
1611
  svn_node_kind_t kind;
1715
1612
  svn_revnum_t old_revision;
1716
1613
  svn_boolean_t conflicted;
1717
1614
  svn_boolean_t have_work;
1721
1618
  apr_pool_t *scratch_pool;
1722
1619
  svn_boolean_t deleting_target;
1723
1620
  svn_boolean_t deleting_switched;
1724
 
  svn_boolean_t keep_as_working = FALSE;
1725
 
  svn_boolean_t queue_deletes = TRUE;
1726
1621
 
1727
1622
  if (pb->skip_this)
1728
1623
    return SVN_NO_ERROR;
1740
1635
  {
1741
1636
    svn_boolean_t is_root;
1742
1637
 
 
1638
 
1743
1639
    SVN_ERR(svn_wc__db_is_wcroot(&is_root, eb->db, local_abspath,
1744
1640
                                 scratch_pool));
1745
1641
 
1767
1663
  if (!have_work)
1768
1664
    {
1769
1665
      base_status = status;
1770
 
      base_kind = kind;
1771
1666
    }
1772
1667
  else
1773
 
    SVN_ERR(svn_wc__db_base_get_info(&base_status, &base_kind, &old_revision,
 
1668
    SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, &old_revision,
1774
1669
                                     &repos_relpath,
1775
1670
                                     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1776
1671
                                     NULL, NULL, NULL, NULL, NULL,
1815
1710
      || base_status == svn_wc__db_status_excluded
1816
1711
      || base_status == svn_wc__db_status_server_excluded)
1817
1712
    {
1818
 
      SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath,
1819
 
                                     FALSE /* keep_as_working */,
1820
 
                                     FALSE /* queue_deletes */,
1821
 
                                     FALSE /* remove_locks */,
1822
 
                                     SVN_INVALID_REVNUM /* not_present_rev */,
 
1713
      SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath, TRUE,
 
1714
                                     deleting_target, FALSE,
 
1715
                                     *eb->target_revision,
1823
1716
                                     NULL, NULL,
1824
1717
                                     scratch_pool));
1825
1718
 
1842
1735
    {
1843
1736
      SVN_ERR(check_tree_conflict(&tree_conflict, eb, local_abspath,
1844
1737
                                  status, TRUE,
1845
 
                                  (kind == svn_node_dir)
1846
 
                                        ? svn_node_dir
1847
 
                                        : svn_node_file,
 
1738
                                  kind,
1848
1739
                                  svn_wc_conflict_action_delete,
1849
1740
                                  pb->pool, scratch_pool));
1850
1741
    }
1851
 
  else
1852
 
    queue_deletes = FALSE; /* There is no in-wc representation */
1853
1742
 
1854
1743
  if (tree_conflict != NULL)
1855
1744
    {
1856
 
      svn_wc_conflict_reason_t reason;
1857
1745
      /* When we raise a tree conflict on a node, we don't want to mark the
1858
1746
       * node as skipped, to allow a replacement to continue doing at least
1859
1747
       * a bit of its work (possibly adding a not present node, for the
1864
1752
      svn_hash_sets(pb->deletion_conflicts, apr_pstrdup(pb->pool, base),
1865
1753
                    tree_conflict);
1866
1754
 
1867
 
      SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL, NULL,
1868
 
                                                  eb->db, local_abspath,
1869
 
                                                  tree_conflict,
1870
 
                                                  scratch_pool, scratch_pool));
1871
 
 
1872
 
      if (reason == svn_wc_conflict_reason_edited
1873
 
          || reason == svn_wc_conflict_reason_obstructed)
1874
 
        {
1875
 
          /* The item exists locally and has some sort of local mod.
1876
 
           * It no longer exists in the repository at its target URL@REV.
1877
 
           *
1878
 
           * To prepare the "accept mine" resolution for the tree conflict,
1879
 
           * we must schedule the existing content for re-addition as a copy
1880
 
           * of what it was, but with its local modifications preserved. */
1881
 
          keep_as_working = TRUE;
1882
 
 
1883
 
          /* Fall through to remove the BASE_NODEs properly, with potentially
1884
 
             keeping a not-present marker */
1885
 
        }
1886
 
      else if (reason == svn_wc_conflict_reason_deleted
1887
 
               || reason == svn_wc_conflict_reason_moved_away
1888
 
               || reason == svn_wc_conflict_reason_replaced)
1889
 
        {
1890
 
          /* The item does not exist locally because it was already shadowed.
1891
 
           * We must complete the deletion, leaving the tree conflict info
1892
 
           * as the only difference from a normal deletion. */
1893
 
 
1894
 
          /* Fall through to the normal "delete" code path. */
1895
 
        }
1896
 
      else
1897
 
        SVN_ERR_MALFUNCTION();  /* other reasons are not expected here */
 
1755
      /* Whatever the kind of conflict, we can just clear BASE
 
1756
         by turning whatever is there into a copy */
1898
1757
    }
1899
1758
 
 
1759
  /* Calculate the repository-relative path of the entry which was
 
1760
   * deleted. For updates it's the same as REPOS_RELPATH but for
 
1761
   * switches it is within the switch target. */
 
1762
  SVN_ERR(calculate_repos_relpath(&deleted_repos_relpath, local_abspath,
 
1763
                                  repos_relpath, eb, pb, scratch_pool,
 
1764
                                  scratch_pool));
1900
1765
  SVN_ERR(complete_conflict(tree_conflict, eb, local_abspath, repos_relpath,
1901
 
                            old_revision, NULL,
1902
 
                            (kind == svn_node_dir)
1903
 
                                ? svn_node_dir
1904
 
                                : svn_node_file,
1905
 
                            svn_node_none,
 
1766
                            old_revision, deleted_repos_relpath,
 
1767
                            kind, svn_node_none, NULL,
1906
1768
                            pb->pool, scratch_pool));
1907
1769
 
1908
1770
  /* Issue a wq operation to delete the BASE_NODE data and to delete actual
1917
1779
    {
1918
1780
      /* Delete, and do not leave a not-present node.  */
1919
1781
      SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath,
1920
 
                                     keep_as_working, queue_deletes, FALSE,
 
1782
                                     (tree_conflict != NULL),
 
1783
                                     FALSE, FALSE,
1921
1784
                                     SVN_INVALID_REVNUM /* not_present_rev */,
1922
1785
                                     tree_conflict, NULL,
1923
1786
                                     scratch_pool));
1926
1789
    {
1927
1790
      /* Delete, leaving a not-present node.  */
1928
1791
      SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath,
1929
 
                                     keep_as_working, queue_deletes, FALSE,
 
1792
                                     (tree_conflict != NULL),
 
1793
                                     TRUE, FALSE,
1930
1794
                                     *eb->target_revision,
1931
1795
                                     tree_conflict, NULL,
1932
1796
                                     scratch_pool));
1948
1812
    {
1949
1813
      if (eb->conflict_func)
1950
1814
        SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, local_abspath,
 
1815
                                                 kind,
1951
1816
                                                 tree_conflict,
1952
1817
                                                 NULL /* merge_options */,
1953
1818
                                                 eb->conflict_func,
1955
1820
                                                 eb->cancel_func,
1956
1821
                                                 eb->cancel_baton,
1957
1822
                                                 scratch_pool));
1958
 
      do_notification(eb, local_abspath, svn_node_unknown,
 
1823
      do_notification(eb, local_abspath, kind,
1959
1824
                      svn_wc_notify_tree_conflict, scratch_pool);
1960
1825
    }
1961
1826
  else
1962
1827
    {
1963
1828
      svn_wc_notify_action_t action = svn_wc_notify_update_delete;
1964
 
      svn_node_kind_t node_kind;
1965
1829
 
1966
1830
      if (pb->shadowed || pb->edit_obstructed)
1967
1831
        action = svn_wc_notify_update_shadowed_delete;
1968
1832
 
1969
 
      if (kind == svn_node_dir)
1970
 
        node_kind = svn_node_dir;
1971
 
      else
1972
 
        node_kind = svn_node_file;
1973
 
 
1974
 
      do_notification(eb, local_abspath, node_kind, action, scratch_pool);
 
1833
      do_notification(eb, local_abspath, kind, action, scratch_pool);
1975
1834
    }
1976
1835
 
1977
1836
  svn_pool_destroy(scratch_pool);
1991
1850
  struct dir_baton *pb = parent_baton;
1992
1851
  struct edit_baton *eb = pb->edit_baton;
1993
1852
  struct dir_baton *db;
 
1853
  apr_pool_t *scratch_pool = svn_pool_create(pool);
1994
1854
  svn_node_kind_t kind;
1995
1855
  svn_wc__db_status_t status;
1996
1856
  svn_node_kind_t wc_kind;
2003
1863
  SVN_ERR_ASSERT(! (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_rev)));
2004
1864
 
2005
1865
  SVN_ERR(make_dir_baton(&db, path, eb, pb, TRUE, pool));
 
1866
  SVN_ERR(calculate_repos_relpath(&db->new_repos_relpath, db->local_abspath,
 
1867
                                  NULL, eb, pb, db->pool, scratch_pool));
2006
1868
  *child_baton = db;
2007
1869
 
2008
1870
  if (db->skip_this)
2037
1899
         "administrative directory"),
2038
1900
       svn_dirent_local_style(db->local_abspath, pool));
2039
1901
 
2040
 
  SVN_ERR(svn_io_check_path(db->local_abspath, &kind, db->pool));
2041
 
 
2042
 
  err = svn_wc__db_read_info(&status, &wc_kind, NULL, NULL, NULL, NULL, NULL,
2043
 
                             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2044
 
                             NULL, NULL, NULL, NULL, NULL,
2045
 
                             &conflicted, NULL, NULL, NULL, NULL, NULL, NULL,
2046
 
                             eb->db, db->local_abspath, db->pool, db->pool);
 
1902
  if (!eb->clean_checkout)
 
1903
    {
 
1904
      SVN_ERR(svn_io_check_path(db->local_abspath, &kind, db->pool));
 
1905
 
 
1906
      err = svn_wc__db_read_info(&status, &wc_kind, NULL, NULL, NULL, NULL, NULL,
 
1907
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
1908
                                NULL, NULL, NULL, NULL, NULL,
 
1909
                                &conflicted, NULL, NULL, NULL, NULL, NULL, NULL,
 
1910
                                eb->db, db->local_abspath,
 
1911
                                scratch_pool, scratch_pool);
 
1912
    }
 
1913
  else
 
1914
    {
 
1915
      kind = svn_node_none;
 
1916
      status = svn_wc__db_status_not_present;
 
1917
      wc_kind = svn_node_unknown;
 
1918
      conflicted = FALSE;
 
1919
      err = NULL;
 
1920
    }
 
1921
 
2047
1922
  if (err)
2048
1923
    {
2049
1924
      if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
2056
1931
 
2057
1932
      versioned_locally_and_present = FALSE;
2058
1933
    }
2059
 
  else if (wc_kind == svn_node_dir
2060
 
           && status == svn_wc__db_status_normal)
 
1934
  else if (status == svn_wc__db_status_normal && wc_kind == svn_node_unknown)
2061
1935
    {
2062
 
      /* !! We found the root of a separate working copy obstructing the wc !!
2063
 
 
2064
 
         If the directory would be part of our own working copy then
2065
 
         we wouldn't have been called as an add_directory().
2066
 
 
2067
 
         The only thing we can do is add a not-present node, to allow
2068
 
         a future update to bring in the new files when the problem is
2069
 
         resolved.  Note that svn_wc__db_base_add_not_present_node()
2070
 
         explicitly adds the node into the parent's node database. */
2071
 
 
2072
 
      SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db, db->local_abspath,
2073
 
                                                   db->new_relpath,
2074
 
                                                   eb->repos_root,
2075
 
                                                   eb->repos_uuid,
2076
 
                                                   *eb->target_revision,
2077
 
                                                   svn_node_file,
2078
 
                                                   NULL, NULL,
2079
 
                                                   pool));
2080
 
 
2081
 
      SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
2082
 
      db->skip_this = TRUE;
2083
 
      db->already_notified = TRUE;
2084
 
 
2085
 
      do_notification(eb, db->local_abspath, svn_node_dir,
2086
 
                      svn_wc_notify_update_skip_obstruction, pool);
2087
 
 
2088
 
      return SVN_NO_ERROR;
 
1936
      SVN_ERR_ASSERT(conflicted);
 
1937
      versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
2089
1938
    }
2090
1939
  else if (status == svn_wc__db_status_normal
2091
 
           && (wc_kind == svn_node_file
2092
 
               || wc_kind == svn_node_symlink))
 
1940
           || status == svn_wc__db_status_incomplete)
2093
1941
    {
2094
 
      /* We found a file external occupating the place we need in BASE.
2095
 
 
2096
 
         We can't add a not-present node in this case as that would overwrite
2097
 
         the file external. Luckily the file external itself stops us from
2098
 
         forgetting a child of this parent directory like an obstructing
2099
 
         working copy would.
2100
 
 
2101
 
         The reason we get here is that the adm crawler doesn't report
2102
 
         file externals.
2103
 
      */
2104
 
 
2105
 
      SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
 
1942
      svn_boolean_t root;
 
1943
 
 
1944
      SVN_ERR(svn_wc__db_is_wcroot(&root, eb->db, db->local_abspath,
 
1945
                                   scratch_pool));
 
1946
 
 
1947
      if (root)
 
1948
        {
 
1949
          /* !! We found the root of a working copy obstructing the wc !!
 
1950
 
 
1951
             If the directory would be part of our own working copy then
 
1952
             we wouldn't have been called as an add_directory().
 
1953
 
 
1954
             The only thing we can do is add a not-present node, to allow
 
1955
             a future update to bring in the new files when the problem is
 
1956
             resolved.  Note that svn_wc__db_base_add_not_present_node()
 
1957
             explicitly adds the node into the parent's node database. */
 
1958
 
 
1959
          svn_hash_sets(pb->not_present_nodes,
 
1960
                        apr_pstrdup(pb->pool, db->name),
 
1961
                        svn_node_kind_to_word(svn_node_dir));
 
1962
        }
 
1963
      else if (wc_kind == svn_node_dir)
 
1964
        {
 
1965
          /* We have an editor violation. Github sometimes does this
 
1966
             in its subversion compatibility code, when changing the
 
1967
             depth of a working copy, or on updates from incomplete */
 
1968
        }
 
1969
      else
 
1970
        {
 
1971
          /* We found a file external occupating the place we need in BASE.
 
1972
 
 
1973
            We can't add a not-present node in this case as that would overwrite
 
1974
            the file external. Luckily the file external itself stops us from
 
1975
            forgetting a child of this parent directory like an obstructing
 
1976
            working copy would.
 
1977
 
 
1978
            The reason we get here is that the adm crawler doesn't report
 
1979
            file externals.
 
1980
          */
 
1981
          SVN_ERR_ASSERT(wc_kind == svn_node_file
 
1982
                         || wc_kind == svn_node_symlink);
 
1983
        }
 
1984
 
 
1985
      SVN_ERR(remember_skipped_tree(eb, db->local_abspath, scratch_pool));
2106
1986
      db->skip_this = TRUE;
2107
1987
      db->already_notified = TRUE;
2108
1988
 
2109
 
      do_notification(eb, db->local_abspath, svn_node_file,
2110
 
                      svn_wc_notify_update_skip_obstruction, pool);
 
1989
      do_notification(eb, db->local_abspath, wc_kind,
 
1990
                      svn_wc_notify_update_skip_obstruction, scratch_pool);
 
1991
 
 
1992
      svn_pool_destroy(scratch_pool);
2111
1993
 
2112
1994
      return SVN_NO_ERROR;
2113
1995
    }
2114
 
  else if (wc_kind == svn_node_unknown)
2115
 
    versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
2116
1996
  else
2117
1997
    versioned_locally_and_present = IS_NODE_PRESENT(status);
2118
1998
 
2134
2014
                                                      eb->db,
2135
2015
                                                      db->local_abspath,
2136
2016
                                                      tree_conflict,
2137
 
                                                      db->pool, db->pool));
 
2017
                                                      db->pool, scratch_pool));
2138
2018
 
2139
2019
          tree_conflict = svn_wc__conflict_skel_create(db->pool);
2140
2020
 
2143
2023
                                        eb->db, db->local_abspath,
2144
2024
                                        reason, svn_wc_conflict_action_replace,
2145
2025
                                        move_src_op_root_abspath,
2146
 
                                        db->pool, db->pool));
 
2026
                                        db->pool, scratch_pool));
2147
2027
 
2148
2028
          /* And now stop checking for conflicts here and just perform
2149
2029
             a shadowed update */
2154
2034
        }
2155
2035
      else
2156
2036
        SVN_ERR(node_already_conflicted(&conflicted, &conflict_ignored,
2157
 
                                        eb->db, db->local_abspath, pool));
 
2037
                                        eb->db, db->local_abspath,
 
2038
                                        scratch_pool));
2158
2039
    }
2159
2040
 
2160
2041
  /* Now the "usual" behaviour if already conflicted. Skip it. */
2177
2058
         Note that we can safely assume that no present base node exists,
2178
2059
         because then we would not have received an add_directory.
2179
2060
       */
2180
 
      SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db, db->local_abspath,
2181
 
                                                   db->new_relpath,
2182
 
                                                   eb->repos_root,
2183
 
                                                   eb->repos_uuid,
2184
 
                                                   *eb->target_revision,
2185
 
                                                   svn_node_dir,
2186
 
                                                   NULL, NULL,
2187
 
                                                   pool));
 
2061
      svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, db->name),
 
2062
                    svn_node_kind_to_word(svn_node_dir));
2188
2063
 
2189
 
      /* ### TODO: Also print victim_path in the skip msg. */
2190
2064
      do_notification(eb, db->local_abspath, svn_node_dir,
2191
 
                      svn_wc_notify_skip_conflicted, pool);
 
2065
                      svn_wc_notify_skip_conflicted, scratch_pool);
 
2066
 
 
2067
      svn_pool_destroy(scratch_pool);
2192
2068
      return SVN_NO_ERROR;
2193
2069
    }
2194
2070
  else if (conflict_ignored)
2221
2097
        SVN_ERR(svn_wc__db_scan_addition(&add_status, NULL, NULL, NULL, NULL,
2222
2098
                                         NULL, NULL, NULL, NULL,
2223
2099
                                         eb->db, db->local_abspath,
2224
 
                                         pool, pool));
 
2100
                                         scratch_pool, scratch_pool));
2225
2101
 
2226
2102
 
2227
2103
      /* Is there *something* that is not a dir? */
2244
2120
                                      db->local_abspath,
2245
2121
                                      status, FALSE, svn_node_none,
2246
2122
                                      svn_wc_conflict_action_add,
2247
 
                                      pool, pool));
 
2123
                                      db->pool, scratch_pool));
2248
2124
        }
2249
2125
 
2250
2126
      if (tree_conflict == NULL)
2272
2148
                                        eb->db, db->local_abspath,
2273
2149
                                        svn_wc_conflict_reason_unversioned,
2274
2150
                                        svn_wc_conflict_action_add, NULL,
2275
 
                                        db->pool, pool));
 
2151
                                        db->pool, scratch_pool));
2276
2152
          db->edit_conflict = tree_conflict;
2277
2153
        }
2278
2154
    }
2280
2156
  if (tree_conflict)
2281
2157
    SVN_ERR(complete_conflict(tree_conflict, eb, db->local_abspath,
2282
2158
                              db->old_repos_relpath, db->old_revision,
2283
 
                              db->new_relpath,
2284
 
                              wc_kind,
2285
 
                              svn_node_dir,
2286
 
                              db->pool, pool));
 
2159
                              db->new_repos_relpath,
 
2160
                              wc_kind, svn_node_dir,
 
2161
                              pb->deletion_conflicts
 
2162
                                ? svn_hash_gets(pb->deletion_conflicts,
 
2163
                                                db->name)
 
2164
                                : NULL,
 
2165
                              db->pool, scratch_pool));
2287
2166
 
2288
2167
  SVN_ERR(svn_wc__db_base_add_incomplete_directory(
2289
2168
                                     eb->db, db->local_abspath,
2290
 
                                     db->new_relpath,
 
2169
                                     db->new_repos_relpath,
2291
2170
                                     eb->repos_root,
2292
2171
                                     eb->repos_uuid,
2293
2172
                                     *eb->target_revision,
2296
2175
                                     (! db->shadowed
2297
2176
                                      && status == svn_wc__db_status_added),
2298
2177
                                     tree_conflict, NULL,
2299
 
                                     pool));
 
2178
                                     scratch_pool));
2300
2179
 
2301
2180
  /* Make sure there is a real directory at LOCAL_ABSPATH, unless we are just
2302
2181
     updating the DB */
2303
2182
  if (!db->shadowed)
2304
 
    SVN_ERR(svn_wc__ensure_directory(db->local_abspath, pool));
 
2183
    SVN_ERR(svn_wc__ensure_directory(db->local_abspath, scratch_pool));
2305
2184
 
2306
2185
  if (tree_conflict != NULL)
2307
2186
    {
2308
 
      if (eb->conflict_func)
2309
 
        SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, db->local_abspath,
2310
 
                                                 tree_conflict,
2311
 
                                                 NULL /* merge_options */,
2312
 
                                                 eb->conflict_func,
2313
 
                                                 eb->conflict_baton,
2314
 
                                                 eb->cancel_func,
2315
 
                                                 eb->cancel_baton,
2316
 
                                                 pool));
 
2187
      db->edit_conflict = tree_conflict;
2317
2188
 
2318
2189
      db->already_notified = TRUE;
2319
2190
      do_notification(eb, db->local_abspath, svn_node_dir,
2320
 
                      svn_wc_notify_tree_conflict, pool);
 
2191
                      svn_wc_notify_tree_conflict, scratch_pool);
2321
2192
    }
2322
2193
 
2323
2194
 
2339
2210
 
2340
2211
      db->already_notified = TRUE;
2341
2212
 
2342
 
      do_notification(eb, db->local_abspath, svn_node_dir, action, pool);
 
2213
      do_notification(eb, db->local_abspath, svn_node_dir, action,
 
2214
                      scratch_pool);
2343
2215
    }
2344
2216
 
 
2217
  svn_pool_destroy(scratch_pool);
 
2218
 
2345
2219
  return SVN_NO_ERROR;
2346
2220
}
2347
2221
 
2416
2290
 
2417
2291
  db->was_incomplete = (base_status == svn_wc__db_status_incomplete);
2418
2292
 
 
2293
  SVN_ERR(calculate_repos_relpath(&db->new_repos_relpath, db->local_abspath,
 
2294
                                  db->old_repos_relpath, eb, pb,
 
2295
                                  db->pool, pool));
 
2296
 
2419
2297
  /* Is this path a conflict victim? */
2420
2298
  if (db->shadowed)
2421
2299
    conflicted = FALSE; /* Conflict applies to WORKING */
2475
2353
 
2476
2354
  /* Mark directory as being at target_revision and URL, but incomplete. */
2477
2355
  SVN_ERR(svn_wc__db_temp_op_start_directory_update(eb->db, db->local_abspath,
2478
 
                                                    db->new_relpath,
 
2356
                                                    db->new_repos_relpath,
2479
2357
                                                    *eb->target_revision,
2480
2358
                                                    pool));
2481
2359
 
2498
2376
 
2499
2377
  propchange = apr_array_push(db->propchanges);
2500
2378
  propchange->name = apr_pstrdup(db->pool, name);
2501
 
  propchange->value = value ? svn_string_dup(value, db->pool) : NULL;
 
2379
  propchange->value = svn_string_dup(value, db->pool);
2502
2380
 
2503
2381
  if (!db->edited && svn_property_kind2(name) == svn_prop_regular_kind)
2504
2382
    SVN_ERR(mark_directory_edited(db, pool));
2619
2497
           hi != NULL;
2620
2498
           hi = apr_hash_next(hi))
2621
2499
        {
2622
 
          const char *propname = svn__apr_hash_index_key(hi);
 
2500
          const char *propname = apr_hash_this_key(hi);
2623
2501
          svn_prop_t *prop = apr_array_push(regular_prop_changes);
2624
2502
 
2625
2503
          /* Record a deletion for PROPNAME.  */
2702
2580
  /* Check if we should add some not-present markers before marking the
2703
2581
     directory complete (Issue #3569) */
2704
2582
  {
2705
 
    apr_hash_t *new_children = svn_hash_gets(eb->dir_dirents, db->new_relpath);
 
2583
    apr_hash_t *new_children = svn_hash_gets(eb->dir_dirents,
 
2584
                                             db->new_repos_relpath);
2706
2585
 
2707
2586
    if (new_children != NULL)
2708
2587
      {
2723
2602
 
2724
2603
            svn_pool_clear(iterpool);
2725
2604
 
2726
 
            child_name = svn__apr_hash_index_key(hi);
 
2605
            child_name = apr_hash_this_key(hi);
2727
2606
            child_abspath = svn_dirent_join(db->local_abspath, child_name,
2728
2607
                                            iterpool);
2729
2608
 
2730
 
            dirent = svn__apr_hash_index_val(hi);
 
2609
            dirent = apr_hash_this_val(hi);
2731
2610
            child_kind = (dirent->kind == svn_node_dir)
2732
2611
                                        ? svn_node_dir
2733
2612
                                        : svn_node_file;
2758
2637
 
2759
2638
            svn_error_clear(err);
2760
2639
 
2761
 
            child_relpath = svn_relpath_join(db->new_relpath, child_name,
 
2640
            child_relpath = svn_relpath_join(db->new_repos_relpath, child_name,
2762
2641
                                             iterpool);
2763
2642
 
2764
2643
            SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db,
2776
2655
      }
2777
2656
  }
2778
2657
 
2779
 
  if (apr_hash_count(db->not_present_files))
 
2658
  if (apr_hash_count(db->not_present_nodes))
2780
2659
    {
2781
2660
      apr_hash_index_t *hi;
2782
2661
      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
2786
2665
         transaction, but I can't even trigger it.  I've tried
2787
2666
         ra_local, ra_svn, ra_neon, ra_serf and they all call
2788
2667
         close_file before close_dir. */
2789
 
      for (hi = apr_hash_first(scratch_pool, db->not_present_files);
 
2668
      for (hi = apr_hash_first(scratch_pool, db->not_present_nodes);
2790
2669
           hi;
2791
2670
           hi = apr_hash_next(hi))
2792
2671
        {
2793
 
          const char *child = svn__apr_hash_index_key(hi);
 
2672
          const char *child = apr_hash_this_key(hi);
2794
2673
          const char *child_abspath, *child_relpath;
 
2674
          svn_node_kind_t kind = svn_node_kind_from_word(apr_hash_this_val(hi));
2795
2675
 
2796
2676
          svn_pool_clear(iterpool);
2797
2677
 
2798
2678
          child_abspath = svn_dirent_join(db->local_abspath, child, iterpool);
2799
 
          child_relpath = svn_dirent_join(db->new_relpath, child, iterpool);
 
2679
          child_relpath = svn_dirent_join(db->new_repos_relpath, child, iterpool);
2800
2680
 
2801
2681
          SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db,
2802
2682
                                                       child_abspath,
2804
2684
                                                       eb->repos_root,
2805
2685
                                                       eb->repos_uuid,
2806
2686
                                                       *eb->target_revision,
2807
 
                                                       svn_node_file,
 
2687
                                                       kind,
2808
2688
                                                       NULL, NULL,
2809
2689
                                                       iterpool));
2810
2690
        }
2872
2752
                                    db->local_abspath,
2873
2753
                                    db->old_repos_relpath,
2874
2754
                                    db->old_revision,
2875
 
                                    db->new_relpath,
 
2755
                                    db->new_repos_relpath,
2876
2756
                                    svn_node_dir, svn_node_dir,
 
2757
                                    (db->parent_baton
 
2758
                                     && db->parent_baton->deletion_conflicts)
 
2759
                                      ? svn_hash_gets(
 
2760
                                            db->parent_baton->deletion_conflicts,
 
2761
                                            db->name)
 
2762
                                      : NULL,
2877
2763
                                    db->pool, scratch_pool));
2878
2764
 
2879
2765
          SVN_ERR(svn_wc__conflict_create_markers(&work_item,
2904
2790
      SVN_ERR(svn_wc__db_base_add_directory(
2905
2791
                eb->db, db->local_abspath,
2906
2792
                eb->wcroot_abspath,
2907
 
                db->new_relpath,
 
2793
                db->new_repos_relpath,
2908
2794
                eb->repos_root, eb->repos_uuid,
2909
2795
                *eb->target_revision,
2910
2796
                props,
2914
2800
                (dav_prop_changes->nelts > 0)
2915
2801
                    ? svn_prop_array_to_hash(dav_prop_changes, pool)
2916
2802
                    : NULL,
2917
 
                conflict_skel,
2918
2803
                (! db->shadowed) && new_base_props != NULL,
2919
 
                new_actual_props,
2920
 
                iprops, all_work_items,
 
2804
                new_actual_props, iprops,
 
2805
                conflict_skel, all_work_items,
2921
2806
                scratch_pool));
2922
2807
    }
2923
2808
 
2926
2811
                         eb->cancel_func, eb->cancel_baton,
2927
2812
                         scratch_pool));
2928
2813
 
 
2814
  if (db->parent_baton)
 
2815
    svn_hash_sets(db->parent_baton->not_present_nodes, db->name, NULL);
 
2816
 
2929
2817
  if (conflict_skel && eb->conflict_func)
2930
2818
    SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, db->local_abspath,
 
2819
                                             svn_node_dir,
2931
2820
                                             conflict_skel,
2932
2821
                                             NULL /* merge_options */,
2933
2822
                                             eb->conflict_func,
2962
2851
      eb->notify_func(eb->notify_baton, notify, scratch_pool);
2963
2852
    }
2964
2853
 
 
2854
  if (db->edited)
 
2855
    eb->edited = db->edited;
 
2856
 
2965
2857
  /* We're done with this directory, so remove one reference from the
2966
2858
     bump information. */
2967
2859
  SVN_ERR(maybe_release_dir_info(db));
2985
2877
  svn_error_t *err;
2986
2878
  svn_wc__db_status_t status;
2987
2879
  svn_node_kind_t kind;
 
2880
  svn_skel_t *tree_conflict = NULL;
2988
2881
 
2989
2882
  if (pb->skip_this)
2990
2883
    return SVN_NO_ERROR;
3073
2966
    {
3074
2967
      /* We have a local addition. If this would be a BASE node it would have
3075
2968
         been deleted before we get here. (Which might have turned it into
3076
 
         a copy).
3077
 
 
3078
 
         ### This should be recorded as a tree conflict and the update
3079
 
         ### can just continue, as we can just record the absent status
3080
 
         ### in BASE.
3081
 
       */
 
2969
         a copy). */
3082
2970
      SVN_ERR_ASSERT(status != svn_wc__db_status_normal);
3083
2971
 
3084
 
      return svn_error_createf(
3085
 
         SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
3086
 
         _("Failed to mark '%s' absent: item of the same name is already "
3087
 
           "scheduled for addition"),
3088
 
         svn_dirent_local_style(local_abspath, pool));
 
2972
      if (!pb->shadowed && !pb->edit_obstructed)
 
2973
        SVN_ERR(check_tree_conflict(&tree_conflict, eb, local_abspath,
 
2974
                                    status, FALSE, svn_node_unknown,
 
2975
                                    svn_wc_conflict_action_add,
 
2976
                                    scratch_pool, scratch_pool));
 
2977
 
3089
2978
    }
3090
2979
 
3091
2980
  {
3092
2981
    const char *repos_relpath;
3093
 
    repos_relpath = svn_relpath_join(pb->new_relpath, name, scratch_pool);
 
2982
    repos_relpath = svn_relpath_join(pb->new_repos_relpath, name, scratch_pool);
 
2983
 
 
2984
    if (tree_conflict)
 
2985
      SVN_ERR(complete_conflict(tree_conflict, eb, local_abspath,
 
2986
                                NULL, SVN_INVALID_REVNUM, repos_relpath,
 
2987
                                kind, svn_node_unknown, NULL,
 
2988
                                scratch_pool, scratch_pool));
3094
2989
 
3095
2990
    /* Insert an excluded node below the parent node to note that this child
3096
2991
       is absent. (This puts it in the parent db if the child is obstructed) */
3100
2995
                                              *(eb->target_revision),
3101
2996
                                              absent_kind,
3102
2997
                                              svn_wc__db_status_server_excluded,
3103
 
                                              NULL, NULL,
 
2998
                                              tree_conflict, NULL,
3104
2999
                                              scratch_pool));
 
3000
 
 
3001
    if (tree_conflict)
 
3002
      {
 
3003
        if (eb->conflict_func)
 
3004
          SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, local_abspath,
 
3005
                                                   kind,
 
3006
                                                   tree_conflict,
 
3007
                                                   NULL /* merge_options */,
 
3008
                                                   eb->conflict_func,
 
3009
                                                   eb->conflict_baton,
 
3010
                                                   eb->cancel_func,
 
3011
                                                   eb->cancel_baton,
 
3012
                                                   scratch_pool));
 
3013
        do_notification(eb, local_abspath, kind, svn_wc_notify_tree_conflict,
 
3014
                        scratch_pool);
 
3015
      }
3105
3016
  }
3106
3017
 
3107
3018
  svn_pool_destroy(scratch_pool);
3142
3053
  struct dir_baton *pb = parent_baton;
3143
3054
  struct edit_baton *eb = pb->edit_baton;
3144
3055
  struct file_baton *fb;
3145
 
  svn_node_kind_t kind = svn_node_none;
3146
 
  svn_node_kind_t wc_kind = svn_node_unknown;
3147
 
  svn_wc__db_status_t status = svn_wc__db_status_normal;
 
3056
  svn_node_kind_t kind;
 
3057
  svn_node_kind_t wc_kind;
 
3058
  svn_wc__db_status_t status;
3148
3059
  apr_pool_t *scratch_pool;
3149
 
  svn_boolean_t conflicted = FALSE;
 
3060
  svn_boolean_t conflicted;
3150
3061
  svn_boolean_t conflict_ignored = FALSE;
3151
 
  svn_boolean_t versioned_locally_and_present = FALSE;
 
3062
  svn_boolean_t versioned_locally_and_present;
3152
3063
  svn_skel_t *tree_conflict = NULL;
3153
3064
  svn_error_t *err = SVN_NO_ERROR;
3154
3065
 
3155
3066
  SVN_ERR_ASSERT(! (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_rev)));
3156
3067
 
3157
3068
  SVN_ERR(make_file_baton(&fb, pb, path, TRUE, pool));
 
3069
  SVN_ERR(calculate_repos_relpath(&fb->new_repos_relpath, fb->local_abspath,
 
3070
                                  NULL, eb, pb, fb->pool, pool));
3158
3071
  *file_baton = fb;
3159
3072
 
3160
3073
  if (fb->skip_this)
3186
3099
                                eb->db, fb->local_abspath,
3187
3100
                                scratch_pool, scratch_pool);
3188
3101
    }
 
3102
  else
 
3103
    {
 
3104
      kind =  svn_node_none;
 
3105
      status = svn_wc__db_status_not_present;
 
3106
      wc_kind = svn_node_unknown;
 
3107
      conflicted = FALSE;
 
3108
    }
3189
3109
 
3190
3110
  if (err)
3191
3111
    {
3198
3118
 
3199
3119
      versioned_locally_and_present = FALSE;
3200
3120
    }
3201
 
  else if (wc_kind == svn_node_dir
3202
 
           && status == svn_wc__db_status_normal)
 
3121
  else if (status == svn_wc__db_status_normal && wc_kind == svn_node_unknown)
3203
3122
    {
3204
 
      /* !! We found the root of a separate working copy obstructing the wc !!
3205
 
 
3206
 
         If the directory would be part of our own working copy then
3207
 
         we wouldn't have been called as an add_file().
3208
 
 
3209
 
         The only thing we can do is add a not-present node, to allow
3210
 
         a future update to bring in the new files when the problem is
3211
 
         resolved. */
3212
 
      svn_hash_sets(pb->not_present_files, apr_pstrdup(pb->pool, fb->name),
3213
 
                    (void *)1);
3214
 
 
3215
 
      SVN_ERR(remember_skipped_tree(eb, fb->local_abspath, pool));
3216
 
      fb->skip_this = TRUE;
3217
 
      fb->already_notified = TRUE;
3218
 
 
3219
 
      do_notification(eb, fb->local_abspath, svn_node_file,
3220
 
                      svn_wc_notify_update_skip_obstruction, scratch_pool);
3221
 
 
3222
 
      svn_pool_destroy(scratch_pool);
3223
 
 
3224
 
      return SVN_NO_ERROR;
 
3123
      SVN_ERR_ASSERT(conflicted);
 
3124
      versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
3225
3125
    }
3226
3126
  else if (status == svn_wc__db_status_normal
3227
 
           && (wc_kind == svn_node_file
3228
 
               || wc_kind == svn_node_symlink))
 
3127
           || status == svn_wc__db_status_incomplete)
3229
3128
    {
3230
 
      /* We found a file external occupating the place we need in BASE.
3231
 
 
3232
 
         We can't add a not-present node in this case as that would overwrite
3233
 
         the file external. Luckily the file external itself stops us from
3234
 
         forgetting a child of this parent directory like an obstructing
3235
 
         working copy would.
3236
 
 
3237
 
         The reason we get here is that the adm crawler doesn't report
3238
 
         file externals.
3239
 
      */
 
3129
      svn_boolean_t root;
 
3130
 
 
3131
      SVN_ERR(svn_wc__db_is_wcroot(&root, eb->db, fb->local_abspath,
 
3132
                                   scratch_pool));
 
3133
 
 
3134
      if (root)
 
3135
        {
 
3136
          /* !! We found the root of a working copy obstructing the wc !!
 
3137
 
 
3138
             If the directory would be part of our own working copy then
 
3139
             we wouldn't have been called as an add_directory().
 
3140
 
 
3141
             The only thing we can do is add a not-present node, to allow
 
3142
             a future update to bring in the new files when the problem is
 
3143
             resolved.  Note that svn_wc__db_base_add_not_present_node()
 
3144
             explicitly adds the node into the parent's node database. */
 
3145
 
 
3146
          svn_hash_sets(pb->not_present_nodes,
 
3147
                        apr_pstrdup(pb->pool, fb->name),
 
3148
                        svn_node_kind_to_word(svn_node_dir));
 
3149
        }
 
3150
      else if (wc_kind == svn_node_dir)
 
3151
        {
 
3152
          /* We have an editor violation. Github sometimes does this
 
3153
             in its subversion compatibility code, when changing the
 
3154
             depth of a working copy, or on updates from incomplete */
 
3155
        }
 
3156
      else
 
3157
        {
 
3158
          /* We found a file external occupating the place we need in BASE.
 
3159
 
 
3160
             We can't add a not-present node in this case as that would overwrite
 
3161
             the file external. Luckily the file external itself stops us from
 
3162
             forgetting a child of this parent directory like an obstructing
 
3163
             working copy would.
 
3164
 
 
3165
             The reason we get here is that the adm crawler doesn't report
 
3166
             file externals.
 
3167
           */
 
3168
          SVN_ERR_ASSERT(wc_kind == svn_node_file
 
3169
                         || wc_kind == svn_node_symlink);
 
3170
        }
 
3171
 
3240
3172
      SVN_ERR(remember_skipped_tree(eb, fb->local_abspath, pool));
3241
3173
      fb->skip_this = TRUE;
3242
3174
      fb->already_notified = TRUE;
3243
3175
 
3244
 
      do_notification(eb, fb->local_abspath, svn_node_file,
 
3176
      do_notification(eb, fb->local_abspath, wc_kind,
3245
3177
                      svn_wc_notify_update_skip_obstruction, scratch_pool);
3246
3178
 
3247
3179
      svn_pool_destroy(scratch_pool);
3248
3180
 
3249
3181
      return SVN_NO_ERROR;
3250
3182
    }
3251
 
  else if (wc_kind == svn_node_unknown)
3252
 
    versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
3253
3183
  else
3254
3184
    versioned_locally_and_present = IS_NODE_PRESENT(status);
3255
3185
 
3274
3204
                                                      eb->db,
3275
3205
                                                      fb->local_abspath,
3276
3206
                                                      tree_conflict,
3277
 
                                                      fb->pool, fb->pool));
 
3207
                                                      fb->pool, scratch_pool));
3278
3208
 
3279
3209
          tree_conflict = svn_wc__conflict_skel_create(fb->pool);
3280
3210
 
3283
3213
                                        eb->db, fb->local_abspath,
3284
3214
                                        reason, svn_wc_conflict_action_replace,
3285
3215
                                        move_src_op_root_abspath,
3286
 
                                        fb->pool, fb->pool));
 
3216
                                        fb->pool, scratch_pool));
3287
3217
 
3288
3218
          /* And now stop checking for conflicts here and just perform
3289
3219
             a shadowed update */
3316
3246
         Note that we can safely assume that no present base node exists,
3317
3247
         because then we would not have received an add_file.
3318
3248
       */
3319
 
      svn_hash_sets(pb->not_present_files, apr_pstrdup(pb->pool, fb->name),
3320
 
                    (void *)1);
 
3249
      svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, fb->name),
 
3250
                    svn_node_kind_to_word(svn_node_file));
3321
3251
 
3322
 
      do_notification(eb, fb->local_abspath, svn_node_unknown,
 
3252
      do_notification(eb, fb->local_abspath, svn_node_file,
3323
3253
                      svn_wc_notify_skip_conflicted, scratch_pool);
3324
3254
 
3325
3255
      svn_pool_destroy(scratch_pool);
3380
3310
                                      fb->local_abspath,
3381
3311
                                      status, FALSE, svn_node_none,
3382
3312
                                      svn_wc_conflict_action_add,
3383
 
                                      scratch_pool, scratch_pool));
 
3313
                                      fb->pool, scratch_pool));
3384
3314
        }
3385
3315
 
3386
3316
      if (tree_conflict == NULL)
3421
3351
      || *eb->target_basename == '\0'
3422
3352
      || (strcmp(fb->local_abspath, eb->target_abspath) != 0))
3423
3353
    {
3424
 
      svn_hash_sets(pb->not_present_files, apr_pstrdup(pb->pool, fb->name),
3425
 
                    (void *)1);
 
3354
      svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, fb->name),
 
3355
                    svn_node_kind_to_word(svn_node_file));
3426
3356
    }
3427
3357
 
3428
3358
  if (tree_conflict != NULL)
3432
3362
                                fb->local_abspath,
3433
3363
                                fb->old_repos_relpath,
3434
3364
                                fb->old_revision,
3435
 
                                fb->new_relpath,
3436
 
                                wc_kind,
3437
 
                                svn_node_file,
 
3365
                                fb->new_repos_relpath,
 
3366
                                wc_kind, svn_node_file,
 
3367
                                pb->deletion_conflicts
 
3368
                                  ? svn_hash_gets(pb->deletion_conflicts,
 
3369
                                                  fb->name)
 
3370
                                  : NULL,
3438
3371
                                fb->pool, scratch_pool));
3439
3372
 
3440
3373
      SVN_ERR(svn_wc__db_op_mark_conflict(eb->db,
3442
3375
                                          tree_conflict, NULL,
3443
3376
                                          scratch_pool));
3444
3377
 
3445
 
      if (eb->conflict_func)
3446
 
        SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, fb->local_abspath,
3447
 
                                                 tree_conflict,
3448
 
                                                 NULL /* merge_options */,
3449
 
                                                 eb->conflict_func,
3450
 
                                                 eb->conflict_baton,
3451
 
                                                 eb->cancel_func,
3452
 
                                                 eb->cancel_baton,
3453
 
                                                 scratch_pool));
 
3378
      fb->edit_conflict = tree_conflict;
3454
3379
 
3455
3380
      fb->already_notified = TRUE;
3456
3381
      do_notification(eb, fb->local_abspath, svn_node_file,
3514
3439
 
3515
3440
  /* Sanity check. */
3516
3441
 
3517
 
  /* If replacing, make sure the .svn entry already exists. */
3518
3442
  SVN_ERR(svn_wc__db_read_info(&status, &wc_kind, &fb->old_revision,
3519
3443
                               &fb->old_repos_relpath, NULL, NULL,
3520
3444
                               &fb->changed_rev, &fb->changed_date,
3536
3460
                                     eb->db, fb->local_abspath,
3537
3461
                                     fb->pool, scratch_pool));
3538
3462
 
 
3463
  SVN_ERR(calculate_repos_relpath(&fb->new_repos_relpath, fb->local_abspath,
 
3464
                                  fb->old_repos_relpath, eb, pb,
 
3465
                                  fb->pool, scratch_pool));
 
3466
 
3539
3467
  /* Is this path a conflict victim? */
3540
3468
  if (fb->shadowed)
3541
3469
    conflicted = FALSE; /* Conflict applies to WORKING */
3615
3543
  return SVN_NO_ERROR;
3616
3544
}
3617
3545
 
3618
 
struct lazy_target_baton {
3619
 
  struct file_baton *fb;
3620
 
  struct handler_baton *hb;
3621
 
  struct edit_baton *eb;
3622
 
};
3623
 
 
3624
3546
/* Implements svn_stream_lazyopen_func_t. */
3625
3547
static svn_error_t *
3626
3548
lazy_open_target(svn_stream_t **stream,
3628
3550
                 apr_pool_t *result_pool,
3629
3551
                 apr_pool_t *scratch_pool)
3630
3552
{
3631
 
  struct lazy_target_baton *tb = baton;
 
3553
  struct handler_baton *hb = baton;
3632
3554
 
3633
 
  SVN_ERR(svn_wc__open_writable_base(stream, &tb->hb->new_text_base_tmp_abspath,
3634
 
                                     NULL, &tb->hb->new_text_base_sha1_checksum,
3635
 
                                     tb->fb->edit_baton->db,
3636
 
                                     tb->eb->wcroot_abspath,
3637
 
                                     result_pool, scratch_pool));
 
3555
  SVN_ERR(svn_wc__db_pristine_prepare_install(stream,
 
3556
                                              &hb->install_data,
 
3557
                                              &hb->new_text_base_sha1_checksum,
 
3558
                                              NULL,
 
3559
                                              hb->fb->edit_baton->db,
 
3560
                                              hb->fb->dir_baton->local_abspath,
 
3561
                                              result_pool, scratch_pool));
3638
3562
 
3639
3563
  return SVN_NO_ERROR;
3640
3564
}
3654
3578
  const svn_checksum_t *recorded_base_checksum;
3655
3579
  svn_checksum_t *expected_base_checksum;
3656
3580
  svn_stream_t *source;
3657
 
  struct lazy_target_baton *tb;
3658
3581
  svn_stream_t *target;
3659
3582
 
3660
3583
  if (fb->skip_this)
3748
3671
      hb->source_checksum_stream = source;
3749
3672
    }
3750
3673
 
3751
 
  tb = apr_palloc(handler_pool, sizeof(struct lazy_target_baton));
3752
 
  tb->hb = hb;
3753
 
  tb->fb = fb;
3754
 
  tb->eb = eb;
3755
 
  target = svn_stream_lazyopen_create(lazy_open_target, tb, TRUE, handler_pool);
 
3674
  target = svn_stream_lazyopen_create(lazy_open_target, hb, TRUE, handler_pool);
3756
3675
 
3757
3676
  /* Prepare to apply the delta.  */
3758
3677
  svn_txdelta_apply(source, target,
3759
3678
                    hb->new_text_base_md5_digest,
3760
 
                    hb->new_text_base_tmp_abspath /* error_info */,
 
3679
                    fb->local_abspath /* error_info */,
3761
3680
                    handler_pool,
3762
3681
                    &hb->apply_handler, &hb->apply_baton);
3763
3682
 
3788
3707
  /* Push a new propchange to the file baton's array of propchanges */
3789
3708
  propchange = apr_array_push(fb->propchanges);
3790
3709
  propchange->name = apr_pstrdup(fb->pool, name);
3791
 
  propchange->value = value ? svn_string_dup(value, fb->pool) : NULL;
 
3710
  propchange->value = svn_string_dup(value, fb->pool);
3792
3711
 
3793
3712
  if (!fb->edited && svn_property_kind2(name) == svn_prop_regular_kind)
3794
3713
    SVN_ERR(mark_file_edited(fb, scratch_pool));
3851
3770
 
3852
3771
          SVN_ERR(complete_conflict(fb->edit_conflict, fb->edit_baton,
3853
3772
                                    fb->local_abspath, fb->old_repos_relpath,
3854
 
                                    fb->old_revision, fb->new_relpath,
 
3773
                                    fb->old_revision, fb->new_repos_relpath,
3855
3774
                                    svn_node_file, svn_node_file,
3856
 
                                    fb->pool, scratch_pool));
 
3775
                                    NULL, fb->pool, scratch_pool));
3857
3776
 
3858
3777
          /* Create a copy of the existing (pre update) BASE node in WORKING,
3859
3778
             mark a tree conflict and handle the rest of the update as
3913
3832
  const char *merge_left;
3914
3833
  svn_boolean_t delete_left = FALSE;
3915
3834
  const char *path_ext = "";
3916
 
  const char *new_text_base_tmp_abspath;
 
3835
  const char *new_pristine_abspath;
3917
3836
  enum svn_wc_merge_outcome_t merge_outcome = svn_wc_merge_unchanged;
3918
3837
  svn_skel_t *work_item;
3919
3838
 
3920
3839
  *work_items = NULL;
3921
3840
 
3922
 
  SVN_ERR(svn_wc__db_pristine_get_path(&new_text_base_tmp_abspath,
 
3841
  SVN_ERR(svn_wc__db_pristine_get_path(&new_pristine_abspath,
3923
3842
                                       db, wri_abspath, new_checksum,
3924
3843
                                       scratch_pool, scratch_pool));
3925
3844
 
3972
3891
                                 &merge_outcome,
3973
3892
                                 db,
3974
3893
                                 merge_left,
3975
 
                                 new_text_base_tmp_abspath,
 
3894
                                 new_pristine_abspath,
3976
3895
                                 local_abspath,
3977
3896
                                 wri_abspath,
3978
3897
                                 oldrev_str, newrev_str, mine_str,
4321
4240
          {
4322
4241
            /* If we lose the lock, but not because we are switching to
4323
4242
               another url, remove the state lock from the wc */
4324
 
            if (! eb->switch_relpath
4325
 
                || strcmp(fb->new_relpath, fb->old_repos_relpath) == 0)
 
4243
            if (! eb->switch_repos_relpath
 
4244
                || strcmp(fb->new_repos_relpath, fb->old_repos_relpath) == 0)
4326
4245
              {
4327
4246
                SVN_ERR_ASSERT(prop->value == NULL);
4328
 
                SVN_ERR(svn_wc__db_lock_remove(eb->db, fb->local_abspath,
 
4247
                SVN_ERR(svn_wc__db_lock_remove(eb->db, fb->local_abspath, NULL,
4329
4248
                                               scratch_pool));
4330
4249
 
4331
4250
                lock_state = svn_wc_notify_lock_state_unlocked;
4564
4483
                                fb->local_abspath,
4565
4484
                                fb->old_repos_relpath,
4566
4485
                                fb->old_revision,
4567
 
                                fb->new_relpath,
 
4486
                                fb->new_repos_relpath,
4568
4487
                                svn_node_file, svn_node_file,
 
4488
                                fb->dir_baton->deletion_conflicts
 
4489
                                  ? svn_hash_gets(
 
4490
                                        fb->dir_baton->deletion_conflicts,
 
4491
                                        fb->name)
 
4492
                                  : NULL,
4569
4493
                                fb->pool, scratch_pool));
4570
4494
 
4571
4495
      SVN_ERR(svn_wc__conflict_create_markers(&work_item,
4593
4517
 
4594
4518
  SVN_ERR(svn_wc__db_base_add_file(eb->db, fb->local_abspath,
4595
4519
                                   eb->wcroot_abspath,
4596
 
                                   fb->new_relpath,
 
4520
                                   fb->new_repos_relpath,
4597
4521
                                   eb->repos_root, eb->repos_uuid,
4598
4522
                                   *eb->target_revision,
4599
4523
                                   new_base_props,
4618
4542
 
4619
4543
  if (conflict_skel && eb->conflict_func)
4620
4544
    SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, fb->local_abspath,
 
4545
                                             svn_node_file,
4621
4546
                                             conflict_skel,
4622
4547
                                             NULL /* merge_options */,
4623
4548
                                             eb->conflict_func,
4628
4553
 
4629
4554
  /* Deal with the WORKING tree, based on updates to the BASE tree.  */
4630
4555
 
4631
 
  svn_hash_sets(fb->dir_baton->not_present_files, fb->name, NULL);
 
4556
  svn_hash_sets(fb->dir_baton->not_present_nodes, fb->name, NULL);
4632
4557
 
4633
4558
  /* Send a notification to the callback function.  (Skip notifications
4634
4559
     about files which were already notified for another reason.) */
4687
4612
}
4688
4613
 
4689
4614
 
 
4615
/* Implements svn_wc__proplist_receiver_t.
 
4616
 * Check for the presence of an svn:keywords property and queues an install_file
 
4617
 * work queue item if present. Thus, when the work queue is run to complete the
 
4618
 * switch operation, all files with keywords will go through the translation
 
4619
 * process so URLs etc are updated. */
 
4620
static svn_error_t *
 
4621
update_keywords_after_switch_cb(void *baton,
 
4622
                                const char *local_abspath,
 
4623
                                apr_hash_t *props,
 
4624
                                apr_pool_t *scratch_pool)
 
4625
{
 
4626
  struct edit_baton *eb = baton;
 
4627
  svn_string_t *propval;
 
4628
  svn_boolean_t modified;
 
4629
  svn_boolean_t record_fileinfo;
 
4630
  svn_skel_t *work_items;
 
4631
  const char *install_from;
 
4632
 
 
4633
  propval = svn_hash_gets(props, SVN_PROP_KEYWORDS);
 
4634
  if (!propval)
 
4635
    return SVN_NO_ERROR;
 
4636
 
 
4637
  SVN_ERR(svn_wc__internal_file_modified_p(&modified, eb->db,
 
4638
                                           local_abspath, FALSE,
 
4639
                                           scratch_pool));
 
4640
  if (modified)
 
4641
    {
 
4642
      const char *temp_dir_abspath;
 
4643
      svn_stream_t *working_stream;
 
4644
      svn_stream_t *install_from_stream;
 
4645
 
 
4646
      SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir_abspath, eb->db,
 
4647
                                             local_abspath, scratch_pool,
 
4648
                                             scratch_pool));
 
4649
      SVN_ERR(svn_stream_open_readonly(&working_stream, local_abspath,
 
4650
                                       scratch_pool, scratch_pool));
 
4651
      SVN_ERR(svn_stream_open_unique(&install_from_stream, &install_from,
 
4652
                                     temp_dir_abspath, svn_io_file_del_none,
 
4653
                                     scratch_pool, scratch_pool));
 
4654
      SVN_ERR(svn_stream_copy3(working_stream, install_from_stream,
 
4655
                               eb->cancel_func, eb->cancel_baton,
 
4656
                               scratch_pool));
 
4657
      record_fileinfo = FALSE;
 
4658
    }
 
4659
  else
 
4660
    {
 
4661
      install_from = NULL;
 
4662
      record_fileinfo = TRUE;
 
4663
    }
 
4664
 
 
4665
  SVN_ERR(svn_wc__wq_build_file_install(&work_items, eb->db, local_abspath,
 
4666
                                        install_from,
 
4667
                                        eb->use_commit_times,
 
4668
                                        record_fileinfo,
 
4669
                                        scratch_pool, scratch_pool));
 
4670
  if (install_from)
 
4671
    {
 
4672
      svn_skel_t *work_item;
 
4673
 
 
4674
      SVN_ERR(svn_wc__wq_build_file_remove(&work_item, eb->db,
 
4675
                                           local_abspath, install_from,
 
4676
                                           scratch_pool, scratch_pool));
 
4677
      work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
 
4678
    }
 
4679
 
 
4680
  SVN_ERR(svn_wc__db_wq_add(eb->db, local_abspath, work_items,
 
4681
                            scratch_pool));
 
4682
 
 
4683
  return SVN_NO_ERROR;
 
4684
}
 
4685
 
 
4686
 
4690
4687
/* An svn_delta_editor_t function. */
4691
4688
static svn_error_t *
4692
4689
close_edit(void *edit_baton,
4728
4725
      SVN_ERR(svn_wc__db_op_bump_revisions_post_update(eb->db,
4729
4726
                                                       eb->target_abspath,
4730
4727
                                                       eb->requested_depth,
4731
 
                                                       eb->switch_relpath,
 
4728
                                                       eb->switch_repos_relpath,
4732
4729
                                                       eb->repos_root,
4733
4730
                                                       eb->repos_uuid,
4734
4731
                                                       *(eb->target_revision),
4735
4732
                                                       eb->skipped_trees,
4736
4733
                                                       eb->wcroot_iprops,
 
4734
                                                       ! eb->edited,
4737
4735
                                                       eb->notify_func,
4738
4736
                                                       eb->notify_baton,
4739
4737
                                                       eb->pool));
4773
4771
                 If so, we should get rid of this excluded node now. */
4774
4772
 
4775
4773
              SVN_ERR(svn_wc__db_base_remove(eb->db, eb->target_abspath,
4776
 
                                             FALSE /* keep_as_working */,
4777
 
                                             FALSE /* queue_deletes */,
4778
 
                                             FALSE /* remove_locks */,
 
4774
                                             TRUE, FALSE, FALSE,
4779
4775
                                             SVN_INVALID_REVNUM,
4780
4776
                                             NULL, NULL, scratch_pool));
4781
4777
            }
4782
4778
        }
4783
4779
    }
4784
4780
 
 
4781
  /* Update keywords in switched files.
 
4782
     GOTO #1975 (the year of the Altair 8800). */
 
4783
  if (eb->switch_repos_relpath)
 
4784
    {
 
4785
      svn_depth_t depth;
 
4786
 
 
4787
      if (eb->requested_depth > svn_depth_empty)
 
4788
        depth = eb->requested_depth;
 
4789
      else
 
4790
        depth = svn_depth_infinity;
 
4791
 
 
4792
      SVN_ERR(svn_wc__db_read_props_streamily(eb->db,
 
4793
                                              eb->target_abspath,
 
4794
                                              depth,
 
4795
                                              FALSE, /* pristine */
 
4796
                                              NULL, /* changelists */
 
4797
                                              update_keywords_after_switch_cb,
 
4798
                                              eb,
 
4799
                                              eb->cancel_func,
 
4800
                                              eb->cancel_baton,
 
4801
                                              scratch_pool));
 
4802
    }
 
4803
 
4785
4804
  /* The edit is over: run the wq with proper cancel support,
4786
4805
     but first kill the handler that would run it on the pool
4787
4806
     cleanup at the end of this function. */
4854
4873
 
4855
4874
  /* Get the anchor's repository root and uuid. The anchor must already exist
4856
4875
     in BASE. */
4857
 
  SVN_ERR(svn_wc__db_scan_base_repos(NULL, &repos_root, &repos_uuid,
4858
 
                                     db, anchor_abspath,
4859
 
                                     result_pool, scratch_pool));
 
4876
  SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, &repos_root,
 
4877
                                   &repos_uuid, NULL, NULL, NULL, NULL,
 
4878
                                   NULL, NULL, NULL, NULL, NULL, NULL,
 
4879
                                   db, anchor_abspath,
 
4880
                                   result_pool, scratch_pool));
4860
4881
 
4861
4882
  /* With WC-NG we need a valid repository root */
4862
4883
  SVN_ERR_ASSERT(repos_root != NULL && repos_uuid != NULL);
4884
4905
                                edit_pool, scratch_pool));
4885
4906
 
4886
4907
  if (switch_url)
4887
 
    eb->switch_relpath =
 
4908
    eb->switch_repos_relpath =
4888
4909
      svn_uri_skip_ancestor(repos_root, switch_url, scratch_pool);
4889
4910
  else
4890
 
    eb->switch_relpath = NULL;
 
4911
    eb->switch_repos_relpath = NULL;
4891
4912
 
4892
4913
  if (svn_path_is_empty(target_basename))
4893
4914
    eb->target_abspath = eb->anchor_abspath;
4968
4989
              apr_hash_t *dirents;
4969
4990
 
4970
4991
              /* If we switch, we should look at the new relpath */
4971
 
              if (eb->switch_relpath)
4972
 
                dir_repos_relpath = eb->switch_relpath;
 
4992
              if (eb->switch_repos_relpath)
 
4993
                dir_repos_relpath = eb->switch_repos_relpath;
4973
4994
 
4974
4995
              SVN_ERR(fetch_dirents_func(fetch_dirents_baton, &dirents,
4975
4996
                                         repos_root, dir_repos_relpath,
5022
5043
                      apr_hash_t *dirents;
5023
5044
 
5024
5045
                      /* If we switch, we should look at the new relpath */
5025
 
                      if (eb->switch_relpath)
 
5046
                      if (eb->switch_repos_relpath)
5026
5047
                        dir_repos_relpath = svn_relpath_join(
5027
 
                                                eb->switch_relpath,
 
5048
                                                eb->switch_repos_relpath,
5028
5049
                                                child_name, iterpool);
5029
5050
 
5030
5051
                      SVN_ERR(fetch_dirents_func(fetch_dirents_baton, &dirents,
5223
5244
  svn_revnum_t changed_rev;
5224
5245
  apr_time_t changed_date;
5225
5246
  const char *changed_author;
 
5247
  svn_stream_t *tmp_base_contents;
 
5248
  svn_wc__db_install_data_t *install_data;
5226
5249
  svn_error_t *err;
5227
5250
  apr_pool_t *pool = scratch_pool;
5228
5251
 
5344
5367
  /* Copy NEW_BASE_CONTENTS into a temporary file so our log can refer to
5345
5368
     it, and set TMP_TEXT_BASE_ABSPATH to its path.  Compute its
5346
5369
     NEW_TEXT_BASE_MD5_CHECKSUM and NEW_TEXT_BASE_SHA1_CHECKSUM as we copy. */
5347
 
  {
5348
 
    svn_stream_t *tmp_base_contents;
5349
 
 
5350
 
    SVN_ERR(svn_wc__open_writable_base(&tmp_base_contents,
5351
 
                                       &tmp_text_base_abspath,
5352
 
                                       &new_text_base_md5_checksum,
5353
 
                                       &new_text_base_sha1_checksum,
5354
 
                                       wc_ctx->db, local_abspath,
5355
 
                                       pool, pool));
5356
 
    SVN_ERR(svn_stream_copy3(new_base_contents, tmp_base_contents,
5357
 
                             cancel_func, cancel_baton, pool));
5358
 
  }
 
5370
  if (copyfrom_url)
 
5371
    {
 
5372
      SVN_ERR(svn_wc__db_pristine_prepare_install(&tmp_base_contents,
 
5373
                                                  &install_data,
 
5374
                                                  &new_text_base_sha1_checksum,
 
5375
                                                  &new_text_base_md5_checksum,
 
5376
                                                  wc_ctx->db, local_abspath,
 
5377
                                                  scratch_pool, scratch_pool));
 
5378
    }
 
5379
  else
 
5380
    {
 
5381
      const char *tmp_dir_abspath;
 
5382
 
 
5383
      /* We are not installing a PRISTINE file, but we use the same code to
 
5384
         create whatever we want to install */
 
5385
 
 
5386
      SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmp_dir_abspath,
 
5387
                                             db, dir_abspath,
 
5388
                                             scratch_pool, scratch_pool));
 
5389
 
 
5390
      SVN_ERR(svn_stream_open_unique(&tmp_base_contents, &tmp_text_base_abspath,
 
5391
                                     tmp_dir_abspath, svn_io_file_del_none,
 
5392
                                     scratch_pool, scratch_pool));
 
5393
 
 
5394
      new_text_base_sha1_checksum = NULL;
 
5395
      new_text_base_md5_checksum = NULL;
 
5396
    }
 
5397
  SVN_ERR(svn_stream_copy3(new_base_contents, tmp_base_contents,
 
5398
                           cancel_func, cancel_baton, pool));
5359
5399
 
5360
5400
  /* If the caller gave us a new working file, copy it to a safe (temporary)
5361
5401
     location and set SOURCE_ABSPATH to that path. We'll then translate/copy
5378
5418
     text base.  */
5379
5419
  if (copyfrom_url != NULL)
5380
5420
    {
5381
 
      SVN_ERR(svn_wc__db_pristine_install(db, tmp_text_base_abspath,
 
5421
      SVN_ERR(svn_wc__db_pristine_install(install_data,
5382
5422
                                          new_text_base_sha1_checksum,
5383
5423
                                          new_text_base_md5_checksum, pool));
5384
5424
    }
5445
5485
      }
5446
5486
  }
5447
5487
 
5448
 
  /* ### ideally, we would have a single DB operation, and queue the work
5449
 
     ### items on that. for now, we'll queue them with the second call.  */
5450
 
 
5451
5488
  SVN_ERR(svn_wc__db_op_copy_file(db, local_abspath,
5452
5489
                                  new_base_props,
5453
5490
                                  changed_rev,