You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2012/03/20 11:12:54 UTC
svn commit: r1302816 - /subversion/trunk/subversion/libsvn_client/merge.c
Author: julianfoad
Date: Tue Mar 20 09:54:45 2012
New Revision: 1302816
URL: http://svn.apache.org/viewvc?rev=1302816&view=rev
Log:
Factor out some merge code.
* subversion/libsvn_client/merge.c
(open_source_session): New function, factored out ...
(merge_locked, merge_peg_locked): ... of these.
(find_reintegrate_merge): Take RA sessions and resolved source location as
inputs rather than opening sessions and returning them.
(open_reintegrate_source_and_target): New function, extracted from
find_reintegrate_merge().
(svn_client_find_reintegrate_merge, merge_reintegrate_locked): Use it.
Modified:
subversion/trunk/subversion/libsvn_client/merge.c
Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1302816&r1=1302815&r2=1302816&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Tue Mar 20 09:54:45 2012
@@ -9299,6 +9299,35 @@ open_target_wc(merge_target_t **target_p
return SVN_NO_ERROR;
}
+/* Open an RA session to PATH_OR_URL at PEG_REVISION. Set *RA_SESSION_P to
+ * the session and set *LOCATION_P to the resolved revision, URL and
+ * repository root. Allocate the results in RESULT_POOL. */
+static svn_error_t *
+open_source_session(repo_location_t **location_p,
+ svn_ra_session_t **ra_session_p,
+ const char *path_or_url,
+ const svn_opt_revision_t *peg_revision,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ repo_location_t *location = apr_palloc(result_pool, sizeof(*location));
+ svn_ra_session_t *ra_session;
+
+ SVN_ERR(svn_client__ra_session_from_path(
+ &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,
+ result_pool));
+ SVN_ERR(svn_ra_get_uuid2(ra_session, &location->repo->uuid, result_pool));
+
+ *location_p = location;
+ *ra_session_p = ra_session;
+ return SVN_NO_ERROR;
+}
+
/*-----------------------------------------------------------------------*/
@@ -9322,9 +9351,9 @@ merge_locked(const char *source1,
apr_pool_t *scratch_pool)
{
merge_target_t *target;
+ repo_location_t *source1_loc, *source2_loc;
merge_source_t source;
svn_boolean_t related = FALSE, ancestral = FALSE;
- url_uuid_t source_repos_root, source_repos_root2;
svn_ra_session_t *ra_session1, *ra_session2;
apr_array_header_t *merge_sources;
svn_error_t *err;
@@ -9346,35 +9375,26 @@ merge_locked(const char *source1,
/* Open RA sessions to both sides of our merge source, and resolve URLs
* and revisions. */
sesspool = svn_pool_create(scratch_pool);
- SVN_ERR(svn_client__ra_session_from_path(&ra_session1,
- &source.rev1, &source.url1,
- source1, NULL, revision1, revision1,
- ctx, sesspool));
- SVN_ERR(svn_client__ra_session_from_path(&ra_session2,
- &source.rev2, &source.url2,
- source2, NULL, revision2, revision2,
- ctx, sesspool));
-
- SVN_ERR(svn_ra_get_repos_root2(ra_session1, &source_repos_root.url,
- sesspool));
- SVN_ERR(svn_ra_get_uuid2(ra_session1, &source_repos_root.uuid,
- scratch_pool));
- SVN_ERR(svn_ra_get_repos_root2(ra_session2, &source_repos_root2.url,
- sesspool));
- SVN_ERR(svn_ra_get_uuid2(ra_session2, &source_repos_root2.uuid,
- scratch_pool));
+ SVN_ERR(open_source_session(&source1_loc, &ra_session1, source1, revision1,
+ ctx, sesspool, scratch_pool));
+ source.url1 = source1_loc->url;
+ source.rev1 = source1_loc->rev;
+ SVN_ERR(open_source_session(&source2_loc, &ra_session2, source2, revision2,
+ ctx, sesspool, scratch_pool));
+ source.url2 = source2_loc->url;
+ source.rev2 = source2_loc->rev;
/* 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(&source_repos_root, source.url1,
- &source_repos_root2, source.url2,
+ SVN_ERR(check_same_repos(source1_loc->repo, source.url1,
+ source2_loc->repo, source.url2,
FALSE /* strict_urls */, scratch_pool));
/* Do our working copy and sources come from the same repository? */
- same_repos = is_same_repos(target->loc.repo, &source_repos_root,
+ same_repos = is_same_repos(target->loc.repo, source1_loc->repo,
TRUE /* strict_urls */);
/* Unless we're ignoring ancestry, see if the two sources are related. */
@@ -10390,8 +10410,10 @@ calculate_left_hand_side(const char **ur
* from SOURCE_PATH_OR_URL at SOURCE_PEG_REVISION into the working
* copy at TARGET.
*
- * Set *TARGET_RA_SESSION_P and *SOURCE_RA_SESSION_P to new RA sessions
- * opened to the target and source branches respectively. Set *SOURCE_P to
+ * SOURCE_RA_SESSION and TARGET_RA_SESSION are RA sessions opened to the
+ * source and target branches respectively.
+ *
+ * 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.
* Any of these output pointers may be NULL if not wanted.
@@ -10399,20 +10421,16 @@ calculate_left_hand_side(const char **ur
* See svn_client_find_reintegrate_merge() for other details.
*/
static svn_error_t *
-find_reintegrate_merge(svn_ra_session_t **target_ra_session_p,
- svn_ra_session_t **source_ra_session_p,
- merge_source_t **source_p,
+find_reintegrate_merge(merge_source_t **source_p,
svn_revnum_t *yc_ancestor_rev_p,
- const char *source_path_or_url,
- const svn_opt_revision_t *source_peg_revision,
+ svn_ra_session_t *source_ra_session,
+ const repo_location_t *source_loc,
+ svn_ra_session_t *target_ra_session,
const merge_target_t *target,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_ra_session_t *target_ra_session;
- svn_ra_session_t *source_ra_session;
- repo_location_t source_loc;
const char *yc_ancestor_relpath;
svn_revnum_t yc_ancestor_rev;
merge_source_t source;
@@ -10421,35 +10439,6 @@ find_reintegrate_merge(svn_ra_session_t
svn_error_t *err;
apr_hash_t *subtrees_with_mergeinfo;
- if (! target->loc.url)
- return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
- _("Can't reintegrate into '%s' because it is "
- "locally added and therefore not related to "
- "the merge source"),
- svn_dirent_local_style(target->abspath,
- scratch_pool));
-
- /* Open source session and determine its repository root. */
- SVN_ERR(svn_client__ra_session_from_path(
- &source_ra_session, &source_loc.rev, &source_loc.url,
- source_path_or_url, NULL, source_peg_revision, source_peg_revision,
- ctx, result_pool));
- source_loc.repo = apr_palloc(scratch_pool, sizeof(*source_loc.repo));
- SVN_ERR(svn_ra_get_repos_root2(source_ra_session, &source_loc.repo->url,
- scratch_pool));
- SVN_ERR(svn_ra_get_uuid2(source_ra_session, &source_loc.repo->uuid,
- scratch_pool));
-
- /* source_loc.repo and target->loc.repo are required to be the same,
- as mergeinfo doesn't come into play for cross-repository merging. */
- SVN_ERR(check_same_repos(source_loc.repo,
- svn_dirent_local_style(source_path_or_url,
- scratch_pool),
- target->loc.repo,
- svn_dirent_local_style(target->abspath,
- scratch_pool),
- TRUE /* strict_urls */, scratch_pool));
-
/* As the WC tree is "pure", use its last-updated-to revision as
the default revision for the left side of our merge, since that's
what the repository sub-tree is required to be up to date with
@@ -10457,7 +10446,7 @@ find_reintegrate_merge(svn_ra_session_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
+ if (strcmp(source_loc->url, source_loc->repo->url) == 0
|| strcmp(target->loc.url, target->loc.repo->url) == 0)
return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
_("Neither the reintegrate source nor target "
@@ -10473,17 +10462,12 @@ find_reintegrate_merge(svn_ra_session_t
err = svn_error_quick_wrap(err, _("Reintegrate merge not possible"));
SVN_ERR(err);
- SVN_ERR(svn_client__open_ra_session_internal(&target_ra_session, NULL,
- target->loc.url,
- NULL, NULL, FALSE, FALSE,
- ctx, result_pool));
-
SVN_ERR(calculate_left_hand_side(&source.url1, &source.rev1,
&merged_to_source_mergeinfo_catalog,
&unmerged_to_source_mergeinfo_catalog,
target,
subtrees_with_mergeinfo,
- &source_loc,
+ source_loc,
source_ra_session,
target_ra_session,
ctx,
@@ -10493,10 +10477,6 @@ find_reintegrate_merge(svn_ra_session_t
be performed here? */
if (! source.url1)
{
- if (target_ra_session_p)
- *target_ra_session_p = NULL;
- if (source_ra_session_p)
- *source_ra_session_p = NULL;
if (source_p)
*source_p = NULL;
if (yc_ancestor_rev_p)
@@ -10504,8 +10484,8 @@ find_reintegrate_merge(svn_ra_session_t
return SVN_NO_ERROR;
}
- source.rev2 = source_loc.rev;
- source.url2 = source_loc.url;
+ source.rev2 = source_loc->rev;
+ source.url2 = source_loc->url;
/* 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
@@ -10533,7 +10513,7 @@ find_reintegrate_merge(svn_ra_session_t
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,
+ = svn_uri_skip_ancestor(source_loc->repo->url, source_loc->url,
scratch_pool);
SVN_ERR(find_unsynced_ranges(source_repos_rel_path,
@@ -10567,10 +10547,6 @@ find_reintegrate_merge(svn_ra_session_t
/* Left side: trunk@youngest-trunk-rev-merged-to-branch-at-specified-peg-rev
* Right side: branch@specified-peg-revision */
- if (target_ra_session_p)
- *target_ra_session_p = target_ra_session;
- if (source_ra_session_p)
- *source_ra_session_p = source_ra_session;
if (source_p)
*source_p = apr_pmemdup(result_pool, &source, sizeof(source));
if (yc_ancestor_rev_p)
@@ -10578,6 +10554,73 @@ find_reintegrate_merge(svn_ra_session_t
return SVN_NO_ERROR;
}
+/* Resolve the source and target locations and open RA sessions to them, and
+ * perform some checks appropriate for a reintegrate merge.
+ *
+ * Set *SOURCE_RA_SESSION_P and *SOURCE_LOC_P to a new session and the
+ * repository location of SOURCE_PATH_OR_URL at SOURCE_PEG_REVISION. Set
+ * *TARGET_RA_SESSION_P and *TARGET_P to a new session and the repository
+ * location of the WC at TARGET_ABSPATH.
+ *
+ * Throw a SVN_ERR_CLIENT_UNRELATED_RESOURCES error if the target WC node is
+ * a locally added node or if the source and target are not in the same
+ * repository. Throw a SVN_ERR_CLIENT_NOT_READY_TO_MERGE error if the
+ * target WC is not at a single revision without switched subtrees and
+ * without local mods.
+ *
+ * Allocate all the outputs in RESULT_POOL.
+ */
+static svn_error_t *
+open_reintegrate_source_and_target(svn_ra_session_t **source_ra_session_p,
+ repo_location_t **source_loc_p,
+ svn_ra_session_t **target_ra_session_p,
+ merge_target_t **target_p,
+ const char *source_path_or_url,
+ const svn_opt_revision_t *source_peg_revision,
+ const char *target_abspath,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ repo_location_t *source_loc;
+ merge_target_t *target;
+
+ /* Open the target WC. A reintegrate merge requires the merge target to
+ * reflect a subtree of the repository as found at a single revision. */
+ SVN_ERR(open_target_wc(&target, target_abspath,
+ FALSE, FALSE, FALSE,
+ ctx, scratch_pool, scratch_pool));
+ SVN_ERR(svn_client__open_ra_session_internal(target_ra_session_p, NULL,
+ target->loc.url,
+ NULL, NULL, FALSE, FALSE,
+ ctx, scratch_pool));
+ if (! target->loc.url)
+ return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
+ _("Can't reintegrate into '%s' because it is "
+ "locally added and therefore not related to "
+ "the merge source"),
+ svn_dirent_local_style(target->abspath,
+ scratch_pool));
+
+ SVN_ERR(open_source_session(&source_loc, source_ra_session_p,
+ 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,
+ as mergeinfo doesn't come into play for cross-repository merging. */
+ SVN_ERR(check_same_repos(source_loc->repo,
+ svn_dirent_local_style(source_path_or_url,
+ scratch_pool),
+ target->loc.repo,
+ svn_dirent_local_style(target->abspath,
+ scratch_pool),
+ TRUE /* strict_urls */, scratch_pool));
+
+ *source_loc_p = source_loc;
+ *target_p = target;
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_client_find_reintegrate_merge(const char **url1_p,
svn_revnum_t *rev1_p,
@@ -10591,20 +10634,23 @@ svn_client_find_reintegrate_merge(const
apr_pool_t *scratch_pool)
{
const char *target_abspath;
+ svn_ra_session_t *source_ra_session;
+ repo_location_t *source_loc;
+ svn_ra_session_t *target_ra_session;
merge_target_t *target;
merge_source_t *source;
SVN_ERR(svn_dirent_get_absolute(&target_abspath, target_wcpath,
scratch_pool));
- /* Open the target WC. A reintegrate merge requires the merge target to
- * reflect a subtree of the repository as found at a single revision. */
- SVN_ERR(open_target_wc(&target, target_abspath,
- FALSE, FALSE, FALSE,
- ctx, scratch_pool, scratch_pool));
- SVN_ERR(find_reintegrate_merge(NULL, NULL, &source, NULL,
- source_path_or_url, source_peg_revision,
- target,
+ SVN_ERR(open_reintegrate_source_and_target(
+ &source_ra_session, &source_loc, &target_ra_session, &target,
+ source_path_or_url, source_peg_revision, target_abspath,
+ ctx, scratch_pool, scratch_pool));
+
+ SVN_ERR(find_reintegrate_merge(&source, NULL,
+ source_ra_session, source_loc,
+ target_ra_session, target,
ctx, result_pool, scratch_pool));
if (source)
{
@@ -10635,21 +10681,20 @@ merge_reintegrate_locked(const char *sou
{
svn_ra_session_t *target_ra_session, *source_ra_session;
merge_target_t *target;
+ repo_location_t *source_loc;
merge_source_t *source;
svn_revnum_t yc_ancestor_rev;
svn_boolean_t use_sleep;
svn_error_t *err;
- /* Open the target WC. A reintegrate merge requires the merge target to
- * reflect a subtree of the repository as found at a single revision. */
- SVN_ERR(open_target_wc(&target, target_abspath,
- FALSE, FALSE, FALSE,
- ctx, scratch_pool, scratch_pool));
-
- SVN_ERR(find_reintegrate_merge(&target_ra_session, &source_ra_session,
- &source, &yc_ancestor_rev,
- source_path_or_url, source_peg_revision,
- target,
+ SVN_ERR(open_reintegrate_source_and_target(
+ &source_ra_session, &source_loc, &target_ra_session, &target,
+ source_path_or_url, source_peg_revision, target_abspath,
+ ctx, scratch_pool, scratch_pool));
+
+ SVN_ERR(find_reintegrate_merge(&source, &yc_ancestor_rev,
+ source_ra_session, source_loc,
+ target_ra_session, target,
ctx, scratch_pool, scratch_pool));
if (! source)
@@ -10729,10 +10774,8 @@ merge_peg_locked(const char *source_path
apr_pool_t *scratch_pool)
{
merge_target_t *target;
- const char *source_url;
- svn_revnum_t source_peg_revnum;
+ repo_location_t *source_loc;
apr_array_header_t *merge_sources;
- url_uuid_t source_repos_root;
svn_ra_session_t *ra_session;
apr_pool_t *sesspool;
svn_boolean_t use_sleep = FALSE;
@@ -10747,22 +10790,18 @@ merge_peg_locked(const char *source_path
/* Open an RA session to our source URL, and determine its root URL. */
sesspool = svn_pool_create(scratch_pool);
- SVN_ERR(svn_client__ra_session_from_path(
- &ra_session, &source_peg_revnum, &source_url,
- source_path_or_url, NULL, source_peg_revision, source_peg_revision,
- ctx, sesspool));
- SVN_ERR(svn_ra_get_repos_root2(ra_session, &source_repos_root.url,
- scratch_pool));
- SVN_ERR(svn_ra_get_uuid2(ra_session, &source_repos_root.uuid, scratch_pool));
+ SVN_ERR(open_source_session(&source_loc, &ra_session,
+ source_path_or_url, source_peg_revision,
+ ctx, sesspool, scratch_pool));
/* Normalize our merge sources. */
SVN_ERR(normalize_merge_sources(&merge_sources, source_path_or_url,
- source_url, source_peg_revnum,
+ source_loc->url, source_loc->rev,
ranges_to_merge, ra_session, ctx,
scratch_pool, scratch_pool));
/* Check for same_repos. */
- same_repos = is_same_repos(target->loc.repo, &source_repos_root,
+ same_repos = is_same_repos(target->loc.repo, source_loc->repo,
TRUE /* strict_urls */);
/* We're done with our little RA session. */