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/12/15 10:53:59 UTC

svn commit: r1214677 - in /subversion/trunk/subversion: libsvn_client/client.h libsvn_client/merge.c libsvn_client/ra.c libsvn_client/switch.c tests/libsvn_client/client-test.c

Author: julianfoad
Date: Thu Dec 15 09:53:59 2011
New Revision: 1214677

URL: http://svn.apache.org/viewvc?rev=1214677&view=rev
Log:
Teach svn_client__get_youngest_common_ancestor() to output the ancestor as a
URL as well as a relpath, because some existing callers want that and it
will also simplify writing a higher level version of this API which I intend
to do next.

* subversion/libsvn_client/client.h
* subversion/libsvn_client/ra.c
  (svn_client__get_youngest_common_ancestor): Add a URL output. Make all the
    outputs optional. Improve documentation.

* subversion/libsvn_client/merge.c
  (merge_locked, calculate_left_hand_side, find_reintegrate_merge): Adjust
    calls.

* subversion/libsvn_client/switch.c
  (switch_internal): Same.

* subversion/tests/libsvn_client/client-test.c
  (test_youngest_common_ancestor): Same.

Modified:
    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/tests/libsvn_client/client-test.c

Modified: subversion/trunk/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=1214677&r1=1214676&r2=1214677&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Thu Dec 15 09:53:59 2011
@@ -185,17 +185,24 @@ svn_client__repos_location_segments(apr_
                                     apr_pool_t *pool);
 
 
-/* Set *ANCESTOR_RELPATH and *ANCESTOR_REVISION to the youngest common
-   ancestor path (a path relative to the root of the repository, with
-   no leading '/') and revision, respectively, of the two locations
-   identified as URL1@REV1 and URL2@REV2.  Set *ANCESTOR_RELPATH to
-   NULL and *ANCESTOR_REVISION to SVN_INVALID_REVNUM if they have no
-   common ancestor.  Use the authentication baton cached in CTX to
-   authenticate against the repository.  This function assumes that
-   URL1@REV1 and URL2@REV2 both refer to the same repository.  Use
-   POOL for all allocations. */
+/* Find the common ancestor of two locations in a repository.
+   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.
+
+   Use the authentication baton cached in CTX to authenticate against
+   the repository.  Use POOL for all allocations.
+*/
 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,

Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1214677&r1=1214676&r2=1214677&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Thu Dec 15 09:53:59 2011
@@ -9356,7 +9356,7 @@ merge_locked(const char *source1,
   apr_array_header_t *merge_sources;
   svn_error_t *err;
   svn_boolean_t use_sleep = FALSE;
-  const char *yc_relpath = NULL;
+  const char *yc_url = NULL;
   svn_revnum_t yc_rev = SVN_INVALID_REVNUM;
   apr_pool_t *sesspool;
   svn_boolean_t same_repos;
@@ -9412,7 +9412,7 @@ merge_locked(const char *source1,
 
   /* Unless we're ignoring ancestry, see if the two sources are related.  */
   if (! ignore_ancestry)
-    SVN_ERR(svn_client__get_youngest_common_ancestor(&yc_relpath, &yc_rev,
+    SVN_ERR(svn_client__get_youngest_common_ancestor(NULL, &yc_url, &yc_rev,
                                                      source.url1, source.rev1,
                                                      source.url2, source.rev2,
                                                      ctx, scratch_pool));
@@ -9434,12 +9434,8 @@ merge_locked(const char *source1,
                       merge recording, then record-only two merges:
                       from A to C, and from C to B
   */
-  if (yc_relpath && SVN_IS_VALID_REVNUM(yc_rev))
+  if (yc_url && SVN_IS_VALID_REVNUM(yc_rev))
     {
-      /* Make YC_RELPATH into a full URL. */
-      const char *yc_url = svn_path_url_add_component2(source_repos_root.url,
-                                                       yc_relpath, scratch_pool);
-
       /* Note that our merge sources are related. */
       related = TRUE;
 
@@ -10303,7 +10299,7 @@ calculate_left_hand_side(const char **ur
   apr_hash_t *segments_hash = apr_hash_make(scratch_pool);
   svn_boolean_t never_synced;
   svn_revnum_t youngest_merged_rev;
-  const char *yc_ancestor_relpath;
+  const char *yc_ancestor_url;
   svn_revnum_t yc_ancestor_rev;
   const char *source_url;
   const char *target_url;
@@ -10362,12 +10358,12 @@ calculate_left_hand_side(const char **ur
   target_url = svn_path_url_add_component2(source_repos_root,
                                            target_repos_rel_path,
                                            iterpool);
-  SVN_ERR(svn_client__get_youngest_common_ancestor(&yc_ancestor_relpath,
+  SVN_ERR(svn_client__get_youngest_common_ancestor(NULL, &yc_ancestor_url,
                                                    &yc_ancestor_rev,
                                                    source_url, source_rev,
                                                    target_url, target_rev,
                                                    ctx, iterpool));
-  if (!(yc_ancestor_relpath && SVN_IS_VALID_REVNUM(yc_ancestor_rev)))
+  if (!(yc_ancestor_url && SVN_IS_VALID_REVNUM(yc_ancestor_rev)))
     return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
                              _("'%s@%ld' must be ancestrally related to "
                                "'%s@%ld'"), source_url, source_rev,
@@ -10429,8 +10425,7 @@ calculate_left_hand_side(const char **ur
   if (never_synced)
     {
       /* We never merged to the source.  Just return the branch point. */
-      *url_left = svn_path_url_add_component2(source_repos_root,
-                                              yc_ancestor_relpath, result_pool);
+      *url_left = apr_pstrdup(result_pool, yc_ancestor_url);
       *rev_left = yc_ancestor_rev;
     }
   else
@@ -10590,7 +10585,7 @@ find_reintegrate_merge(svn_ra_session_t 
   if (strcmp(source.url1, target_url))
     SVN_ERR(svn_ra_reparent(target_ra_session, source.url1, scratch_pool));
 
-  SVN_ERR(svn_client__get_youngest_common_ancestor(&yc_ancestor_relpath,
+  SVN_ERR(svn_client__get_youngest_common_ancestor(&yc_ancestor_relpath, NULL,
                                                    &yc_ancestor_rev,
                                                    source.url2, source.rev2,
                                                    source.url1, source.rev1,

Modified: subversion/trunk/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/ra.c?rev=1214677&r1=1214676&r2=1214677&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/ra.c (original)
+++ subversion/trunk/subversion/libsvn_client/ra.c Thu Dec 15 09:53:59 2011
@@ -801,6 +801,7 @@ 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,
@@ -811,6 +812,7 @@ svn_client__get_youngest_common_ancestor
 {
   apr_pool_t *sesspool = svn_pool_create(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;
@@ -820,6 +822,7 @@ svn_client__get_youngest_common_ancestor
 
   /* 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));
 
   /* We're going to cheat and use history-as-mergeinfo because it
      saves us a bunch of annoying custom data comparisons and such. */
@@ -878,7 +881,13 @@ svn_client__get_youngest_common_ancestor
       yc_revision = 0;
     }
 
-  *ancestor_relpath = yc_relpath;
-  *ancestor_revision = yc_revision;
+  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;
   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=1214677&r1=1214676&r2=1214677&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/switch.c (original)
+++ subversion/trunk/subversion/libsvn_client/switch.c Thu Dec 15 09:53:59 2011
@@ -197,7 +197,7 @@ switch_internal(svn_revnum_t *result_rev
      ### okay? */
   if (! ignore_ancestry)
     {
-      const char *target_url, *yc_relpath;
+      const char *target_url, *yc_url;
       svn_revnum_t target_rev, yc_rev;
 
       SVN_ERR(svn_wc__node_get_url(&target_url, ctx->wc_ctx, local_abspath,
@@ -206,11 +206,11 @@ switch_internal(svn_revnum_t *result_rev
                                         local_abspath, 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(&yc_relpath, &yc_rev,
+      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_relpath && SVN_IS_VALID_REVNUM(yc_rev)))
+      if (! (yc_url && SVN_IS_VALID_REVNUM(yc_rev)))
         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/tests/libsvn_client/client-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_client/client-test.c?rev=1214677&r1=1214676&r2=1214677&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_client/client-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_client/client-test.c Thu Dec 15 09:53:59 2011
@@ -684,7 +684,7 @@ 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, &yc_ancestor_rev,
+            &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));
@@ -705,7 +705,7 @@ 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, &yc_ancestor_rev,
+            &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));



Re: svn commit: r1214677 - in /subversion/trunk/subversion: libsvn_client/client.h libsvn_client/merge.c libsvn_client/ra.c libsvn_client/switch.c tests/libsvn_client/client-test.c

Posted by Julian Foad <ju...@btopenworld.com>.
C. Michael Pilato wrote:

> On 12/15/2011 04:53 AM, julianfoad@apache.org wrote:
>>  Teach svn_client__get_youngest_common_ancestor() to output the ancestor as 
>> a  URL as well as a relpath, because some existing callers want that and it
>>  will also simplify writing a higher level version of this API which I 
>> intend  to do next.
> 
> May I suggest that if you plan to publicize this functionality, you let the
> server do this YCA calculation with a new RA function, only falling back to
> the client-side calculation when communicating with older servers?

That sounds like a good optimization to make if and when we find this operation becoming frequently used and inefficient.  I'm certainly not opposed to it but at the moment it doesn't appear to be either very frequent (assuming once or twice or so per merge is OK) or too inefficient.

While I'm first putting an extra call to it in the 'svn' client, the same code path goes on to call one of the libsvn_client merge functions and those also call get_youngest_common_ancestor in some cases, so by refactoring I may be able to eliminate the duplication.

- Julian

Re: svn commit: r1214677 - in /subversion/trunk/subversion: libsvn_client/client.h libsvn_client/merge.c libsvn_client/ra.c libsvn_client/switch.c tests/libsvn_client/client-test.c

Posted by "C. Michael Pilato" <cm...@collab.net>.
On 12/15/2011 04:53 AM, julianfoad@apache.org wrote:
> Author: julianfoad
> Date: Thu Dec 15 09:53:59 2011
> New Revision: 1214677
> 
> URL: http://svn.apache.org/viewvc?rev=1214677&view=rev
> Log:
> Teach svn_client__get_youngest_common_ancestor() to output the ancestor as a
> URL as well as a relpath, because some existing callers want that and it
> will also simplify writing a higher level version of this API which I intend
> to do next.

May I suggest that if you plan to publicize this functionality, you let the
server do this YCA calculation with a new RA function, only falling back to
the client-side calculation when communicating with older servers?

-- 
C. Michael Pilato <cm...@collab.net>
CollabNet   <>   www.collab.net   <>   Distributed Development On Demand