diff options
Diffstat (limited to 'subversion/libsvn_client/mergeinfo.c')
| -rw-r--r-- | subversion/libsvn_client/mergeinfo.c | 187 | 
1 files changed, 124 insertions, 63 deletions
diff --git a/subversion/libsvn_client/mergeinfo.c b/subversion/libsvn_client/mergeinfo.c index 6dd34343e0d1..2d277f5f616e 100644 --- a/subversion/libsvn_client/mergeinfo.c +++ b/subversion/libsvn_client/mergeinfo.c @@ -1021,6 +1021,11 @@ svn_client__elide_mergeinfo(const char *target_abspath,     Set *REPOS_ROOT to the root URL of the repository associated with     PATH_OR_URL. +   If RA_SESSION is NOT NULL and PATH_OR_URL refers to a URL, RA_SESSION +   (which must be of the repository containing PATH_OR_URL) will be used +   instead of a temporary RA session. Caller is responsible for reparenting +   the session if it wants to use it after the call. +     Allocate *MERGEINFO_CATALOG and all its contents in RESULT_POOL.  Use     SCRATCH_POOL for all temporary allocations. @@ -1034,17 +1039,30 @@ get_mergeinfo(svn_mergeinfo_catalog_t *mergeinfo_catalog,                svn_boolean_t include_descendants,                svn_boolean_t ignore_invalid_mergeinfo,                svn_client_ctx_t *ctx, +              svn_ra_session_t *ra_session,                apr_pool_t *result_pool,                apr_pool_t *scratch_pool)  { -  svn_ra_session_t *ra_session;    const char *local_abspath;    svn_boolean_t use_url = svn_path_is_url(path_or_url);    svn_client__pathrev_t *peg_loc; -  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &peg_loc, -                                            path_or_url, NULL, peg_revision, -                                            peg_revision, ctx, scratch_pool)); +  if (ra_session && svn_path_is_url(path_or_url)) +    { +      SVN_ERR(svn_ra_reparent(ra_session, path_or_url, scratch_pool)); +      SVN_ERR(svn_client__resolve_rev_and_url(&peg_loc, ra_session, +                                              path_or_url, +                                              peg_revision, +                                              peg_revision, +                                              ctx, scratch_pool)); +    } +  else +    { +      SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &peg_loc, +                                                path_or_url, NULL, +                                                peg_revision, +                                                peg_revision, ctx, scratch_pool)); +    }    /* If PATH_OR_URL is as working copy path determine if we will need to       contact the repository for the requested PEG_REVISION. */ @@ -1064,10 +1082,6 @@ get_mergeinfo(svn_mergeinfo_catalog_t *mergeinfo_catalog,        }      } -  /* Check server Merge Tracking capability. */ -  SVN_ERR(svn_ra__assert_mergeinfo_capable_server(ra_session, path_or_url, -                                                  scratch_pool)); -    SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, result_pool));    if (use_url) @@ -1391,17 +1405,21 @@ filter_log_entry_with_rangelist(void *baton,               obviously back.  If it was added or replaced it's still around               possibly it was replaced one or more times, but it's back now.               Regardless, LOG_ENTRY->REVISION is *not* an eligible revision! */ -          if (ancestor_is_self /* Explicit mergeinfo on TARGET_PATH_AFFECTED */ +          if (nearest_ancestor_mergeinfo && +              ancestor_is_self /* Explicit mergeinfo on TARGET_PATH_AFFECTED */                && (change->action != 'M'))              {                svn_rangelist_t *rangelist =                    svn_hash_gets(nearest_ancestor_mergeinfo, path); -              svn_merge_range_t *youngest_range = APR_ARRAY_IDX( -                rangelist, rangelist->nelts - 1, svn_merge_range_t *); +              if (rangelist) +                { +                  svn_merge_range_t *youngest_range = APR_ARRAY_IDX( +                    rangelist, rangelist->nelts - 1, svn_merge_range_t *); -              if (youngest_range -                  && (youngest_range->end > log_entry->revision)) -                continue; +                  if (youngest_range +                      && (youngest_range->end > log_entry->revision)) +                    continue; +                }              }            if (nearest_ancestor_mergeinfo) @@ -1496,33 +1514,22 @@ logs_for_mergeinfo_rangelist(const char *source_url,                               svn_log_entry_receiver_t log_receiver,                               void *log_receiver_baton,                               svn_client_ctx_t *ctx, +                             svn_ra_session_t *ra_session,                               apr_pool_t *scratch_pool)  { -  apr_array_header_t *target;    svn_merge_range_t *oldest_range, *youngest_range; -  apr_array_header_t *revision_ranges; -  svn_opt_revision_t oldest_rev, youngest_rev; +  svn_revnum_t oldest_rev, youngest_rev;    struct filter_log_entry_baton_t fleb;    if (! rangelist->nelts)      return SVN_NO_ERROR; -  /* Sort the rangelist. */ -  qsort(rangelist->elts, rangelist->nelts, -        rangelist->elt_size, svn_sort_compare_ranges); - -  /* Build a single-member log target list using SOURCE_URL. */ -  target = apr_array_make(scratch_pool, 1, sizeof(const char *)); -  APR_ARRAY_PUSH(target, const char *) = source_url; -    /* Calculate and construct the bounds of our log request. */    youngest_range = APR_ARRAY_IDX(rangelist, rangelist->nelts - 1,                                   svn_merge_range_t *); -  youngest_rev.kind = svn_opt_revision_number; -  youngest_rev.value.number = youngest_range->end; +  youngest_rev = youngest_range->end;    oldest_range = APR_ARRAY_IDX(rangelist, 0, svn_merge_range_t *); -  oldest_rev.kind = svn_opt_revision_number; -  oldest_rev.value.number = oldest_range->start; +  oldest_rev = oldest_range->start;    if (! target_mergeinfo_catalog)      target_mergeinfo_catalog = apr_hash_make(scratch_pool); @@ -1547,19 +1554,29 @@ logs_for_mergeinfo_rangelist(const char *source_url,    fleb.log_receiver_baton = log_receiver_baton;    fleb.ctx = ctx; -  /* Drive the log. */ -  revision_ranges = apr_array_make(scratch_pool, 1, -                                   sizeof(svn_opt_revision_range_t *)); -  if (oldest_revs_first) -    APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *) -      = svn_opt__revision_range_create(&oldest_rev, &youngest_rev, scratch_pool); +  if (!ra_session) +    SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, source_url, +                                                 NULL, NULL, FALSE, FALSE, ctx, +                                                 scratch_pool, scratch_pool));    else -    APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *) -      = svn_opt__revision_range_create(&youngest_rev, &oldest_rev, scratch_pool); -  SVN_ERR(svn_client_log5(target, &youngest_rev, revision_ranges, -                          0, discover_changed_paths, FALSE, FALSE, revprops, -                          filter_log_entry_with_rangelist, &fleb, ctx, -                          scratch_pool)); +    SVN_ERR(svn_ra_reparent(ra_session, source_url, scratch_pool)); + +  { +    apr_array_header_t *target; +    target = apr_array_make(scratch_pool, 1, sizeof(const char *)); +    APR_ARRAY_PUSH(target, const char *) = ""; + +    SVN_ERR(svn_ra_get_log2(ra_session, target, +                            oldest_revs_first ? oldest_rev : youngest_rev, +                            oldest_revs_first ? youngest_rev : oldest_rev, +                            0 /* limit */, +                            discover_changed_paths, +                            FALSE /* strict_node_history */, +                            FALSE /* include_merged_revisions */, +                            revprops, +                            filter_log_entry_with_rangelist, &fleb, +                            scratch_pool)); +  }    /* Check for cancellation. */    if (ctx->cancel_func) @@ -1620,7 +1637,7 @@ svn_client_mergeinfo_get_merged(apr_hash_t **mergeinfo_p,    svn_mergeinfo_t mergeinfo;    SVN_ERR(get_mergeinfo(&mergeinfo_cat, &repos_root, path_or_url, -                        peg_revision, FALSE, FALSE, ctx, pool, pool)); +                        peg_revision, FALSE, FALSE, ctx, NULL, pool, pool));    if (mergeinfo_cat)      {        const char *repos_relpath; @@ -1666,6 +1683,7 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,                            svn_depth_t depth,                            const apr_array_header_t *revprops,                            svn_client_ctx_t *ctx, +                          svn_ra_session_t *ra_session,                            apr_pool_t *result_pool,                            apr_pool_t *scratch_pool)  { @@ -1719,6 +1737,9 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,    subpool = svn_pool_create(scratch_pool); +  if (ra_session) +    target_session = ra_session; +    /* We need the union of TARGET_PATH_OR_URL@TARGET_PEG_REVISION's mergeinfo       and MERGE_SOURCE_URL's history.  It's not enough to do path       matching, because renames in the history of MERGE_SOURCE_URL @@ -1735,11 +1756,27 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,               it ourselves.  We do need to get the repos_root               though, because get_mergeinfo() won't do it for us. */            target_mergeinfo_cat = *target_mergeinfo_catalog; -          SVN_ERR(svn_client__ra_session_from_path2(&target_session, &pathrev, -                                                    target_path_or_url, NULL, -                                                    target_peg_revision, -                                                    target_peg_revision, -                                                    ctx, subpool)); + +          if (ra_session && svn_path_is_url(target_path_or_url)) +            { +              SVN_ERR(svn_ra_reparent(ra_session, target_path_or_url, subpool)); +              SVN_ERR(svn_client__resolve_rev_and_url(&pathrev, ra_session, +                                                      target_path_or_url, +                                                      target_peg_revision, +                                                      target_peg_revision, +                                                      ctx, subpool)); +              target_session = ra_session; +            } +          else +            { +              SVN_ERR(svn_client__ra_session_from_path2(&target_session, +                                                        &pathrev, +                                                        target_path_or_url, +                                                        NULL, +                                                        target_peg_revision, +                                                        target_peg_revision, +                                                        ctx, subpool)); +            }            SVN_ERR(svn_ra_get_repos_root2(target_session, &repos_root,                                           scratch_pool));          } @@ -1751,7 +1788,7 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,            SVN_ERR(get_mergeinfo(target_mergeinfo_catalog, &repos_root,                                  target_path_or_url, target_peg_revision,                                  depth == svn_depth_infinity, TRUE, -                                ctx, result_pool, scratch_pool)); +                                ctx, ra_session, result_pool, scratch_pool));            target_mergeinfo_cat = *target_mergeinfo_catalog;          }      } @@ -1763,7 +1800,7 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,        SVN_ERR(get_mergeinfo(&target_mergeinfo_cat, &repos_root,                              target_path_or_url, target_peg_revision,                              depth == svn_depth_infinity, TRUE, -                            ctx, scratch_pool, scratch_pool)); +                            ctx, ra_session, scratch_pool, scratch_pool));      }    if (!svn_path_is_url(target_path_or_url)) @@ -1833,11 +1870,28 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,                                                       scratch_pool));        } -    SVN_ERR(svn_client__ra_session_from_path2(&source_session, &pathrev, -                                              source_path_or_url, NULL, -                                              source_peg_revision, -                                              source_peg_revision, -                                              ctx, subpool)); +    if (target_session +        && svn_path_is_url(source_path_or_url) +        && repos_root +        && svn_uri_skip_ancestor(repos_root, source_path_or_url, subpool)) +      { +        /* We can re-use the existing session */ +        source_session = target_session; +        SVN_ERR(svn_ra_reparent(source_session, source_path_or_url, subpool)); +        SVN_ERR(svn_client__resolve_rev_and_url(&pathrev, source_session, +                                                source_path_or_url, +                                                source_peg_revision, +                                                source_peg_revision, +                                                ctx, subpool)); +      } +    else +      { +        SVN_ERR(svn_client__ra_session_from_path2(&source_session, &pathrev, +                                                  source_path_or_url, NULL, +                                                  source_peg_revision, +                                                  source_peg_revision, +                                                  ctx, subpool)); +      }      SVN_ERR(svn_client__get_revision_number(&start_rev, &youngest_rev,                                              ctx->wc_ctx, source_path_or_url,                                              source_session, @@ -1856,9 +1910,6 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,                                                   scratch_pool));      if (start_rev > end_rev)        oldest_revs_first = FALSE; - -    /* Close the source and target sessions. */ -    svn_pool_destroy(subpool);    }    /* Separate the explicit or inherited mergeinfo on TARGET_PATH_OR_URL, @@ -2115,7 +2166,10 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,    log_target = svn_path_url_add_component2(repos_root, log_target + 1,                                             scratch_pool); -  SVN_ERR(logs_for_mergeinfo_rangelist(log_target, merge_source_fspaths, +  { +    svn_error_t *err; + +    err = logs_for_mergeinfo_rangelist(log_target, merge_source_fspaths,                                         finding_merged,                                         master_inheritable_rangelist,                                         oldest_revs_first, @@ -2126,8 +2180,13 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,                                         discover_changed_paths,                                         revprops,                                         log_receiver, log_receiver_baton, -                                       ctx, scratch_pool)); -  return SVN_NO_ERROR; +                                       ctx, target_session, scratch_pool); + +    /* Close the source and target sessions. */ +    svn_pool_destroy(subpool); /* For SVN_ERR_CEASE_INVOCATION */ + +    return svn_error_trace(err); +  }  }  svn_error_t * @@ -2146,13 +2205,15 @@ svn_client_mergeinfo_log2(svn_boolean_t finding_merged,                            svn_client_ctx_t *ctx,                            apr_pool_t *scratch_pool)  { -  return svn_client__mergeinfo_log(finding_merged, target_path_or_url, +  return svn_error_trace( +         svn_client__mergeinfo_log(finding_merged, target_path_or_url,                                     target_peg_revision, NULL,                                     source_path_or_url, source_peg_revision,                                     source_start_revision, source_end_revision,                                     log_receiver, log_receiver_baton,                                     discover_changed_paths, depth, revprops, -                                   ctx, scratch_pool, scratch_pool); +                                   ctx, NULL, +                                   scratch_pool, scratch_pool));  }  svn_error_t * @@ -2190,7 +2251,7 @@ svn_client_suggest_merge_sources(apr_array_header_t **suggestions,    /* ### TODO: Share ra_session batons to improve efficiency? */    SVN_ERR(get_mergeinfo(&mergeinfo_cat, &repos_root, path_or_url, -                        peg_revision, FALSE, FALSE, ctx, pool, pool)); +                        peg_revision, FALSE, FALSE, ctx, NULL, pool, pool));    if (mergeinfo_cat && apr_hash_count(mergeinfo_cat))      {  | 
