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

« back to all changes in this revision

Viewing changes to subversion/libsvn_client/merge.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:
54
54
#include "client.h"
55
55
#include "mergeinfo.h"
56
56
 
57
 
#include "private/svn_opt_private.h"
58
 
#include "private/svn_wc_private.h"
 
57
#include "private/svn_fspath.h"
59
58
#include "private/svn_mergeinfo_private.h"
60
 
#include "private/svn_fspath.h"
61
 
#include "private/svn_ra_private.h"
62
59
#include "private/svn_client_private.h"
 
60
#include "private/svn_sorts_private.h"
63
61
#include "private/svn_subr_private.h"
 
62
#include "private/svn_wc_private.h"
64
63
 
65
64
#include "svn_private_config.h"
66
65
 
570
569
}
571
570
 
572
571
/* Create *LEFT and *RIGHT conflict versions for conflict victim
573
 
 * at VICTIM_ABSPATH, with kind NODE_KIND, using information obtained
574
 
 * from MERGE_SOURCE and TARGET.
 
572
 * at VICTIM_ABSPATH, with merge-left node kind MERGE_LEFT_NODE_KIND
 
573
 * and merge-right node kind MERGE_RIGHT_NODE_KIND, using information
 
574
 * obtained from MERGE_SOURCE and TARGET.
575
575
 * Allocate returned conflict versions in RESULT_POOL. */
576
576
static svn_error_t *
577
577
make_conflict_versions(const svn_wc_conflict_version_t **left,
578
578
                       const svn_wc_conflict_version_t **right,
579
579
                       const char *victim_abspath,
580
 
                       svn_node_kind_t node_kind,
 
580
                       svn_node_kind_t merge_left_node_kind,
 
581
                       svn_node_kind_t merge_right_node_kind,
581
582
                       const merge_source_t *merge_source,
582
583
                       const merge_target_t *target,
583
584
                       apr_pool_t *result_pool,
597
598
            merge_source->loc1->repos_root_url,
598
599
            merge_source->loc1->repos_uuid,
599
600
            svn_relpath_join(left_relpath, child, scratch_pool),
600
 
            merge_source->loc1->rev, node_kind, result_pool);
 
601
            merge_source->loc1->rev,
 
602
            merge_left_node_kind, result_pool);
601
603
 
602
604
  *right = svn_wc_conflict_version_create2(
603
605
             merge_source->loc2->repos_root_url,
604
606
             merge_source->loc2->repos_uuid,
605
607
             svn_relpath_join(right_relpath, child, scratch_pool),
606
 
             merge_source->loc2->rev, node_kind, result_pool);
 
608
             merge_source->loc2->rev,
 
609
             merge_right_node_kind, result_pool);
607
610
 
608
611
  return SVN_NO_ERROR;
609
612
}
633
636
  for (hi = apr_hash_first(pool, *mergeinfo); hi; hi = apr_hash_next(hi))
634
637
    {
635
638
      int i;
636
 
      const char *merge_source_path = svn__apr_hash_index_key(hi);
637
 
      svn_rangelist_t *rangelist = svn__apr_hash_index_val(hi);
 
639
      const char *merge_source_path = apr_hash_this_key(hi);
 
640
      svn_rangelist_t *rangelist = apr_hash_this_val(hi);
638
641
 
639
642
      svn_pool_clear(iterpool);
640
643
 
764
767
  /* If PATH itself has been added there is no need to filter. */
765
768
  SVN_ERR(svn_wc__node_get_origin(&is_copy,  &target_base.rev, &repos_relpath,
766
769
                                  &target_base.repos_root_url,
767
 
                                  &target_base.repos_uuid, NULL,
 
770
                                  &target_base.repos_uuid, NULL, NULL,
768
771
                                  ctx->wc_ctx, target_abspath, FALSE,
769
772
                                  pool, pool));
770
773
 
863
866
               hi; hi = apr_hash_next(hi))
864
867
            {
865
868
              int j;
866
 
              const char *source_path = svn__apr_hash_index_key(hi);
867
 
              svn_rangelist_t *rangelist = svn__apr_hash_index_val(hi);
 
869
              const char *source_path = apr_hash_this_key(hi);
 
870
              svn_rangelist_t *rangelist = apr_hash_this_val(hi);
868
871
              const char *merge_source_url;
869
872
              svn_rangelist_t *adjusted_rangelist =
870
873
                apr_array_make(iterpool, 0, sizeof(svn_merge_range_t *));
1182
1185
   */
1183
1186
  svn_wc_conflict_reason_t tree_conflict_reason;
1184
1187
  svn_wc_conflict_action_t tree_conflict_action;
 
1188
  svn_node_kind_t tree_conflict_local_node_kind;
 
1189
  svn_node_kind_t tree_conflict_merge_left_node_kind;
 
1190
  svn_node_kind_t tree_conflict_merge_right_node_kind;
1185
1191
 
1186
1192
  /* When TREE_CONFLICT_REASON is CONFLICT_REASON_SKIP, the skip state to
1187
1193
     add to the notification */
1233
1239
     merge_tree_baton_t for an explanation. */
1234
1240
  svn_wc_conflict_reason_t tree_conflict_reason;
1235
1241
  svn_wc_conflict_action_t tree_conflict_action;
 
1242
  svn_node_kind_t tree_conflict_local_node_kind;
 
1243
  svn_node_kind_t tree_conflict_merge_left_node_kind;
 
1244
  svn_node_kind_t tree_conflict_merge_right_node_kind;
1236
1245
 
1237
1246
  /* When TREE_CONFLICT_REASON is CONFLICT_REASON_SKIP, the skip state to
1238
1247
     add to the notification */
1280
1289
      notify->kind = kind;
1281
1290
      notify->content_state = notify->prop_state = state;
1282
1291
 
1283
 
      (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2, notify,
1284
 
                                    scratch_pool);
 
1292
      merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
 
1293
                                 scratch_pool);
1285
1294
    }
1286
1295
  return SVN_NO_ERROR;
1287
1296
}
1294
1303
 * The tree conflict, with its victim specified by VICTIM_PATH, is
1295
1304
 * assumed to have happened during a merge using merge baton MERGE_B.
1296
1305
 *
1297
 
 * NODE_KIND must be the node kind of "old" and "theirs" and "mine";
1298
 
 * this function cannot cope with node kind clashes.
1299
1306
 * ACTION and REASON correspond to the fields
1300
1307
 * of the same names in svn_wc_tree_conflict_description_t.
1301
1308
 */
1303
1310
record_tree_conflict(merge_cmd_baton_t *merge_b,
1304
1311
                     const char *local_abspath,
1305
1312
                     struct merge_dir_baton_t *parent_baton,
1306
 
                     svn_node_kind_t node_kind,
 
1313
                     svn_node_kind_t local_node_kind,
 
1314
                     svn_node_kind_t merge_left_node_kind,
 
1315
                     svn_node_kind_t merge_right_node_kind,
1307
1316
                     svn_wc_conflict_action_t action,
1308
1317
                     svn_wc_conflict_reason_t reason,
1309
1318
                     const svn_wc_conflict_description2_t *existing_conflict,
1357
1366
            reason = svn_wc_conflict_reason_moved_here;
1358
1367
        }
1359
1368
 
1360
 
      SVN_ERR(make_conflict_versions(&left, &right, local_abspath, node_kind,
 
1369
      SVN_ERR(make_conflict_versions(&left, &right, local_abspath,
 
1370
                                     merge_left_node_kind,
 
1371
                                     merge_right_node_kind,
1361
1372
                                     &merge_b->merge_source, merge_b->target,
1362
1373
                                     result_pool, scratch_pool));
1363
1374
 
1366
1377
          left = existing_conflict->src_left_version;
1367
1378
 
1368
1379
      conflict = svn_wc_conflict_description_create_tree2(
1369
 
                        local_abspath, node_kind, svn_wc_operation_merge,
 
1380
                        local_abspath, local_node_kind,
 
1381
                        svn_wc_operation_merge,
1370
1382
                        left, right, result_pool);
1371
1383
 
1372
1384
      conflict->action = action;
1402
1414
 
1403
1415
      notify = svn_wc_create_notify(local_abspath, svn_wc_notify_tree_conflict,
1404
1416
                                    scratch_pool);
1405
 
      notify->kind = node_kind;
 
1417
      notify->kind = local_node_kind;
1406
1418
 
1407
 
      (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2, notify,
1408
 
                                    scratch_pool);
 
1419
      merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
 
1420
                                 scratch_pool);
1409
1421
    }
1410
1422
 
1411
1423
  return SVN_NO_ERROR;
1439
1451
      notify = svn_wc_create_notify(local_abspath, action, scratch_pool);
1440
1452
      notify->kind = kind;
1441
1453
 
1442
 
      (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2, notify,
1443
 
                                    scratch_pool);
 
1454
      merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
 
1455
                                 scratch_pool);
1444
1456
    }
1445
1457
 
1446
1458
  return SVN_NO_ERROR;
1473
1485
      notify->content_state = content_state;
1474
1486
      notify->prop_state = prop_state;
1475
1487
 
1476
 
      (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2, notify,
1477
 
                                    scratch_pool);
 
1488
      merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
 
1489
                                 scratch_pool);
1478
1490
    }
1479
1491
 
1480
1492
  return SVN_NO_ERROR;
1531
1543
           hi;
1532
1544
           hi = apr_hash_next(hi))
1533
1545
        {
1534
 
          const char *del_abspath = svn__apr_hash_index_key(hi);
 
1546
          const char *del_abspath = apr_hash_this_key(hi);
1535
1547
          svn_wc_notify_t *notify;
1536
1548
 
1537
1549
          notify = svn_wc_create_notify(del_abspath,
1538
1550
                                        svn_wc_notify_update_delete,
1539
1551
                                        scratch_pool);
1540
1552
          notify->kind = svn_node_kind_from_word(
1541
 
                                    svn__apr_hash_index_val(hi));
 
1553
                                    apr_hash_this_val(hi));
1542
1554
 
1543
 
          (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2,
1544
 
                                        notify, scratch_pool);
 
1555
          merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2,
 
1556
                                     notify, scratch_pool);
1545
1557
        }
1546
1558
 
1547
1559
      db->pending_deletes = NULL;
1607
1619
          notify->kind = svn_node_dir;
1608
1620
          notify->content_state = notify->prop_state = db->skip_reason;
1609
1621
 
1610
 
          (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2,
1611
 
                                        notify,
1612
 
                                        scratch_pool);
 
1622
          merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2,
 
1623
                                     notify,
 
1624
                                     scratch_pool);
1613
1625
        }
1614
1626
 
1615
1627
      if (merge_b->merge_source.ancestral
1623
1635
      /* open_directory() decided that a tree conflict should be raised */
1624
1636
 
1625
1637
      SVN_ERR(record_tree_conflict(merge_b, local_abspath, db->parent_baton,
1626
 
                                   svn_node_dir, db->tree_conflict_action,
 
1638
                                   db->tree_conflict_local_node_kind,
 
1639
                                   db->tree_conflict_merge_left_node_kind,
 
1640
                                   db->tree_conflict_merge_right_node_kind,
 
1641
                                   db->tree_conflict_action,
1627
1642
                                   db->tree_conflict_reason,
1628
1643
                                   NULL, TRUE,
1629
1644
                                   scratch_pool));
1686
1701
          notify->kind = svn_node_file;
1687
1702
          notify->content_state = notify->prop_state = fb->skip_reason;
1688
1703
 
1689
 
          (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2,
1690
 
                                        notify,
1691
 
                                        scratch_pool);
 
1704
          merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2,
 
1705
                                     notify,
 
1706
                                     scratch_pool);
1692
1707
        }
1693
1708
 
1694
1709
      if (merge_b->merge_source.ancestral
1702
1717
      /* open_file() decided that a tree conflict should be raised */
1703
1718
 
1704
1719
      SVN_ERR(record_tree_conflict(merge_b, local_abspath, fb->parent_baton,
1705
 
                                   svn_node_file, fb->tree_conflict_action,
 
1720
                                   fb->tree_conflict_local_node_kind,
 
1721
                                   fb->tree_conflict_merge_left_node_kind,
 
1722
                                   fb->tree_conflict_merge_right_node_kind,
 
1723
                                   fb->tree_conflict_action,
1706
1724
                                   fb->tree_conflict_reason,
1707
1725
                                   NULL, TRUE,
1708
1726
                                   scratch_pool));
1742
1760
  fb->tree_conflict_action = svn_wc_conflict_action_edit;
1743
1761
  fb->skip_reason = svn_wc_notify_state_unknown;
1744
1762
 
 
1763
  if (left_source)
 
1764
    fb->tree_conflict_merge_left_node_kind = svn_node_file;
 
1765
  else
 
1766
    fb->tree_conflict_merge_left_node_kind = svn_node_none;
 
1767
 
 
1768
  if (right_source)
 
1769
    fb->tree_conflict_merge_right_node_kind = svn_node_file;
 
1770
  else
 
1771
    fb->tree_conflict_merge_right_node_kind = svn_node_none;
 
1772
 
1745
1773
  *new_file_baton = fb;
1746
1774
 
1747
1775
  if (pdb)
1758
1786
  else if (left_source != NULL)
1759
1787
    {
1760
1788
      /* Node is expected to be a file, which will be changed or deleted. */
1761
 
      svn_node_kind_t kind;
1762
1789
      svn_boolean_t is_deleted;
1763
1790
      svn_boolean_t excluded;
1764
1791
      svn_depth_t parent_depth;
1770
1797
        svn_wc_notify_state_t obstr_state;
1771
1798
 
1772
1799
        SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, &excluded,
1773
 
                                          &kind, &parent_depth,
 
1800
                                          &fb->tree_conflict_local_node_kind,
 
1801
                                          &parent_depth,
1774
1802
                                          merge_b, local_abspath,
1775
1803
                                          scratch_pool));
1776
1804
 
1783
1811
          }
1784
1812
 
1785
1813
        if (is_deleted)
1786
 
          kind = svn_node_none;
 
1814
          fb->tree_conflict_local_node_kind = svn_node_none;
1787
1815
      }
1788
1816
 
1789
 
      if (kind == svn_node_none)
 
1817
      if (fb->tree_conflict_local_node_kind == svn_node_none)
1790
1818
        {
1791
1819
          fb->shadowed = TRUE;
1792
1820
 
1820
1848
          return SVN_NO_ERROR;
1821
1849
          /* ### /Similar */
1822
1850
        }
1823
 
      else if (kind != svn_node_file)
 
1851
      else if (fb->tree_conflict_local_node_kind != svn_node_file)
1824
1852
        {
 
1853
          svn_boolean_t added;
1825
1854
          fb->shadowed = TRUE;
1826
1855
 
1827
 
          fb->tree_conflict_reason = svn_wc_conflict_reason_obstructed;
 
1856
          SVN_ERR(svn_wc__node_is_added(&added, merge_b->ctx->wc_ctx,
 
1857
                                        local_abspath, scratch_pool));
 
1858
 
 
1859
          fb->tree_conflict_reason = added ? svn_wc_conflict_reason_added
 
1860
                                           : svn_wc_conflict_reason_obstructed;
1828
1861
 
1829
1862
          /* ### Similar to directory */
1830
1863
          *skip = TRUE;
1879
1912
 
1880
1913
          /* Update the tree conflict to store that this is a replace */
1881
1914
          SVN_ERR(record_tree_conflict(merge_b, local_abspath, pdb,
 
1915
                                       old_tc->node_kind,
 
1916
                                       old_tc->src_left_version->node_kind,
1882
1917
                                       svn_node_file,
1883
1918
                                       fb->tree_conflict_action,
1884
1919
                                       fb->tree_conflict_reason,
1905
1940
                  && ((pdb && pdb->added) || fb->add_is_replace)))
1906
1941
        {
1907
1942
          svn_wc_notify_state_t obstr_state;
1908
 
          svn_node_kind_t kind;
1909
1943
          svn_boolean_t is_deleted;
1910
1944
 
1911
1945
          SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, NULL,
1912
 
                                            &kind, NULL,
1913
 
                                            merge_b, local_abspath,
 
1946
                                            &fb->tree_conflict_local_node_kind,
 
1947
                                            NULL, merge_b, local_abspath,
1914
1948
                                            scratch_pool));
1915
1949
 
1916
1950
          if (obstr_state != svn_wc_notify_state_inapplicable)
1920
1954
              fb->tree_conflict_reason = CONFLICT_REASON_SKIP;
1921
1955
              fb->skip_reason = obstr_state;
1922
1956
            }
1923
 
          else if (kind != svn_node_none && !is_deleted)
 
1957
          else if (fb->tree_conflict_local_node_kind != svn_node_none
 
1958
                   && !is_deleted)
1924
1959
            {
1925
1960
              /* Set a tree conflict */
 
1961
              svn_boolean_t added;
 
1962
 
1926
1963
              fb->shadowed = TRUE;
1927
 
              fb->tree_conflict_reason = svn_wc_conflict_reason_obstructed;
 
1964
              SVN_ERR(svn_wc__node_is_added(&added, merge_b->ctx->wc_ctx,
 
1965
                                            local_abspath, scratch_pool));
 
1966
 
 
1967
              fb->tree_conflict_reason = added ? svn_wc_conflict_reason_added
 
1968
                                               : svn_wc_conflict_reason_obstructed;
1928
1969
            }
1929
1970
        }
1930
1971
 
2000
2041
                                      scratch_pool, scratch_pool));
2001
2042
 
2002
2043
  SVN_ERR(make_conflict_versions(&left, &right, local_abspath,
2003
 
                                 svn_node_file, &merge_b->merge_source, merge_b->target,
 
2044
                                 svn_node_file, svn_node_file,
 
2045
                                 &merge_b->merge_source, merge_b->target,
2004
2046
                                 scratch_pool, scratch_pool));
2005
2047
 
2006
2048
  /* Do property merge now, if we are not going to perform a text merge */
2427
2469
       */
2428
2470
      SVN_ERR(record_tree_conflict(merge_b, local_abspath, fb->parent_baton,
2429
2471
                                   svn_node_file,
 
2472
                                   svn_node_file,
 
2473
                                   svn_node_none,
2430
2474
                                   svn_wc_conflict_action_delete,
2431
2475
                                   svn_wc_conflict_reason_edited,
2432
2476
                                   NULL, TRUE,
2447
2491
   When *SKIP is TRUE, the diff driver avoids work on getting the details
2448
2492
   for the closing callbacks.
2449
2493
 
2450
 
   The SKIP and SKIP_DESCENDANTS work independantly.
 
2494
   The SKIP and SKIP_DESCENDANTS work independently.
2451
2495
 */
2452
2496
static svn_error_t *
2453
2497
merge_dir_opened(void **new_dir_baton,
2477
2521
 
2478
2522
  *new_dir_baton = db;
2479
2523
 
 
2524
  if (left_source)
 
2525
    db->tree_conflict_merge_left_node_kind = svn_node_dir;
 
2526
  else
 
2527
    db->tree_conflict_merge_left_node_kind = svn_node_none;
 
2528
 
 
2529
  if (right_source)
 
2530
    db->tree_conflict_merge_right_node_kind = svn_node_dir;
 
2531
  else
 
2532
    db->tree_conflict_merge_right_node_kind = svn_node_none;
 
2533
 
2480
2534
  if (pdb)
2481
2535
    {
2482
2536
      db->parent_baton = pdb;
2493
2547
  else if (left_source != NULL)
2494
2548
    {
2495
2549
      /* Node is expected to be a directory. */
2496
 
      svn_node_kind_t kind;
2497
2550
      svn_boolean_t is_deleted;
2498
2551
      svn_boolean_t excluded;
2499
2552
      svn_depth_t parent_depth;
2505
2558
      {
2506
2559
        svn_wc_notify_state_t obstr_state;
2507
2560
        SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, &excluded,
2508
 
                                          &kind, &parent_depth,
2509
 
                                          merge_b, local_abspath,
2510
 
                                          scratch_pool));
 
2561
                                          &db->tree_conflict_local_node_kind,
 
2562
                                          &parent_depth, merge_b,
 
2563
                                          local_abspath, scratch_pool));
2511
2564
 
2512
2565
        if (obstr_state != svn_wc_notify_state_inapplicable)
2513
2566
          {
2542
2595
          }
2543
2596
 
2544
2597
        if (is_deleted)
2545
 
          kind = svn_node_none;
 
2598
          db->tree_conflict_local_node_kind = svn_node_none;
2546
2599
      }
2547
2600
 
2548
 
      if (kind == svn_node_none)
 
2601
      if (db->tree_conflict_local_node_kind == svn_node_none)
2549
2602
        {
2550
2603
          db->shadowed = TRUE;
2551
2604
 
2581
2634
          return SVN_NO_ERROR;
2582
2635
          /* ### /avoid breaking tests */
2583
2636
        }
2584
 
      else if (kind != svn_node_dir)
 
2637
      else if (db->tree_conflict_local_node_kind != svn_node_dir)
2585
2638
        {
 
2639
          svn_boolean_t added;
 
2640
 
2586
2641
          db->shadowed = TRUE;
 
2642
          SVN_ERR(svn_wc__node_is_added(&added, merge_b->ctx->wc_ctx,
 
2643
                                        local_abspath, scratch_pool));
2587
2644
 
2588
 
          db->tree_conflict_reason = svn_wc_conflict_reason_obstructed;
 
2645
          db->tree_conflict_reason = added ? svn_wc_conflict_reason_added
 
2646
                                           : svn_wc_conflict_reason_obstructed;
2589
2647
 
2590
2648
          /* ### To avoid breaking tests */
2591
2649
          *skip = TRUE;
2672
2730
 
2673
2731
              /* Update the tree conflict to store that this is a replace */
2674
2732
              SVN_ERR(record_tree_conflict(merge_b, local_abspath, pdb,
 
2733
                                           old_tc->node_kind,
 
2734
                                           old_tc->src_left_version->node_kind,
2675
2735
                                           svn_node_dir,
2676
2736
                                           db->tree_conflict_action,
2677
2737
                                           db->tree_conflict_reason,
2686
2746
             && ((pdb && pdb->added) || db->add_is_replace)))
2687
2747
        {
2688
2748
          svn_wc_notify_state_t obstr_state;
2689
 
          svn_node_kind_t kind;
2690
2749
          svn_boolean_t is_deleted;
2691
2750
 
2692
2751
          SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, NULL,
2693
 
                                            &kind, NULL,
2694
 
                                            merge_b, local_abspath,
 
2752
                                            &db->tree_conflict_local_node_kind,
 
2753
                                            NULL, merge_b, local_abspath,
2695
2754
                                            scratch_pool));
2696
2755
 
2697
2756
          /* In this case of adding a directory, we have an exception to the
2701
2760
           * versioned but unexpectedly missing from disk, or is unversioned
2702
2761
           * but obstructed by a node of the wrong kind. */
2703
2762
          if (obstr_state == svn_wc_notify_state_obstructed
2704
 
              && (is_deleted || kind == svn_node_none))
 
2763
              && (is_deleted ||
 
2764
                  db->tree_conflict_local_node_kind == svn_node_none))
2705
2765
            {
2706
2766
              svn_node_kind_t disk_kind;
2707
2767
 
2722
2782
              db->tree_conflict_reason = CONFLICT_REASON_SKIP;
2723
2783
              db->skip_reason = obstr_state;
2724
2784
            }
2725
 
          else if (kind != svn_node_none && !is_deleted)
 
2785
          else if (db->tree_conflict_local_node_kind != svn_node_none
 
2786
                   && !is_deleted)
2726
2787
            {
2727
2788
              /* Set a tree conflict */
 
2789
              svn_boolean_t added;
2728
2790
              db->shadowed = TRUE;
2729
 
              db->tree_conflict_reason = svn_wc_conflict_reason_obstructed;
2730
 
 
2731
 
              if ((merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
2732
 
                  && !(pdb && pdb->shadowed))
2733
 
                {
2734
 
                  store_path(merge_b->skipped_abspaths, local_abspath);
2735
 
                }
 
2791
 
 
2792
              SVN_ERR(svn_wc__node_is_added(&added, merge_b->ctx->wc_ctx,
 
2793
                                            local_abspath, scratch_pool));
 
2794
 
 
2795
              db->tree_conflict_reason = added ? svn_wc_conflict_reason_added
 
2796
                                               : svn_wc_conflict_reason_obstructed;
2736
2797
            }
2737
2798
        }
2738
2799
 
2758
2819
 
2759
2820
          if (old_tc)
2760
2821
            {
2761
 
              /* svn_wc_add4 and svn_wc_add_from_disk2 can't add a node
 
2822
              /* svn_wc_add4 and svn_wc_add_from_disk3 can't add a node
2762
2823
                 over an existing tree conflict */
2763
2824
 
2764
2825
              /* ### These functions should take some tree conflict argument
2796
2857
            }
2797
2858
          else
2798
2859
            {
2799
 
              SVN_ERR(svn_wc_add_from_disk2(merge_b->ctx->wc_ctx, local_abspath,
 
2860
              SVN_ERR(svn_wc_add_from_disk3(merge_b->ctx->wc_ctx, local_abspath,
2800
2861
                                            apr_hash_make(scratch_pool),
 
2862
                                            FALSE /* skip checks */,
2801
2863
                                            NULL, NULL /* no notify! */,
2802
2864
                                            scratch_pool));
2803
2865
            }
2806
2868
            {
2807
2869
              /* ### Should be atomic with svn_wc_add(4|_from_disk2)() */
2808
2870
              SVN_ERR(record_tree_conflict(merge_b, local_abspath, pdb,
 
2871
                                           old_tc->node_kind,
 
2872
                                           svn_node_none,
2809
2873
                                           svn_node_dir,
2810
2874
                                           db->tree_conflict_action,
2811
2875
                                           db->tree_conflict_reason,
2875
2939
      svn_wc_notify_state_t prop_state;
2876
2940
 
2877
2941
      SVN_ERR(make_conflict_versions(&left, &right, local_abspath,
2878
 
                                     svn_node_dir, &merge_b->merge_source,
 
2942
                                     svn_node_dir, svn_node_dir,
 
2943
                                     &merge_b->merge_source,
2879
2944
                                     merge_b->target,
2880
2945
                                     scratch_pool, scratch_pool));
2881
2946
 
3225
3290
       */
3226
3291
      SVN_ERR(record_tree_conflict(merge_b, local_abspath, db->parent_baton,
3227
3292
                                   svn_node_dir,
 
3293
                                   svn_node_dir,
 
3294
                                   svn_node_none,
3228
3295
                                   svn_wc_conflict_action_delete,
3229
3296
                                   svn_wc_conflict_reason_edited,
3230
3297
                                   NULL, TRUE,
3643
3710
      notify->merge_range = NULL;
3644
3711
    }
3645
3712
 
3646
 
  (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2, notify,
3647
 
                                scratch_pool);
 
3713
  merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
 
3714
                             scratch_pool);
3648
3715
 
3649
3716
  return SVN_NO_ERROR;
3650
3717
}
3792
3859
                                            younger_rev, older_rev, ctx,
3793
3860
                                            scratch_pool);
3794
3861
 
3795
 
  /* If PRIMARY_URL@peg_rev doesn't exist then
3796
 
      svn_client__repos_location_segments() typically returns an
3797
 
      SVN_ERR_FS_NOT_FOUND error, but if it doesn't exist for a
3798
 
      forward merge over ra_neon then we get SVN_ERR_RA_DAV_REQUEST_FAILED.
3799
 
      http://subversion.tigris.org/issues/show_bug.cgi?id=3137 fixed some of
3800
 
      the cases where different RA layers returned different error codes to
3801
 
      signal the "path not found"...but it looks like there is more to do.
3802
 
 
3803
 
      ### Do we still need to special case for ra_neon (since it no longer
3804
 
          exists)? */
3805
3862
  if (err)
3806
3863
    {
3807
 
      if (err->apr_err == SVN_ERR_FS_NOT_FOUND
3808
 
          || err->apr_err == SVN_ERR_RA_DAV_REQUEST_FAILED)
 
3864
      const char *rel_source_path;  /* PRIMARY_URL relative to RA_SESSION */
 
3865
      svn_node_kind_t kind;
 
3866
 
 
3867
      if (err->apr_err != SVN_ERR_FS_NOT_FOUND)
 
3868
        return svn_error_trace(err);
 
3869
 
 
3870
      svn_error_clear(err);
 
3871
 
 
3872
      /* PRIMARY_URL@peg_rev doesn't exist.  Check if PRIMARY_URL@older_rev
 
3873
         exists, if neither exist then the editor can simply ignore this
 
3874
         subtree. */
 
3875
 
 
3876
      SVN_ERR(svn_ra_get_path_relative_to_session(
 
3877
                ra_session, &rel_source_path, primary_url, scratch_pool));
 
3878
 
 
3879
      SVN_ERR(svn_ra_check_path(ra_session, rel_source_path,
 
3880
                                older_rev, &kind, scratch_pool));
 
3881
      if (kind == svn_node_none)
3809
3882
        {
3810
 
          /* PRIMARY_URL@peg_rev doesn't exist.  Check if PRIMARY_URL@older_rev
3811
 
             exists, if neither exist then the editor can simply ignore this
3812
 
             subtree. */
3813
 
          const char *rel_source_path;  /* PRIMARY_URL relative to RA_SESSION */
3814
 
          svn_node_kind_t kind;
3815
 
 
3816
 
          svn_error_clear(err);
3817
 
          err = NULL;
3818
 
 
3819
 
          SVN_ERR(svn_ra_get_path_relative_to_session(
3820
 
                    ra_session, &rel_source_path, primary_url, scratch_pool));
3821
 
 
3822
 
          SVN_ERR(svn_ra_check_path(ra_session, rel_source_path,
3823
 
                                    older_rev, &kind, scratch_pool));
3824
 
          if (kind == svn_node_none)
3825
 
            {
3826
 
              /* Neither PRIMARY_URL@peg_rev nor PRIMARY_URL@older_rev exist,
3827
 
                 so there is nothing to merge.  Set CHILD->REMAINING_RANGES
3828
 
                 identical to PARENT's. */
3829
 
              child->remaining_ranges =
3830
 
                svn_rangelist_dup(parent->remaining_ranges, scratch_pool);
3831
 
            }
3832
 
          else
3833
 
            {
3834
 
              svn_rangelist_t *deleted_rangelist;
3835
 
              svn_revnum_t rev_primary_url_deleted;
3836
 
 
3837
 
              /* PRIMARY_URL@older_rev exists, so it was deleted at some
3838
 
                 revision prior to peg_rev, find that revision. */
3839
 
              SVN_ERR(svn_ra_get_deleted_rev(ra_session, rel_source_path,
3840
 
                                             older_rev, younger_rev,
3841
 
                                             &rev_primary_url_deleted,
3842
 
                                             scratch_pool));
3843
 
 
3844
 
              /* PRIMARY_URL@older_rev exists and PRIMARY_URL@peg_rev doesn't,
3845
 
                 so svn_ra_get_deleted_rev() should always find the revision
3846
 
                 PRIMARY_URL@older_rev was deleted. */
3847
 
              SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(rev_primary_url_deleted));
3848
 
 
3849
 
              /* If this is a reverse merge reorder CHILD->REMAINING_RANGES and
3850
 
                 PARENT->REMAINING_RANGES so both will work with the
3851
 
                 svn_rangelist_* APIs below. */
3852
 
              if (is_rollback)
3853
 
                {
3854
 
                  /* svn_rangelist_reverse operates in place so it's safe
3855
 
                     to use our scratch_pool. */
3856
 
                  SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
3857
 
                                                scratch_pool));
3858
 
                  SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
3859
 
                                                scratch_pool));
3860
 
                }
3861
 
 
3862
 
              /* Find the intersection of CHILD->REMAINING_RANGES with the
3863
 
                 range over which PRIMARY_URL@older_rev exists (ending at
3864
 
                 the youngest revision at which it still exists). */
3865
 
              SVN_ERR(rangelist_intersect_range(&child->remaining_ranges,
3866
 
                                                child->remaining_ranges,
3867
 
                                                older_rev,
3868
 
                                                rev_primary_url_deleted - 1,
3869
 
                                                FALSE,
3870
 
                                                scratch_pool, scratch_pool));
3871
 
 
3872
 
              /* Merge into CHILD->REMAINING_RANGES the intersection of
3873
 
                 PARENT->REMAINING_RANGES with the range beginning when
3874
 
                 PRIMARY_URL@older_rev was deleted until younger_rev. */
3875
 
              SVN_ERR(rangelist_intersect_range(&deleted_rangelist,
3876
 
                                                parent->remaining_ranges,
3877
 
                                                rev_primary_url_deleted - 1,
3878
 
                                                peg_rev,
3879
 
                                                FALSE,
3880
 
                                                scratch_pool, scratch_pool));
3881
 
              SVN_ERR(svn_rangelist_merge2(child->remaining_ranges,
3882
 
                                           deleted_rangelist, scratch_pool,
3883
 
                                           scratch_pool));
3884
 
 
3885
 
              /* Return CHILD->REMAINING_RANGES and PARENT->REMAINING_RANGES
3886
 
                 to reverse order if necessary. */
3887
 
              if (is_rollback)
3888
 
                {
3889
 
                  SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
3890
 
                                                scratch_pool));
3891
 
                  SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
3892
 
                                                scratch_pool));
3893
 
                }
3894
 
            }
 
3883
          /* Neither PRIMARY_URL@peg_rev nor PRIMARY_URL@older_rev exist,
 
3884
             so there is nothing to merge.  Set CHILD->REMAINING_RANGES
 
3885
             identical to PARENT's. */
 
3886
          child->remaining_ranges =
 
3887
            svn_rangelist_dup(parent->remaining_ranges, scratch_pool);
3895
3888
        }
3896
3889
      else
3897
3890
        {
3898
 
          return svn_error_trace(err);
 
3891
          svn_rangelist_t *deleted_rangelist;
 
3892
          svn_revnum_t rev_primary_url_deleted;
 
3893
 
 
3894
          /* PRIMARY_URL@older_rev exists, so it was deleted at some
 
3895
             revision prior to peg_rev, find that revision. */
 
3896
          SVN_ERR(svn_ra_get_deleted_rev(ra_session, rel_source_path,
 
3897
                                         older_rev, younger_rev,
 
3898
                                         &rev_primary_url_deleted,
 
3899
                                         scratch_pool));
 
3900
 
 
3901
          /* PRIMARY_URL@older_rev exists and PRIMARY_URL@peg_rev doesn't,
 
3902
             so svn_ra_get_deleted_rev() should always find the revision
 
3903
             PRIMARY_URL@older_rev was deleted. */
 
3904
          SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(rev_primary_url_deleted));
 
3905
 
 
3906
          /* If this is a reverse merge reorder CHILD->REMAINING_RANGES and
 
3907
             PARENT->REMAINING_RANGES so both will work with the
 
3908
             svn_rangelist_* APIs below. */
 
3909
          if (is_rollback)
 
3910
            {
 
3911
              /* svn_rangelist_reverse operates in place so it's safe
 
3912
                 to use our scratch_pool. */
 
3913
              SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
 
3914
                                            scratch_pool));
 
3915
              SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
 
3916
                                            scratch_pool));
 
3917
            }
 
3918
 
 
3919
          /* Find the intersection of CHILD->REMAINING_RANGES with the
 
3920
             range over which PRIMARY_URL@older_rev exists (ending at
 
3921
             the youngest revision at which it still exists). */
 
3922
          SVN_ERR(rangelist_intersect_range(&child->remaining_ranges,
 
3923
                                            child->remaining_ranges,
 
3924
                                            older_rev,
 
3925
                                            rev_primary_url_deleted - 1,
 
3926
                                            FALSE,
 
3927
                                            scratch_pool, scratch_pool));
 
3928
 
 
3929
          /* Merge into CHILD->REMAINING_RANGES the intersection of
 
3930
             PARENT->REMAINING_RANGES with the range beginning when
 
3931
             PRIMARY_URL@older_rev was deleted until younger_rev. */
 
3932
          SVN_ERR(rangelist_intersect_range(&deleted_rangelist,
 
3933
                                            parent->remaining_ranges,
 
3934
                                            rev_primary_url_deleted - 1,
 
3935
                                            peg_rev,
 
3936
                                            FALSE,
 
3937
                                            scratch_pool, scratch_pool));
 
3938
          SVN_ERR(svn_rangelist_merge2(child->remaining_ranges,
 
3939
                                       deleted_rangelist, scratch_pool,
 
3940
                                       scratch_pool));
 
3941
 
 
3942
          /* Return CHILD->REMAINING_RANGES and PARENT->REMAINING_RANGES
 
3943
             to reverse order if necessary. */
 
3944
          if (is_rollback)
 
3945
            {
 
3946
              SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
 
3947
                                            scratch_pool));
 
3948
              SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
 
3949
                                            scratch_pool));
 
3950
            }
3899
3951
        }
3900
3952
    }
3901
3953
  else /* PRIMARY_URL@peg_rev exists. */
4684
4736
                                NULL, NULL, NULL, NULL,
4685
4737
                                ctx->wc_ctx, child->abspath,
4686
4738
                                TRUE /* ignore_enoent */,
4687
 
                                FALSE /* show_hidden */,
4688
4739
                                scratch_pool, scratch_pool));
4689
4740
  /* If CHILD has no base revision then it hasn't been committed yet, so it
4690
4741
     can't have any "future" history. */
4779
4830
  *gap_start = *gap_end = SVN_INVALID_REVNUM;
4780
4831
 
4781
4832
  /* Easy out: There can't be a gap between adjacent revisions. */
4782
 
  if (abs(source->loc1->rev - source->loc2->rev) == 1)
 
4833
  if (labs(source->loc1->rev - source->loc2->rev) == 1)
4783
4834
    return SVN_NO_ERROR;
4784
4835
 
4785
4836
  /* Get SOURCE as mergeinfo. */
5174
5225
     the WC with its on-disk mergeinfo. */
5175
5226
  for (hi = apr_hash_first(scratch_pool, merges); hi; hi = apr_hash_next(hi))
5176
5227
    {
5177
 
      const char *local_abspath = svn__apr_hash_index_key(hi);
5178
 
      svn_rangelist_t *ranges = svn__apr_hash_index_val(hi);
 
5228
      const char *local_abspath = apr_hash_this_key(hi);
 
5229
      svn_rangelist_t *ranges = apr_hash_this_val(hi);
5179
5230
      svn_rangelist_t *rangelist;
5180
5231
      svn_error_t *err;
5181
5232
      const char *local_abspath_rel_to_target;
5326
5377
  for (hi = apr_hash_first(scratch_pool, merge_b->skipped_abspaths); hi;
5327
5378
       hi = apr_hash_next(hi))
5328
5379
    {
5329
 
      const char *skipped_abspath = svn__apr_hash_index_key(hi);
 
5380
      const char *skipped_abspath = apr_hash_this_key(hi);
5330
5381
      svn_wc_notify_state_t obstruction_state;
5331
5382
 
5332
5383
      svn_pool_clear(iterpool);
5882
5933
              split_range2->start = end_rev;
5883
5934
              APR_ARRAY_IDX(child->remaining_ranges, 0,
5884
5935
                            svn_merge_range_t *) = split_range1;
5885
 
              svn_sort__array_insert(&split_range2, child->remaining_ranges, 1);
 
5936
              svn_sort__array_insert(child->remaining_ranges, &split_range2, 1);
5886
5937
            }
5887
5938
        }
5888
5939
    }
6017
6068
 
6018
6069
  /* Find where to insert the new element */
6019
6070
  insert_index =
6020
 
    svn_sort__bsearch_lower_bound(&insert_element, children_with_mergeinfo,
 
6071
    svn_sort__bsearch_lower_bound(children_with_mergeinfo, &insert_element,
6021
6072
                                  compare_merge_path_t_as_paths);
6022
6073
 
6023
6074
  new_element = svn_client__merge_path_dup(insert_element, pool);
6024
 
  svn_sort__array_insert(&new_element, children_with_mergeinfo, insert_index);
 
6075
  svn_sort__array_insert(children_with_mergeinfo, &new_element, insert_index);
6025
6076
}
6026
6077
 
6027
6078
/* Helper for get_mergeinfo_paths().
6088
6139
    } /*(parent == NULL) */
6089
6140
 
6090
6141
  /* Add all of PARENT's non-missing children that are not already present.*/
6091
 
  SVN_ERR(svn_wc__node_get_children(&children, ctx->wc_ctx,
6092
 
                                    parent_abspath, FALSE, pool, pool));
 
6142
  SVN_ERR(svn_wc__node_get_children_of_working_node(&children, ctx->wc_ctx,
 
6143
                                                    parent_abspath,
 
6144
                                                    pool, pool));
6093
6145
  iterpool = svn_pool_create(pool);
6094
6146
  for (i = 0; i < children->nelts; i++)
6095
6147
    {
6188
6240
           hi;
6189
6241
           hi = apr_hash_next(hi))
6190
6242
        {
6191
 
          const char *missing_root_path = svn__apr_hash_index_key(hi);
 
6243
          const char *missing_root_path = apr_hash_this_key(hi);
6192
6244
 
6193
6245
          if (svn_dirent_is_ancestor(missing_root_path,
6194
6246
                                     local_abspath))
6246
6298
       hi;
6247
6299
       hi = apr_hash_next(hi))
6248
6300
    {
6249
 
      const char *wc_path = svn__apr_hash_index_key(hi);
6250
 
      svn_string_t *mergeinfo_string = svn__apr_hash_index_val(hi);
 
6301
      const char *wc_path = apr_hash_this_key(hi);
 
6302
      svn_string_t *mergeinfo_string = apr_hash_this_val(hi);
6251
6303
      svn_mergeinfo_t mergeinfo;
6252
6304
      svn_error_t *err;
6253
6305
 
6360
6412
           hi;
6361
6413
           hi = apr_hash_next(hi))
6362
6414
        {
6363
 
          const char *wc_path = svn__apr_hash_index_key(hi);
6364
 
          svn_mergeinfo_t mergeinfo = svn__apr_hash_index_val(hi);
 
6415
          const char *wc_path = apr_hash_this_key(hi);
 
6416
          svn_mergeinfo_t mergeinfo = apr_hash_this_val(hi);
6365
6417
          svn_client__merge_path_t *mergeinfo_child =
6366
6418
            svn_client__merge_path_create(wc_path, result_pool);
6367
6419
 
6429
6481
          svn_pool_clear(iterpool);
6430
6482
          svn_stringbuf_appendcstr(missing_subtree_err_buf,
6431
6483
                                   svn_dirent_local_style(
6432
 
                                     svn__apr_hash_index_key(hi), iterpool));
 
6484
                                     apr_hash_this_key(hi), iterpool));
6433
6485
          svn_stringbuf_appendcstr(missing_subtree_err_buf, "\n");
6434
6486
        }
6435
6487
 
6445
6497
           hi;
6446
6498
           hi = apr_hash_next(hi))
6447
6499
        {
6448
 
           const char *wc_path = svn__apr_hash_index_key(hi);
 
6500
           const char *wc_path = apr_hash_this_key(hi);
6449
6501
           svn_client__merge_path_t *child = get_child_with_mergeinfo(
6450
6502
             children_with_mergeinfo, wc_path);
6451
6503
 
6473
6525
           hi = apr_hash_next(hi))
6474
6526
        {
6475
6527
           svn_boolean_t new_shallow_child = FALSE;
6476
 
           const char *wc_path = svn__apr_hash_index_key(hi);
6477
 
           svn_depth_t *child_depth = svn__apr_hash_index_val(hi);
 
6528
           const char *wc_path = apr_hash_this_key(hi);
 
6529
           svn_depth_t *child_depth = apr_hash_this_val(hi);
6478
6530
           svn_client__merge_path_t *shallow_child = get_child_with_mergeinfo(
6479
6531
             children_with_mergeinfo, wc_path);
6480
6532
 
6528
6580
           hi;
6529
6581
           hi = apr_hash_next(hi))
6530
6582
        {
6531
 
           const char *wc_path = svn__apr_hash_index_key(hi);
 
6583
           const char *wc_path = apr_hash_this_key(hi);
6532
6584
           svn_client__merge_path_t *child = get_child_with_mergeinfo(
6533
6585
             children_with_mergeinfo, wc_path);
6534
6586
 
6571
6623
 
6572
6624
      SVN_ERR(svn_wc__node_get_children_of_working_node(
6573
6625
        &immediate_children, ctx->wc_ctx,
6574
 
        target->abspath, FALSE, scratch_pool, scratch_pool));
 
6626
        target->abspath, scratch_pool, scratch_pool));
6575
6627
 
6576
6628
      for (j = 0; j < immediate_children->nelts; j++)
6577
6629
        {
6655
6707
          const apr_array_header_t *children;
6656
6708
          int j;
6657
6709
 
6658
 
          SVN_ERR(svn_wc__node_get_children(&children,
 
6710
          SVN_ERR(svn_wc__node_get_children_of_working_node(
 
6711
                                            &children,
6659
6712
                                            ctx->wc_ctx,
6660
 
                                            child->abspath, FALSE,
 
6713
                                            child->abspath,
6661
6714
                                            iterpool, iterpool));
6662
6715
          for (j = 0; j < children->nelts; j++)
6663
6716
            {
7104
7157
              SVN_ERR(svn_client__get_copy_source(&original_repos_relpath,
7105
7158
                                                  &original_revision,
7106
7159
                                                  segment_url,
7107
 
                                                  &range_start_rev, ctx,
 
7160
                                                  &range_start_rev,
 
7161
                                                  ra_session, ctx,
7108
7162
                                                  result_pool, scratch_pool));
7109
7163
              /* Got copyfrom data?  Fix up the first segment to cover
7110
7164
                 back to COPYFROM_REV + 1, and then prepend a new
7117
7171
                  new_segment->path = original_repos_relpath;
7118
7172
                  new_segment->range_start = original_revision;
7119
7173
                  new_segment->range_end = original_revision;
7120
 
                  svn_sort__array_insert(&new_segment, segments, 0);
 
7174
                  svn_sort__array_insert(segments, &new_segment, 0);
7121
7175
                }
7122
7176
            }
7123
7177
        }
7783
7837
       hi;
7784
7838
       hi = apr_hash_next(hi))
7785
7839
    {
7786
 
      const char *abspath_with_new_mergeinfo = svn__apr_hash_index_key(hi);
 
7840
      const char *abspath_with_new_mergeinfo = apr_hash_this_key(hi);
7787
7841
      svn_mergeinfo_t path_inherited_mergeinfo;
7788
7842
      svn_mergeinfo_t path_explicit_mergeinfo;
7789
7843
      svn_client__merge_path_t *new_child;
7886
7940
      for (hi = apr_hash_first(pool, subtrees);
7887
7941
           hi; hi = apr_hash_next(hi))
7888
7942
        {
7889
 
          const char *path_touched_by_merge = svn__apr_hash_index_key(hi);
 
7943
          const char *path_touched_by_merge = apr_hash_this_key(hi);
7890
7944
          if (svn_dirent_is_ancestor(local_abspath, path_touched_by_merge))
7891
7945
            return TRUE;
7892
7946
        }
8001
8055
       hi;
8002
8056
       hi = apr_hash_next(hi))
8003
8057
    {
8004
 
      const char *path = svn__apr_hash_index_key(hi);
8005
 
      svn_log_changed_path2_t *change = svn__apr_hash_index_val(hi);
 
8058
      const char *path = apr_hash_this_key(hi);
 
8059
      svn_log_changed_path2_t *change = apr_hash_this_val(hi);
8006
8060
 
8007
8061
        {
8008
8062
          const char *child;
8638
8692
 
8639
8693
          /* Allow mergeinfo on switched subtrees to elide to the
8640
8694
             repository. Otherwise limit elision to the merge target
8641
 
             for now.  do_directory_merge() will eventually try to
 
8695
             for now.  do_merge() will eventually try to
8642
8696
             elide that when the merge is complete. */
8643
8697
          SVN_ERR(svn_client__elide_mergeinfo(
8644
8698
            child->abspath,
8687
8741
  iterpool = svn_pool_create(pool);
8688
8742
  for (hi = apr_hash_first(pool, added_abspaths); hi; hi = apr_hash_next(hi))
8689
8743
    {
8690
 
      const char *added_abspath = svn__apr_hash_index_key(hi);
 
8744
      const char *added_abspath = apr_hash_this_key(hi);
8691
8745
      const char *dir_abspath;
8692
8746
      svn_mergeinfo_t parent_mergeinfo;
8693
8747
      svn_mergeinfo_t added_path_mergeinfo;
8896
8950
       hi;
8897
8951
       hi = apr_hash_next(hi))
8898
8952
    {
8899
 
      const char *fspath = svn__apr_hash_index_key(hi);
 
8953
      const char *fspath = apr_hash_this_key(hi);
8900
8954
      const char *rel_path;
8901
8955
      const char *cwmi_abspath;
8902
8956
      svn_rangelist_t *paths_explicit_rangelist = NULL;
9053
9107
 
9054
9108
      svn_pool_clear(iterpool);
9055
9109
 
9056
 
      /* Issue #4269: Keep track of the longest common ancestor of all the
9057
 
         subtrees which require merges.  This may be a child of
9058
 
         TARGET->ABSPATH, which will allow us to narrow the log request
9059
 
         below. */
 
9110
      /* CHILD->REMAINING_RANGES will be NULL if child is absent. */
9060
9111
      if (child->remaining_ranges && child->remaining_ranges->nelts)
9061
9112
        {
 
9113
          /* Issue #4269: Keep track of the longest common ancestor of all the
 
9114
             subtrees which require merges.  This may be a child of
 
9115
             TARGET->ABSPATH, which will allow us to narrow the log request
 
9116
             below. */
9062
9117
          if (longest_common_subtree_ancestor)
9063
9118
            longest_common_subtree_ancestor = svn_dirent_get_longest_ancestor(
9064
9119
              longest_common_subtree_ancestor, child->abspath, scratch_pool);
9065
9120
          else
9066
9121
            longest_common_subtree_ancestor = child->abspath;
 
9122
 
 
9123
          SVN_ERR(svn_rangelist_merge2(subtree_remaining_ranges,
 
9124
                                       child->remaining_ranges,
 
9125
                                       scratch_pool, iterpool));
9067
9126
        }
9068
 
 
9069
 
      /* CHILD->REMAINING_RANGES will be NULL if child is absent. */
9070
 
      if (child->remaining_ranges && child->remaining_ranges->nelts)
9071
 
        SVN_ERR(svn_rangelist_merge2(subtree_remaining_ranges,
9072
 
                                     child->remaining_ranges,
9073
 
                                     scratch_pool, iterpool));
9074
9127
    }
9075
9128
  svn_pool_destroy(iterpool);
9076
9129
 
9464
9517
    {
9465
9518
      if (!merge_b->record_only)
9466
9519
        {
9467
 
          /* Reset cur_ancestor_abspath to null so that subsequent cherry
 
9520
          /* Reset the last notification path so that subsequent cherry
9468
9521
             picked revision ranges will be notified upon subsequent
9469
9522
             operative merge. */
9470
9523
          merge_b->notify_begin.last_abspath = NULL;
10226
10279
      svn_boolean_t is_modified;
10227
10280
 
10228
10281
      SVN_ERR(svn_wc__has_local_mods(&is_modified, ctx->wc_ctx,
10229
 
                                     target_abspath,
 
10282
                                     target_abspath, TRUE,
10230
10283
                                     ctx->cancel_func,
10231
10284
                                     ctx->cancel_baton,
10232
10285
                                     scratch_pool));
10724
10777
       hi = apr_hash_next(hi))
10725
10778
    {
10726
10779
      const char *subtree_missing_this_rev;
10727
 
      const char *path = svn__apr_hash_index_key(hi);
 
10780
      const char *path = apr_hash_this_key(hi);
10728
10781
      const char *rel_path;
10729
10782
      const char *source_rel_path;
10730
10783
      svn_boolean_t in_catalog;
10852
10905
           hi_catalog;
10853
10906
           hi_catalog = apr_hash_next(hi_catalog))
10854
10907
        {
10855
 
          svn_mergeinfo_t mergeinfo = svn__apr_hash_index_val(hi_catalog);
 
10908
          svn_mergeinfo_t mergeinfo = apr_hash_this_val(hi_catalog);
10856
10909
 
10857
10910
          SVN_ERR(svn_rangelist__merge_many(potentially_unmerged_ranges,
10858
10911
                                            mergeinfo,
11058
11111
       hi;
11059
11112
       hi = apr_hash_next(hi))
11060
11113
    {
11061
 
      const char *target_path = svn__apr_hash_index_key(hi);
11062
 
      svn_mergeinfo_t target_history_as_mergeinfo = svn__apr_hash_index_val(hi);
 
11114
      const char *target_path = apr_hash_this_key(hi);
 
11115
      svn_mergeinfo_t target_history_as_mergeinfo = apr_hash_this_val(hi);
11063
11116
      const char *path_rel_to_session
11064
11117
        = svn_relpath_skip_ancestor(target_repos_rel_path, target_path);
11065
11118
      const char *source_path;
11143
11196
       hi;
11144
11197
       hi = apr_hash_next(hi))
11145
11198
    {
11146
 
      const char *source_path = svn__apr_hash_index_key(hi);
 
11199
      const char *source_path = apr_hash_this_key(hi);
11147
11200
      const char *path_rel_to_session =
11148
11201
        svn_relpath_skip_ancestor(source_repos_rel_path, source_path);
11149
11202
      const char *source_url;
11150
 
      svn_mergeinfo_t source_mergeinfo = svn__apr_hash_index_val(hi);
 
11203
      svn_mergeinfo_t source_mergeinfo = apr_hash_this_val(hi);
11151
11204
      svn_mergeinfo_t filtered_mergeinfo;
11152
11205
      svn_client__pathrev_t *target_pathrev;
11153
11206
      svn_mergeinfo_t target_history_as_mergeinfo;
11296
11349
       hi;
11297
11350
       hi = apr_hash_next(hi))
11298
11351
    {
11299
 
      const char *local_abspath = svn__apr_hash_index_key(hi);
 
11352
      const char *local_abspath = apr_hash_this_key(hi);
11300
11353
      svn_client__pathrev_t *target_child;
11301
11354
      const char *repos_relpath;
11302
11355
      svn_mergeinfo_t target_history_as_mergeinfo;
11523
11576
          SVN_ERR(svn_mergeinfo__catalog_to_formatted_string(
11524
11577
            &source_mergeinfo_cat_string,
11525
11578
            final_unmerged_catalog,
11526
 
            "  ", "    Missing ranges: ", scratch_pool));
 
11579
            "  ", _("    Missing ranges: "), scratch_pool));
11527
11580
          return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE,
11528
11581
                                   NULL,
11529
11582
                                   _("Reintegrate can only be used if "
11943
11996
  for (hi = apr_hash_first(scratch_pool, branch_history->history); hi;
11944
11997
       hi = apr_hash_next(hi))
11945
11998
    {
11946
 
      const char *fspath = svn__apr_hash_index_key(hi);
11947
 
      svn_rangelist_t *rangelist = svn__apr_hash_index_val(hi);
 
11999
      const char *fspath = apr_hash_this_key(hi);
 
12000
      svn_rangelist_t *rangelist = apr_hash_this_val(hi);
11948
12001
      int i;
11949
12002
 
11950
12003
      for (i = 0; i < rangelist->nelts; i++)
12347
12400
  return SVN_NO_ERROR;
12348
12401
}
12349
12402
 
12350
 
/* The body of client_find_automatic_merge(), which see.
 
12403
/* Find the last point at which the branch at S_T->source was completely
 
12404
 * merged to the branch at S_T->target or vice-versa.
 
12405
 *
 
12406
 * Fill in S_T->source_branch and S_T->target_branch and S_T->yca.
 
12407
 * Set *BASE_P to the merge base.  Set *IS_REINTEGRATE_LIKE to true if
 
12408
 * an automatic merge from source to target would be a reintegration
 
12409
 * merge: that is, if the last automatic merge was in the opposite
 
12410
 * direction; or to false otherwise.
 
12411
 *
 
12412
 * If there is no youngest common ancestor, throw an error.
12351
12413
 */
12352
12414
static svn_error_t *
12353
12415
find_automatic_merge(svn_client__pathrev_t **base_p,
12417
12479
 * Like find_automatic_merge() except that the target is
12418
12480
 * specified by @a target_path_or_url at @a target_revision, which must
12419
12481
 * refer to a repository location, instead of by a WC path argument.
 
12482
 *
 
12483
 * Set *MERGE_P to a new structure with all fields filled in except the
 
12484
 * 'allow_*' flags.
12420
12485
 */
12421
12486
static svn_error_t *
12422
12487
find_automatic_merge_no_wc(automatic_merge_t **merge_p,
12492
12557
  source_and_target_t *s_t = apr_palloc(result_pool, sizeof(*s_t));
12493
12558
  automatic_merge_t *merge = apr_palloc(result_pool, sizeof(*merge));
12494
12559
 
 
12560
  SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
 
12561
 
12495
12562
  /* "Open" the target WC.  Check the target WC for mixed-rev, local mods and
12496
12563
   * switched subtrees yet to faster exit and notify user before contacting
12497
12564
   * with server.  After we find out what kind of merge is required, then if a
12523
12590
                               ctx, result_pool, scratch_pool));
12524
12591
  merge->yca = s_t->yca;
12525
12592
  merge->right = s_t->source;
 
12593
  merge->target = &s_t->target->loc;
12526
12594
  merge->allow_mixed_rev = allow_mixed_rev;
12527
12595
  merge->allow_local_mods = allow_local_mods;
12528
12596
  merge->allow_switched_subtrees = allow_switched_subtrees;
12711
12779
 
12712
12780
  target_is_wc = (! svn_path_is_url(target_path_or_url))
12713
12781
                 && (target_revision->kind == svn_opt_revision_unspecified
12714
 
                     || target_revision->kind == svn_opt_revision_working);
 
12782
                     || target_revision->kind == svn_opt_revision_working
 
12783
                     || target_revision->kind == svn_opt_revision_base);
12715
12784
  if (target_is_wc)
12716
 
    SVN_ERR(client_find_automatic_merge(
12717
 
              &merge,
12718
 
              source_path_or_url, source_revision,
12719
 
              target_path_or_url,
12720
 
              TRUE, TRUE, TRUE,  /* allow_* */
12721
 
              ctx, scratch_pool, scratch_pool));
 
12785
    {
 
12786
      const char *target_abspath;
 
12787
 
 
12788
      SVN_ERR(svn_dirent_get_absolute(&target_abspath, target_path_or_url,
 
12789
                                      scratch_pool));
 
12790
      SVN_ERR(client_find_automatic_merge(
 
12791
                &merge,
 
12792
                source_path_or_url, source_revision,
 
12793
                target_abspath,
 
12794
                TRUE, TRUE, TRUE,  /* allow_* */
 
12795
                ctx, scratch_pool, scratch_pool));
 
12796
    }
12722
12797
  else
12723
12798
    SVN_ERR(find_automatic_merge_no_wc(
12724
12799
              &merge,