Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 228653
Collapse All | Expand All

(-)file_not_specified_in_diff (-253 / +552 lines)
Line  Link Here
0
-- subversion/libsvn_client/merge.c
0
++ subversion/libsvn_client/merge.c
Lines 1311-1322 Link Here
1311
} notification_receiver_baton_t;
1311
} notification_receiver_baton_t;
1312
1312
1313
1313
1314
/* Finds a nearest ancestor in CHILDREN_WITH_MERGEINFO for PATH.
1314
/* Finds a nearest ancestor in CHILDREN_WITH_MERGEINFO for PATH. If
1315
   PATH_IS_OWN_ANCESTOR is TRUE then a child in CHILDREN_WITH_MERGEINFO
1316
   where child->path == PATH is considered PATH's ancestor.  If FALSE,
1317
   then child->path must be a proper ancestor of PATH.
1318
1315
   CHILDREN_WITH_MERGEINFO is expected to be sorted in Depth first
1319
   CHILDREN_WITH_MERGEINFO is expected to be sorted in Depth first
1316
   order of path. Nearest ancestor's index from
1320
   order of path. Nearest ancestor's index from
1317
   CHILDREN_WITH_MERGEINFO is returned. */
1321
   CHILDREN_WITH_MERGEINFO is returned. */
1318
static int
1322
static int
1319
find_nearest_ancestor(apr_array_header_t *children_with_mergeinfo,
1323
find_nearest_ancestor(apr_array_header_t *children_with_mergeinfo,
1324
                      svn_boolean_t path_is_own_ancestor,
1320
                      const char *path)
1325
                      const char *path)
1321
{
1326
{
1322
  int i;
1327
  int i;
Lines 1332-1339 Link Here
1332
    {
1337
    {
1333
      svn_client__merge_path_t *child =
1338
      svn_client__merge_path_t *child =
1334
        APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
1339
        APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
1335
      if (svn_path_is_ancestor(child->path, path))
1340
      if (svn_path_is_ancestor(child->path, path)
1336
        ancestor_index = i;
1341
          && (svn_path_compare_paths(child->path, path) != 0
1342
              || path_is_own_ancestor))
1343
        ancestor_index = i;      
1337
    }
1344
    }
1338
  return ancestor_index;
1345
  return ancestor_index;
1339
}
1346
}
Lines 1371-1379 Link Here
1371
      /* See if this is an operative directory merge. */
1378
      /* See if this is an operative directory merge. */
1372
      if (!(notify_b->is_single_file_merge) && is_operative_notification)
1379
      if (!(notify_b->is_single_file_merge) && is_operative_notification)
1373
        {
1380
        {
1381
          /* Find NOTIFY->PATH's nearest ancestor in
1382
             NOTIFY->CHILDREN_WITH_MERGEINFO.  Normally we consider a child in
1383
             NOTIFY->CHILDREN_WITH_MERGEINFO representing PATH to be an
1384
             ancestor of PATH, but if this is a deletion of PATH then the
1385
             notification must be for a proper ancestor of PATH.  This ensures
1386
             we don't get notifications like:
1387
             
1388
               --- Merging rX into 'PARENT/CHILD'
1389
               D    PARENT/CHILD
1390
1391
             But rather:
1392
1393
               --- Merging rX into 'PARENT'
1394
               D    PARENT/CHILD
1395
          */
1374
          int new_nearest_ancestor_index =
1396
          int new_nearest_ancestor_index =
1375
            find_nearest_ancestor(notify_b->children_with_mergeinfo,
1397
            find_nearest_ancestor(
1376
                                  notify->path);
1398
              notify_b->children_with_mergeinfo,
1399
              notify->action == svn_wc_notify_update_delete ? FALSE : TRUE,
1400
              notify->path);
1401
1377
          if (new_nearest_ancestor_index != notify_b->cur_ancestor_index)
1402
          if (new_nearest_ancestor_index != notify_b->cur_ancestor_index)
1378
            {
1403
            {
1379
              svn_client__merge_path_t *child =
1404
              svn_client__merge_path_t *child =
Lines 1853-1859 Link Here
1853
      const char *child_repos_path;
1878
      const char *child_repos_path;
1854
      const svn_wc_entry_t *child_entry;
1879
      const svn_wc_entry_t *child_entry;
1855
      const char *child_url1, *child_url2;
1880
      const char *child_url1, *child_url2;
1856
      svn_mergeinfo_t implicit_mergeinfo;
1857
      svn_client__merge_path_t *child =
1881
      svn_client__merge_path_t *child =
1858
        APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
1882
        APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
1859
1883
Lines 1875-1881 Link Here
1875
                                      FALSE, iterpool));
1899
                                      FALSE, iterpool));
1876
1900
1877
      SVN_ERR(get_full_mergeinfo(&(child->pre_merge_mergeinfo), 
1901
      SVN_ERR(get_full_mergeinfo(&(child->pre_merge_mergeinfo), 
1878
                                 &implicit_mergeinfo, child_entry,
1902
                                 &(child->implicit_mergeinfo), child_entry,
1879
                                 &(child->indirect_mergeinfo),
1903
                                 &(child->indirect_mergeinfo),
1880
                                 svn_mergeinfo_inherited, NULL, child->path,
1904
                                 svn_mergeinfo_inherited, NULL, child->path,
1881
                                 MAX(revision1, revision2),
1905
                                 MAX(revision1, revision2),
Lines 1888-1894 Link Here
1888
                                         child_url2, revision2,
1912
                                         child_url2, revision2,
1889
                                         inheritable, 
1913
                                         inheritable, 
1890
                                         child->pre_merge_mergeinfo,
1914
                                         child->pre_merge_mergeinfo,
1891
                                         implicit_mergeinfo,
1915
                                         child->implicit_mergeinfo,
1892
                                         ra_session, child_entry, merge_b->ctx,
1916
                                         ra_session, child_entry, merge_b->ctx,
1893
                                         pool));
1917
                                         pool));
1894
    }
1918
    }
Lines 1925-1932 Link Here
1925
/*** Other Helper Functions ***/
1949
/*** Other Helper Functions ***/
1926
1950
1927
1951
1928
/* Create mergeinfo describing the merge of RANGE into our target, accounting
1952
/* Create mergeinfo describing the merge of RANGELIST into TARGET_WCPATH,
1929
   for paths unaffected by the merge due to skips or conflicts from
1953
   accounting for paths unaffected by the merge due to skips or conflicts from
1930
   NOTIFY_B. For 'immediates' merge it sets an inheritable mergeinfo
1954
   NOTIFY_B. For 'immediates' merge it sets an inheritable mergeinfo
1931
   corresponding to current merge on merge target. For 'files' merge it sets
1955
   corresponding to current merge on merge target. For 'files' merge it sets
1932
   an inheritable mergeinfo corrsponding to current merge on merged files.
1956
   an inheritable mergeinfo corrsponding to current merge on merged files.
Lines 1934-1952 Link Here
1934
   TARGET_MISSING_CHILD should be true, otherwise it is false.*/
1958
   TARGET_MISSING_CHILD should be true, otherwise it is false.*/
1935
static svn_error_t *
1959
static svn_error_t *
1936
determine_merges_performed(apr_hash_t **merges, const char *target_wcpath,
1960
determine_merges_performed(apr_hash_t **merges, const char *target_wcpath,
1937
                           svn_merge_range_t *range,
1961
                           apr_array_header_t *rangelist,
1938
                           svn_depth_t depth,
1962
                           svn_depth_t depth,
1939
                           svn_wc_adm_access_t *adm_access,
1963
                           svn_wc_adm_access_t *adm_access,
1940
                           notification_receiver_baton_t *notify_b,
1964
                           notification_receiver_baton_t *notify_b,
1941
                           merge_cmd_baton_t *merge_b,
1965
                           merge_cmd_baton_t *merge_b,
1942
                           apr_pool_t *pool)
1966
                           apr_pool_t *pool)
1943
{
1967
{
1944
  apr_array_header_t *rangelist = apr_array_make(pool, 1, sizeof(range));
1945
  apr_size_t nbr_skips = (notify_b->skipped_paths != NULL ?
1968
  apr_size_t nbr_skips = (notify_b->skipped_paths != NULL ?
1946
                          apr_hash_count(notify_b->skipped_paths) : 0);
1969
                          apr_hash_count(notify_b->skipped_paths) : 0);
1947
  
1970
  
1948
  *merges = apr_hash_make(pool);
1971
  *merges = apr_hash_make(pool);
1949
  APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = range;
1950
  apr_hash_set(*merges, target_wcpath, APR_HASH_KEY_STRING, rangelist);
1972
  apr_hash_set(*merges, target_wcpath, APR_HASH_KEY_STRING, rangelist);
1951
  if (nbr_skips > 0)
1973
  if (nbr_skips > 0)
1952
    {
1974
    {
Lines 1978-1984 Link Here
1978
             ### see issue #2915. */
2000
             ### see issue #2915. */
1979
          apr_hash_set(*merges, (const char *) skipped_path,
2001
          apr_hash_set(*merges, (const char *) skipped_path,
1980
                       APR_HASH_KEY_STRING,
2002
                       APR_HASH_KEY_STRING,
1981
                       apr_array_make(pool, 0, sizeof(range)));
2003
                       apr_array_make(pool, 0, sizeof(svn_merge_range_t)));
1982
2004
1983
          if (nbr_skips < notify_b->nbr_notifications)
2005
          if (nbr_skips < notify_b->nbr_notifications)
1984
            /* ### Use RANGELIST as the mergeinfo for all children of
2006
            /* ### Use RANGELIST as the mergeinfo for all children of
Lines 1996-2005 Link Here
1996
           hi = apr_hash_next(hi))
2018
           hi = apr_hash_next(hi))
1997
        {
2019
        {
1998
          const svn_wc_entry_t *child_entry;
2020
          const svn_wc_entry_t *child_entry;
1999
          svn_merge_range_t *child_merge_range;
2000
          apr_array_header_t *rangelist_of_child = NULL;
2021
          apr_array_header_t *rangelist_of_child = NULL;
2001
          apr_hash_this(hi, &merged_path, NULL, NULL);
2022
          apr_hash_this(hi, &merged_path, NULL, NULL);
2002
          child_merge_range = svn_merge_range_dup(range, pool);
2003
          SVN_ERR(svn_wc__entry_versioned(&child_entry,
2023
          SVN_ERR(svn_wc__entry_versioned(&child_entry,
2004
                                          merged_path,
2024
                                          merged_path,
2005
                                          adm_access, FALSE,
2025
                                          adm_access, FALSE,
Lines 2014-2027 Link Here
2014
                 1. Merge target directory if depth is immediates.
2034
                 1. Merge target directory if depth is immediates.
2015
                 2. If merge is on a file and requested depth is 'files'.
2035
                 2. If merge is on a file and requested depth is 'files'.
2016
               */
2036
               */
2017
              child_merge_range->inheritable = TRUE;
2037
              int i;
2018
              rangelist_of_child = apr_array_make(pool, 1, sizeof(range));
2038
              rangelist_of_child = svn_rangelist_dup(rangelist, pool);
2039
              for (i = 0; i < rangelist_of_child->nelts; i++)
2040
                {
2041
                  svn_merge_range_t *rng =
2042
                    APR_ARRAY_IDX(rangelist_of_child, i, svn_merge_range_t *);
2043
                  rng->inheritable = TRUE;
2044
                }
2019
            }
2045
            }
2020
          if (rangelist_of_child)
2046
          if (rangelist_of_child)
2021
            {
2047
            {
2022
              APR_ARRAY_PUSH(rangelist_of_child, svn_merge_range_t *) =
2023
                child_merge_range;
2024
2025
              apr_hash_set(*merges, (const char *)merged_path,
2048
              apr_hash_set(*merges, (const char *)merged_path,
2026
                           APR_HASH_KEY_STRING, rangelist_of_child);
2049
                           APR_HASH_KEY_STRING, rangelist_of_child);
2027
            }
2050
            }
Lines 2510-2525 Link Here
2510
    }
2533
    }
2511
}
2534
}
2512
2535
2513
/* For each child of CHILDREN_WITH_MERGEINFO create a new remaining_ranges
2536
/* Helper for do_directory_merge().
2514
   by removing the first item from the original range list and overwrite the
2537
2515
   original remaining_ranges with this new list.
2538
   Remove the first remaining revision range for each child in
2516
   All the allocations are persistent from a POOL.
2539
   CHILDREN_WITH_MERGEINFO *iff* that child was already merged.  END_REV is the
2517
   TODO, we should have remaining_ranges in reverse order to avoid recreating
2540
   ending revision of the most recently merged range, i.e. the same end_rev
2518
   the remaining_ranges every time instead of one 'pop' operation.  */
2541
   passed to drive_merge_report_editor() by do_directory_merge().  If a
2542
   range is removed from a child's remaining_ranges array, allocate the new
2543
   remaining_ranges array in POOL.
2544
2545
   ### TODO: We should have remaining_ranges in reverse order to avoid
2546
   ### recreating and reallocationg the remaining_ranges every time we want
2547
   ### to remove the first range.  If the ranges were reversed we could simply
2548
   ### pop the last element in the array. */
2519
static void
2549
static void
2520
remove_first_range_from_remaining_ranges(
2550
remove_first_range_from_remaining_ranges(svn_revnum_t end_rev,
2521
                                apr_array_header_t *children_with_mergeinfo,
2551
                                         apr_array_header_t
2522
                                apr_pool_t *pool)
2552
                                           *children_with_mergeinfo,
2553
                                         apr_pool_t *pool)
2523
{
2554
{
2524
  int i, j;
2555
  int i, j;
2525
  for (i = 0; i < children_with_mergeinfo->nelts; i++)
2556
  for (i = 0; i < children_with_mergeinfo->nelts; i++)
Lines 2531-2547 Link Here
2531
        continue;
2562
        continue;
2532
      if (child->remaining_ranges->nelts > 0)
2563
      if (child->remaining_ranges->nelts > 0)
2533
        {
2564
        {
2534
          apr_array_header_t *orig_remaining_ranges = child->remaining_ranges;
2565
          svn_merge_range_t *first_range =
2535
          child->remaining_ranges =
2566
            APR_ARRAY_IDX(child->remaining_ranges, 0, svn_merge_range_t *);
2536
            apr_array_make(pool, (child->remaining_ranges->nelts - 1),
2567
          if (first_range->end == end_rev)
2537
                           sizeof(svn_merge_range_t *));
2538
          for (j = 1; j < orig_remaining_ranges->nelts; j++)
2539
            {
2568
            {
2540
              svn_merge_range_t *range = APR_ARRAY_IDX(orig_remaining_ranges,
2569
              apr_array_header_t *orig_remaining_ranges =
2541
                                                       j,
2570
                child->remaining_ranges;
2542
                                                       svn_merge_range_t *);
2571
              child->remaining_ranges =
2543
              APR_ARRAY_PUSH(child->remaining_ranges, svn_merge_range_t *)
2572
                apr_array_make(pool, (child->remaining_ranges->nelts - 1),
2544
                                                                  = range;
2573
                               sizeof(svn_merge_range_t *));
2574
              for (j = 1; j < orig_remaining_ranges->nelts; j++)
2575
                {
2576
                  svn_merge_range_t *range =
2577
                    APR_ARRAY_IDX(orig_remaining_ranges,
2578
                                  j,
2579
                                  svn_merge_range_t *);
2580
                  APR_ARRAY_PUSH(child->remaining_ranges,
2581
                                 svn_merge_range_t *) = range;
2582
                }          
2545
            }
2583
            }
2546
        }
2584
        }
2547
    }
2585
    }
Lines 3455-3460 Link Here
3455
}
3493
}
3456
3494
3457
3495
3496
/* Implements the svn_log_entry_receiver_t interface. */
3497
static svn_error_t *
3498
log_changed_revs(void *baton,
3499
                  svn_log_entry_t *log_entry,
3500
                  apr_pool_t *pool)
3501
{
3502
  apr_array_header_t *revs = baton;
3503
  svn_revnum_t *revision = apr_palloc(revs->pool, sizeof(*revision));
3504
  *revision = log_entry->revision;
3505
  APR_ARRAY_PUSH(revs, svn_revnum_t *) = revision;
3506
  return SVN_NO_ERROR;
3507
}
3508
3509
3510
/* Set *OPERATIVE_RANGES_P to an array of svn_merge_range_t * merge
3511
   range objects copied wholesale from RANGES which have the property
3512
   that in some revision within that range the object identified by
3513
   RA_SESSION was modified (if by "modified" we mean "'svn log' would
3514
   return that revision).  *OPERATIVE_RANGES_P is allocated from the
3515
   same pool as RANGES, and the ranges within it are shared with
3516
   RANGES, too.  Use POOL for temporary allocations.  */
3517
static svn_error_t *
3518
remove_noop_merge_ranges(apr_array_header_t **operative_ranges_p,
3519
                         svn_ra_session_t *ra_session,
3520
                         apr_array_header_t *ranges,
3521
                         apr_pool_t *pool)
3522
{
3523
  int i;
3524
  svn_revnum_t oldest_rev = SVN_INVALID_REVNUM;
3525
  svn_revnum_t youngest_rev = SVN_INVALID_REVNUM;
3526
  apr_array_header_t *changed_revs =
3527
    apr_array_make(pool, ranges->nelts, sizeof(svn_revnum_t *));
3528
  apr_array_header_t *operative_ranges =
3529
    apr_array_make(ranges->pool, ranges->nelts, ranges->elt_size);
3530
  apr_array_header_t *log_targets = 
3531
    apr_array_make(pool, 1, sizeof(const char *));
3532
  APR_ARRAY_PUSH(log_targets, const char *) = "";
3533
3534
  /* Find the revision extremes of the RANGES we have. */
3535
  for (i = 0; i < ranges->nelts; i++)
3536
    {
3537
      svn_merge_range_t *r = APR_ARRAY_IDX(ranges, i, svn_merge_range_t *);
3538
      svn_revnum_t max_rev = MAX(r->start, r->end);
3539
      svn_revnum_t min_rev = MIN(r->start, r->end) + 1;
3540
3541
      if ((! SVN_IS_VALID_REVNUM(youngest_rev)) || (max_rev > youngest_rev))
3542
        youngest_rev = max_rev;
3543
      if ((! SVN_IS_VALID_REVNUM(oldest_rev)) || (min_rev < oldest_rev))
3544
        oldest_rev = min_rev;
3545
    }
3546
3547
  /* Get logs across those ranges, recording which revisions hold
3548
     changes to our object's history. */
3549
  SVN_ERR(svn_ra_get_log2(ra_session, log_targets, youngest_rev, 
3550
                          oldest_rev, 0, FALSE, FALSE, FALSE, 
3551
                          apr_array_make(pool, 0, sizeof(const char *)),
3552
                          log_changed_revs, changed_revs, pool));
3553
3554
  /* Now, copy from RANGES to *OPERATIVE_RANGES, filtering out ranges
3555
     that aren't operative (by virtue of not having any revisions
3556
     represented in the CHANGED_REVS array). */
3557
  for (i = 0; i < ranges->nelts; i++)
3558
    {
3559
      svn_merge_range_t *range = APR_ARRAY_IDX(ranges, i, svn_merge_range_t *);
3560
      int j;
3561
3562
      for (j = 0; j < changed_revs->nelts; j++)
3563
        {
3564
          svn_revnum_t *changed_rev = 
3565
            APR_ARRAY_IDX(changed_revs, j, svn_revnum_t *);
3566
          if ((*changed_rev > MIN(range->start, range->end))
3567
              && (*changed_rev <= MAX(range->start, range->end)))
3568
            {
3569
              APR_ARRAY_PUSH(operative_ranges, svn_merge_range_t *) = range;
3570
              break;
3571
            }
3572
        }
3573
    }
3574
  *operative_ranges_p = operative_ranges;
3575
  return SVN_NO_ERROR;
3576
}
3577
  
3578
3458
/*-----------------------------------------------------------------------*/
3579
/*-----------------------------------------------------------------------*/
3459
3580
3460
/*** Merge Source Normalization ***/
3581
/*** Merge Source Normalization ***/
Lines 3859-3864 Link Here
3859
3980
3860
/*** Merge Workhorse Functions ***/
3981
/*** Merge Workhorse Functions ***/
3861
3982
3983
/* Helper for do_directory_merge() and do_file_merge() which filters out a
3984
   path's own natural history from the mergeinfo describing a merge.
3985
3986
   Given the natural history IMPLICIT_MERGEINFO of some wc merge target path,
3987
   the repository relative merge source path SOURCE_REL_PATH, and the
3988
   requested merge range REQUESTED_RANGE from SOURCE_REL_PATH, remove any
3989
   portion of REQUESTED_RANGE which is already described in
3990
   IMPLICIT_MERGEINFO.  Store the result in *FILTERED_RANGELIST.
3991
3992
   *FILTERED_RANGELIST is allocated in POOL. */
3993
static svn_error_t *
3994
filter_natural_history_from_mergeinfo(apr_array_header_t **filtered_rangelist,
3995
                                      const char *source_rel_path,
3996
                                      svn_mergeinfo_t implicit_mergeinfo,
3997
                                      svn_merge_range_t *requested_range,
3998
                                      apr_pool_t *pool)
3999
{
4000
  /* Make the REQUESTED_RANGE into a rangelist. */
4001
  apr_array_header_t *requested_rangelist =
4002
    apr_array_make(pool, 0, sizeof(svn_merge_range_t *));
4003
  APR_ARRAY_PUSH(requested_rangelist, svn_merge_range_t *) =
4004
    svn_merge_range_dup(requested_range, pool);
4005
4006
  *filtered_rangelist = NULL;
4007
4008
  /* If the IMPLICIT_MERGEINFO already describes ranges associated
4009
     with SOURCE_REL_PATH then filter those ranges out. */
4010
  if (implicit_mergeinfo)
4011
    {
4012
      apr_array_header_t *implied_rangelist =
4013
        apr_hash_get(implicit_mergeinfo, source_rel_path,
4014
                     APR_HASH_KEY_STRING);
4015
4016
      if (implied_rangelist)
4017
        SVN_ERR(svn_rangelist_remove(filtered_rangelist,
4018
                                     implied_rangelist,
4019
                                     requested_rangelist,
4020
                                     FALSE, pool));
4021
    }
4022
4023
  /* If no filtering was performed the filtered rangelist is
4024
     simply the requested rangelist.*/
4025
  if (! (*filtered_rangelist))
4026
    *filtered_rangelist = requested_rangelist;
4027
4028
  return SVN_NO_ERROR;
4029
}
4030
3862
/* The single-file, simplified version of do_directory_merge(), which see for
4031
/* The single-file, simplified version of do_directory_merge(), which see for
3863
   parameter descriptions. 
4032
   parameter descriptions. 
3864
4033
Lines 3868-3873 Link Here
3868
   merge source are historically related (ancestors, uncles, second
4037
   merge source are historically related (ancestors, uncles, second
3869
   cousins thrice removed, etc...).  (This is used to simulate the
4038
   cousins thrice removed, etc...).  (This is used to simulate the
3870
   history checks that the repository logic does in the directory case.)  
4039
   history checks that the repository logic does in the directory case.)  
4040
4041
   Note: MERGE_B->RA_SESSION1 must be associated with URL1 and
4042
   MERGE_B->RA_SESSION2 with URL2.
3871
*/
4043
*/
3872
static svn_error_t *
4044
static svn_error_t *
3873
do_file_merge(const char *url1,
4045
do_file_merge(const char *url1,
Lines 3900-3905 Link Here
3900
  svn_boolean_t is_rollback = (revision1 > revision2);
4072
  svn_boolean_t is_rollback = (revision1 > revision2);
3901
  const char *primary_url = is_rollback ? url1 : url2;
4073
  const char *primary_url = is_rollback ? url1 : url2;
3902
  svn_boolean_t honor_mergeinfo, record_mergeinfo;
4074
  svn_boolean_t honor_mergeinfo, record_mergeinfo;
4075
  svn_mergeinfo_t implicit_mergeinfo;
3903
4076
3904
  mergeinfo_behavior(&honor_mergeinfo, &record_mergeinfo, merge_b);
4077
  mergeinfo_behavior(&honor_mergeinfo, &record_mergeinfo, merge_b);
3905
4078
Lines 3922-3953 Link Here
3922
  if (honor_mergeinfo)
4095
  if (honor_mergeinfo)
3923
    {
4096
    {
3924
      const char *source_root_url;
4097
      const char *source_root_url;
3925
      svn_mergeinfo_t implicit_mergeinfo;
4098
            
3926
3927
      
3928
      SVN_ERR(svn_ra_get_repos_root2(merge_b->ra_session1,
4099
      SVN_ERR(svn_ra_get_repos_root2(merge_b->ra_session1,
3929
                                     &source_root_url, pool));
4100
                                     &source_root_url, pool));
3930
      SVN_ERR(svn_client__path_relative_to_root(&mergeinfo_path, primary_url,
4101
      SVN_ERR(svn_client__path_relative_to_root(&mergeinfo_path, primary_url,
3931
                                                source_root_url, TRUE, NULL,
4102
                                                source_root_url, TRUE, NULL,
3932
                                                NULL, pool));
4103
                                                NULL, pool));
3933
4104
4105
      /* Fetch mergeinfo (temporarily reparenting ra_session1 to
4106
         working copy target URL). */
4107
      SVN_ERR(svn_ra_reparent(merge_b->ra_session1, entry->url, pool));
4108
      SVN_ERR(get_full_mergeinfo(&target_mergeinfo, &implicit_mergeinfo, 
4109
                                 entry, &indirect, svn_mergeinfo_inherited,
4110
                                 merge_b->ra_session1, target_wcpath, 
4111
                                 MAX(revision1, revision2),
4112
                                 MIN(revision1, revision2),
4113
                                 adm_access, ctx, pool));
4114
4115
      SVN_ERR(svn_ra_reparent(merge_b->ra_session1, url1, pool));
4116
3934
      /* Calculate remaining merges unless this is a record only merge.
4117
      /* Calculate remaining merges unless this is a record only merge.
3935
         In that case the remaining range is the whole range described
4118
         In that case the remaining range is the whole range described
3936
         by REVISION1:REVISION2. */
4119
         by REVISION1:REVISION2. */
3937
      if (!merge_b->record_only)
4120
      if (!merge_b->record_only)
3938
        {
4121
        {
3939
          /* Fetch mergeinfo (temporarily reparenting ra_session1 to
3940
             working copy target URL). */
3941
          SVN_ERR(svn_ra_reparent(merge_b->ra_session1, entry->url, pool));
3942
          SVN_ERR(get_full_mergeinfo(&target_mergeinfo, &implicit_mergeinfo, 
3943
                                     entry, &indirect, svn_mergeinfo_inherited,
3944
                                     merge_b->ra_session1, target_wcpath, 
3945
                                     MAX(revision1, revision2),
3946
                                     MIN(revision1, revision2),
3947
                                     adm_access, ctx, pool));
3948
3949
          SVN_ERR(svn_ra_reparent(merge_b->ra_session1, url1, pool));
3950
3951
          SVN_ERR(calculate_remaining_ranges(&remaining_ranges,
4122
          SVN_ERR(calculate_remaining_ranges(&remaining_ranges,
3952
                                             source_root_url,
4123
                                             source_root_url,
3953
                                             url1, revision1, url2, revision2,
4124
                                             url1, revision1, url2, revision2,
Lines 3969-3984 Link Here
3969
4140
3970
  if (!merge_b->record_only)
4141
  if (!merge_b->record_only)
3971
    {
4142
    {
3972
      for (i = 0; i < remaining_ranges->nelts; i++)
4143
      apr_array_header_t *ranges_to_merge = remaining_ranges;
4144
      
4145
      /* If we have ancestrally related sources and more than one
4146
         range to merge, eliminate no-op ranges before going through
4147
         the effort of downloading the many copies of the file
4148
         required to do these merges (two copies per range). */
4149
      if (merge_b->sources_ancestral && (remaining_ranges->nelts > 1))
3973
        {
4150
        {
4151
          const char *old_sess_url = NULL;
4152
          SVN_ERR(svn_client__ensure_ra_session_url(&old_sess_url, 
4153
                                                    merge_b->ra_session1,
4154
                                                    primary_url, subpool));
4155
          SVN_ERR(remove_noop_merge_ranges(&ranges_to_merge, 
4156
                                           merge_b->ra_session1, 
4157
                                           remaining_ranges, subpool));
4158
          if (old_sess_url)
4159
            SVN_ERR(svn_ra_reparent(merge_b->ra_session1, old_sess_url, 
4160
                                    subpool));
4161
          svn_pool_clear(subpool);
4162
        }
4163
4164
      for (i = 0; i < ranges_to_merge->nelts; i++)
4165
        {
3974
          svn_wc_notify_t *n;
4166
          svn_wc_notify_t *n;
3975
          svn_boolean_t header_sent = FALSE;
4167
          svn_boolean_t header_sent = FALSE;
3976
          svn_error_t *err = SVN_NO_ERROR;
4168
          svn_error_t *err = SVN_NO_ERROR;
4169
          svn_ra_session_t *ra_session1, *ra_session2;
3977
4170
3978
          /* When using this merge range, account for the exclusivity of
4171
          /* When using this merge range, account for the exclusivity of
3979
             its low value (which is indicated by this operation being a
4172
             its low value (which is indicated by this operation being a
3980
             merge vs. revert). */
4173
             merge vs. revert). */
3981
          svn_merge_range_t *r = APR_ARRAY_IDX(remaining_ranges, i,
4174
          svn_merge_range_t *r = APR_ARRAY_IDX(ranges_to_merge, i,
3982
                                               svn_merge_range_t *);
4175
                                               svn_merge_range_t *);
3983
4176
3984
          svn_pool_clear(subpool);
4177
          svn_pool_clear(subpool);
Lines 3991-4002 Link Here
3991
          if (merge_b->sources_ancestral)
4184
          if (merge_b->sources_ancestral)
3992
            n->merge_range = r;
4185
            n->merge_range = r;
3993
4186
4187
          /* Issue #3174: If we are honoring mergeinfo, then URL1, URL2,
4188
             REVISION1, and REVISION2 meet the conditions described in
4189
             'MERGEINFO MERGE SOURCE NORMALIZATION'.  This means that
4190
             URL1@REVISION1 may be the copy source of URL2@REVISION2.
4191
             If this is the case, then URL1 != URL2.  Since
4192
             MERGE_B->RA_SESSION1 is always opened with URL1, the only time
4193
             we can safely call single_file_merge_get_file() with that RA
4194
             session is for REVISION1 (or REVISION2 if this is a reverse
4195
             merge). */
4196
          ra_session1 = merge_b->ra_session1;
4197
          ra_session2 = merge_b->ra_session2;
4198
          if (honor_mergeinfo && strcmp(url1, url2) != 0)
4199
            {
4200
              if (!is_rollback && r->start != revision1)
4201
                ra_session1 = ra_session2; /* Use URL2's RA session. */
4202
              else if (is_rollback && r->end != revision2)
4203
                ra_session2 = ra_session1; /* Use URL1's RA session. */
4204
            }
4205
 
3994
          /* While we currently don't allow it, in theory we could be
4206
          /* While we currently don't allow it, in theory we could be
3995
             fetching two fulltexts from two different repositories here. */
4207
             fetching two fulltexts from two different repositories here. */
3996
          SVN_ERR(single_file_merge_get_file(&tmpfile1, merge_b->ra_session1,
4208
          SVN_ERR(single_file_merge_get_file(&tmpfile1, ra_session1,
3997
                                             &props1, r->start, target_wcpath,
4209
                                             &props1, r->start, target_wcpath,
3998
                                             subpool));
4210
                                             subpool));
3999
          SVN_ERR(single_file_merge_get_file(&tmpfile2, merge_b->ra_session2,
4211
          SVN_ERR(single_file_merge_get_file(&tmpfile2, ra_session2,
4000
                                             &props2, r->end, target_wcpath,
4212
                                             &props2, r->end, target_wcpath,
4001
                                             subpool));
4213
                                             subpool));
4002
4214
Lines 4078-4084 Link Here
4078
            return err;
4290
            return err;
4079
          svn_error_clear(err);
4291
          svn_error_clear(err);
4080
4292
4081
          if ((i < (remaining_ranges->nelts - 1))
4293
          if ((i < (ranges_to_merge->nelts - 1))
4082
              && is_path_conflicted_by_merge(merge_b))
4294
              && is_path_conflicted_by_merge(merge_b))
4083
            {
4295
            {
4084
              conflicted_range = r;
4296
              conflicted_range = r;
Lines 4088-4111 Link Here
4088
    } /* !merge_b->record_only */
4300
    } /* !merge_b->record_only */
4089
4301
4090
  /* Record updated WC mergeinfo to account for our new merges, minus
4302
  /* Record updated WC mergeinfo to account for our new merges, minus
4091
     any unresolved conflicts and skips. */
4303
     any unresolved conflicts and skips.  We use the original
4304
     REMAINING_RANGES here instead of the possibly-pared-down
4305
     RANGES_TO_MERGE because we want to record all the requested
4306
     merge ranges, include the noop ones.  */
4092
  if (record_mergeinfo && remaining_ranges->nelts)
4307
  if (record_mergeinfo && remaining_ranges->nelts)
4093
    {
4308
    {
4094
      apr_hash_t *merges;
4309
      apr_hash_t *merges;
4095
      SVN_ERR(determine_merges_performed(&merges, target_wcpath,
4310
      apr_array_header_t *filtered_rangelist;
4096
                                         &range, svn_depth_infinity,
4311
4097
                                         adm_access, notify_b, merge_b,
4312
      /* Filter any ranges from TARGET_WCPATH's own history, there is no
4098
                                         subpool));
4313
         need to record this explicitly in mergeinfo, it is already part
4099
      /* If merge target has indirect mergeinfo set it before
4314
         of TARGET_WCPATH's natural history (implicit mergeinfo). */
4100
         recording the first merge range. */
4315
      SVN_ERR(filter_natural_history_from_mergeinfo(&filtered_rangelist,
4101
      if (indirect)
4316
                                                    mergeinfo_path,
4102
        SVN_ERR(svn_client__record_wc_mergeinfo(target_wcpath,
4317
                                                    implicit_mergeinfo,
4103
                                                target_mergeinfo,
4318
                                                    &range, subpool));
4104
                                                adm_access, subpool));
4319
4320
      if (filtered_rangelist->nelts)
4321
        {
4322
          SVN_ERR(determine_merges_performed(&merges, target_wcpath,
4323
                                             filtered_rangelist,
4324
                                             svn_depth_infinity,
4325
                                             adm_access, notify_b,
4326
                                             merge_b, subpool));
4327
          /* If merge target has indirect mergeinfo set it before
4328
             recording the first merge range. */
4329
          if (indirect)
4330
            SVN_ERR(svn_client__record_wc_mergeinfo(target_wcpath,
4331
                                                    target_mergeinfo,
4332
                                                    adm_access, subpool));
4105
          
4333
          
4106
      SVN_ERR(update_wc_mergeinfo(target_wcpath, entry, mergeinfo_path,
4334
          SVN_ERR(update_wc_mergeinfo(target_wcpath, entry, mergeinfo_path,
4107
                                  merges, is_rollback, adm_access,
4335
                                      merges, is_rollback, adm_access,
4108
                                  ctx, subpool));
4336
                                      ctx, subpool));
4337
        }
4109
    }
4338
    }
4110
4339
4111
  svn_pool_destroy(subpool);
4340
  svn_pool_destroy(subpool);
Lines 4258-4263 Link Here
4258
                                    ra_session, mergeinfo_path,
4487
                                    ra_session, mergeinfo_path,
4259
                                    adm_access, merge_b));
4488
                                    adm_access, merge_b));
4260
4489
4490
  /* Always start with a range which describes our most inclusive merge. */
4491
  range.start = revision1;
4492
  range.end = revision2;
4493
  range.inheritable = inheritable;
4494
4261
  if (honor_mergeinfo && !merge_b->record_only)
4495
  if (honor_mergeinfo && !merge_b->record_only)
4262
    {
4496
    {
4263
      svn_revnum_t start_rev, end_rev;
4497
      svn_revnum_t start_rev, end_rev;
Lines 4267-4385 Link Here
4267
         end revisions. */
4501
         end revisions. */
4268
      start_rev = get_most_inclusive_start_rev(children_with_mergeinfo,
4502
      start_rev = get_most_inclusive_start_rev(children_with_mergeinfo,
4269
                                               is_rollback);
4503
                                               is_rollback);
4270
      if (start_rev == SVN_INVALID_REVNUM)
4504
    
4271
        start_rev = revision1;
4505
      /* Is there anything to merge? */
4506
      if (SVN_IS_VALID_REVNUM(start_rev))
4507
        {
4508
          range.start = start_rev;
4509
          end_rev = get_youngest_end_rev(children_with_mergeinfo, is_rollback);
4272
4510
4273
      end_rev = get_youngest_end_rev(children_with_mergeinfo, is_rollback);
4511
          /* Build a range which describes our most inclusive merge. */
4512
          range.start = start_rev;
4274
4513
4275
      /* Build a range which describes our most inclusive merge. */
4514
          /* While END_REV is valid, do the following:
4276
      range.start = start_rev;
4277
      range.end = revision2;
4278
      range.inheritable = inheritable;
4279
4515
4280
      /* While END_REV is valid, do the following:
4516
             1. slice each remaining ranges around this 'end_rev'.
4517
             2. starting with START_REV, call
4518
                drive_merge_report_editor() on MERGE_B->target for 
4519
                start_rev:end_rev.
4520
             3. remove the first item from each remaining range.
4521
             4. set START_REV=END_REV and pick the next END_REV.
4522
             5. lather, rinse, repeat.
4523
          */
4524
          iterpool = svn_pool_create(pool);
4525
          while (end_rev != SVN_INVALID_REVNUM)
4526
            {
4527
              svn_revnum_t next_end_rev;
4528
              const char *real_url1 = url1, *real_url2 = url2;
4529
              const char *old_sess1_url = NULL, *old_sess2_url = NULL;
4281
4530
4282
         1. slice each remaining ranges around this 'end_rev'.
4531
              svn_pool_clear(iterpool);
4283
         2. starting with START_REV, call
4284
            drive_merge_report_editor() on MERGE_B->target for 
4285
            start_rev:end_rev.
4286
         3. remove the first item from each remaining range.
4287
         4. set START_REV=END_REV and pick the next END_REV.
4288
         5. lather, rinse, repeat.
4289
      */
4290
      iterpool = svn_pool_create(pool);
4291
      while (end_rev != SVN_INVALID_REVNUM)
4292
        {
4293
          svn_revnum_t next_end_rev;
4294
          const char *real_url1 = url1, *real_url2 = url2;
4295
          const char *old_sess1_url = NULL, *old_sess2_url = NULL;
4296
4532
4297
          svn_pool_clear(iterpool);
4533
              /* Use persistent pool while playing with remaining_ranges. */
4534
              slice_remaining_ranges(children_with_mergeinfo, is_rollback,
4535
                                     end_rev, pool);
4536
              notify_b->cur_ancestor_index = -1;
4298
4537
4299
          /* Use persistent pool while playing with remaining_ranges. */
4538
              /* URL1@REVISION1 is a real location; URL2@REVISION2 is a
4300
          slice_remaining_ranges(children_with_mergeinfo, is_rollback,
4539
                 real location -- that much we know (thanks to the merge
4301
                                 end_rev, pool);
4540
                 source normalization code).  But for revisions between
4302
          notify_b->cur_ancestor_index = -1;
4541
                 them, the URLs might differ.  Here are the rules:
4303
4542
4304
          /* URL1@REVISION1 is a real location; URL2@REVISION2 is a
4543
                   * If URL1 == URL2, then all URLs between REVISION1 and
4305
             real location -- that much we know (thanks to the merge
4544
                     REVISION2 also match URL1/URL2.
4306
             source normalization code).  But for revisions between
4307
             them, the URLs might differ.  Here are the rules:
4308
4545
4309
               * If URL1 == URL2, then all URLs between REVISION1 and
4546
                   * If URL1 != URL2, then:
4310
                 REVISION2 also match URL1/URL2.
4311
4547
4312
               * If URL1 != URL2, then:
4548
                       * If REVISION1 < REVISION2, only REVISION1 maps to
4549
                         URL1.  The revisions between REVISION1+1 and
4550
                         REVISION2 (inclusive) map to URL2.
4313
4551
4314
                   * If REVISION1 < REVISION2, only REVISION1 maps to
4552
                       * If REVISION1 > REVISION2, Only REVISION2 maps to
4315
                     URL1.  The revisions between REVISION1+1 and
4553
                         URL2.  The revisions between REVISION1 and
4316
                     REVISION2 (inclusive) map to URL2.
4554
                         REVISION2+1 (inclusive) map to URL1.
4317
4555
                   
4318
                   * If REVISION1 > REVISION2, Only REVISION2 maps to
4556
                 We need to adjust our URLs accordingly, here.
4319
                     URL2.  The revisions between REVISION1 and
4557
              */
4320
                     REVISION2+1 (inclusive) map to URL1.
4558
              if (! same_urls)
4321
               
4322
             We need to adjust our URLs accordingly, here.
4323
          */
4324
          if (! same_urls)
4325
            {
4326
              if (is_rollback && (end_rev != revision2))
4327
                {
4559
                {
4328
                  real_url2 = url1;
4560
                  if (is_rollback && (end_rev != revision2))
4329
                  SVN_ERR(svn_client__ensure_ra_session_url
4561
                    {
4330
                          (&old_sess2_url, merge_b->ra_session2,
4562
                      real_url2 = url1;
4331
                           real_url2, iterpool));
4563
                      SVN_ERR(svn_client__ensure_ra_session_url
4564
                              (&old_sess2_url, merge_b->ra_session2,
4565
                               real_url2, iterpool));
4566
                    }
4567
                  if ((! is_rollback) && (start_rev != revision1))
4568
                    {
4569
                      real_url1 = url2;
4570
                      SVN_ERR(svn_client__ensure_ra_session_url
4571
                              (&old_sess1_url, merge_b->ra_session1,
4572
                               real_url1, iterpool));
4573
                    }
4332
                }
4574
                }
4333
              if ((! is_rollback) && (start_rev != revision1))
4575
              SVN_ERR(drive_merge_report_editor(merge_b->target,
4576
                                                real_url1, start_rev,
4577
                                                real_url2, end_rev,
4578
                                                children_with_mergeinfo,
4579
                                                is_rollback,
4580
                                                depth, notify_b, adm_access,
4581
                                                &merge_callbacks, merge_b,
4582
                                                iterpool));
4583
              if (old_sess1_url)
4584
                SVN_ERR(svn_ra_reparent(merge_b->ra_session1, 
4585
                                        old_sess1_url, iterpool));
4586
              if (old_sess2_url)
4587
                SVN_ERR(svn_ra_reparent(merge_b->ra_session2, 
4588
                                        old_sess2_url, iterpool));
4589
4590
              /* Prepare for the next iteration (if any). */
4591
              remove_first_range_from_remaining_ranges(
4592
                end_rev, children_with_mergeinfo, pool);
4593
              next_end_rev = get_youngest_end_rev(children_with_mergeinfo,
4594
                                                  is_rollback);
4595
              if ((next_end_rev != SVN_INVALID_REVNUM)
4596
                  && is_path_conflicted_by_merge(merge_b))
4334
                {
4597
                {
4335
                  real_url1 = url2;
4598
                  svn_merge_range_t conflicted_range;
4336
                  SVN_ERR(svn_client__ensure_ra_session_url
4599
                  conflicted_range.start = start_rev;
4337
                          (&old_sess1_url, merge_b->ra_session1,
4600
                  conflicted_range.end = end_rev;
4338
                           real_url1, iterpool));
4601
                  err = make_merge_conflict_error(merge_b->target,
4602
                                                  &conflicted_range, pool);
4603
                  range.end = end_rev;
4604
                  break;
4339
                }
4605
                }
4606
              start_rev = end_rev;
4607
              end_rev = next_end_rev;
4340
            }
4608
            }
4341
          SVN_ERR(drive_merge_report_editor(merge_b->target,
4609
          svn_pool_destroy(iterpool);
4342
                                            real_url1, start_rev, real_url2, 
4343
                                            end_rev, children_with_mergeinfo,
4344
                                            is_rollback,
4345
                                            depth, notify_b, adm_access,
4346
                                            &merge_callbacks, merge_b,
4347
                                            iterpool));
4348
          if (old_sess1_url)
4349
            SVN_ERR(svn_ra_reparent(merge_b->ra_session1, 
4350
                                    old_sess1_url, iterpool));
4351
          if (old_sess2_url)
4352
            SVN_ERR(svn_ra_reparent(merge_b->ra_session2, 
4353
                                    old_sess2_url, iterpool));
4354
4355
          /* Prepare for the next iteration (if any). */
4356
          remove_first_range_from_remaining_ranges(children_with_mergeinfo, 
4357
                                                   pool);
4358
          next_end_rev = get_youngest_end_rev(children_with_mergeinfo, 
4359
                                              is_rollback);
4360
          if ((next_end_rev != SVN_INVALID_REVNUM)
4361
              && is_path_conflicted_by_merge(merge_b))
4362
            {
4363
              svn_merge_range_t conflicted_range;
4364
              conflicted_range.start = start_rev;
4365
              conflicted_range.end = end_rev;
4366
              err = make_merge_conflict_error(merge_b->target,
4367
                                              &conflicted_range, pool);
4368
              range.end = end_rev;
4369
              break;
4370
            }
4371
          start_rev = end_rev;
4372
          end_rev = next_end_rev;
4373
        }
4610
        }
4374
      svn_pool_destroy(iterpool);
4375
    }
4611
    }
4376
  else
4612
  else
4377
    {
4613
    {
4378
      /* Build a range which describes our most inclusive merge. */
4379
      range.start = revision1;
4380
      range.end = revision2;
4381
      range.inheritable = inheritable;
4382
4383
      if (!merge_b->record_only)
4614
      if (!merge_b->record_only)
4384
        {
4615
        {
4385
          /* Reset cur_ancestor_index to -1 so that subsequent cherry
4616
          /* Reset cur_ancestor_index to -1 so that subsequent cherry
Lines 4405-4410 Link Here
4405
  iterpool = svn_pool_create(pool);
4636
  iterpool = svn_pool_create(pool);
4406
  if (record_mergeinfo)
4637
  if (record_mergeinfo)
4407
    {
4638
    {
4639
      apr_array_header_t *filtered_rangelist;
4640
      svn_client__merge_path_t *merge_target =
4641
        APR_ARRAY_IDX(children_with_mergeinfo, 0, svn_client__merge_path_t *);
4642
4408
      /* Update the WC mergeinfo here to account for our new
4643
      /* Update the WC mergeinfo here to account for our new
4409
         merges, minus any unresolved conflicts and skips. */
4644
         merges, minus any unresolved conflicts and skips. */
4410
      apr_hash_t *merges;
4645
      apr_hash_t *merges;
Lines 4414-4428 Link Here
4414
         calculate the merges performed. */
4649
         calculate the merges performed. */
4415
      remove_absent_children(merge_b->target,
4650
      remove_absent_children(merge_b->target,
4416
                             children_with_mergeinfo, notify_b);
4651
                             children_with_mergeinfo, notify_b);
4417
      SVN_ERR(determine_merges_performed(&merges, merge_b->target, &range,
4652
4418
                                         depth, adm_access, notify_b, merge_b,
4653
      /* Filter any ranges from MERGE_B->TARGET's own history, there is no
4419
                                         iterpool));
4654
         need to record this explicitly in mergeinfo, it is already part of
4420
      SVN_ERR(record_mergeinfo_on_merged_children(depth, adm_access, notify_b,
4655
         MERGE_B->TARGET's natural history (implicit mergeinfo). */
4421
                                                  merge_b, iterpool));
4656
      SVN_ERR(filter_natural_history_from_mergeinfo(
4422
      SVN_ERR(update_wc_mergeinfo(merge_b->target, parent_entry,
4657
        &filtered_rangelist, mergeinfo_path, merge_target->implicit_mergeinfo,
4423
                                  mergeinfo_path, merges,
4658
        &range, iterpool));
4424
                                  is_rollback, adm_access, merge_b->ctx,
4659
4425
                                  iterpool));
4660
      if (filtered_rangelist->nelts)
4661
        {
4662
          SVN_ERR(determine_merges_performed(&merges, merge_b->target,
4663
                                             filtered_rangelist, depth,
4664
                                             adm_access, notify_b,
4665
                                             merge_b, iterpool));
4666
4667
          SVN_ERR(record_mergeinfo_on_merged_children(depth, adm_access,
4668
                                                      notify_b, merge_b,
4669
                                                      iterpool));
4670
          SVN_ERR(update_wc_mergeinfo(merge_b->target, parent_entry,
4671
                                      mergeinfo_path, merges,
4672
                                      is_rollback, adm_access, merge_b->ctx,
4673
                                      iterpool));
4674
        }
4675
4426
      for (i = 0; i < children_with_mergeinfo->nelts; i++)
4676
      for (i = 0; i < children_with_mergeinfo->nelts; i++)
4427
        {
4677
        {
4428
          const char *child_repos_path;
4678
          const char *child_repos_path;
Lines 4430-4436 Link Here
4430
          const svn_wc_entry_t *child_entry;
4680
          const svn_wc_entry_t *child_entry;
4431
          apr_array_header_t *child_merge_rangelist;
4681
          apr_array_header_t *child_merge_rangelist;
4432
          apr_hash_t *child_merges;
4682
          apr_hash_t *child_merges;
4433
          svn_merge_range_t *child_merge_range;
4434
          svn_client__merge_path_t *child =
4683
          svn_client__merge_path_t *child =
4435
                         APR_ARRAY_IDX(children_with_mergeinfo, i,
4684
                         APR_ARRAY_IDX(children_with_mergeinfo, i,
4436
                                       svn_client__merge_path_t *);
4685
                                       svn_client__merge_path_t *);
Lines 4449-4467 Link Here
4449
                                          adm_access, FALSE, iterpool));
4698
                                          adm_access, FALSE, iterpool));
4450
4699
4451
          child_merges = apr_hash_make(iterpool);
4700
          child_merges = apr_hash_make(iterpool);
4452
          child_merge_range = svn_merge_range_dup(&range, iterpool);
4701
4453
          if (child_entry->kind == svn_node_file)
4702
          /* As we did above for the merge target, filter any ranges from
4454
            child_merge_range->inheritable = TRUE;
4703
             each child's natural history before setting mergeinfo. */
4704
          SVN_ERR(filter_natural_history_from_mergeinfo(
4705
            &child_merge_rangelist, child_merge_src_canon_path,
4706
            child->implicit_mergeinfo, &range, iterpool));
4707
4708
          if (child_merge_rangelist->nelts == 0)
4709
            continue;
4455
          else
4710
          else
4456
            child_merge_range->inheritable =
4711
            {
4457
                              (!(child->missing_child)
4712
              int j;
4458
                                 && (depth == svn_depth_infinity
4713
              for (j = 0; j < child_merge_rangelist->nelts; j++)
4714
                {
4715
                  svn_merge_range_t *rng =
4716
                    APR_ARRAY_IDX(child_merge_rangelist, j,
4717
                                  svn_merge_range_t *);
4718
                  if (child_entry->kind == svn_node_file)
4719
                    rng->inheritable = TRUE;
4720
                  else
4721
                    rng->inheritable = (!(child->missing_child)
4722
                                        && (depth == svn_depth_infinity
4459
                                     || depth == svn_depth_immediates));
4723
                                     || depth == svn_depth_immediates));
4460
          child_merge_rangelist =
4724
                }
4461
                             apr_array_make(iterpool, 1,
4725
            }
4462
                                            sizeof(child_merge_range));
4463
          APR_ARRAY_PUSH(child_merge_rangelist,
4464
                         svn_merge_range_t *) = child_merge_range;
4465
          apr_hash_set(child_merges, child->path, APR_HASH_KEY_STRING,
4726
          apr_hash_set(child_merges, child->path, APR_HASH_KEY_STRING,
4466
                       child_merge_rangelist);
4727
                       child_merge_rangelist);
4467
          /* If merge target has indirect mergeinfo set it before
4728
          /* If merge target has indirect mergeinfo set it before
Lines 4489-4498 Link Here
4489
                                                   merge_b,
4750
                                                   merge_b,
4490
                                                   children_with_mergeinfo,
4751
                                                   children_with_mergeinfo,
4491
                                                   i, iterpool));
4752
                                                   i, iterpool));
4753
4754
          /* Elide explicit subtree mergeinfo. */
4492
          if (i > 0)
4755
          if (i > 0)
4493
            SVN_ERR(svn_client__elide_mergeinfo(child->path, merge_b->target,
4756
            {
4494
                                                child_entry, adm_access,
4757
              svn_boolean_t in_switched_subtree = FALSE;
4495
                                                merge_b->ctx, iterpool));
4758
              
4759
              if (child->switched)
4760
                in_switched_subtree = TRUE;
4761
              else if (i > 1)
4762
                {
4763
                  /* Check if CHILD is part of a switched subtree */
4764
                  svn_client__merge_path_t *parent;
4765
                  int j = i - 1;
4766
                  for (; j > 0; j--)
4767
                    {
4768
                      parent = APR_ARRAY_IDX(children_with_mergeinfo, j,
4769
                                             svn_client__merge_path_t *);
4770
                      if (parent
4771
                          && parent->switched
4772
                          && svn_path_is_ancestor(parent->path, child->path))
4773
                        {
4774
                          in_switched_subtree = TRUE;
4775
                          break;
4776
                        }
4777
                    }
4778
                }
4779
4780
              /* Allow mergeinfo on switched subtrees to elide to the
4781
                 repository. Otherwise limit elision to the merge target
4782
                 for now.  do_directory_merge() will eventually try to
4783
                 elide that when the merge is complete. */
4784
              SVN_ERR(svn_client__elide_mergeinfo(
4785
                child->path,
4786
                in_switched_subtree ? NULL : merge_b->target,
4787
                child_entry, adm_access, merge_b->ctx, iterpool));
4788
            }
4496
        } /* (i = 0; i < children_with_mergeinfo->nelts; i++) */
4789
        } /* (i = 0; i < children_with_mergeinfo->nelts; i++) */
4497
      
4790
      
4498
      /* If a path has an immediate parent with non-inheritable mergeinfo at
4791
      /* If a path has an immediate parent with non-inheritable mergeinfo at
4499
-- subversion/libsvn_client/mergeinfo.c
4792
++ subversion/libsvn_client/mergeinfo.c
Lines 164-177 Link Here
164
          SVN_ERR(svn_client__parse_mergeinfo(&wc_mergeinfo, entry, wcpath,
164
          SVN_ERR(svn_client__parse_mergeinfo(&wc_mergeinfo, entry, wcpath,
165
                                              pristine, adm_access, ctx,
165
                                              pristine, adm_access, ctx,
166
                                              pool));
166
                                              pool));
167
168
          /* If WCPATH is switched, don't look any higher for inherited
169
             mergeinfo. */
170
          SVN_ERR(svn_wc__path_switched(wcpath, &switched, entry, pool));
171
          if (switched)
172
            break;
173
        }
167
        }
174
168
169
      /* If WCPATH is switched, don't look any higher for inherited
170
         mergeinfo. */
171
      SVN_ERR(svn_wc__path_switched(wcpath, &switched, entry, pool));
172
      if (switched)
173
        break;
174
175
      /* Subsequent svn_wc_adm_access_t need to be opened with
175
      /* Subsequent svn_wc_adm_access_t need to be opened with
176
         an absolute path so we can walk up and out of the WC
176
         an absolute path so we can walk up and out of the WC
177
         if necessary.  If we are using LIMIT_PATH it needs to
177
         if necessary.  If we are using LIMIT_PATH it needs to
Lines 725-781 Link Here
725
    {
725
    {
726
      svn_mergeinfo_t target_mergeinfo;
726
      svn_mergeinfo_t target_mergeinfo;
727
      svn_mergeinfo_t mergeinfo = NULL;
727
      svn_mergeinfo_t mergeinfo = NULL;
728
      svn_boolean_t inherited, switched;
728
      svn_boolean_t inherited;
729
      const char *walk_path;
729
      const char *walk_path;
730
730
731
      /* Check for second easy out: TARGET_WCPATH is switched. */
731
      /* Get the TARGET_WCPATH's explicit mergeinfo. */
732
      SVN_ERR(svn_wc__path_switched(target_wcpath, &switched, entry, pool));
732
      SVN_ERR(svn_client__get_wc_mergeinfo(&target_mergeinfo, &inherited,
733
      if (!switched)
733
                                           FALSE, svn_mergeinfo_inherited,
734
        {
734
                                           entry, target_wcpath,
735
          /* Get the TARGET_WCPATH's explicit mergeinfo. */
735
                                           wc_elision_limit_path
736
          SVN_ERR(svn_client__get_wc_mergeinfo(&target_mergeinfo, &inherited,
736
                                             ? wc_elision_limit_path
737
                                               FALSE, svn_mergeinfo_inherited,
737
                                             : NULL,
738
                                               entry, target_wcpath,
738
                                           &walk_path, adm_access,
739
                                               wc_elision_limit_path
739
                                           ctx, pool));
740
                                                 ? wc_elision_limit_path
741
                                                 : NULL,
742
                                               &walk_path, adm_access,
743
                                               ctx, pool));
744
740
745
         /* If TARGET_WCPATH has no explicit mergeinfo, there's nothing to
741
     /* If TARGET_WCPATH has no explicit mergeinfo, there's nothing to
746
             elide, we're done. */
742
         elide, we're done. */
747
          if (inherited || target_mergeinfo == NULL)
743
      if (inherited || target_mergeinfo == NULL)
748
            return SVN_NO_ERROR;
744
        return SVN_NO_ERROR;
749
745
750
          /* Get TARGET_WCPATH's inherited mergeinfo from the WC. */
746
      /* Get TARGET_WCPATH's inherited mergeinfo from the WC. */
751
          SVN_ERR(svn_client__get_wc_mergeinfo(&mergeinfo, &inherited, FALSE,
747
      SVN_ERR(svn_client__get_wc_mergeinfo(&mergeinfo, &inherited, FALSE,
752
                                               svn_mergeinfo_nearest_ancestor,
748
                                           svn_mergeinfo_nearest_ancestor,
753
                                               entry, target_wcpath,
749
                                           entry, target_wcpath,
754
                                               wc_elision_limit_path
750
                                           wc_elision_limit_path
755
                                                 ? wc_elision_limit_path
751
                                             ? wc_elision_limit_path
756
                                                 : NULL,
752
                                             : NULL,
757
                                               &walk_path, adm_access,
753
                                           &walk_path, adm_access,
758
                                               ctx, pool));
754
                                           ctx, pool));
759
755
760
          /* If TARGET_WCPATH inherited no mergeinfo from the WC and we are
756
      /* If TARGET_WCPATH inherited no mergeinfo from the WC and we are
761
             not limiting our search to the working copy then check if it
757
         not limiting our search to the working copy then check if it
762
             inherits any from the repos. */
758
         inherits any from the repos. */
763
          if (!mergeinfo && !wc_elision_limit_path)
759
      if (!mergeinfo && !wc_elision_limit_path)
764
            {
760
        {
765
              SVN_ERR(svn_client__get_wc_or_repos_mergeinfo
761
          SVN_ERR(svn_client__get_wc_or_repos_mergeinfo
766
                      (&mergeinfo, entry, &inherited, TRUE,
762
                  (&mergeinfo, entry, &inherited, TRUE,
767
                       svn_mergeinfo_nearest_ancestor,
763
                   svn_mergeinfo_nearest_ancestor,
768
                       NULL, target_wcpath, adm_access, ctx, pool));
764
                   NULL, target_wcpath, adm_access, ctx, pool));
769
            }
765
        }
770
766
771
          /* If there is nowhere to elide TARGET_WCPATH's mergeinfo to and
767
      /* If there is nowhere to elide TARGET_WCPATH's mergeinfo to and
772
             the elision is limited, then we are done.*/
768
         the elision is limited, then we are done.*/
773
          if (!mergeinfo && wc_elision_limit_path)
769
      if (!mergeinfo && wc_elision_limit_path)
774
            return SVN_NO_ERROR;
770
        return SVN_NO_ERROR;
775
771
776
          SVN_ERR(elide_mergeinfo(mergeinfo, target_mergeinfo, target_wcpath,
772
      SVN_ERR(elide_mergeinfo(mergeinfo, target_mergeinfo, target_wcpath,
777
                                  NULL, adm_access, pool));
773
                              NULL, adm_access, pool));
778
        }
779
    }
774
    }
780
  return SVN_NO_ERROR;
775
  return SVN_NO_ERROR;
781
}
776
}
782
-- subversion/libsvn_client/mergeinfo.h
777
++ subversion/libsvn_client/mergeinfo.h
Lines 51-56 Link Here
51
  apr_array_header_t *remaining_ranges; /* Per path remaining ranges list. */
51
  apr_array_header_t *remaining_ranges; /* Per path remaining ranges list. */
52
  svn_mergeinfo_t pre_merge_mergeinfo;  /* mergeinfo on a path prior to a
52
  svn_mergeinfo_t pre_merge_mergeinfo;  /* mergeinfo on a path prior to a
53
                                           merge.*/
53
                                           merge.*/
54
  svn_mergeinfo_t implicit_mergeinfo;   /* Implicit mergeinfo on a path prior
55
                                           to a merge.*/
54
  svn_boolean_t indirect_mergeinfo;
56
  svn_boolean_t indirect_mergeinfo;
55
  svn_boolean_t scheduled_for_deletion; /* PATH is scheduled for deletion. */
57
  svn_boolean_t scheduled_for_deletion; /* PATH is scheduled for deletion. */
56
} svn_client__merge_path_t;
58
} svn_client__merge_path_t;
Lines 72-78 Link Here
72
   inherited mergeinfo for WCPATH is retrieved.
74
   inherited mergeinfo for WCPATH is retrieved.
73
75
74
   Don't look for inherited mergeinfo any higher than LIMIT_PATH
76
   Don't look for inherited mergeinfo any higher than LIMIT_PATH
75
   (ignored if NULL).
77
   (ignored if NULL) or beyond any switched path.
76
78
77
   Set *WALKED_PATH to the path climbed from WCPATH to find inherited
79
   Set *WALKED_PATH to the path climbed from WCPATH to find inherited
78
   mergeinfo, or "" if none was found. (ignored if NULL). */
80
   mergeinfo, or "" if none was found. (ignored if NULL). */
Lines 196-205 Link Here
196
   copy (or possibly repository) ancestor with equivalent mergeinfo.
198
   copy (or possibly repository) ancestor with equivalent mergeinfo.
197
199
198
   If WC_ELISION_LIMIT_PATH is NULL check up to the root of the working copy
200
   If WC_ELISION_LIMIT_PATH is NULL check up to the root of the working copy
199
   for an elision destination, if none is found check the repository,
201
   or the nearest switched parent for an elision destination, if none is found
200
   otherwise check as far as WC_ELISION_LIMIT_PATH within the working copy.
202
   check the repository, otherwise check as far as WC_ELISION_LIMIT_PATH
201
   TARGET_PATH and WC_ELISION_LIMIT_PATH, if it exists, must both be absolute
203
   within the working copy.  TARGET_PATH and WC_ELISION_LIMIT_PATH, if it
202
   or relative to the working directory.
204
   exists, must both be absolute or relative to the working directory.
203
205
204
   Elision occurs if:
206
   Elision occurs if:
205
207
206
-- subversion/libsvn_wc/merge.c
208
++ subversion/libsvn_wc/merge.c
Lines 624-632 Link Here
624
        }
624
        }
625
      else
625
      else
626
        {
626
        {
627
          svn_boolean_t same;
627
          svn_boolean_t same, special;
628
          /* If 'special', then use the detranslated form of the
629
             target file.  This is so we don't try to follow symlinks,
630
             but the same treatment is probably also appropriate for
631
             whatever special file types we may invent in the future. */
632
          SVN_ERR(svn_wc__get_special(&special, merge_target,
633
                                      adm_access, pool));
628
          SVN_ERR(svn_io_files_contents_same_p(&same, result_target,
634
          SVN_ERR(svn_io_files_contents_same_p(&same, result_target,
629
                                               merge_target, pool));
635
                                               (special ?
636
                                                  tmp_target : 
637
                                                  merge_target),
638
                                               pool));
630
639
631
          *merge_outcome = same ? svn_wc_merge_unchanged : svn_wc_merge_merged;
640
          *merge_outcome = same ? svn_wc_merge_unchanged : svn_wc_merge_merged;
632
        }
641
        }

Return to bug 228653