Author: rhuijben
Date: Thu Dec 19 09:46:43 2013
New Revision: 1552265

URL: http://svn.apache.org/r1552265
Log:
Re-use ra sessions when determining where a path is copied from using a
libsvn_client internal api. Give public api a caller from our test suite
by adding a simple C test.

* subversion/libsvn_client/client.h
  (svn_client__get_copy_source): Add argument.

* subversion/libsvn_client/log.c
  (svn_client__get_copy_source): Add support for using an existing session.

* subversion/libsvn_client/merge.c
  (normalize_merge_sources_internal): Pass existing ra session.

* subversion/libsvn_client/mergeinfo.c
  (svn_client_suggest_merge_sources): Open ra session and pass it to two
    functions instead of having them create and close their own sessions.
    Use subpool.

* subversion/tests/libsvn_client/client-test.c
  (test_suggest_mergesources): New test.
  (test_funcs): Add test_suggest_mergesources.

Modified:
    subversion/trunk/subversion/libsvn_client/client.h
    subversion/trunk/subversion/libsvn_client/log.c
    subversion/trunk/subversion/libsvn_client/merge.c
    subversion/trunk/subversion/libsvn_client/mergeinfo.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=1552265&r1=1552264&r2=1552265&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Thu Dec 19 09:46:43 2013
@@ -93,12 +93,17 @@ svn_client__get_revision_number(svn_revn
 /* Set *ORIGINAL_REPOS_RELPATH and *ORIGINAL_REVISION to the original location
    that served as the source of the copy from which PATH_OR_URL at REVISION was
    created, or NULL and SVN_INVALID_REVNUM (respectively) if PATH_OR_URL at
-   REVISION was not the result of a copy operation. */
+   REVISION was not the result of a copy operation.
+
+   If RA_SESSION is not NULL it is an existing session to the repository that
+   might be reparented temporarily to obtain the information.
+   */
 svn_error_t *
 svn_client__get_copy_source(const char **original_repos_relpath,
                             svn_revnum_t *original_revision,
                             const char *path_or_url,
                             const svn_opt_revision_t *revision,
+                            svn_ra_session_t *ra_session,
                             svn_client_ctx_t *ctx,
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool);

Modified: subversion/trunk/subversion/libsvn_client/log.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/log.c?rev=1552265&r1=1552264&r2=1552265&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/log.c (original)
+++ subversion/trunk/subversion/libsvn_client/log.c Thu Dec 19 09:46:43 2013
@@ -96,6 +96,7 @@ svn_client__get_copy_source(const char *
                             svn_revnum_t *original_revision,
                             const char *path_or_url,
                             const svn_opt_revision_t *revision,
+                            svn_ra_session_t *ra_session,
                             svn_client_ctx_t *ctx,
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool)
@@ -103,18 +104,49 @@ svn_client__get_copy_source(const char *
   svn_error_t *err;
   copyfrom_info_t copyfrom_info = { 0 };
   apr_pool_t *sesspool = svn_pool_create(scratch_pool);
-  svn_ra_session_t *ra_session;
   svn_client__pathrev_t *at_loc;
+  const char *old_session_url = NULL;
 
   copyfrom_info.is_first = TRUE;
   copyfrom_info.path = NULL;
   copyfrom_info.rev = SVN_INVALID_REVNUM;
   copyfrom_info.pool = result_pool;
 
-  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &at_loc,
-                                            path_or_url, NULL,
-                                            revision, revision,
-                                            ctx, sesspool));
+  if (!ra_session)
+    {
+      SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &at_loc,
+                                                path_or_url, NULL,
+                                                revision, revision,
+                                                ctx, sesspool));
+    }
+  else
+    {
+      const char *url;
+      if (svn_path_is_url(path_or_url))
+        url = path_or_url;
+      else
+        {
+          SVN_ERR(svn_client_url_from_path2(&url, path_or_url, ctx, sesspool,
+                                            sesspool));
+
+          return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
+                                   _("'%s' has no URL"), path_or_url);
+        }
+
+      SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
+                                                url, sesspool));
+
+      err = svn_client__resolve_rev_and_url(&at_loc, ra_session, path_or_url,
+                                            revision, revision, ctx,
+                                            sesspool);
+
+      /* On error reparent back (and return), otherwise reparent to new
+         location */
+      SVN_ERR(svn_error_compose_create(
+                err,
+                svn_ra_reparent(ra_session, err ? old_session_url
+                                                : at_loc->url, sesspool)));
+    }
 
   /* Find the copy source.  Walk the location segments to find the revision
      at which this node was created (copied or added). */
@@ -124,6 +156,11 @@ svn_client__get_copy_source(const char *
                                      copyfrom_info_receiver, &copyfrom_info,
                                      scratch_pool);
 
+  if (old_session_url)
+    err = svn_error_compose_create(
+                    err,
+                    svn_ra_reparent(ra_session, old_session_url, sesspool));
+
   svn_pool_destroy(sesspool);
 
   if (err)

Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1552265&r1=1552264&r2=1552265&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Thu Dec 19 09:46:43 2013
@@ -7066,7 +7066,8 @@ normalize_merge_sources_internal(apr_arr
               SVN_ERR(svn_client__get_copy_source(&original_repos_relpath,
                                                   &original_revision,
                                                   segment_url,
-                                                  &range_start_rev, ctx,
+                                                  &range_start_rev,
+                                                  ra_session, ctx,
                                                   result_pool, scratch_pool));
               /* Got copyfrom data?  Fix up the first segment to cover
                  back to COPYFROM_REV + 1, and then prepend a new

Modified: subversion/trunk/subversion/libsvn_client/mergeinfo.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/mergeinfo.c?rev=1552265&r1=1552264&r2=1552265&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_client/mergeinfo.c Thu Dec 19 09:46:43 
2013
@@ -2231,6 +2231,8 @@ svn_client_suggest_merge_sources(apr_arr
   svn_mergeinfo_catalog_t mergeinfo_cat;
   svn_mergeinfo_t mergeinfo;
   apr_hash_index_t *hi;
+  apr_pool_t *session_pool = svn_pool_create(pool);
+  svn_ra_session_t *ra_session;
 
   list = apr_array_make(pool, 1, sizeof(const char *));
 
@@ -2249,17 +2251,21 @@ svn_client_suggest_merge_sources(apr_arr
         1. The copyfrom source.
         2. All remaining merge sources (unordered).
   */
+  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, NULL, path_or_url,
+                                            NULL, peg_revision, peg_revision,
+                                            ctx, session_pool));
 
-  /* ### TODO: Share ra_session batons to improve efficiency? */
   SVN_ERR(get_mergeinfo(&mergeinfo_cat, &repos_root, path_or_url,
-                        peg_revision, FALSE, FALSE, ctx, NULL, pool, pool));
+                        peg_revision, FALSE, FALSE,
+                        ctx, ra_session, session_pool, session_pool));
 
   if (mergeinfo_cat && apr_hash_count(mergeinfo_cat))
     {
       /* We asked only for the PATH_OR_URL's mergeinfo, not any of its
          descendants.  So if there is anything in the catalog it is the
          mergeinfo for PATH_OR_URL. */
-      mergeinfo = svn__apr_hash_index_val(apr_hash_first(pool, mergeinfo_cat));
+      mergeinfo = svn__apr_hash_index_val(apr_hash_first(session_pool,
+                                                         mergeinfo_cat));
     }
   else
     {
@@ -2267,17 +2273,19 @@ svn_client_suggest_merge_sources(apr_arr
     }
 
   SVN_ERR(svn_client__get_copy_source(&copyfrom_path, &copyfrom_rev,
-                                      path_or_url, peg_revision, ctx,
-                                      pool, pool));
+                                      path_or_url, peg_revision, ra_session,
+                                      ctx, session_pool, session_pool));
   if (copyfrom_path)
     {
       APR_ARRAY_PUSH(list, const char *) =
-        svn_path_url_add_component2(repos_root, copyfrom_path, pool);
+        svn_path_url_add_component2(repos_root, copyfrom_path, session_pool);
     }
 
   if (mergeinfo)
     {
-      for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
+      for (hi = apr_hash_first(session_pool, mergeinfo);
+           hi;
+           hi = apr_hash_next(hi))
         {
           const char *rel_path = svn__apr_hash_index_key(hi);
 
@@ -2287,6 +2295,8 @@ svn_client_suggest_merge_sources(apr_arr
         }
     }
 
+  svn_pool_destroy(session_pool);
+
   *suggestions = list;
   return SVN_NO_ERROR;
 }

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=1552265&r1=1552264&r2=1552265&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_client/client-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_client/client-test.c Thu Dec 19 
09:46:43 2013
@@ -769,6 +769,39 @@ test_foreign_repos_copy(const svn_test_o
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_suggest_mergesources(const svn_test_opts_t *opts,
+                          apr_pool_t *pool)
+{
+  const char *repos_url;
+  svn_client_ctx_t *ctx;
+  svn_client_mtcc_t *mtcc;
+  apr_array_header_t *results;
+  svn_opt_revision_t peg_rev;
+
+  peg_rev.kind = svn_opt_revision_unspecified;
+
+  /* Create a filesytem and repository containing the Greek tree. */
+  SVN_ERR(create_greek_repos(&repos_url, "mergesources", opts, pool));
+
+  SVN_ERR(svn_client_create_context(&ctx, pool));
+
+  SVN_ERR(svn_client_mtcc_create(&mtcc, repos_url, -1, ctx, pool, pool));
+  SVN_ERR(svn_client_mtcc_add_copy("A", 1, "AA", mtcc, pool));
+  SVN_ERR(svn_client_mtcc_commit(NULL, NULL, NULL, mtcc, pool));
+
+  SVN_ERR(svn_client_suggest_merge_sources(
+                    &results,
+                    svn_path_url_add_component2(repos_url, "AA", pool),
+                    &peg_rev, ctx, pool));
+  SVN_TEST_ASSERT(results != NULL);
+  SVN_TEST_ASSERT(results->nelts >= 1);
+  SVN_TEST_STRING_ASSERT(APR_ARRAY_IDX(results, 0, const char *),
+                          svn_path_url_add_component2(repos_url, "A", pool));
+
+  return SVN_NO_ERROR;
+}
+
 /* ========================================================================== 
*/
 
 
@@ -789,5 +822,7 @@ struct svn_test_descriptor_t test_funcs[
     SVN_TEST_OPTS_PASS(test_16k_add, "test adding 16k files"),
 #endif
     SVN_TEST_OPTS_PASS(test_youngest_common_ancestor, "test 
youngest_common_ancestor"),
+    SVN_TEST_OPTS_PASS(test_suggest_mergesources,
+                       "test svn_client_suggest_merge_sources"),
     SVN_TEST_NULL
   };


Reply via email to