You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2012/03/30 16:12:54 UTC
svn commit: r1307434 [2/6] - in /subversion/branches/revprop-packing: ./
subversion/include/ subversion/include/private/ subversion/libsvn_client/
subversion/libsvn_fs_fs/ subversion/libsvn_ra_serf/
subversion/libsvn_ra_svn/ subversion/libsvn_repos/ su...
Modified: subversion/branches/revprop-packing/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/merge.c?rev=1307434&r1=1307433&r2=1307434&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_client/merge.c Fri Mar 30 14:12:52 2012
@@ -158,17 +158,11 @@
/*** Repos-Diff Editor Callbacks ***/
-/* Repository root and UUID for a repository. */
-typedef struct url_uuid_t
-{
- const char *url;
- const char *uuid;
-} url_uuid_t;
-
/* A location in a repository. */
typedef struct repo_location_t
{
- url_uuid_t *repo;
+ const char *repos_root_url;
+ const char *repos_uuid;
svn_revnum_t rev;
const char *url;
} repo_location_t;
@@ -177,12 +171,12 @@ typedef struct repo_location_t
typedef struct merge_source_t
{
/* "left" side URL and revision (inclusive iff youngest) */
- /* The "repo" field is not currently initialized or used. */
- repo_location_t loc1;
+ /* The "repos_*" fields are not currently initialized or used. */
+ const repo_location_t *loc1;
/* "right" side URL and revision (inclusive iff youngest) */
- /* The "repo" field is not currently initialized or used. */
- repo_location_t loc2;
+ /* The "repos_*" fields are not currently initialized or used. */
+ const repo_location_t *loc2;
} merge_source_t;
@@ -196,8 +190,8 @@ typedef struct merge_target_t
svn_node_kind_t kind;
/* The repository location of the base node of the target WC. If the node
- * is locally added, then URL & REV are NULL & SVN_INVALID_REVNUM. REPO
- * is always valid. */
+ * is locally added, then URL & REV are NULL & SVN_INVALID_REVNUM.
+ * REPOS_ROOT_URL and REPOS_UUID are always valid. */
repo_location_t loc;
} merge_target_t;
@@ -328,6 +322,112 @@ typedef struct merge_cmd_baton_t {
/*** Utilities ***/
+/* Return a new repo_location_t structure, allocated in RESULT_POOL,
+ * initialized with deep copies of REPOS_ROOT_URL, REPOS_UUID, REV and URL. */
+static repo_location_t *
+repo_location_create(const char *repos_root_url,
+ const char *repos_uuid,
+ svn_revnum_t rev,
+ const char *url,
+ apr_pool_t *result_pool)
+{
+ repo_location_t *loc = apr_palloc(result_pool, sizeof(*loc));
+
+ loc->repos_root_url = apr_pstrdup(result_pool, repos_root_url);
+ loc->repos_uuid = apr_pstrdup(result_pool, repos_uuid);
+ loc->rev = rev;
+ loc->url = apr_pstrdup(result_pool, url);
+ return loc;
+}
+
+/* Return a deep copy of LOC, allocated in RESULT_POOL. */
+static repo_location_t *
+repo_location_dup(const repo_location_t *loc,
+ apr_pool_t *result_pool)
+{
+ return repo_location_create(loc->repos_root_url, loc->repos_uuid,
+ loc->rev, loc->url, result_pool);
+}
+
+/* Return a new merge_source_t structure, allocated in RESULT_POOL,
+ * initialized with deep copies of LOC1 and LOC2. */
+static merge_source_t *
+merge_source_create(const repo_location_t *loc1,
+ const repo_location_t *loc2,
+ apr_pool_t *result_pool)
+{
+ merge_source_t *s
+ = apr_palloc(result_pool, sizeof(*s));
+
+ s->loc1 = repo_location_dup(loc1, result_pool);
+ s->loc2 = repo_location_dup(loc2, result_pool);
+ return s;
+}
+
+/* Return a deep copy of SOURCE, allocated in RESULT_POOL. */
+static merge_source_t *
+merge_source_dup(const merge_source_t *source,
+ apr_pool_t *result_pool)
+{
+ merge_source_t *s = apr_palloc(result_pool, sizeof(*s));
+
+ s->loc1 = repo_location_dup(source->loc1, result_pool);
+ s->loc2 = repo_location_dup(source->loc2, result_pool);
+ return s;
+}
+
+/* Like svn_client__repos_location() but using repo_location_t for input
+ * and output. */
+static svn_error_t *
+repos_location(repo_location_t **op_loc_p,
+ svn_ra_session_t *ra_session,
+ const repo_location_t *peg_loc,
+ svn_revnum_t op_revnum,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ *op_loc_p = apr_palloc(result_pool, sizeof(**op_loc_p));
+ (*op_loc_p)->repos_root_url = peg_loc->repos_root_url;
+ (*op_loc_p)->repos_uuid = peg_loc->repos_uuid;
+ (*op_loc_p)->rev = op_revnum;
+ SVN_ERR(svn_client__repos_location(&(*op_loc_p)->url, ra_session,
+ peg_loc->url, peg_loc->rev,
+ op_revnum,
+ ctx, result_pool, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+/* Set *ANCESTOR_P to the location of the youngest common ancestor of
+ * LOC1 and LOC2. If the locations have no common ancestor, set
+ * *ANCESTOR_P to NULL.
+ *
+ * Like svn_client__get_youngest_common_ancestor() but using repo_location_t
+ * for input and output.
+ */
+static svn_error_t *
+get_youngest_common_ancestor(repo_location_t **ancestor_p,
+ const repo_location_t *loc1,
+ const repo_location_t *loc2,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *url;
+ svn_revnum_t rev;
+
+ SVN_ERR(svn_client__get_youngest_common_ancestor(
+ NULL, &url, &rev,
+ loc1->url, loc1->rev, loc2->url, loc2->rev,
+ ctx, result_pool));
+ if (url)
+ *ancestor_p = repo_location_create(loc1->repos_root_url, loc1->repos_uuid,
+ rev, url, result_pool);
+ else
+ *ancestor_p = NULL;
+ return SVN_NO_ERROR;
+}
+
/* Return SVN_ERR_UNSUPPORTED_FEATURE if URL is not inside the repository
of LOCAL_ABSPATH. Use SCRATCH_POOL for temporary allocations. */
static svn_error_t *
@@ -336,45 +436,45 @@ check_repos_match(merge_cmd_baton_t *mer
const char *url,
apr_pool_t *scratch_pool)
{
- if (!svn_uri__is_ancestor(merge_b->target->loc.repo->url, url))
+ if (!svn_uri__is_ancestor(merge_b->target->loc.repos_root_url, url))
return svn_error_createf(
SVN_ERR_UNSUPPORTED_FEATURE, NULL,
_("Url '%s' of '%s' is not in repository '%s'"),
url, svn_dirent_local_style(local_abspath, scratch_pool),
- merge_b->target->loc.repo->url);
+ merge_b->target->loc.repos_root_url);
return SVN_NO_ERROR;
}
-/* Return TRUE iff the repository identified by REPOS_ROOT1 is the same as
- * that identified by REPOS_ROOT2. If STRICT_URLS is true, the URLs must
+/* Return TRUE iff the repository of LOCATION1 is the same as
+ * that of LOCATION2. If STRICT_URLS is true, the URLs must
* match (and the UUIDs, just to be sure), otherwise just the UUIDs must
* match and the URLs can differ (a common case is http versus https). */
static svn_boolean_t
-is_same_repos(const url_uuid_t *repos_root1,
- const url_uuid_t *repos_root2,
+is_same_repos(const repo_location_t *location1,
+ const repo_location_t *location2,
svn_boolean_t strict_urls)
{
if (strict_urls)
- return (strcmp(repos_root1->url, repos_root2->url) == 0
- && strcmp(repos_root1->uuid, repos_root2->uuid) == 0);
+ return (strcmp(location1->repos_root_url, location2->repos_root_url) == 0
+ && strcmp(location1->repos_uuid, location2->repos_uuid) == 0);
else
- return (strcmp(repos_root1->uuid, repos_root2->uuid) == 0);
+ return (strcmp(location1->repos_uuid, location2->repos_uuid) == 0);
}
-/* If the repository identified by REPOS_ROOT1 is not the same as that
- * identified by REPOS_ROOT2, throw a SVN_ERR_CLIENT_UNRELATED_RESOURCES
+/* If the repository identified of LOCATION1 is not the same as that
+ * of LOCATION2, throw a SVN_ERR_CLIENT_UNRELATED_RESOURCES
* error mentioning PATH1 and PATH2. For STRICT_URLS, see is_same_repos().
*/
static svn_error_t *
-check_same_repos(const url_uuid_t *repos_root1,
+check_same_repos(const repo_location_t *location1,
const char *path1,
- const url_uuid_t *repos_root2,
+ const repo_location_t *location2,
const char *path2,
svn_boolean_t strict_urls,
apr_pool_t *scratch_pool)
{
- if (! is_same_repos(repos_root1, repos_root2, strict_urls))
+ if (! is_same_repos(location1, location2, strict_urls))
return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
_("'%s' must be from the same repository as "
"'%s'"), path1, path2);
@@ -520,33 +620,33 @@ make_conflict_versions(const svn_wc_conf
svn_node_kind_t node_kind,
merge_cmd_baton_t *merge_b)
{
- const char *src_repos_url; /* root URL of source repository */
const char *left_url;
const char *right_url;
- SVN_ERR(svn_ra_get_repos_root2(merge_b->ra_session1, &src_repos_url,
- merge_b->pool));
-
/* Construct the source URLs of the victim. */
{
const char *child = svn_dirent_skip_ancestor(merge_b->target->abspath,
victim_abspath);
SVN_ERR_ASSERT(child != NULL);
- left_url = svn_path_url_add_component2(merge_b->merge_source.loc1.url,
+ left_url = svn_path_url_add_component2(merge_b->merge_source.loc1->url,
child, merge_b->pool);
- right_url = svn_path_url_add_component2(merge_b->merge_source.loc2.url,
+ right_url = svn_path_url_add_component2(merge_b->merge_source.loc2->url,
child, merge_b->pool);
}
*left = svn_wc_conflict_version_create(
- src_repos_url,
- svn_uri_skip_ancestor(src_repos_url, left_url, merge_b->pool),
- merge_b->merge_source.loc1.rev, node_kind, merge_b->pool);
+ merge_b->merge_source.loc1->repos_root_url,
+ svn_uri_skip_ancestor(
+ merge_b->merge_source.loc1->repos_root_url,
+ left_url, merge_b->pool),
+ merge_b->merge_source.loc1->rev, node_kind, merge_b->pool);
*right = svn_wc_conflict_version_create(
- src_repos_url,
- svn_uri_skip_ancestor(src_repos_url, right_url, merge_b->pool),
- merge_b->merge_source.loc2.rev, node_kind, merge_b->pool);
+ merge_b->merge_source.loc2->repos_root_url,
+ svn_uri_skip_ancestor(
+ merge_b->merge_source.loc2->repos_root_url,
+ right_url, merge_b->pool),
+ merge_b->merge_source.loc2->rev, node_kind, merge_b->pool);
return SVN_NO_ERROR;
}
@@ -863,8 +963,7 @@ filter_self_referential_mergeinfo(apr_ar
int i;
apr_pool_t *iterpool;
svn_boolean_t is_added;
- const char *target_base_url;
- svn_revnum_t target_base_rev;
+ repo_location_t target_base;
/* Issue #3383: We don't want mergeinfo from a foreign repos.
@@ -892,9 +991,9 @@ filter_self_referential_mergeinfo(apr_ar
if (is_added)
return SVN_NO_ERROR;
- SVN_ERR(svn_client_url_from_path2(&target_base_url, target_abspath,
+ SVN_ERR(svn_client_url_from_path2(&target_base.url, target_abspath,
ctx, pool, pool));
- SVN_ERR(svn_wc__node_get_base_rev(&target_base_rev, ctx->wc_ctx,
+ SVN_ERR(svn_wc__node_get_base_rev(&target_base.rev, ctx->wc_ctx,
target_abspath, pool));
adjusted_props = apr_array_make(pool, (*props)->nelts, sizeof(svn_prop_t));
@@ -965,7 +1064,7 @@ filter_self_referential_mergeinfo(apr_ar
the cost of a roundtrip communication with the repository. */
SVN_ERR(split_mergeinfo_on_revision(&younger_mergeinfo,
&mergeinfo,
- target_base_rev,
+ target_base.rev,
iterpool));
/* Filter self-referential mergeinfo from younger_mergeinfo. */
@@ -994,7 +1093,7 @@ filter_self_referential_mergeinfo(apr_ar
for (j = 0; j < rangelist->nelts; j++)
{
svn_error_t *err2;
- const char *start_url;
+ repo_location_t *start_loc;
svn_merge_range_t *range =
APR_ARRAY_IDX(rangelist, j, svn_merge_range_t *);
@@ -1006,10 +1105,10 @@ filter_self_referential_mergeinfo(apr_ar
/* Check if PATH@BASE_REVISION exists at
RANGE->START on the same line of history.
(start+1 because RANGE->start is not inclusive.) */
- err2 = svn_client__repos_location(&start_url, ra_session,
- target_base_url, target_base_rev,
- range->start + 1,
- ctx, iterpool, iterpool);
+ err2 = repos_location(&start_loc, ra_session,
+ &target_base,
+ range->start + 1,
+ ctx, iterpool, iterpool);
if (err2)
{
if (err2->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES
@@ -1054,7 +1153,7 @@ filter_self_referential_mergeinfo(apr_ar
PATH@RANGE->END actually belong to some other
line of history and we want to record this
mergeinfo, not filter it. */
- if (strcmp(start_url, merge_source_url) != 0)
+ if (strcmp(start_loc->url, merge_source_url) != 0)
{
APR_ARRAY_PUSH(adjusted_rangelist,
svn_merge_range_t *) = range;
@@ -1083,8 +1182,8 @@ filter_self_referential_mergeinfo(apr_ar
svn_mergeinfo_t implicit_mergeinfo;
SVN_ERR(svn_client__get_history_as_mergeinfo(
- &implicit_mergeinfo, NULL, target_base_url,
- target_base_rev, target_base_rev, SVN_INVALID_REVNUM,
+ &implicit_mergeinfo, NULL, target_base.url,
+ target_base.rev, target_base.rev, SVN_INVALID_REVNUM,
ra_session, ctx, iterpool));
/* Remove PATH's implicit mergeinfo from the incoming mergeinfo. */
@@ -1176,7 +1275,7 @@ merge_props_changed(svn_wc_notify_state_
http://svn.haxx.se/dev/archive-2008-09/0006.shtml. If the
merge sources are not ancestral then there is no concept of a
'forward' or 'reverse' merge and we filter unconditionally. */
- if (merge_b->merge_source.loc1.rev < merge_b->merge_source.loc2.rev
+ if (merge_b->merge_source.loc1->rev < merge_b->merge_source.loc2->rev
|| !merge_b->sources_ancestral)
SVN_ERR(filter_self_referential_mergeinfo(&props,
local_abspath,
@@ -1804,7 +1903,7 @@ merge_file_added(svn_wc_notify_state_t *
mine_abspath);
SVN_ERR_ASSERT(child != NULL);
copyfrom_url = svn_path_url_add_component2(
- merge_b->merge_source.loc2.url,
+ merge_b->merge_source.loc2->url,
child, scratch_pool);
copyfrom_rev = rev2;
SVN_ERR(check_repos_match(merge_b, mine_abspath, copyfrom_url,
@@ -2199,7 +2298,7 @@ merge_dir_added(svn_wc_notify_state_t *s
add. */
if (merge_b->same_repos)
{
- copyfrom_url = svn_path_url_add_component2(merge_b->merge_source.loc2.url,
+ copyfrom_url = svn_path_url_add_component2(merge_b->merge_source.loc2->url,
child, scratch_pool);
copyfrom_rev = rev;
@@ -3361,7 +3460,7 @@ fix_deleted_subtree_ranges(const merge_s
{
int i;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- svn_boolean_t is_rollback = source->loc2.rev < source->loc1.rev;
+ svn_boolean_t is_rollback = source->loc2->rev < source->loc1->rev;
/* CHILDREN_WITH_MERGEINFO is sorted in depth-first order, so
start at index 1 to examine only subtrees. */
@@ -3435,13 +3534,13 @@ fix_deleted_subtree_ranges(const merge_s
SVN_ERR_ASSERT(child_repos_src_path);
child_primary_source_url =
- svn_path_url_add_component2((source->loc1.rev < source->loc2.rev)
- ? source->loc2.url : source->loc1.url,
+ svn_path_url_add_component2((source->loc1->rev < source->loc2->rev)
+ ? source->loc2->url : source->loc1->url,
child_repos_src_path, iterpool);
SVN_ERR(adjust_deleted_subtree_ranges(child, parent,
- source->loc1.rev,
- source->loc2.rev,
+ source->loc1->rev,
+ source->loc2->rev,
child_primary_source_url,
ra_session,
merge_b->ctx, result_pool,
@@ -3989,8 +4088,8 @@ calculate_remaining_ranges(svn_client__m
apr_pool_t *scratch_pool)
{
const char *mergeinfo_path;
- const char *primary_url = (source->loc1.rev < source->loc2.rev)
- ? source->loc2.url : source->loc1.url;
+ const char *primary_url = (source->loc1->rev < source->loc2->rev)
+ ? source->loc2->url : source->loc1->url;
svn_mergeinfo_t adjusted_target_mergeinfo = NULL;
svn_revnum_t child_base_revision;
@@ -4030,7 +4129,7 @@ calculate_remaining_ranges(svn_client__m
merged (or, in the case of reverse merges, ranges not yet merged). */
SVN_ERR(filter_merged_revisions(parent, child, mergeinfo_path,
adjusted_target_mergeinfo,
- source->loc1.rev, source->loc2.rev,
+ source->loc1->rev, source->loc2->rev,
child_inherits_implicit,
ra_session, ctx, result_pool,
scratch_pool));
@@ -4067,20 +4166,19 @@ calculate_remaining_ranges(svn_client__m
can't have any "future" history. */
if (SVN_IS_VALID_REVNUM(child_base_revision)
&& ((child->remaining_ranges)->nelts == 0) /* Inoperative merge */
- && (source->loc2.rev < source->loc1.rev) /* Reverse merge */
- && (child_base_revision <= source->loc2.rev)) /* From CHILD's future */
+ && (source->loc2->rev < source->loc1->rev) /* Reverse merge */
+ && (child_base_revision <= source->loc2->rev)) /* From CHILD's future */
{
/* Hmmm, an inoperative reverse merge from the "future". If it is
from our own future return a helpful error. */
svn_error_t *err;
- const char *start_url;
+ repo_location_t *start_loc;
- err = svn_client__repos_location(&start_url,
- ra_session,
- source->loc1.url,
- source->loc1.rev,
- child_base_revision,
- ctx, scratch_pool, scratch_pool);
+ err = repos_location(&start_loc,
+ ra_session,
+ source->loc1,
+ child_base_revision,
+ ctx, scratch_pool, scratch_pool);
if (err)
{
if (err->apr_err == SVN_ERR_FS_NOT_FOUND
@@ -4095,7 +4193,7 @@ calculate_remaining_ranges(svn_client__m
SVN_ERR(svn_wc__node_get_url(&url, ctx->wc_ctx, child->abspath,
scratch_pool, scratch_pool));
- if (strcmp(start_url, url) == 0)
+ if (strcmp(start_loc->url, url) == 0)
return svn_error_create(SVN_ERR_CLIENT_MERGE_UPDATE_REQUIRED, NULL,
_("Cannot reverse-merge a range from a "
"path's own future history; try "
@@ -4141,10 +4239,10 @@ find_gaps_in_merge_source_history(svn_re
apr_pool_t *scratch_pool)
{
svn_mergeinfo_t implicit_src_mergeinfo;
- svn_revnum_t young_rev = MAX(source->loc1.rev, source->loc2.rev);
- svn_revnum_t old_rev = MIN(source->loc1.rev, source->loc2.rev);
- const char *primary_url = (source->loc1.rev < source->loc2.rev)
- ? source->loc2.url : source->loc1.url;
+ svn_revnum_t young_rev = MAX(source->loc1->rev, source->loc2->rev);
+ svn_revnum_t old_rev = MIN(source->loc1->rev, source->loc2->rev);
+ const char *primary_url = (source->loc1->rev < source->loc2->rev)
+ ? source->loc2->url : source->loc1->url;
const char *merge_src_fspath;
apr_array_header_t *rangelist;
@@ -4193,7 +4291,7 @@ find_gaps_in_merge_source_history(svn_re
/* As mentioned above, multiple gaps *shouldn't* be possible. */
SVN_ERR_ASSERT(apr_hash_count(implicit_src_mergeinfo) == 1);
- *gap_start = MIN(source->loc1.rev, source->loc2.rev);
+ *gap_start = MIN(source->loc1->rev, source->loc2->rev);
*gap_end = (APR_ARRAY_IDX(rangelist,
rangelist->nelts - 1,
svn_merge_range_t *))->start;
@@ -4201,8 +4299,8 @@ find_gaps_in_merge_source_history(svn_re
else if (apr_hash_count(implicit_src_mergeinfo) > 1) /* Rename */
{
apr_array_header_t *requested_rangelist =
- svn_rangelist__initialize(MIN(source->loc1.rev, source->loc2.rev),
- MAX(source->loc1.rev, source->loc2.rev),
+ svn_rangelist__initialize(MIN(source->loc1->rev, source->loc2->rev),
+ MAX(source->loc1->rev, source->loc2->rev),
TRUE, scratch_pool);
apr_array_header_t *implicit_rangelist =
apr_array_make(scratch_pool, 2, sizeof(svn_merge_range_t *));
@@ -4291,10 +4389,10 @@ populate_remaining_ranges(apr_array_head
NULL, /* child->inherited_mergeinfo */
svn_mergeinfo_inherited, ra_session,
child->abspath,
- MAX(source->loc1.rev,
- source->loc2.rev),
- MIN(source->loc1.rev,
- source->loc2.rev),
+ MAX(source->loc1->rev,
+ source->loc2->rev),
+ MIN(source->loc1->rev,
+ source->loc2->rev),
merge_b->ctx, result_pool,
iterpool));
}
@@ -4315,14 +4413,14 @@ populate_remaining_ranges(apr_array_head
child_inherits_implicit = (parent && !child->switched);
SVN_ERR(ensure_implicit_mergeinfo(parent, child,
child_inherits_implicit,
- source->loc1.rev,
- source->loc2.rev,
+ source->loc1->rev,
+ source->loc2->rev,
ra_session, merge_b->ctx,
result_pool, iterpool));
}
- child->remaining_ranges = svn_rangelist__initialize(source->loc1.rev,
- source->loc2.rev,
+ child->remaining_ranges = svn_rangelist__initialize(source->loc1->rev,
+ source->loc2->rev,
TRUE,
result_pool);
}
@@ -4356,7 +4454,9 @@ populate_remaining_ranges(apr_array_head
for (i = 0; i < children_with_mergeinfo->nelts; i++)
{
const char *child_repos_path;
- merge_source_t child_source = *source;
+ repo_location_t loc1 = *source->loc1;
+ repo_location_t loc2 = *source->loc2;
+ merge_source_t child_source = { &loc1, &loc2 };
svn_client__merge_path_t *child =
APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
svn_client__merge_path_t *parent = NULL;
@@ -4374,10 +4474,10 @@ populate_remaining_ranges(apr_array_head
child_repos_path = svn_dirent_skip_ancestor(merge_b->target->abspath,
child->abspath);
SVN_ERR_ASSERT(child_repos_path != NULL);
- child_source.loc1.url = svn_path_url_add_component2(
- source->loc1.url, child_repos_path, iterpool);
- child_source.loc2.url = svn_path_url_add_component2(
- source->loc2.url, child_repos_path, iterpool);
+ loc1.url = svn_path_url_add_component2(
+ source->loc1->url, child_repos_path, iterpool);
+ loc2.url = svn_path_url_add_component2(
+ source->loc2->url, child_repos_path, iterpool);
/* Get the explicit/inherited mergeinfo for CHILD. If CHILD is the
merge target then also get its implicit mergeinfo. Otherwise defer
@@ -4390,8 +4490,8 @@ populate_remaining_ranges(apr_array_head
&(child->inherited_mergeinfo),
svn_mergeinfo_inherited, ra_session,
child->abspath,
- MAX(source->loc1.rev, source->loc2.rev),
- MIN(source->loc1.rev, source->loc2.rev),
+ MAX(source->loc1->rev, source->loc2->rev),
+ MIN(source->loc1->rev, source->loc2->rev),
merge_b->ctx, result_pool, iterpool));
/* If CHILD isn't the merge target find its parent. */
@@ -4442,7 +4542,7 @@ populate_remaining_ranges(apr_array_head
/* If this is a reverse merge reorder CHILD->REMAINING_RANGES
so it will work with the svn_rangelist_* APIs below. */
- if (source->loc1.rev > source->loc2.rev)
+ if (source->loc1->rev > source->loc2->rev)
SVN_ERR(svn_rangelist_reverse(child->remaining_ranges, iterpool));
for (j = 0; j < child->remaining_ranges->nelts; j++)
@@ -4484,7 +4584,7 @@ populate_remaining_ranges(apr_array_head
result_pool));
}
- if (source->loc1.rev > source->loc2.rev) /* Reverse merge */
+ if (source->loc1->rev > source->loc2->rev) /* Reverse merge */
SVN_ERR(svn_rangelist_reverse(child->remaining_ranges, iterpool));
}
}
@@ -4657,7 +4757,7 @@ update_wc_mergeinfo(svn_mergeinfo_catalo
IS_ROLLBACK is true if the caller is recording a reverse merge and false
otherwise. RANGELIST is the set of revisions being merged from
- MERGEINFO_PATH to MERGE_B->TARGET_ABSPATH. */
+ MERGEINFO_PATH to MERGE_B->target. */
static svn_error_t *
record_skips(const char *mergeinfo_path,
const apr_array_header_t *rangelist,
@@ -4776,7 +4876,7 @@ remove_absent_children(const char *targe
false then for each path (if any) in MERGE_B->PATHS_WITH_DELETED_MERGEINFO
remove that path from CHILDREN_WITH_MERGEINFO by setting that
child to NULL. The one exception is for the merge target itself,
- MERGE_B->TARGET_ABSPATH, this must always be present in
+ MERGE_B->target->abspath, this must always be present in
CHILDREN_WITH_MERGEINFO so this is never removed by this
function. */
static void
@@ -4885,11 +4985,11 @@ drive_merge_report_editor(const char *ta
svn_revnum_t target_start;
svn_boolean_t honor_mergeinfo = HONOR_MERGEINFO(merge_b);
const char *old_sess1_url, *old_sess2_url;
- svn_boolean_t is_rollback = source->loc1.rev > source->loc2.rev;
+ svn_boolean_t is_rollback = source->loc1->rev > source->loc2->rev;
/* Start with a safe default starting revision for the editor and the
merge target. */
- target_start = source->loc1.rev;
+ target_start = source->loc1->rev;
/* If we are honoring mergeinfo the starting revision for the merge target
might not be SOURCE->rev1, in fact the merge target might not need *any*
@@ -4915,7 +5015,7 @@ drive_merge_report_editor(const char *ta
if (child->remaining_ranges->nelts == 0)
{
/* The merge target doesn't need anything merged. */
- target_start = source->loc2.rev;
+ target_start = source->loc2->rev;
}
else
{
@@ -4926,11 +5026,11 @@ drive_merge_report_editor(const char *ta
svn_merge_range_t *range =
APR_ARRAY_IDX(child->remaining_ranges, 0,
svn_merge_range_t *);
- if ((!is_rollback && range->start > source->loc2.rev)
- || (is_rollback && range->start < source->loc2.rev))
+ if ((!is_rollback && range->start > source->loc2->rev)
+ || (is_rollback && range->start < source->loc2->rev))
{
/* Merge target's first remaining range doesn't intersect. */
- target_start = source->loc2.rev;
+ target_start = source->loc2->rev;
}
else
{
@@ -4943,18 +5043,18 @@ drive_merge_report_editor(const char *ta
SVN_ERR(svn_client__ensure_ra_session_url(&old_sess1_url,
merge_b->ra_session1,
- source->loc1.url, scratch_pool));
+ source->loc1->url, scratch_pool));
/* Temporarily point our second RA session to SOURCE->url1, too. We use
this to request individual file contents. */
SVN_ERR(svn_client__ensure_ra_session_url(&old_sess2_url,
merge_b->ra_session2,
- source->loc1.url, scratch_pool));
+ source->loc1->url, scratch_pool));
/* Get the diff editor and a reporter with which to, ultimately,
drive it. */
SVN_ERR(svn_client__get_diff_editor(&diff_editor, &diff_edit_baton,
depth,
- merge_b->ra_session2, source->loc1.rev,
+ merge_b->ra_session2, source->loc1->rev,
FALSE /* walk_deleted_dirs */,
TRUE /* text_deltas */,
&merge_callbacks, merge_b,
@@ -4963,10 +5063,10 @@ drive_merge_report_editor(const char *ta
notification_receiver, notify_b,
scratch_pool));
SVN_ERR(svn_ra_do_diff3(merge_b->ra_session1,
- &reporter, &report_baton, source->loc2.rev,
+ &reporter, &report_baton, source->loc2->rev,
"", depth, merge_b->ignore_ancestry,
TRUE, /* text_deltas */
- source->loc2.url, diff_editor, diff_edit_baton,
+ source->loc2->url, diff_editor, diff_edit_baton,
scratch_pool));
/* Drive the reporter. */
@@ -5011,8 +5111,8 @@ drive_merge_report_editor(const char *ta
{
range = APR_ARRAY_IDX(child->remaining_ranges, 0,
svn_merge_range_t *);
- if ((!is_rollback && range->start > source->loc2.rev)
- || (is_rollback && range->start < source->loc2.rev))
+ if ((!is_rollback && range->start > source->loc2->rev)
+ || (is_rollback && range->start < source->loc2->rev))
{
/* This child's first remaining range comes after the range
we are currently merging, so skip it. We expect to get
@@ -5050,14 +5150,14 @@ drive_merge_report_editor(const char *ta
SVN_ERR_ASSERT(child_repos_path);
if ((child->remaining_ranges->nelts == 0)
- || (is_rollback && (range->start < source->loc2.rev))
- || (!is_rollback && (range->start > source->loc2.rev)))
+ || (is_rollback && (range->start < source->loc2->rev))
+ || (!is_rollback && (range->start > source->loc2->rev)))
{
/* Nothing to merge to this child. We'll claim we have
it up to date so the server doesn't send us
anything. */
SVN_ERR(reporter->set_path(report_baton, child_repos_path,
- source->loc2.rev, depth, FALSE,
+ source->loc2->rev, depth, FALSE,
NULL, iterpool));
}
else
@@ -5354,7 +5454,7 @@ insert_child_to_merge(apr_array_header_t
get_mergeinfo_paths() is iterating over and *CURR_INDEX is index for
*CHILD.
- If CHILD->ABSPATH is equal to MERGE_CMD_BATON->TARGET_ABSPATH do nothing.
+ If CHILD->ABSPATH is equal to MERGE_CMD_BATON->target->abspath do nothing.
Else if CHILD->ABSPATH is switched or absent then make sure its immediate
(as opposed to nearest) parent in CHILDREN_WITH_MERGEINFO is marked as
missing a child. If the immediate parent does not exist in
@@ -5621,14 +5721,14 @@ get_wc_explicit_mergeinfo_catalog(apr_ha
/* Helper for do_directory_merge() when performing merge-tracking aware
merges.
- Walk of the working copy tree rooted at MERGE_CMD_BATON->TARGET_ABSPATH to
+ Walk of the working copy tree rooted at MERGE_CMD_BATON->target->abspath to
depth DEPTH. Create an svn_client__merge_path_t * for any path which meets
one or more of the following criteria:
1) Path has working svn:mergeinfo.
2) Path is switched.
3) Path is a subtree of the merge target (i.e. is not equal to
- MERGE_CMD_BATON->TARGET_ABSPATH) and has no mergeinfo of its own but
+ MERGE_CMD_BATON->target->abspath) and has no mergeinfo of its own but
its immediate parent has mergeinfo with non-inheritable ranges. If
this isn't a dry-run and the merge is between differences in the same
repository, then this function will set working mergeinfo on the path
@@ -5640,10 +5740,10 @@ get_wc_explicit_mergeinfo_catalog(apr_ha
sibling is switched, absent, scheduled for deletion, or missing due to
a sparse checkout.
6) Path is absent from disk due to an authz restriction.
- 7) Path is equal to MERGE_CMD_BATON->TARGET_ABSPATH.
+ 7) Path is equal to MERGE_CMD_BATON->target->abspath.
8) Path is an immediate *directory* child of
- MERGE_CMD_BATON->TARGET_ABSPATH and DEPTH is svn_depth_immediates.
- 9) Path is an immediate *file* child of MERGE_CMD_BATON->TARGET_ABSPATH
+ MERGE_CMD_BATON->target->abspath and DEPTH is svn_depth_immediates.
+ 9) Path is an immediate *file* child of MERGE_CMD_BATON->target->abspath
and DEPTH is svn_depth_files.
10) Path is at a depth of 'empty' or 'files'.
11) Path is missing from disk (e.g. due to an OS-level deletion).
@@ -5656,7 +5756,7 @@ get_wc_explicit_mergeinfo_catalog(apr_ha
sorted by svn_path_compare_paths(). Set the remaining_ranges field of each
element to NULL.
- Note: Since the walk is rooted at MERGE_CMD_BATON->TARGET_ABSPATH, the
+ Note: Since the walk is rooted at MERGE_CMD_BATON->target->abspath, the
latter is guaranteed to be in *CHILDREN_WITH_MERGEINFO and due to the
depth-first ordering it is guaranteed to be the first element in
*CHILDREN_WITH_MERGEINFO.
@@ -5708,8 +5808,9 @@ get_mergeinfo_paths(apr_array_header_t *
= svn_mergeinfo__is_noninheritable(
mergeinfo_child->pre_merge_mergeinfo, iterpool);
- insert_child_to_merge(children_with_mergeinfo, mergeinfo_child,
- result_pool);
+ /* Append it. We'll sort below. */
+ APR_ARRAY_PUSH(children_with_mergeinfo, svn_client__merge_path_t *)
+ = svn_client__merge_path_dup(mergeinfo_child, result_pool);
}
/* Sort CHILDREN_WITH_MERGEINFO by each child's path (i.e. as per
@@ -5878,7 +5979,7 @@ get_mergeinfo_paths(apr_array_header_t *
}
}
- /* Case 7: The merge target MERGE_CMD_BATON->TARGET_ABSPATH is always
+ /* Case 7: The merge target MERGE_CMD_BATON->target->abspath is always
present. */
if (!get_child_with_mergeinfo(children_with_mergeinfo,
merge_cmd_baton->target->abspath))
@@ -5891,10 +5992,10 @@ get_mergeinfo_paths(apr_array_header_t *
}
/* Case 8: Path is an immediate *directory* child of
- MERGE_CMD_BATON->TARGET_ABSPATH and DEPTH is svn_depth_immediates.
+ MERGE_CMD_BATON->target->abspath and DEPTH is svn_depth_immediates.
Case 9: Path is an immediate *file* child of
- MERGE_CMD_BATON->TARGET_ABSPATH and DEPTH is svn_depth_files. */
+ MERGE_CMD_BATON->target->abspath and DEPTH is svn_depth_files. */
if (depth == svn_depth_immediates || depth == svn_depth_files)
{
int j;
@@ -6201,8 +6302,8 @@ static int
compare_merge_source_ts(const void *a,
const void *b)
{
- svn_revnum_t a_rev = ((const merge_source_t *)a)->loc1.rev;
- svn_revnum_t b_rev = ((const merge_source_t *)b)->loc1.rev;
+ svn_revnum_t a_rev = (*(const merge_source_t *const *)a)->loc1->rev;
+ svn_revnum_t b_rev = (*(const merge_source_t *const *)b)->loc1->rev;
if (a_rev == b_rev)
return 0;
return a_rev < b_rev ? 1 : -1;
@@ -6210,7 +6311,7 @@ compare_merge_source_ts(const void *a,
/* Set *MERGE_SOURCE_TS_P to a list of merge sources generated by
slicing history location SEGMENTS with a given requested merge
- RANGE. Use SOURCE_ROOT_URL for full source URL calculation.
+ RANGE. Use SOURCE_LOC for full source URL calculation.
Order the merge sources in *MERGE_SOURCE_TS_P from oldest to
youngest. */
@@ -6218,7 +6319,7 @@ static svn_error_t *
combine_range_with_segments(apr_array_header_t **merge_source_ts_p,
const svn_merge_range_t *range,
const apr_array_header_t *segments,
- const char *source_root_url,
+ const repo_location_t *source_loc,
apr_pool_t *pool)
{
apr_array_header_t *merge_source_ts =
@@ -6232,6 +6333,7 @@ combine_range_with_segments(apr_array_he
{
svn_location_segment_t *segment =
APR_ARRAY_IDX(segments, i, svn_location_segment_t *);
+ repo_location_t loc1, loc2;
merge_source_t *merge_source;
const char *path1 = NULL;
svn_revnum_t rev1;
@@ -6279,20 +6381,22 @@ combine_range_with_segments(apr_array_he
continue;
/* Build our merge source structure. */
- merge_source = apr_pcalloc(pool, sizeof(*merge_source));
- merge_source->loc1.url = svn_path_url_add_component2(source_root_url,
- path1,
- pool);
- merge_source->loc2.url = svn_path_url_add_component2(source_root_url,
- segment->path,
- pool);
- merge_source->loc1.rev = rev1;
- merge_source->loc2.rev = MIN(segment->range_end, maxrev);
+ loc1.repos_root_url = source_loc->repos_root_url;
+ loc1.repos_uuid = source_loc->repos_uuid;
+ loc1.rev = rev1;
+ loc1.url = svn_path_url_add_component2(source_loc->repos_root_url,
+ path1, pool);
+ loc2.repos_root_url = source_loc->repos_root_url;
+ loc2.repos_uuid = source_loc->repos_uuid;
+ loc2.rev = MIN(segment->range_end, maxrev);
+ loc2.url = svn_path_url_add_component2(source_loc->repos_root_url,
+ segment->path, pool);
+ merge_source = merge_source_create(&loc1, &loc2, pool);
/* If this is subtractive, reverse the whole calculation. */
if (subtractive)
{
- repo_location_t tmploc = merge_source->loc1;
+ const repo_location_t *tmploc = merge_source->loc1;
merge_source->loc1 = merge_source->loc2;
merge_source->loc2 = tmploc;
}
@@ -6314,22 +6418,21 @@ combine_range_with_segments(apr_array_he
* no SOURCE_PATH_OR_URL argument;
* MERGE_RANGE_TS (array of svn_merge_range_t *) instead of RANGES;
* SOURCE_PEG_REVNUM instead of SOURCE_PEG_REVISION.
- * RA_SESSION is an RA session open to the repository of SOURCE_URL; it may
+ * RA_SESSION is an RA session open to the repository of SOURCE_LOC; it may
* be temporarily reparented within this function.
*/
static svn_error_t *
normalize_merge_sources_internal(apr_array_header_t **merge_sources_p,
- const char *source_url,
- svn_revnum_t source_peg_revnum,
+ const repo_location_t *source_loc,
const apr_array_header_t *merge_range_ts,
svn_ra_session_t *ra_session,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
+ svn_revnum_t source_peg_revnum = source_loc->rev;
svn_revnum_t oldest_requested, youngest_requested;
svn_revnum_t trim_revision = SVN_INVALID_REVNUM;
- const char *source_root_url;
apr_array_header_t *segments;
int i;
@@ -6351,26 +6454,23 @@ normalize_merge_sources_internal(apr_arr
all the underlying APIs would do in this case right now anyway). */
if (source_peg_revnum < youngest_requested)
{
- const char *start_url;
+ repo_location_t *start_loc;
- SVN_ERR(svn_client__repos_location(&start_url,
- ra_session, source_url,
- source_peg_revnum,
- youngest_requested,
- ctx, scratch_pool, scratch_pool));
+ SVN_ERR(repos_location(&start_loc,
+ ra_session, source_loc,
+ youngest_requested,
+ ctx, scratch_pool, scratch_pool));
source_peg_revnum = youngest_requested;
}
/* Fetch the locations for our merge range span. */
SVN_ERR(svn_client__repos_location_segments(&segments,
- ra_session, source_url,
+ ra_session, source_loc->url,
source_peg_revnum,
youngest_requested,
oldest_requested,
ctx, result_pool));
- SVN_ERR(svn_ra_get_repos_root2(ra_session, &source_root_url, scratch_pool));
-
/* See if we fetched enough history to do the job. "Surely we did,"
you say. "After all, we covered the entire requested merge
range." Yes, that's true, but if our first segment doesn't
@@ -6414,9 +6514,9 @@ normalize_merge_sources_internal(apr_arr
range_start_rev.kind = svn_opt_revision_number;
range_start_rev.value.number = segment2->range_start;
- segment_url = svn_path_url_add_component2(source_root_url,
- segment2->path,
- scratch_pool);
+ segment_url = svn_path_url_add_component2(
+ source_loc->repos_root_url, segment2->path,
+ scratch_pool);
SVN_ERR(svn_client__get_copy_source(segment_url,
&range_start_rev,
©from_path,
@@ -6467,7 +6567,7 @@ normalize_merge_sources_internal(apr_arr
/* Copy the resulting merge sources into master list thereof. */
SVN_ERR(combine_range_with_segments(&merge_sources, range,
- segments, source_root_url,
+ segments, source_loc,
result_pool));
apr_array_cat(*merge_sources_p, merge_sources);
}
@@ -6480,12 +6580,12 @@ normalize_merge_sources_internal(apr_arr
requested merges; order the objects from oldest to youngest.
Determine the requested merges by examining SOURCE_PATH_OR_URL (and its
- associated URL and revision, SOURCE_URL and SOURCE_PEG_REVNUM) (which
+ associated URL and revision, SOURCE_LOC) (which
specifies the line of history from which merges will be pulled) and
RANGES_TO_MERGE (a list of svn_opt_revision_range_t's which provide
revision ranges).
- RA_SESSION is an RA session open to the repository of SOURCE_URL; it may
+ RA_SESSION is an RA session open to the repository of SOURCE_LOC; it may
be temporarily reparented within this function. Use RA_SESSION to answer
historical questions.
@@ -6500,8 +6600,7 @@ normalize_merge_sources_internal(apr_arr
static svn_error_t *
normalize_merge_sources(apr_array_header_t **merge_sources_p,
const char *source_path_or_url,
- const char *source_url,
- svn_revnum_t source_peg_revnum,
+ const repo_location_t *source_loc,
const apr_array_header_t *ranges_to_merge,
svn_ra_session_t *ra_session,
svn_client_ctx_t *ctx,
@@ -6560,7 +6659,7 @@ normalize_merge_sources(apr_array_header
}
SVN_ERR(normalize_merge_sources_internal(
- merge_sources_p, source_url, source_peg_revnum,
+ merge_sources_p, source_loc,
merge_range_ts, ra_session, ctx, result_pool, scratch_pool));
svn_pool_destroy(iterpool);
@@ -6641,26 +6740,25 @@ subrange_source(const merge_source_t *so
svn_revnum_t end_rev,
apr_pool_t *pool)
{
- svn_boolean_t is_rollback = (source->loc1.rev > source->loc2.rev);
- svn_boolean_t same_urls = (strcmp(source->loc1.url, source->loc2.url) == 0);
- merge_source_t *real_source = apr_palloc(pool, sizeof(*source));
-
- real_source->loc1.url = source->loc1.url;
- real_source->loc1.rev = start_rev;
- real_source->loc2.url = source->loc2.url;
- real_source->loc2.rev = end_rev;
+ svn_boolean_t is_rollback = (source->loc1->rev > source->loc2->rev);
+ svn_boolean_t same_urls = (strcmp(source->loc1->url, source->loc2->url) == 0);
+ repo_location_t loc1 = *source->loc1;
+ repo_location_t loc2 = *source->loc2;
+
+ loc1.rev = start_rev;
+ loc2.rev = end_rev;
if (! same_urls)
{
- if (is_rollback && (end_rev != source->loc2.rev))
+ if (is_rollback && (end_rev != source->loc2->rev))
{
- real_source->loc2.url = source->loc1.url;
+ loc2.url = source->loc1->url;
}
- if ((! is_rollback) && (start_rev != source->loc1.rev))
+ if ((! is_rollback) && (start_rev != source->loc1->rev))
{
- real_source->loc1.url = source->loc2.url;
+ loc1.url = source->loc2->url;
}
}
- return real_source;
+ return merge_source_create(&loc1, &loc2, pool);
}
/* The single-file, simplified version of do_directory_merge(), which see for
@@ -6698,8 +6796,8 @@ do_file_merge(svn_mergeinfo_catalog_t re
svn_mergeinfo_t target_mergeinfo;
svn_merge_range_t *conflicted_range = NULL;
svn_boolean_t inherited = FALSE;
- svn_boolean_t is_rollback = (source->loc1.rev > source->loc2.rev);
- const char *primary_url = is_rollback ? source->loc1.url : source->loc2.url;
+ svn_boolean_t is_rollback = (source->loc1->rev > source->loc2->rev);
+ const char *primary_url = is_rollback ? source->loc1->url : source->loc2->url;
svn_boolean_t honor_mergeinfo = HONOR_MERGEINFO(merge_b);
svn_client__merge_path_t *merge_target = NULL;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@@ -6709,8 +6807,8 @@ do_file_merge(svn_mergeinfo_catalog_t re
/* Note that this is a single-file merge. */
notify_b->is_single_file_merge = TRUE;
- range.start = source->loc1.rev;
- range.end = source->loc2.rev;
+ range.start = source->loc1->rev;
+ range.end = source->loc2->rev;
range.inheritable = TRUE;
if (honor_mergeinfo)
{
@@ -6723,8 +6821,8 @@ do_file_merge(svn_mergeinfo_catalog_t re
&(merge_target->implicit_mergeinfo),
&inherited, svn_mergeinfo_inherited,
merge_b->ra_session1, target_abspath,
- MAX(source->loc1.rev, source->loc2.rev),
- MIN(source->loc1.rev, source->loc2.rev),
+ MAX(source->loc1->rev, source->loc2->rev),
+ MIN(source->loc1->rev, source->loc2->rev),
ctx, scratch_pool, iterpool);
if (err)
@@ -6745,6 +6843,9 @@ do_file_merge(svn_mergeinfo_catalog_t re
by SOURCE->rev1:rev2. */
if (!merge_b->record_only)
{
+ /* ### Bug? calculate_remaining_ranges() needs 'source' to adhere
+ * to the requirements of 'MERGEINFO MERGE SOURCE NORMALIZATION'
+ * here, but it doesn't appear to be guaranteed so. */
SVN_ERR(calculate_remaining_ranges(NULL, merge_target,
source,
target_mergeinfo,
@@ -6808,13 +6909,13 @@ do_file_merge(svn_mergeinfo_catalog_t re
real_source = subrange_source(source, r->start, r->end, iterpool);
SVN_ERR(single_file_merge_get_file(&tmpfile1, &props1,
merge_b->ra_session1,
- real_source->loc1.url,
- real_source->loc1.rev,
+ real_source->loc1->url,
+ real_source->loc1->rev,
target_abspath, iterpool));
SVN_ERR(single_file_merge_get_file(&tmpfile2, &props2,
merge_b->ra_session2,
- real_source->loc2.url,
- real_source->loc2.rev,
+ real_source->loc2->url,
+ real_source->loc2->rev,
target_abspath, iterpool));
/* Discover any svn:mime-type values in the proplists */
@@ -7163,8 +7264,8 @@ do_mergeinfo_unaware_dir_merge(const mer
svn_client__merge_path_t *item
= svn_client__merge_path_create(target_dir_wcpath, pool);
- item->remaining_ranges = svn_rangelist__initialize(source->loc1.rev,
- source->loc2.rev,
+ item->remaining_ranges = svn_rangelist__initialize(source->loc1->rev,
+ source->loc2->rev,
TRUE, pool);
APR_ARRAY_PUSH(notify_b->children_with_mergeinfo,
svn_client__merge_path_t *) = item;
@@ -7640,7 +7741,7 @@ record_mergeinfo_for_dir_merge(svn_merge
svn_merge_range_t range = *merged_range;
- /* Regardless of what subtrees in MERGE_B->TARGET_ABSPATH might be missing
+ /* Regardless of what subtrees in MERGE_B->target->abspath might be missing
could this merge have been operative? */
operative_merge = subtree_touched_by_merge(merge_b->target->abspath,
notify_b, iterpool);
@@ -7651,7 +7752,7 @@ record_mergeinfo_for_dir_merge(svn_merge
if (!operative_merge)
range.inheritable = TRUE;
- /* Remove absent children at or under TARGET_WCPATH from
+ /* Remove absent children at or under MERGE_B->target->abspath from
NOTIFY_B->CHILDREN_WITH_MERGEINFO
before we calculate the merges performed. */
remove_absent_children(merge_b->target->abspath,
@@ -7775,7 +7876,7 @@ record_mergeinfo_for_dir_merge(svn_merge
svn_mergeinfo_t subtree_history_as_mergeinfo;
apr_array_header_t *child_merge_src_rangelist;
const char *subtree_mergeinfo_url =
- svn_path_url_add_component2(merge_b->target->loc.repo->url,
+ svn_path_url_add_component2(merge_b->target->loc.repos_root_url,
child_merge_src_fspath + 1,
iterpool);
@@ -7950,7 +8051,7 @@ record_mergeinfo_for_added_subtrees(
iterpool);
/* Create the new mergeinfo path for added_path's mergeinfo.
- (added_abspath had better be a child of target_abspath
+ (added_abspath had better be a child of MERGE_B->target->abspath
or something is *really* wrong.) */
rel_added_path = svn_dirent_is_child(merge_b->target->abspath,
added_abspath, iterpool);
@@ -7974,7 +8075,7 @@ record_mergeinfo_for_added_subtrees(
take the intersection of the naive mergeinfo with
MERGEINFO_PATH/rel_added_path's history. */
added_path_mergeinfo_url =
- svn_path_url_add_component2(merge_b->target->loc.repo->url,
+ svn_path_url_add_component2(merge_b->target->loc.repos_root_url,
added_path_mergeinfo_fspath + 1,
iterpool);
SVN_ERR(svn_client__get_history_as_mergeinfo(
@@ -8014,7 +8115,7 @@ typedef struct log_noop_baton_t
of this file.*/
apr_array_header_t *children_with_mergeinfo;
- /* Absolute repository path of MERGE_B->TARGET_ABSPATH. */
+ /* Absolute repository path of MERGE_B->target->abspath. */
const char *target_fspath;
/* Absolute repository path of younger of the two merge sources
@@ -8075,7 +8176,7 @@ rangelist_merge_revision(apr_array_heade
Add LOG_ENTRY->REVISION to BATON->OPERATIVE_RANGES.
If LOG_ENTRY->REVISION has already been fully merged to
- MERGE_B->TARGET_ABSPATH per the mergeinfo in CHILDREN_WITH_MERGEINFO,
+ MERGE_B->target->abspath per the mergeinfo in CHILDREN_WITH_MERGEINFO,
then add LOG_ENTRY->REVISION to BATON->MERGED_RANGES.
Use SCRATCH_POOL for temporary allocations. Allocate additions to
@@ -8108,7 +8209,7 @@ log_noop_revs(void *baton,
/* Examine each path affected by LOG_ENTRY->REVISION. If the explicit or
inherited mergeinfo for *all* of the corresponding paths under
- MERGE_B->TARGET_ABSPATH reflects that LOG_ENTRY->REVISION has been
+ MERGE_B->target->abspath reflects that LOG_ENTRY->REVISION has been
merged, then add LOG_ENTRY->REVISION to BATON->MERGED_RANGES. */
for (hi = apr_hash_first(scratch_pool, log_entry->changed_paths2);
hi;
@@ -8204,7 +8305,7 @@ log_noop_revs(void *baton,
Find all the ranges required by subtrees in
CHILDREN_WITH_MERGEINFO that are *not* required by
- MERGE_B->TARGET_ABSPATH (i.e. CHILDREN_WITH_MERGEINFO[0]). If such
+ MERGE_B->target->abspath (i.e. CHILDREN_WITH_MERGEINFO[0]). If such
ranges exist, then find any subset of ranges which, if merged, would be
inoperative. Finally, if any inoperative ranges are found then remove
these ranges from all of the subtree's REMAINING_RANGES.
@@ -8236,7 +8337,7 @@ remove_noop_subtree_ranges(const merge_s
/* This function is only intended to work with forward merges. */
- if (source->loc1.rev > source->loc2.rev)
+ if (source->loc1->rev > source->loc2->rev)
return SVN_NO_ERROR;
/* Another easy out: There are no subtrees. */
@@ -8249,10 +8350,10 @@ remove_noop_subtree_ranges(const merge_s
/* Given the requested merge of SOURCE->rev1:rev2 might there be any
part of this range required for subtrees but not for the target? */
- requested_ranges = svn_rangelist__initialize(MIN(source->loc1.rev,
- source->loc2.rev),
- MAX(source->loc1.rev,
- source->loc2.rev),
+ requested_ranges = svn_rangelist__initialize(MIN(source->loc1->rev,
+ source->loc2->rev),
+ MAX(source->loc1->rev,
+ source->loc2->rev),
TRUE, scratch_pool);
SVN_ERR(svn_rangelist_remove(&subtree_gap_ranges,
root_child->remaining_ranges,
@@ -8306,12 +8407,12 @@ remove_noop_subtree_ranges(const merge_s
SVN_ERR(svn_client__path_relative_to_root(
&(log_gap_baton.target_fspath), merge_b->ctx->wc_ctx,
merge_b->target->abspath,
- merge_b->target->loc.repo->url, TRUE, NULL,
+ merge_b->target->loc.repos_root_url, TRUE, NULL,
result_pool, scratch_pool));
SVN_ERR(svn_client__path_relative_to_root(
&(log_gap_baton.source_fspath), merge_b->ctx->wc_ctx,
- source->loc2.url,
- merge_b->target->loc.repo->url, TRUE, NULL,
+ source->loc2->url,
+ merge_b->target->loc.repos_root_url, TRUE, NULL,
result_pool, scratch_pool));
log_gap_baton.merged_ranges = apr_array_make(scratch_pool, 0,
sizeof(svn_revnum_t *));
@@ -8428,8 +8529,8 @@ do_directory_merge(svn_mergeinfo_catalog
svn_ra_session_t *ra_session;
svn_client__merge_path_t *target_merge_path;
- svn_boolean_t is_rollback = (source->loc1.rev > source->loc2.rev);
- const char *primary_url = is_rollback ? source->loc1.url : source->loc2.url;
+ svn_boolean_t is_rollback = (source->loc1->rev > source->loc2->rev);
+ const char *primary_url = is_rollback ? source->loc1->url : source->loc2->url;
svn_boolean_t honor_mergeinfo = HONOR_MERGEINFO(merge_b);
/* Note that this is not a single-file merge. */
@@ -8479,8 +8580,8 @@ do_directory_merge(svn_mergeinfo_catalog
/* Always start with a range which describes the most inclusive merge
possible, i.e. SOURCE->rev1:rev2. */
- range.start = source->loc1.rev;
- range.end = source->loc2.rev;
+ range.start = source->loc1->rev;
+ range.end = source->loc2->rev;
range.inheritable = TRUE;
if (honor_mergeinfo && !merge_b->reintegrate_merge)
@@ -8926,14 +9027,14 @@ do_merge(apr_hash_t **modified_subtrees,
/* Sanity check: if our left- and right-side merge sources are
the same, there's nothing to here. */
- if ((strcmp(source->loc1.url, source->loc2.url) == 0)
- && (source->loc1.rev == source->loc2.rev))
+ if ((strcmp(source->loc1->url, source->loc2->url) == 0)
+ && (source->loc1->rev == source->loc2->rev))
continue;
/* Establish RA sessions to our URLs, reuse where possible. */
- SVN_ERR(ensure_ra_session_url(&ra_session1, source->loc1.url,
+ SVN_ERR(ensure_ra_session_url(&ra_session1, source->loc1->url,
ctx, scratch_pool));
- SVN_ERR(ensure_ra_session_url(&ra_session2, source->loc2.url,
+ SVN_ERR(ensure_ra_session_url(&ra_session2, source->loc2->url,
ctx, scratch_pool));
/* Populate the portions of the merge context baton that need to
@@ -9070,14 +9171,14 @@ merge_cousins_and_supplement_mergeinfo(c
SVN_ERR_ASSERT(svn_dirent_is_absolute(target->abspath));
SVN_ERR(normalize_merge_sources_internal(
- &remove_sources, source->loc1.url, source->loc1.rev,
- svn_rangelist__initialize(source->loc1.rev, yc_rev, TRUE,
+ &remove_sources, source->loc1,
+ svn_rangelist__initialize(source->loc1->rev, yc_rev, TRUE,
scratch_pool),
URL1_ra_session, ctx, scratch_pool, subpool));
SVN_ERR(normalize_merge_sources_internal(
- &add_sources, source->loc2.url, source->loc2.rev,
- svn_rangelist__initialize(yc_rev, source->loc2.rev, TRUE,
+ &add_sources, source->loc2,
+ svn_rangelist__initialize(yc_rev, source->loc2->rev, TRUE,
scratch_pool),
URL2_ra_session, ctx, scratch_pool, subpool));
@@ -9294,9 +9395,8 @@ open_target_wc(merge_target_t **target_p
SVN_ERR(svn_wc_read_kind(&target->kind, ctx->wc_ctx, wc_abspath, FALSE,
scratch_pool));
- target->loc.repo = apr_palloc(result_pool, sizeof(*target->loc.repo));
- SVN_ERR(svn_client__wc_node_get_origin(&target->loc.repo->url,
- &target->loc.repo->uuid,
+ SVN_ERR(svn_client__wc_node_get_origin(&target->loc.repos_root_url,
+ &target->loc.repos_uuid,
&target->loc.rev, &target->loc.url,
wc_abspath, ctx,
result_pool, scratch_pool));
@@ -9329,10 +9429,9 @@ open_source_session(repo_location_t **lo
&ra_session, &location->rev, &location->url,
path_or_url, NULL, peg_revision, peg_revision,
ctx, result_pool));
- location->repo = apr_palloc(result_pool, sizeof(*location->repo));
- SVN_ERR(svn_ra_get_repos_root2(ra_session, &location->repo->url,
+ SVN_ERR(svn_ra_get_repos_root2(ra_session, &location->repos_root_url,
result_pool));
- SVN_ERR(svn_ra_get_uuid2(ra_session, &location->repo->uuid, result_pool));
+ SVN_ERR(svn_ra_get_uuid2(ra_session, &location->repos_uuid, result_pool));
*location_p = location;
*ra_session_p = ra_session;
@@ -9363,14 +9462,12 @@ merge_locked(const char *source1,
{
merge_target_t *target;
repo_location_t *source1_loc, *source2_loc;
- merge_source_t source;
svn_boolean_t related = FALSE, ancestral = FALSE;
svn_ra_session_t *ra_session1, *ra_session2;
apr_array_header_t *merge_sources;
svn_error_t *err;
svn_boolean_t use_sleep = FALSE;
- const char *yc_url = NULL;
- svn_revnum_t yc_rev = SVN_INVALID_REVNUM;
+ repo_location_t *yca = NULL;
apr_pool_t *sesspool;
svn_boolean_t same_repos;
@@ -9388,32 +9485,25 @@ merge_locked(const char *source1,
sesspool = svn_pool_create(scratch_pool);
SVN_ERR(open_source_session(&source1_loc, &ra_session1, source1, revision1,
ctx, sesspool, scratch_pool));
- source.loc1 = *source1_loc;
SVN_ERR(open_source_session(&source2_loc, &ra_session2, source2, revision2,
ctx, sesspool, scratch_pool));
- source.loc2 = *source2_loc;
/* We can't do a diff between different repositories. */
/* ### We should also insist that the root URLs of the two sources match,
* as we are only carrying around a single source-repos-root from now
* on, and URL calculations will go wrong if they differ.
* Alternatively, teach the code to cope with differing root URLs. */
- SVN_ERR(check_same_repos(source1_loc->repo, source.loc1.url,
- source2_loc->repo, source.loc2.url,
+ SVN_ERR(check_same_repos(source1_loc, source1_loc->url,
+ source2_loc, source2_loc->url,
FALSE /* strict_urls */, scratch_pool));
/* Do our working copy and sources come from the same repository? */
- same_repos = is_same_repos(target->loc.repo, source1_loc->repo,
- TRUE /* strict_urls */);
+ same_repos = is_same_repos(&target->loc, source1_loc, TRUE /* strict_urls */);
/* Unless we're ignoring ancestry, see if the two sources are related. */
if (! ignore_ancestry)
- SVN_ERR(svn_client__get_youngest_common_ancestor(NULL, &yc_url, &yc_rev,
- source.loc1.url,
- source.loc1.rev,
- source.loc2.url,
- source.loc2.rev,
- ctx, scratch_pool));
+ SVN_ERR(get_youngest_common_ancestor(&yca, source1_loc, source2_loc,
+ ctx, scratch_pool, scratch_pool));
/* Check for a youngest common ancestor. If we have one, we'll be
doing merge tracking.
@@ -9432,32 +9522,32 @@ merge_locked(const char *source1,
merge recording, then record-only two merges:
from A to C, and from C to B
*/
- if (yc_url && SVN_IS_VALID_REVNUM(yc_rev))
+ if (yca)
{
/* Note that our merge sources are related. */
related = TRUE;
/* If the common ancestor matches the right side of our merge,
then we only need to reverse-merge the left side. */
- if ((strcmp(yc_url, source.loc2.url) == 0)
- && (yc_rev == source.loc2.rev))
+ if ((strcmp(yca->url, source2_loc->url) == 0)
+ && (yca->rev == source2_loc->rev))
{
ancestral = TRUE;
SVN_ERR(normalize_merge_sources_internal(
- &merge_sources, source.loc1.url, source.loc1.rev,
- svn_rangelist__initialize(source.loc1.rev, yc_rev, TRUE,
+ &merge_sources, source1_loc,
+ svn_rangelist__initialize(source1_loc->rev, yca->rev, TRUE,
scratch_pool),
ra_session1, ctx, scratch_pool, scratch_pool));
}
/* If the common ancestor matches the left side of our merge,
then we only need to merge the right side. */
- else if ((strcmp(yc_url, source.loc1.url) == 0)
- && (yc_rev == source.loc1.rev))
+ else if ((strcmp(yca->url, source1_loc->url) == 0)
+ && (yca->rev == source1_loc->rev))
{
ancestral = TRUE;
SVN_ERR(normalize_merge_sources_internal(
- &merge_sources, source.loc2.url, source.loc2.rev,
- svn_rangelist__initialize(yc_rev, source.loc2.rev, TRUE,
+ &merge_sources, source2_loc,
+ svn_rangelist__initialize(yca->rev, source2_loc->rev, TRUE,
scratch_pool),
ra_session2, ctx, scratch_pool, scratch_pool));
}
@@ -9465,11 +9555,13 @@ merge_locked(const char *source1,
side, and merge the right. */
else
{
+ merge_source_t source = { source1_loc, source2_loc };
+
err = merge_cousins_and_supplement_mergeinfo(target,
ra_session1,
ra_session2,
&source,
- yc_rev,
+ yca->rev,
same_repos,
depth,
ignore_ancestry, force,
@@ -9495,6 +9587,8 @@ merge_locked(const char *source1,
}
else
{
+ merge_source_t source = { source1_loc, source2_loc };
+
/* Build a single-item merge_source_t array. */
merge_sources = apr_array_make(scratch_pool, 1, sizeof(merge_source_t *));
APR_ARRAY_PUSH(merge_sources, merge_source_t *) = &source;
@@ -9793,24 +9887,24 @@ log_find_operative_revs(void *baton,
return SVN_NO_ERROR;
}
-/* Determine if the mergeinfo on a reintegrate source SOURCE_REPOS_REL_PATH,
+/* Determine if the mergeinfo on a reintegrate source SOURCE_LOC,
reflects that the source is fully synced with the reintegrate target
- TARGET_REPOS_REL_PATH, even if a naive interpretation of the source's
+ TARGET_LOC, even if a naive interpretation of the source's
mergeinfo says otherwise -- See issue #3577.
UNMERGED_CATALOG represents the history (as mergeinfo) from
- TARGET_REPOS_REL_PATH that is not represented in SOURCE_REPOS_REL_PATH's
+ TARGET_LOC that is not represented in SOURCE_LOC's
explicit/inherited mergeinfo as represented by MERGED_CATALOG.
MERGEINFO_CATALOG may be empty if the source has no explicit or inherited
mergeinfo.
- Using RA_SESSION, which is pointed at TARGET_REPOS_REL_PATH, check that all
+ Using RA_SESSION, which is pointed at TARGET_LOC, check that all
of the unmerged revisions in UNMERGED_CATALOG's mergeinfos are "phantoms",
that is, one of the following conditions holds:
- 1) The revision affects no corresponding paths in SOURCE_REPOS_REL_PATH.
+ 1) The revision affects no corresponding paths in SOURCE_LOC.
- 2) The revision affects corresponding paths in SOURCE_REPOS_REL_PATH,
+ 2) The revision affects corresponding paths in SOURCE_LOC,
but based on the mergeinfo in MERGED_CATALOG, the change was
previously merged.
@@ -9822,8 +9916,8 @@ log_find_operative_revs(void *baton,
Use SCRATCH_POOL for all temporary allocations. */
static svn_error_t *
-find_unsynced_ranges(const char *source_repos_rel_path,
- const char *target_repos_rel_path,
+find_unsynced_ranges(const repo_location_t *source_loc,
+ const repo_location_t *target_loc,
svn_mergeinfo_catalog_t unmerged_catalog,
svn_mergeinfo_catalog_t merged_catalog,
svn_mergeinfo_catalog_t true_unmerged_catalog,
@@ -9857,6 +9951,12 @@ find_unsynced_ranges(const char *source_
are not yet merged to it. */
if (potentially_unmerged_ranges)
{
+ const char *source_repos_rel_path
+ = svn_uri_skip_ancestor(source_loc->repos_root_url, source_loc->url,
+ scratch_pool);
+ const char *target_repos_rel_path
+ = svn_uri_skip_ancestor(target_loc->repos_root_url, target_loc->url,
+ scratch_pool);
svn_revnum_t oldest_rev =
(APR_ARRAY_IDX(potentially_unmerged_ranges,
0,
@@ -9931,6 +10031,10 @@ find_youngest_merged_rev(svn_revnum_t *y
* branch SOURCE_URL@SOURCE_REV. Extend SOURCE_MERGEINFO, modifying it in
* place, to include the natural history (implicit mergeinfo) of
* SOURCE_URL@SOURCE_REV. ### But make these additions in SCRATCH_POOL.
+ *
+ * ### [JAF] This function is named '..._subroutine' simply because I
+ * factored it out based on code similarity, without knowing what it's
+ * purpose is. We should clarify its purpose and choose a better name.
*/
static svn_error_t *
find_unmerged_mergeinfo_subroutine(svn_mergeinfo_t *filtered_mergeinfo_p,
@@ -10232,7 +10336,7 @@ find_unmerged_mergeinfo(svn_mergeinfo_ca
/* Helper for svn_client_merge_reintegrate() which calculates the
'left hand side' of the underlying two-URL merge that a --reintegrate
merge actually performs. If no merge should be performed, set
- *URL_LEFT to NULL and *REV_LEFT to SVN_INVALID_REVNUM.
+ *LEFT_P to NULL.
TARGET->abspath is the absolute working copy path of the reintegrate
merge.
@@ -10255,12 +10359,11 @@ find_unmerged_mergeinfo(svn_mergeinfo_ca
SOURCE_RA_SESSION is a session opened to the SOURCE_LOC
and TARGET_RA_SESSION is open to TARGET->loc.url.
- *URL_LEFT, *MERGED_TO_SOURCE_CATALOG , and *UNMERGED_TO_SOURCE_CATALOG are
+ *LEFT_P, *MERGED_TO_SOURCE_CATALOG , and *UNMERGED_TO_SOURCE_CATALOG are
allocated in RESULT_POOL. SCRATCH_POOL is used for all temporary
allocations. */
static svn_error_t *
-calculate_left_hand_side(const char **url_left,
- svn_revnum_t *rev_left,
+calculate_left_hand_side(repo_location_t **left_p,
svn_mergeinfo_t *merged_to_source_catalog,
svn_mergeinfo_t *unmerged_to_source_catalog,
const merge_target_t *target,
@@ -10280,24 +10383,22 @@ calculate_left_hand_side(const char **ur
/* hash of paths mapped to arrays of svn_mergeinfo_t. */
apr_hash_t *target_history_hash = apr_hash_make(scratch_pool);
svn_revnum_t youngest_merged_rev;
- const char *yc_ancestor_url;
- svn_revnum_t yc_ancestor_rev;
+ repo_location_t *yc_ancestor;
const char *source_repos_rel_path;
/* Initialize our return variables. */
- *url_left = NULL;
- *rev_left = SVN_INVALID_REVNUM;
+ *left_p = NULL;
- /* TARGET_ABSPATH may not have explicit mergeinfo and thus may not be
+ /* TARGET->abspath may not have explicit mergeinfo and thus may not be
contained within SUBTREES_WITH_MERGEINFO. If this is the case then
- add a dummy item for TARGET_ABSPATH so we get its history (i.e. implicit
+ add a dummy item for TARGET->abspath so we get its history (i.e. implicit
mergeinfo) below. */
if (!apr_hash_get(subtrees_with_mergeinfo, target->abspath,
APR_HASH_KEY_STRING))
apr_hash_set(subtrees_with_mergeinfo, target->abspath,
APR_HASH_KEY_STRING, apr_hash_make(result_pool));
- /* Get the history segments (as mergeinfo) for TARGET_ABSPATH and any of
+ /* Get the history segments (as mergeinfo) for TARGET->abspath and any of
its subtrees with explicit mergeinfo. */
for (hi = apr_hash_first(scratch_pool, subtrees_with_mergeinfo);
hi;
@@ -10317,7 +10418,7 @@ calculate_left_hand_side(const char **ur
NULL, FALSE,
NULL, scratch_pool,
iterpool));
- url = svn_path_url_add_component2(target->loc.repo->url,
+ url = svn_path_url_add_component2(target->loc.repos_root_url,
path_rel_to_root, iterpool);
SVN_ERR(svn_client__get_history_as_mergeinfo(&target_history_as_mergeinfo,
NULL /* has_rev_zero_hist */,
@@ -10332,15 +10433,12 @@ calculate_left_hand_side(const char **ur
APR_HASH_KEY_STRING, target_history_as_mergeinfo);
}
- /* Check that SOURCE_URL@SOURCE_REV and TARGET_URL@TARGET_REV are
+ /* Check that SOURCE_LOC and TARGET->loc are
actually related, we can't reintegrate if they are not. Also
- get an initial value for YC_ANCESTOR_REV. */
- SVN_ERR(svn_client__get_youngest_common_ancestor(NULL, &yc_ancestor_url,
- &yc_ancestor_rev,
- source_loc->url, source_loc->rev,
- target->loc.url, target->loc.rev,
- ctx, iterpool));
- if (!(yc_ancestor_url && SVN_IS_VALID_REVNUM(yc_ancestor_rev)))
+ get an initial value for the YCA revision number. */
+ SVN_ERR(get_youngest_common_ancestor(&yc_ancestor, source_loc, &target->loc,
+ ctx, iterpool, iterpool));
+ if (! yc_ancestor)
return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
_("'%s@%ld' must be ancestrally related to "
"'%s@%ld'"), source_loc->url, source_loc->rev,
@@ -10349,7 +10447,7 @@ calculate_left_hand_side(const char **ur
/* If the source revision is the same as the youngest common
revision, then there can't possibly be any unmerged revisions
that we need to apply to target. */
- if (source_loc->rev == yc_ancestor_rev)
+ if (source_loc->rev == yc_ancestor->rev)
{
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
@@ -10363,7 +10461,7 @@ calculate_left_hand_side(const char **ur
svn_mergeinfo_inherited,
TRUE, iterpool));
- source_repos_rel_path = svn_uri_skip_ancestor(source_loc->repo->url,
+ source_repos_rel_path = svn_uri_skip_ancestor(source_loc->repos_root_url,
source_loc->url, scratch_pool);
if (mergeinfo_catalog)
SVN_ERR(svn_mergeinfo__add_prefix_to_catalog(&mergeinfo_catalog,
@@ -10382,7 +10480,7 @@ calculate_left_hand_side(const char **ur
TARGET_REPOS_REL_PATH@TARGET_REV to SOURCE_REPOS_REL_PATH@SOURCE_REV. */
SVN_ERR(find_unmerged_mergeinfo(&unmerged_catalog,
&youngest_merged_rev,
- yc_ancestor_rev,
+ yc_ancestor->rev,
mergeinfo_catalog,
target_history_hash,
source_repos_rel_path,
@@ -10402,19 +10500,16 @@ calculate_left_hand_side(const char **ur
if (youngest_merged_rev == SVN_INVALID_REVNUM)
{
/* We never merged to the source. Just return the branch point. */
- *url_left = apr_pstrdup(result_pool, yc_ancestor_url);
- *rev_left = yc_ancestor_rev;
+ *left_p = repo_location_dup(yc_ancestor, result_pool);
}
else
{
/* We've previously merged some or all of the target, up to
- youngest_merged_rev, from TARGET_ABSPATH to the source. Set
- *URL_LEFT and *REV_LEFT to cover the youngest part of this range. */
- *rev_left = youngest_merged_rev;
- SVN_ERR(svn_client__repos_location(url_left, target_ra_session,
- target->loc.url, target->loc.rev,
- youngest_merged_rev,
- ctx, result_pool, iterpool));
+ youngest_merged_rev, to the source. Set
+ *LEFT_P to cover the youngest part of this range. */
+ SVN_ERR(repos_location(left_p, target_ra_session,
+ &target->loc, youngest_merged_rev,
+ ctx, result_pool, iterpool));
}
svn_pool_destroy(iterpool);
@@ -10430,14 +10525,14 @@ calculate_left_hand_side(const char **ur
*
* Set *SOURCE_P to
* the source-left and source-right locations of the required merge. Set
- * *YC_ANCESTOR_REV_P to the revision number of the youngest ancestor.
+ * *YC_ANCESTOR_P to the location of the youngest ancestor.
* Any of these output pointers may be NULL if not wanted.
*
* See svn_client_find_reintegrate_merge() for other details.
*/
static svn_error_t *
find_reintegrate_merge(merge_source_t **source_p,
- svn_revnum_t *yc_ancestor_rev_p,
+ repo_location_t **yc_ancestor_p,
svn_ra_session_t *source_ra_session,
const repo_location_t *source_loc,
svn_ra_session_t *target_ra_session,
@@ -10446,8 +10541,8 @@ find_reintegrate_merge(merge_source_t **
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- const char *yc_ancestor_relpath;
- svn_revnum_t yc_ancestor_rev;
+ repo_location_t *yc_ancestor;
+ repo_location_t *loc1;
merge_source_t source;
svn_mergeinfo_t unmerged_to_source_mergeinfo_catalog;
svn_mergeinfo_t merged_to_source_mergeinfo_catalog;
@@ -10461,8 +10556,8 @@ find_reintegrate_merge(merge_source_t **
/* ### Bogus/obsolete comment? */
/* Can't reintegrate to or from the root of the repository. */
- if (strcmp(source_loc->url, source_loc->repo->url) == 0
- || strcmp(target->loc.url, target->loc.repo->url) == 0)
+ if (strcmp(source_loc->url, source_loc->repos_root_url) == 0
+ || strcmp(target->loc.url, target->loc.repos_root_url) == 0)
return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
_("Neither the reintegrate source nor target "
"can be the root of the repository"));
@@ -10477,7 +10572,7 @@ find_reintegrate_merge(merge_source_t **
err = svn_error_quick_wrap(err, _("Reintegrate merge not possible"));
SVN_ERR(err);
- SVN_ERR(calculate_left_hand_side(&source.loc1.url, &source.loc1.rev,
+ SVN_ERR(calculate_left_hand_side(&loc1,
&merged_to_source_mergeinfo_catalog,
&unmerged_to_source_mergeinfo_catalog,
target,
@@ -10486,54 +10581,46 @@ find_reintegrate_merge(merge_source_t **
source_ra_session,
target_ra_session,
ctx,
- result_pool, scratch_pool));
+ scratch_pool, scratch_pool));
/* Did calculate_left_hand_side() decide that there was no merge to
be performed here? */
- if (! source.loc1.url)
+ if (! loc1)
{
if (source_p)
*source_p = NULL;
- if (yc_ancestor_rev_p)
- *yc_ancestor_rev_p = SVN_INVALID_REVNUM;
+ if (yc_ancestor_p)
+ *yc_ancestor_p = NULL;
return SVN_NO_ERROR;
}
- source.loc2 = *source_loc;
+ source.loc1 = loc1;
+ source.loc2 = source_loc;
/* If the target was moved after the source was branched from it,
it is possible that the left URL differs from the target's current
URL. If so, then adjust TARGET_RA_SESSION to point to the old URL. */
- if (strcmp(source.loc1.url, target->loc.url))
- SVN_ERR(svn_ra_reparent(target_ra_session, source.loc1.url, scratch_pool));
+ if (strcmp(source.loc1->url, target->loc.url))
+ SVN_ERR(svn_ra_reparent(target_ra_session, source.loc1->url, scratch_pool));
- SVN_ERR(svn_client__get_youngest_common_ancestor(&yc_ancestor_relpath, NULL,
- &yc_ancestor_rev,
- source.loc2.url,
- source.loc2.rev,
- source.loc1.url,
- source.loc1.rev,
- ctx, scratch_pool));
+ SVN_ERR(get_youngest_common_ancestor(&yc_ancestor, source.loc2, source.loc1,
+ ctx, scratch_pool, scratch_pool));
- if (!(yc_ancestor_relpath && SVN_IS_VALID_REVNUM(yc_ancestor_rev)))
+ if (! yc_ancestor)
return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
_("'%s@%ld' must be ancestrally related to "
"'%s@%ld'"),
- source.loc1.url, source.loc1.rev,
- source.loc2.url, source.loc2.rev);
+ source.loc1->url, source.loc1->rev,
+ source.loc2->url, source.loc2->rev);
- if (source.loc1.rev > yc_ancestor_rev)
+ if (source.loc1->rev > yc_ancestor->rev)
{
/* Have we actually merged anything to the source from the
target? If so, make sure we've merged a contiguous
prefix. */
svn_mergeinfo_t final_unmerged_catalog = apr_hash_make(scratch_pool);
- const char *source_repos_rel_path
- = svn_uri_skip_ancestor(source_loc->repo->url, source_loc->url,
- scratch_pool);
- SVN_ERR(find_unsynced_ranges(source_repos_rel_path,
- yc_ancestor_relpath,
+ SVN_ERR(find_unsynced_ranges(source_loc, yc_ancestor,
unmerged_to_source_mergeinfo_catalog,
merged_to_source_mergeinfo_catalog,
final_unmerged_catalog,
@@ -10555,7 +10642,7 @@ find_reintegrate_merge(merge_source_t **
"previously merged from %s to the "
"reintegrate source, but this is "
"not the case:\n%s"),
- yc_ancestor_rev + 1, source.loc2.rev,
+ yc_ancestor->rev + 1, source.loc2->rev,
target->loc.url,
source_mergeinfo_cat_string->data);
}
@@ -10564,9 +10651,10 @@ find_reintegrate_merge(merge_source_t **
/* Left side: trunk@youngest-trunk-rev-merged-to-branch-at-specified-peg-rev
* Right side: branch@specified-peg-revision */
if (source_p)
- *source_p = apr_pmemdup(result_pool, &source, sizeof(source));
- if (yc_ancestor_rev_p)
- *yc_ancestor_rev_p = yc_ancestor_rev;
+ *source_p = merge_source_dup(&source, result_pool);
+
+ if (yc_ancestor_p)
+ *yc_ancestor_p = repo_location_dup(yc_ancestor, result_pool);
return SVN_NO_ERROR;
}
@@ -10622,12 +10710,12 @@ open_reintegrate_source_and_target(svn_r
source_path_or_url, source_peg_revision,
ctx, result_pool, scratch_pool));
- /* source_loc->repo and target->loc.repo are required to be the same,
+ /* source_loc and target->loc are required to be in the same repository,
as mergeinfo doesn't come into play for cross-repository merging. */
- SVN_ERR(check_same_repos(source_loc->repo,
+ SVN_ERR(check_same_repos(source_loc,
svn_dirent_local_style(source_path_or_url,
scratch_pool),
- target->loc.repo,
+ &target->loc,
svn_dirent_local_style(target->abspath,
scratch_pool),
TRUE /* strict_urls */, scratch_pool));
@@ -10670,10 +10758,10 @@ svn_client_find_reintegrate_merge(const
ctx, result_pool, scratch_pool));
if (source)
{
- *url1_p = source->loc1.url;
- *rev1_p = source->loc1.rev;
- *url2_p = source->loc2.url;
- *rev2_p = source->loc2.rev;
+ *url1_p = source->loc1->url;
+ *rev1_p = source->loc1->rev;
+ *url2_p = source->loc2->url;
+ *rev2_p = source->loc2->rev;
}
else
{
@@ -10699,7 +10787,7 @@ merge_reintegrate_locked(const char *sou
merge_target_t *target;
repo_location_t *source_loc;
merge_source_t *source;
- svn_revnum_t yc_ancestor_rev;
+ repo_location_t *yc_ancestor;
svn_boolean_t use_sleep;
svn_error_t *err;
@@ -10708,7 +10796,7 @@ merge_reintegrate_locked(const char *sou
source_path_or_url, source_peg_revision, target_abspath,
ctx, scratch_pool, scratch_pool));
- SVN_ERR(find_reintegrate_merge(&source, &yc_ancestor_rev,
+ SVN_ERR(find_reintegrate_merge(&source, &yc_ancestor,
source_ra_session, source_loc,
target_ra_session, target,
ctx, scratch_pool, scratch_pool));
@@ -10726,7 +10814,7 @@ merge_reintegrate_locked(const char *sou
err = merge_cousins_and_supplement_mergeinfo(target,
target_ra_session,
source_ra_session,
- source, yc_ancestor_rev,
+ source, yc_ancestor->rev,
TRUE /* same_repos */,
svn_depth_infinity,
FALSE /* ignore_ancestry */,
@@ -10812,13 +10900,12 @@ merge_peg_locked(const char *source_path
/* Normalize our merge sources. */
SVN_ERR(normalize_merge_sources(&merge_sources, source_path_or_url,
[... 171 lines stripped ...]