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 2011/11/09 17:45:39 UTC
svn commit: r1199840 - /subversion/trunk/subversion/libsvn_client/merge.c
Author: julianfoad
Date: Wed Nov 9 16:45:38 2011
New Revision: 1199840
URL: http://svn.apache.org/viewvc?rev=1199840&view=rev
Log:
Factor out the checks for 'same repository' in the merge code. The only
functional change is to always return SVN_ERR_UNSUPPORTED_FEATURE for a
mis-match; previously we sometimes returned SVN_ERR_RA_UUID_MISMATCH.
* subversion/libsvn_client/merge.c
(url_uuid_t): New type, copied from relocate.c.
(is_same_repos, check_same_repos): New functions.
(merge_cousins_and_supplement_mergeinfo): Take repository roots as structs
rather than just URLs, and simplify by calling is_same_repos().
(merge_locked, merge_reintegrate_locked, merge_peg_locked): Use the new
type and functions.
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=1199840&r1=1199839&r2=1199840&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Wed Nov 9 16:45:38 2011
@@ -293,6 +293,13 @@ typedef struct merge_cmd_baton_t {
/*** Utilities ***/
+/* Repository root and UUID for a repository. */
+typedef struct url_uuid_t
+{
+ const char *url;
+ const char *uuid;
+} url_uuid_t;
+
/* 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 *
@@ -310,6 +317,42 @@ check_repos_match(merge_cmd_baton_t *mer
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
+ * 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,
+ 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);
+ else
+ return (strcmp(repos_root1->uuid, repos_root2->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
+ * 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,
+ const char *path1,
+ const url_uuid_t *repos_root2,
+ const char *path2,
+ svn_boolean_t strict_urls,
+ apr_pool_t *scratch_pool)
+{
+ if (! is_same_repos(repos_root1, repos_root2, strict_urls))
+ return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
+ _("'%s' must be from the same repository as "
+ "'%s'"), path1, path2);
+ return SVN_NO_ERROR;
+}
+
/* Return true iff we're in dry-run mode and WCPATH would have been
deleted by now if we weren't in dry-run mode.
Used to avoid spurious notifications (e.g. conflicts) from a merge
@@ -9037,8 +9080,8 @@ merge_cousins_and_supplement_mergeinfo(c
const char *URL2,
svn_revnum_t rev2,
svn_revnum_t yc_rev,
- const char *source_repos_root,
- const char *wc_repos_root,
+ url_uuid_t *source_repos_root,
+ url_uuid_t *wc_repos_root,
svn_depth_t depth,
svn_boolean_t ignore_ancestry,
svn_boolean_t force,
@@ -9063,20 +9106,8 @@ merge_cousins_and_supplement_mergeinfo(c
SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
- if (strcmp(wc_repos_root, source_repos_root) != 0)
- {
- const char *source_repos_uuid;
- const char *wc_repos_uuid;
-
- SVN_ERR(svn_ra_get_uuid2(URL1_ra_session, &source_repos_uuid,
- subpool));
- SVN_ERR(svn_client_get_repos_root(NULL /* root_url */, &wc_repos_uuid,
- target_abspath,
- ctx, subpool, subpool));
- same_repos = (strcmp(wc_repos_uuid, source_repos_uuid) == 0);
- }
- else
- same_repos = TRUE;
+ same_repos = is_same_repos(source_repos_root, wc_repos_root,
+ TRUE /* strict_urls */);
peg_revision.kind = svn_opt_revision_number;
@@ -9090,7 +9121,7 @@ merge_cousins_and_supplement_mergeinfo(c
APR_ARRAY_PUSH(ranges, svn_opt_revision_range_t *) = range;
peg_revision.value.number = rev1;
SVN_ERR(normalize_merge_sources(&remove_sources, URL1, URL1,
- source_repos_root, &peg_revision,
+ source_repos_root->url, &peg_revision,
ranges, URL1_ra_session, ctx, scratch_pool,
subpool));
@@ -9104,7 +9135,7 @@ merge_cousins_and_supplement_mergeinfo(c
APR_ARRAY_PUSH(ranges, svn_opt_revision_range_t *) = range;
peg_revision.value.number = rev2;
SVN_ERR(normalize_merge_sources(&add_sources, URL2, URL2,
- source_repos_root, &peg_revision,
+ source_repos_root->url, &peg_revision,
ranges, URL2_ra_session, ctx,
scratch_pool, subpool));
@@ -9325,8 +9356,7 @@ merge_locked(const char *source1,
const char *URL1, *URL2;
svn_revnum_t rev1, rev2;
svn_boolean_t related = FALSE, ancestral = FALSE;
- const char *wc_repos_root, *source_repos_root;
- const char *wc_repos_uuid, *source_repos_uuid1, *source_repos_uuid2;
+ url_uuid_t wc_repos_root, source_repos_root, source_repos_root2;
svn_revnum_t youngest_rev = SVN_INVALID_REVNUM;
svn_ra_session_t *ra_session1, *ra_session2;
apr_array_header_t *merge_sources;
@@ -9399,7 +9429,7 @@ merge_locked(const char *source1,
scratch_pool));
/* Determine the working copy target's repository root URL. */
- SVN_ERR(svn_client_get_repos_root(&wc_repos_root, &wc_repos_uuid,
+ SVN_ERR(svn_client_get_repos_root(&wc_repos_root.url, &wc_repos_root.uuid,
target_abspath,
ctx, scratch_pool, scratch_pool));
@@ -9420,23 +9450,27 @@ merge_locked(const char *source1,
NULL, ra_session2, revision2,
sesspool));
- SVN_ERR(svn_ra_get_uuid2(ra_session1, &source_repos_uuid1, scratch_pool));
- SVN_ERR(svn_ra_get_uuid2(ra_session2, &source_repos_uuid2, scratch_pool));
+ 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));
/* We can't do a diff between different repositories. */
- if (strcmp(source_repos_uuid1, source_repos_uuid2) != 0)
- return svn_error_createf(SVN_ERR_RA_UUID_MISMATCH, NULL,
- _("'%s' isn't in the same repository as '%s'"),
- URL1, URL2);
-
- /* Get the repository root URL from one of our sessions. */
- SVN_ERR(svn_ra_get_repos_root2(ra_session1, &source_repos_root, sesspool));
+ /* ### 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, URL1,
+ &source_repos_root2, URL2,
+ FALSE /* strict_urls */, scratch_pool));
/* Do our working copy and sources come from the same repository? */
- if (strcmp(wc_repos_root, source_repos_root) != 0)
- same_repos = (strcmp(wc_repos_uuid, source_repos_uuid1) == 0);
- else
- same_repos = TRUE;
+ same_repos = is_same_repos(&wc_repos_root, &source_repos_root,
+ TRUE /* strict_urls */);
/* Unless we're ignoring ancestry, see if the two sources are related. */
if (! ignore_ancestry)
@@ -9473,7 +9507,7 @@ merge_locked(const char *source1,
related = TRUE;
/* Make YC_PATH into a full URL. */
- yc_path = svn_path_url_add_component2(source_repos_root, yc_path,
+ yc_path = svn_path_url_add_component2(source_repos_root.url, yc_path,
scratch_pool);
/* If the common ancestor matches the right side of our merge,
@@ -9491,7 +9525,7 @@ merge_locked(const char *source1,
APR_ARRAY_PUSH(ranges, svn_opt_revision_range_t *) = range;
peg_revision.value.number = rev1;
SVN_ERR(normalize_merge_sources(&merge_sources, URL1, URL1,
- source_repos_root, &peg_revision,
+ source_repos_root.url, &peg_revision,
ranges, ra_session1, ctx,
scratch_pool, scratch_pool));
}
@@ -9510,7 +9544,7 @@ merge_locked(const char *source1,
APR_ARRAY_PUSH(ranges, svn_opt_revision_range_t *) = range;
peg_revision.value.number = rev2;
SVN_ERR(normalize_merge_sources(&merge_sources, URL2, URL2,
- source_repos_root, &peg_revision,
+ source_repos_root.url, &peg_revision,
ranges, ra_session2, ctx,
scratch_pool, scratch_pool));
}
@@ -9524,8 +9558,8 @@ merge_locked(const char *source1,
URL1, rev1,
URL2, rev2,
yc_rev,
- source_repos_root,
- wc_repos_root,
+ &source_repos_root,
+ &wc_repos_root,
depth,
ignore_ancestry, force,
record_only, dry_run,
@@ -10568,7 +10602,7 @@ merge_reintegrate_locked(const char *sou
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool)
{
- const char *wc_repos_root, *source_repos_root;
+ url_uuid_t wc_repos_root, source_repos_root;
svn_opt_revision_t working_revision;
svn_ra_session_t *target_ra_session;
svn_ra_session_t *source_ra_session;
@@ -10605,22 +10639,22 @@ merge_reintegrate_locked(const char *sou
svn_dirent_local_style(source, scratch_pool));
/* Determine the working copy target's repository root URL. */
- SVN_ERR(svn_client_get_repos_root(&wc_repos_root, NULL, target_abspath,
+ SVN_ERR(svn_client_get_repos_root(&wc_repos_root.url, &wc_repos_root.uuid,
+ target_abspath,
ctx, scratch_pool, scratch_pool));
/* Determine the source's repository root URL. */
- SVN_ERR(svn_client_get_repos_root(&source_repos_root, NULL, url2,
+ SVN_ERR(svn_client_get_repos_root(&source_repos_root.url,
+ &source_repos_root.uuid, url2,
ctx, scratch_pool, scratch_pool));
/* source_repos_root and wc_repos_root are required to be the same,
as mergeinfo doesn't come into play for cross-repository merging. */
- if (strcmp(source_repos_root, wc_repos_root) != 0)
- return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
- _("'%s' must be from the same repository as "
- "'%s'"), svn_dirent_local_style(source,
- scratch_pool),
- svn_dirent_local_style(target_abspath,
- scratch_pool));
+ SVN_ERR(check_same_repos(&source_repos_root,
+ svn_dirent_local_style(source, scratch_pool),
+ &wc_repos_root,
+ svn_dirent_local_style(target_abspath, scratch_pool),
+ TRUE /* strict_urls */, scratch_pool));
/* A reintegrate merge requires the merge target to reflect a subtree
* of the repository as found at a single revision. */
@@ -10636,7 +10670,7 @@ merge_reintegrate_locked(const char *sou
(with regard to the WC). */
rev1 = target_base_rev;
- source_repos_rel_path = svn_uri_skip_ancestor(wc_repos_root, url2,
+ source_repos_rel_path = svn_uri_skip_ancestor(wc_repos_root.url, url2,
scratch_pool);
SVN_ERR(svn_client__path_relative_to_root(&target_repos_rel_path,
ctx->wc_ctx, target_abspath,
@@ -10677,7 +10711,7 @@ merge_reintegrate_locked(const char *sou
subtrees_with_mergeinfo,
rev1,
source_repos_rel_path,
- source_repos_root,
+ source_repos_root.url,
rev2,
source_ra_session,
target_ra_session,
@@ -10751,12 +10785,12 @@ merge_reintegrate_locked(const char *sou
### related" in this source file). We can merge to trunk without
### implementing this. */
err = merge_cousins_and_supplement_mergeinfo(target_abspath,
- target_ra_session,
- source_ra_session,
+ target_ra_session, /* ### */
+ source_ra_session, /* wrong */
url1, rev1, url2, rev2,
yc_ancestor_rev,
- source_repos_root,
- wc_repos_root,
+ &source_repos_root, /* way */
+ &wc_repos_root, /* round? */
svn_depth_infinity,
FALSE, FALSE, FALSE, dry_run,
merge_options, &use_sleep,
@@ -10847,8 +10881,7 @@ merge_peg_locked(const char *source,
{
const char *URL;
apr_array_header_t *merge_sources;
- const char *wc_repos_root, *source_repos_root;
- const char *wc_repos_uuid, *source_repos_uuid;
+ url_uuid_t wc_repos_root, source_repos_root;
svn_ra_session_t *ra_session;
apr_pool_t *sesspool;
svn_boolean_t use_sleep = FALSE;
@@ -10886,7 +10919,7 @@ merge_peg_locked(const char *source,
scratch_pool));
/* Determine the working copy target's repository root URL. */
- SVN_ERR(svn_client_get_repos_root(&wc_repos_root, &wc_repos_uuid,
+ SVN_ERR(svn_client_get_repos_root(&wc_repos_root.url, &wc_repos_root.uuid,
target_abspath,
ctx, scratch_pool, scratch_pool));
@@ -10895,20 +10928,19 @@ merge_peg_locked(const char *source,
SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, URL, NULL,
NULL, FALSE, TRUE,
ctx, sesspool));
- SVN_ERR(svn_ra_get_repos_root2(ra_session, &source_repos_root, scratch_pool));
- SVN_ERR(svn_ra_get_uuid2(ra_session, &source_repos_uuid, scratch_pool));
+ 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));
/* Normalize our merge sources. */
SVN_ERR(normalize_merge_sources(&merge_sources, source, URL,
- source_repos_root, peg_revision,
+ source_repos_root.url, peg_revision,
ranges_to_merge, ra_session, ctx,
scratch_pool, scratch_pool));
/* Check for same_repos. */
- if (strcmp(wc_repos_root, source_repos_root) != 0)
- same_repos = (strcmp(wc_repos_uuid, source_repos_uuid) == 0);
- else
- same_repos = TRUE;
+ same_repos = is_same_repos(&wc_repos_root, &source_repos_root,
+ TRUE /* strict_urls */);
/* We're done with our little RA session. */
svn_pool_destroy(sesspool);