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;
 }


Reply via email to