Author: julianfoad
Date: Tue Apr 3 13:19:45 2012
New Revision: 1308887
URL: http://svn.apache.org/viewvc?rev=1308887&view=rev
Log:
Consolidate some use of svn_client__pathrev_t: change
svn_client__repos_location() and svn_client__get_youngest_common_ancestor()
to use it instead of having wrappers around them, and add some handy
constructors and a relpath extractor.
* subversion/include/private/svn_client_private.h,
subversion/libsvn_client/util.c
(svn_client__pathrev_create_with_relpath,
svn_client__pathrev_create_with_session, svn_client__pathrev_relpath):
New functions.
* subversion/libsvn_client/client.h
(svn_client__repos_location, svn_client__get_youngest_common_ancestor):
Take and return pathrev_t instead of separate URL and revision. Add a
scratch pool to the latter.
* subversion/libsvn_client/ra.c
(resolve_rev_and_url): Return pathrev_t instead of separate URL and
revision.
(svn_client__repos_location, svn_client__get_youngest_common_ancestor):
See above.
(svn_client__ra_session_from_path, svn_client__youngest_common_ancestor):
Track the changes.
* subversion/libsvn_client/merge.c
(repos_location, get_youngest_common_ancestor): Remove these wrappers.
(filter_self_referential_mergeinfo, calculate_remaining_ranges,
normalize_merge_sources_internal, merge_locked, calculate_left_hand_side,
find_reintegrate_merge, find_symmetric_merge): Track the changes.
* subversion/libsvn_client/switch.c
(switch_internal): Track the change to
svn_client__get_youngest_common_ancestor().
* subversion/tests/libsvn_client/client-test.c
(test_youngest_common_ancestor): Track the change to
svn_client__get_youngest_common_ancestor().
Modified:
subversion/trunk/subversion/include/private/svn_client_private.h
subversion/trunk/subversion/libsvn_client/client.h
subversion/trunk/subversion/libsvn_client/merge.c
subversion/trunk/subversion/libsvn_client/ra.c
subversion/trunk/subversion/libsvn_client/switch.c
subversion/trunk/subversion/libsvn_client/util.c
subversion/trunk/subversion/tests/libsvn_client/client-test.c
Modified: subversion/trunk/subversion/include/private/svn_client_private.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_client_private.h?rev=1308887&r1=1308886&r2=1308887&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_client_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_client_private.h Tue Apr 3
13:19:45 2012
@@ -29,6 +29,7 @@
#include <apr_pools.h>
+#include "svn_ra.h"
#include "svn_client.h"
#include "svn_types.h"
@@ -55,11 +56,36 @@ svn_client__pathrev_create(const char *r
const char *url,
apr_pool_t *result_pool);
+/* Return a new path-rev structure, allocated in RESULT_POOL,
+ * initialized with deep copies of REPOS_ROOT_URL, REPOS_UUID, and REV,
+ * and using the repository-relative RELPATH to construct the URL. */
+svn_client__pathrev_t *
+svn_client__pathrev_create_with_relpath(const char *repos_root_url,
+ const char *repos_uuid,
+ svn_revnum_t rev,
+ const char *relpath,
+ apr_pool_t *result_pool);
+
+/* Set *PATHREV_P to a new path-rev structure, allocated in RESULT_POOL,
+ * initialized with deep copies of the repository root URL and UUID from
+ * RA_SESSION, and of REV and URL. */
+svn_error_t *
+svn_client__pathrev_create_with_session(svn_client__pathrev_t **pathrev_p,
+ svn_ra_session_t *ra_session,
+ svn_revnum_t rev,
+ const char *url,
+ apr_pool_t *result_pool);
+
/* Return a deep copy of the path-rev LOC, allocated in RESULT_POOL. */
svn_client__pathrev_t *
svn_client__pathrev_dup(const svn_client__pathrev_t *loc,
apr_pool_t *result_pool);
+/* Return the repository-relative relpath of PATHREV. */
+const char *
+svn_client__pathrev_relpath(const svn_client__pathrev_t *pathrev,
+ apr_pool_t *result_pool);
+
/** Return @c SVN_ERR_ILLEGAL_TARGET if TARGETS contains a mixture of
* URLs and paths; otherwise return SVN_NO_ERROR.
Modified: subversion/trunk/subversion/libsvn_client/client.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=1308887&r1=1308886&r2=1308887&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Tue Apr 3 13:19:45 2012
@@ -36,6 +36,7 @@
#include "svn_client.h"
#include "private/svn_magic.h"
+#include "private/svn_client_private.h"
#ifdef __cplusplus
extern "C" {
@@ -146,16 +147,15 @@ svn_client__repos_locations(const char *
/* Trace a line of history of a particular versioned resource back to a
* specific revision.
*
- * Set *OP_URL to the URL that the object PEG_URL@PEG_REVNUM had in
+ * Set *OP_LOC_P to the location that the object PEG_LOC had in
* revision OP_REVNUM.
*
* RA_SESSION is an open RA session to the correct repository; it may be
* temporarily reparented inside this function. */
svn_error_t *
-svn_client__repos_location(const char **start_url,
+svn_client__repos_location(svn_client__pathrev_t **op_loc_p,
svn_ra_session_t *ra_session,
- const char *peg_url,
- svn_revnum_t peg_revnum,
+ const svn_client__pathrev_t *peg_loc,
svn_revnum_t op_revnum,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
@@ -194,13 +194,9 @@ svn_client__repos_location_segments(apr_
Ancestry is determined by the 'copy-from' relationship and the normal
successor relationship.
- Set *ANCESTOR_RELPATH, *ANCESTOR_URL, and *ANCESTOR_REVISION to the
- path (relative to the root of the repository, with no leading '/'),
- URL, and revision, respectively, of the youngest common ancestor of
- the two locations URL1@REV1 and URL2@REV2. Set *ANCESTOR_RELPATH and
- *ANCESTOR_URL to NULL and *ANCESTOR_REVISION to SVN_INVALID_REVNUM if
- they have no common ancestor. This function assumes that URL1@REV1
- and URL2@REV2 both refer to the same repository.
+ Set *ANCESTOR_P to the location of the youngest common ancestor of
+ LOC1 and LOC2. If the locations have no common ancestor (including if
+ they don't have the same repository root URL), set *ANCESTOR_P to NULL.
Use the authentication baton cached in CTX to authenticate against
the repository. Use POOL for all allocations.
@@ -208,15 +204,12 @@ svn_client__repos_location_segments(apr_
See also svn_client__youngest_common_ancestor().
*/
svn_error_t *
-svn_client__get_youngest_common_ancestor(const char **ancestor_relpath,
- const char **ancestor_url,
- svn_revnum_t *ancestor_revision,
- const char *url1,
- svn_revnum_t rev1,
- const char *url2,
- svn_revnum_t rev2,
+svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
+ const svn_client__pathrev_t *loc1,
+ const svn_client__pathrev_t *loc2,
svn_client_ctx_t *ctx,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* Given PATH_OR_URL, which contains either a working copy path or an
absolute URL, a peg revision PEG_REVISION, and a desired revision
Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1308887&r1=1308886&r2=1308887&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Tue Apr 3 13:19:45 2012
@@ -338,59 +338,6 @@ merge_source_dup(const merge_source_t *s
return s;
}
-/* Like svn_client__repos_location() but using svn_client__pathrev_t for input
- * and output. */
-static svn_error_t *
-repos_location(svn_client__pathrev_t **op_loc_p,
- svn_ra_session_t *ra_session,
- const svn_client__pathrev_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
- * svn_client__pathrev_t for input and output.
- */
-static svn_error_t *
-get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
- const svn_client__pathrev_t *loc1,
- const svn_client__pathrev_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 = svn_client__pathrev_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 *
@@ -1071,10 +1018,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 = repos_location(&start_loc, ra_session,
- &target_base,
- range->start + 1,
- ctx, iterpool, iterpool);
+ err2 = svn_client__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
@@ -4140,11 +4087,11 @@ calculate_remaining_ranges(svn_client__m
svn_error_t *err;
svn_client__pathrev_t *start_loc;
- err = repos_location(&start_loc,
- ra_session,
- source->loc1,
- child_base_revision,
- ctx, scratch_pool, scratch_pool);
+ err = svn_client__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
@@ -6422,10 +6369,10 @@ normalize_merge_sources_internal(apr_arr
{
svn_client__pathrev_t *start_loc;
- SVN_ERR(repos_location(&start_loc,
- ra_session, source_loc,
- youngest_requested,
- ctx, scratch_pool, scratch_pool));
+ SVN_ERR(svn_client__repos_location(&start_loc,
+ ra_session, source_loc,
+ youngest_requested,
+ ctx, scratch_pool, scratch_pool));
source_peg_revnum = youngest_requested;
}
@@ -9468,8 +9415,8 @@ merge_locked(const char *source1,
/* Unless we're ignoring ancestry, see if the two sources are related. */
if (! ignore_ancestry)
- SVN_ERR(get_youngest_common_ancestor(&yca, source1_loc, source2_loc,
- ctx, scratch_pool, scratch_pool));
+ SVN_ERR(svn_client__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.
@@ -10402,8 +10349,8 @@ calculate_left_hand_side(svn_client__pat
/* Check that SOURCE_LOC and TARGET->loc are
actually related, we can't reintegrate if they are not. Also
get an initial value for the YCA revision number. */
- SVN_ERR(get_youngest_common_ancestor(&yc_ancestor, source_loc, &target->loc,
- ctx, iterpool, iterpool));
+ SVN_ERR(svn_client__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 "
@@ -10473,9 +10420,9 @@ calculate_left_hand_side(svn_client__pat
/* We've previously merged some or all of the target, up to
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_ERR(svn_client__repos_location(left_p, target_ra_session,
+ &target->loc, youngest_merged_rev,
+ ctx, result_pool, iterpool));
}
svn_pool_destroy(iterpool);
@@ -10569,8 +10516,9 @@ find_reintegrate_merge(merge_source_t **
if (strcmp(source.loc1->url, target->loc.url))
SVN_ERR(svn_ra_reparent(target_ra_session, source.loc1->url,
scratch_pool));
- SVN_ERR(get_youngest_common_ancestor(&yc_ancestor, source.loc2, source.loc1,
- ctx, scratch_pool, scratch_pool));
+ SVN_ERR(svn_client__get_youngest_common_ancestor(
+ &yc_ancestor, source.loc2, source.loc1,
+ ctx, scratch_pool, scratch_pool));
if (! yc_ancestor)
return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
@@ -11136,8 +11084,9 @@ find_symmetric_merge(svn_client__pathrev
{
svn_client__pathrev_t *base_on_source, *base_on_target, *mid;
- SVN_ERR(get_youngest_common_ancestor(yca_p, s_t->source, &s_t->target->loc,
- ctx, result_pool, result_pool));
+ SVN_ERR(svn_client__get_youngest_common_ancestor(
+ yca_p, s_t->source, &s_t->target->loc,
+ ctx, result_pool, result_pool));
/* Find the latest revision of A synced to B and the latest
* revision of B synced to A.
Modified: subversion/trunk/subversion/libsvn_client/ra.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/ra.c?rev=1308887&r1=1308886&r2=1308887&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/ra.c (original)
+++ subversion/trunk/subversion/libsvn_client/ra.c Tue Apr 3 13:19:45 2012
@@ -391,9 +391,7 @@ svn_client_open_ra_session(svn_ra_sessio
for a URL or 'working' for a WC path. If REVISION->kind is
'unspecified', the operative revision is the peg revision.
- Store the actual revision number of the object in *REV_P, and the
- final resulting URL in *URL_P. REV_P and/or URL_P may be NULL if not
- wanted.
+ Store the actual location of the object in *RESOLVED_LOC_P.
RA_SESSION should be an open RA session pointing at the URL of
PATH_OR_URL, or NULL, in which case this function will open its own
@@ -404,8 +402,7 @@ svn_client_open_ra_session(svn_ra_sessio
Use POOL for all allocations. */
static svn_error_t *
-resolve_rev_and_url(svn_revnum_t *rev_p,
- const char **url_p,
+resolve_rev_and_url(svn_client__pathrev_t **resolved_loc_p,
svn_ra_session_t *ra_session,
const char *path_or_url,
const svn_opt_revision_t *peg_revision,
@@ -430,11 +427,8 @@ resolve_rev_and_url(svn_revnum_t *rev_p,
ra_session, path_or_url, &peg_rev,
&start_rev, NULL, ctx, pool));
- if (rev_p)
- *rev_p = rev;
- if (url_p)
- *url_p = url;
-
+ *resolved_loc_p = svn_client__pathrev_create_with_session(ra_session,
+ rev, url, pool);
return SVN_NO_ERROR;
}
@@ -452,7 +446,7 @@ svn_client__ra_session_from_path(svn_ra_
svn_ra_session_t *ra_session;
const char *initial_url;
const char *corrected_url;
- const char *resolved_url;
+ svn_client__pathrev_t *resolved_loc;
SVN_ERR(svn_client_url_from_path2(&initial_url, path_or_url, ctx, pool,
pool));
@@ -471,16 +465,18 @@ svn_client__ra_session_from_path(svn_ra_
if (corrected_url && svn_path_is_url(path_or_url))
path_or_url = corrected_url;
- SVN_ERR(resolve_rev_and_url(rev_p, &resolved_url, ra_session,
+ SVN_ERR(resolve_rev_and_url(&resolved_loc, ra_session,
path_or_url, peg_revision, revision,
ctx, pool));
/* Make the session point to the real URL. */
- SVN_ERR(svn_ra_reparent(ra_session, resolved_url, pool));
+ SVN_ERR(svn_ra_reparent(ra_session, resolved_loc->url, pool));
*ra_session_p = ra_session;
+ if (rev_p)
+ *rev_p = resolved_loc->rev;
if (url_p)
- *url_p = resolved_url;
+ *url_p = resolved_loc->url;
return SVN_NO_ERROR;
}
@@ -649,24 +645,28 @@ repos_locations(const char **start_url,
}
svn_error_t *
-svn_client__repos_location(const char **op_url,
+svn_client__repos_location(svn_client__pathrev_t **op_loc_p,
svn_ra_session_t *ra_session,
- const char *peg_url,
- svn_revnum_t peg_revnum,
+ const svn_client__pathrev_t *peg_loc,
svn_revnum_t op_revnum,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
const char *old_session_url;
+ const char *op_url;
SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
- peg_url, scratch_pool));
- SVN_ERR(repos_locations(op_url, NULL,
- ra_session, peg_url, peg_revnum,
+ peg_loc->url, scratch_pool));
+ SVN_ERR(repos_locations(&op_url, NULL, ra_session,
+ peg_loc->url, peg_loc->rev,
op_revnum, SVN_INVALID_REVNUM,
result_pool, scratch_pool));
SVN_ERR(svn_ra_reparent(ra_session, old_session_url, scratch_pool));
+
+ *op_loc_p = svn_client__pathrev_create(peg_loc->repos_root_url,
+ peg_loc->repos_uuid,
+ op_revnum, op_url, result_pool);
return SVN_NO_ERROR;
}
@@ -808,19 +808,15 @@ svn_client__repos_locations(const char *
svn_error_t *
-svn_client__get_youngest_common_ancestor(const char **ancestor_relpath,
- const char **ancestor_url,
- svn_revnum_t *ancestor_revision,
- const char *url1,
- svn_revnum_t rev1,
- const char *url2,
- svn_revnum_t rev2,
+svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
+ const svn_client__pathrev_t *loc1,
+ const svn_client__pathrev_t *loc2,
svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- apr_pool_t *sesspool = svn_pool_create(pool);
+ apr_pool_t *sesspool = svn_pool_create(scratch_pool);
svn_ra_session_t *session;
- const char *repos_root_url;
apr_hash_t *history1, *history2;
apr_hash_index_t *hi;
svn_revnum_t yc_revision = SVN_INVALID_REVNUM;
@@ -828,31 +824,36 @@ svn_client__get_youngest_common_ancestor
svn_boolean_t has_rev_zero_history1;
svn_boolean_t has_rev_zero_history2;
+ if (strcmp(loc1->repos_root_url, loc2->repos_root_url) != 0)
+ {
+ *ancestor_p = NULL;
+ return SVN_NO_ERROR;
+ }
+
/* Open an RA session for the two locations. */
- SVN_ERR(svn_client_open_ra_session(&session, url1, ctx, sesspool));
- SVN_ERR(svn_ra_get_repos_root2(session, &repos_root_url, pool));
+ SVN_ERR(svn_client_open_ra_session(&session, loc1->url, ctx, sesspool));
/* We're going to cheat and use history-as-mergeinfo because it
saves us a bunch of annoying custom data comparisons and such. */
SVN_ERR(svn_client__get_history_as_mergeinfo(&history1,
&has_rev_zero_history1,
- url1, rev1,
+ loc1->url, loc1->rev,
SVN_INVALID_REVNUM,
SVN_INVALID_REVNUM,
- session, ctx, pool));
+ session, ctx, scratch_pool));
SVN_ERR(svn_client__get_history_as_mergeinfo(&history2,
&has_rev_zero_history2,
- url2, rev2,
+ loc2->url, loc2->rev,
SVN_INVALID_REVNUM,
SVN_INVALID_REVNUM,
- session, ctx, pool));
+ session, ctx, scratch_pool));
/* Close the source and target sessions. */
svn_pool_destroy(sesspool);
/* Loop through the first location's history, check for overlapping
paths and ranges in the second location's history, and
remembering the youngest matching location. */
- for (hi = apr_hash_first(pool, history1); hi; hi = apr_hash_next(hi))
+ for (hi = apr_hash_first(scratch_pool, history1); hi; hi = apr_hash_next(hi))
{
const char *path = svn__apr_hash_index_key(hi);
apr_ssize_t path_len = svn__apr_hash_index_klen(hi);
@@ -865,7 +866,7 @@ svn_client__get_youngest_common_ancestor
/* We have a path match. Now, did our two histories share
any revisions at that path? */
SVN_ERR(svn_rangelist_intersect(&common, ranges1, ranges2,
- TRUE, pool));
+ TRUE, scratch_pool));
if (common->nelts)
{
svn_merge_range_t *yc_range =
@@ -888,14 +889,19 @@ svn_client__get_youngest_common_ancestor
yc_revision = 0;
}
- if (ancestor_relpath)
- *ancestor_relpath = yc_relpath;
- if (ancestor_url)
- *ancestor_url
- = yc_relpath ? svn_path_url_add_component2(repos_root_url, yc_relpath,
- pool) : NULL;
- if (ancestor_revision)
- *ancestor_revision = yc_revision;
+ if (yc_relpath)
+ {
+ const char *yc_url = svn_path_url_add_component2(
+ loc1->repos_root_url, yc_relpath, result_pool);
+
+ *ancestor_p = svn_client__pathrev_create(
+ loc1->repos_root_url, loc1->repos_uuid,
+ yc_revision, yc_url, result_pool);
+ }
+ else
+ {
+ *ancestor_p = NULL;
+ }
return SVN_NO_ERROR;
}
@@ -912,22 +918,32 @@ svn_client__youngest_common_ancestor(con
{
apr_pool_t *sesspool = svn_pool_create(scratch_pool);
svn_ra_session_t *session;
- const char *url1, *url2;
- svn_revnum_t rev1, rev2;
+ svn_client__pathrev_t loc1, *loc2, *ancestor;
/* Resolve the two locations */
- SVN_ERR(svn_client__ra_session_from_path(&session, &rev1, &url1,
+ SVN_ERR(svn_client__ra_session_from_path(&session, &loc1.rev, &loc1.url,
path_or_url1, NULL,
revision1, revision1,
ctx, sesspool));
- SVN_ERR(resolve_rev_and_url(&rev2, &url2, session,
+ SVN_ERR(svn_ra_get_repos_root2(session, &loc1.repos_root_url, sesspool));
+ SVN_ERR(svn_ra_get_uuid2(session, &loc1.repos_uuid, sesspool));
+ SVN_ERR(resolve_rev_and_url(&loc2, session,
path_or_url2, revision2, revision2,
ctx, scratch_pool));
SVN_ERR(svn_client__get_youngest_common_ancestor(
- NULL, ancestor_url, ancestor_rev,
- url1, rev1, url2, rev2, ctx, result_pool));
+ &ancestor, &loc1, loc2, ctx, result_pool, scratch_pool));
+ if (ancestor)
+ {
+ *ancestor_url = ancestor->url;
+ *ancestor_rev = ancestor->rev;
+ }
+ else
+ {
+ *ancestor_url = NULL;
+ *ancestor_rev = SVN_INVALID_REVNUM;
+ }
svn_pool_destroy(sesspool);
return SVN_NO_ERROR;
}
Modified: subversion/trunk/subversion/libsvn_client/switch.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/switch.c?rev=1308887&r1=1308886&r2=1308887&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/switch.c (original)
+++ subversion/trunk/subversion/libsvn_client/switch.c Tue Apr 3 13:19:45 2012
@@ -197,20 +197,23 @@ switch_internal(svn_revnum_t *result_rev
### okay? */
if (! ignore_ancestry)
{
- const char *target_url, *yc_url;
- svn_revnum_t target_rev, yc_rev;
+ const char *target_url;
+ svn_revnum_t target_rev;
+ svn_client__pathrev_t *switch_loc, *target_loc, *yca;
+ SVN_ERR(svn_client__pathrev_create_with_session(
+ &switch_loc, ra_session, revnum, switch_rev_url, pool));
SVN_ERR(svn_wc__node_get_url(&target_url, ctx->wc_ctx, local_abspath,
pool, pool));
SVN_ERR(svn_wc__node_get_base_rev(&target_rev, ctx->wc_ctx,
local_abspath, pool));
+ SVN_ERR(svn_client__pathrev_create_with_session(
+ &target_loc, ra_session, target_rev, target_url, pool));
/* ### It would be nice if this function could reuse the existing
ra session instead of opening two for its own use. */
- SVN_ERR(svn_client__get_youngest_common_ancestor(NULL, &yc_url, &yc_rev,
- switch_rev_url, revnum,
- target_url, target_rev,
- ctx, pool));
- if (! (yc_url && SVN_IS_VALID_REVNUM(yc_rev)))
+ SVN_ERR(svn_client__get_youngest_common_ancestor(
+ &yca, switch_loc, target_loc, ctx, pool, pool));
+ if (! yca)
return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
_("'%s' shares no common ancestry with '%s'"),
switch_url, local_abspath);
Modified: subversion/trunk/subversion/libsvn_client/util.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/util.c?rev=1308887&r1=1308886&r2=1308887&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/util.c (original)
+++ subversion/trunk/subversion/libsvn_client/util.c Tue Apr 3 13:19:45 2012
@@ -58,6 +58,37 @@ svn_client__pathrev_create(const char *r
}
svn_client__pathrev_t *
+svn_client__pathrev_create_with_relpath(const char *repos_root_url,
+ const char *repos_uuid,
+ svn_revnum_t rev,
+ const char *relpath,
+ apr_pool_t *result_pool)
+{
+ return svn_client__pathrev_create(
+ repos_root_url, repos_uuid, rev,
+ svn_path_url_add_component2(repos_root_url, relpath, result_pool),
+ result_pool);
+}
+
+svn_error_t *
+svn_client__pathrev_create_with_session(svn_client__pathrev_t **pathrev_p,
+ svn_ra_session_t *ra_session,
+ svn_revnum_t rev,
+ const char *url,
+ apr_pool_t *result_pool)
+{
+ svn_client__pathrev_t *pathrev = apr_palloc(result_pool, sizeof(*pathrev));
+
+ SVN_ERR(svn_ra_get_repos_root2(ra_session, &pathrev->repos_root_url,
+ result_pool));
+ SVN_ERR(svn_ra_get_uuid2(ra_session, &pathrev->repos_uuid, result_pool));
+ pathrev->rev = rev;
+ pathrev->url = url;
+ *pathrev_p = pathrev;
+ return SVN_NO_ERROR;
+}
+
+svn_client__pathrev_t *
svn_client__pathrev_dup(const svn_client__pathrev_t *loc,
apr_pool_t *result_pool)
{
@@ -65,6 +96,14 @@ svn_client__pathrev_dup(const svn_client
loc->rev, loc->url, result_pool);
}
+const char *
+svn_client__pathrev_relpath(const svn_client__pathrev_t *pathrev,
+ apr_pool_t *result_pool)
+{
+ return svn_uri_skip_ancestor(pathrev->repos_root_url, pathrev->url,
+ result_pool);
+}
+
svn_client_commit_item3_t *
svn_client_commit_item3_create(apr_pool_t *pool)
{
Modified: subversion/trunk/subversion/tests/libsvn_client/client-test.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_client/client-test.c?rev=1308887&r1=1308886&r2=1308887&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_client/client-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_client/client-test.c Tue Apr 3
13:19:45 2012
@@ -656,14 +656,14 @@ test_youngest_common_ancestor(const svn_
apr_pool_t *pool)
{
const char *repos_url;
+ const char *repos_uuid = "fake-uuid"; /* the functions we call don't care */
svn_client_ctx_t *ctx;
svn_opt_revision_t head_rev = { svn_opt_revision_head, { 0 } };
svn_opt_revision_t zero_rev = { svn_opt_revision_number, { 0 } };
svn_client_copy_source_t source;
apr_array_header_t *sources;
const char *dest;
- const char *yc_ancestor_relpath;
- svn_revnum_t yc_ancestor_rev;
+ svn_client__pathrev_t *yc_ancestor;
/* Create a filesytem and repository containing the Greek tree. */
SVN_ERR(create_greek_repos(&repos_url, "test-youngest-common-ancestor",
opts, pool));
@@ -684,12 +684,15 @@ test_youngest_common_ancestor(const svn_
/* Test: YCA(iota@2, A/iota@2) is iota@1. */
SVN_ERR(svn_client__get_youngest_common_ancestor(
- &yc_ancestor_relpath, NULL, &yc_ancestor_rev,
- svn_path_url_add_component2(repos_url, "iota", pool), 2,
- svn_path_url_add_component2(repos_url, "A/iota", pool), 2,
- ctx, pool));
- SVN_TEST_STRING_ASSERT(yc_ancestor_relpath, "iota");
- SVN_TEST_ASSERT(yc_ancestor_rev == 1);
+ &yc_ancestor,
+ svn_client__pathrev_create_with_relpath(
+ repos_url, repos_uuid, 2, "iota", pool),
+ svn_client__pathrev_create_with_relpath(
+ repos_url, repos_uuid, 2, "A/iota", pool),
+ ctx, pool, pool));
+ SVN_TEST_STRING_ASSERT(svn_client__pathrev_relpath(yc_ancestor, pool),
+ "iota");
+ SVN_TEST_ASSERT(yc_ancestor->rev == 1);
/* Copy the root directory (at revision 0) into A as 'ROOT'. */
sources = apr_array_make(pool, 1, sizeof(svn_client_copy_source_t *));
@@ -705,12 +708,14 @@ test_youngest_common_ancestor(const svn_
/* Test: YCA(''@0, A/ROOT@3) is ''@0 (handled as a special case). */
SVN_ERR(svn_client__get_youngest_common_ancestor(
- &yc_ancestor_relpath, NULL, &yc_ancestor_rev,
- svn_path_url_add_component2(repos_url, "", pool), 0,
- svn_path_url_add_component2(repos_url, "A/ROOT", pool), 3,
- ctx, pool));
- SVN_TEST_STRING_ASSERT(yc_ancestor_relpath, "");
- SVN_TEST_ASSERT(yc_ancestor_rev == 0);
+ &yc_ancestor,
+ svn_client__pathrev_create_with_relpath(
+ repos_url, repos_uuid, 0, "", pool),
+ svn_client__pathrev_create_with_relpath(
+ repos_url, repos_uuid, 3, "A/ROOT", pool),
+ ctx, pool, pool));
+ SVN_TEST_STRING_ASSERT(svn_client__pathrev_relpath(yc_ancestor, pool), "");
+ SVN_TEST_ASSERT(yc_ancestor->rev == 0);
return SVN_NO_ERROR;
}