You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/05/16 16:57:42 UTC

svn commit: r1339210 [1/3] - in /subversion/branches/ev2-export: ./ build/generator/templates/ contrib/server-side/ subversion/include/ subversion/libsvn_client/ subversion/libsvn_ra/ subversion/libsvn_ra_serf/ subversion/libsvn_repos/ subversion/libsv...

Author: hwright
Date: Wed May 16 14:57:41 2012
New Revision: 1339210

URL: http://svn.apache.org/viewvc?rev=1339210&view=rev
Log:
On the ev2-export branch:
Bring up-to-date with trunk.

(Hey, at least it's been 2 days since the last merge.)

Removed:
    subversion/branches/ev2-export/contrib/server-side/svn-fast-backup
Modified:
    subversion/branches/ev2-export/   (props changed)
    subversion/branches/ev2-export/CHANGES
    subversion/branches/ev2-export/build/generator/templates/vcnet_vcxproj.ezt
    subversion/branches/ev2-export/subversion/include/svn_types.h
    subversion/branches/ev2-export/subversion/libsvn_client/blame.c
    subversion/branches/ev2-export/subversion/libsvn_client/cat.c
    subversion/branches/ev2-export/subversion/libsvn_client/client.h
    subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c
    subversion/branches/ev2-export/subversion/libsvn_client/diff.c
    subversion/branches/ev2-export/subversion/libsvn_client/export.c
    subversion/branches/ev2-export/subversion/libsvn_client/list.c
    subversion/branches/ev2-export/subversion/libsvn_client/log.c
    subversion/branches/ev2-export/subversion/libsvn_client/merge.c
    subversion/branches/ev2-export/subversion/libsvn_client/mergeinfo.c
    subversion/branches/ev2-export/subversion/libsvn_client/prop_commands.c
    subversion/branches/ev2-export/subversion/libsvn_client/ra.c
    subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/log.c
    subversion/branches/ev2-export/subversion/libsvn_repos/replay.c
    subversion/branches/ev2-export/subversion/libsvn_subr/io.c
    subversion/branches/ev2-export/subversion/libsvn_subr/skel.c
    subversion/branches/ev2-export/subversion/libsvn_subr/stream.c
    subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c
    subversion/branches/ev2-export/subversion/svnsync/sync.c
    subversion/branches/ev2-export/subversion/tests/cmdline/authz_tests.py
    subversion/branches/ev2-export/subversion/tests/cmdline/diff_tests.py
    subversion/branches/ev2-export/subversion/tests/cmdline/import_tests.py
    subversion/branches/ev2-export/subversion/tests/cmdline/log_tests.py

Propchange: subversion/branches/ev2-export/
------------------------------------------------------------------------------
  Merged /subversion/trunk:r1338208-1339207

Modified: subversion/branches/ev2-export/CHANGES
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/CHANGES?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/CHANGES (original)
+++ subversion/branches/ev2-export/CHANGES Wed May 16 14:57:41 2012
@@ -19,6 +19,7 @@ http://svn.apache.org/repos/asf/subversi
     * new SVNUseUTF8 configuration option for mod_dav_svn (issue #2487)
     * new SVNHooksEnv configuration option for mod_dav_svn (r1239966)
     * new --ignore-properties option for 'svn diff' (r1239553. -617)
+    * new --properties-only option for 'svn diff' (r1336110)
     * new --patch-compatible option for 'svn diff' (r1239561)
     * new SvnPubSub distributed commit hooks (tools/server-side/svnpubsub)
     * 'svn diff' can compare arbitrary files and directories (r1310291, et al)

Modified: subversion/branches/ev2-export/build/generator/templates/vcnet_vcxproj.ezt
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/build/generator/templates/vcnet_vcxproj.ezt?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/build/generator/templates/vcnet_vcxproj.ezt (original)
+++ subversion/branches/ev2-export/build/generator/templates/vcnet_vcxproj.ezt Wed May 16 14:57:41 2012
@@ -33,7 +33,8 @@
 [for platforms][for configs]  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='[configs.name]|[platforms]'" Label="Configuration">
     <ConfigurationType>[config_type]</ConfigurationType>
     <UseDebugLibraries>[is configs.name "Debug"]true[else]false[end]</UseDebugLibraries>
-    <PlatformToolset>[toolset_version]</PlatformToolset>
+[is configs.name "Release"]    <WholeProgramOptimization>true</WholeProgramOptimization>
+[end]    <PlatformToolset>[toolset_version]</PlatformToolset>
   </PropertyGroup>
 [end][end]  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">

Modified: subversion/branches/ev2-export/subversion/include/svn_types.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/svn_types.h?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/svn_types.h (original)
+++ subversion/branches/ev2-export/subversion/include/svn_types.h Wed May 16 14:57:41 2012
@@ -910,6 +910,10 @@ typedef struct svn_log_entry_t
    * Whether @a revision should be interpreted as non-inheritable in the
    * same sense of #svn_merge_range_t.
    *
+   * Only set when this #svn_log_entry_t instance is returned by the
+   * libsvn_client mergeinfo apis. Currently always FALSE when the
+   * #svn_log_entry_t instance is reported by the ra layer.
+   *
    * @since New in 1.7.
    */
   svn_boolean_t non_inheritable;

Modified: subversion/branches/ev2-export/subversion/libsvn_client/blame.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/blame.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/blame.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/blame.c Wed May 16 14:57:41 2012
@@ -593,6 +593,7 @@ svn_client_blame5(const char *target,
   struct file_rev_baton frb;
   svn_ra_session_t *ra_session;
   svn_revnum_t start_revnum, end_revnum;
+  svn_client__pathrev_t *end_loc;
   struct blame *walk, *walk_merged = NULL;
   apr_pool_t *iterpool;
   svn_stream_t *last_stream;
@@ -610,9 +611,10 @@ svn_client_blame5(const char *target,
     SVN_ERR(svn_dirent_get_absolute(&target_abspath_or_url, target, pool));
 
   /* Get an RA plugin for this filesystem object. */
-  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &end_revnum, NULL,
-                                           target, NULL, peg_revision, end,
-                                           ctx, pool));
+  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &end_loc,
+                                            target, NULL, peg_revision, end,
+                                            ctx, pool));
+  end_revnum = end_loc->rev;
 
   SVN_ERR(svn_client__get_revision_number(&start_revnum, NULL, ctx->wc_ctx,
                                           target_abspath_or_url, ra_session,

Modified: subversion/branches/ev2-export/subversion/libsvn_client/cat.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/cat.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/cat.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/cat.c Wed May 16 14:57:41 2012
@@ -183,11 +183,10 @@ svn_client_cat2(svn_stream_t *out,
                 apr_pool_t *pool)
 {
   svn_ra_session_t *ra_session;
-  svn_revnum_t rev;
+  svn_client__pathrev_t *loc;
   svn_string_t *eol_style;
   svn_string_t *keywords;
   apr_hash_t *props;
-  const char *url;
   svn_stream_t *output = out;
   svn_error_t *err;
 
@@ -227,20 +226,21 @@ svn_client_cat2(svn_stream_t *out,
     }
 
   /* Get an RA plugin for this filesystem object. */
-  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &rev,
-                                           &url, path_or_url, NULL,
-                                           peg_revision,
-                                           revision, ctx, pool));
+  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
+                                            path_or_url, NULL,
+                                            peg_revision,
+                                            revision, ctx, pool));
 
   /* Grab some properties we need to know in order to figure out if anything
      special needs to be done with this file. */
-  err = svn_ra_get_file(ra_session, "", rev, NULL, NULL, &props, pool);
+  err = svn_ra_get_file(ra_session, "", loc->rev, NULL, NULL, &props, pool);
   if (err)
     {
       if (err->apr_err == SVN_ERR_FS_NOT_FILE)
         {
           return svn_error_createf(SVN_ERR_CLIENT_IS_DIRECTORY, err,
-                                   _("URL '%s' refers to a directory"), url);
+                                   _("URL '%s' refers to a directory"),
+                                   loc->url);
         }
       else
         {
@@ -284,7 +284,7 @@ svn_client_cat2(svn_stream_t *out,
           SVN_ERR(svn_subst_build_keywords2
                   (&kw, keywords->data,
                    cmt_rev->data,
-                   url,
+                   loc->url,
                    when,
                    cmt_author ? cmt_author->data : NULL,
                    pool));
@@ -297,7 +297,7 @@ svn_client_cat2(svn_stream_t *out,
                                            eol_str, FALSE, kw, TRUE, pool);
     }
 
-  SVN_ERR(svn_ra_get_file(ra_session, "", rev, output, NULL, NULL, pool));
+  SVN_ERR(svn_ra_get_file(ra_session, "", loc->rev, output, NULL, NULL, pool));
 
   if (out != output)
     /* Close the interjected stream */

Modified: subversion/branches/ev2-export/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/client.h?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/client.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/client.h Wed May 16 14:57:41 2012
@@ -227,29 +227,15 @@ svn_client__get_youngest_common_ancestor
    for a URL or 'working' for a WC path.  If REVISION->kind is
    'unspecified', the operative revision is the peg revision.
 
-   Store the resulting ra_session in *RA_SESSION_P.  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 resulting ra_session in *RA_SESSION_P.  Store the final
+   resolved location of the object in *RESOLVED_LOC_P.  RESOLVED_LOC_P
+   may be NULL if not wanted.
 
    Use authentication baton cached in CTX to authenticate against the
    repository.
 
    Use POOL for all allocations. */
 svn_error_t *
-svn_client__ra_session_from_path(svn_ra_session_t **ra_session_p,
-                                 svn_revnum_t *rev_p,
-                                 const char **url_p,
-                                 const char *path_or_url,
-                                 const char *base_dir_abspath,
-                                 const svn_opt_revision_t *peg_revision,
-                                 const svn_opt_revision_t *revision,
-                                 svn_client_ctx_t *ctx,
-                                 apr_pool_t *pool);
-
-/* Like svn_client__ra_session_from_path() but returning a path-rev
- * instead of separate URL and rev outputs.  RESOLVED_LOC_P may be NULL
- * if not wanted. */
-svn_error_t *
 svn_client__ra_session_from_path2(svn_ra_session_t **ra_session_p,
                                  svn_client__pathrev_t **resolved_loc_p,
                                  const char *path_or_url,

Modified: subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c Wed May 16 14:57:41 2012
@@ -194,7 +194,11 @@ fixup_commit_error(const char *local_abs
 
 /* Add a new commit candidate (described by all parameters except
    `COMMITTABLES') to the COMMITTABLES hash.  All of the commit item's
-   members are allocated out of RESULT_POOL. */
+   members are allocated out of RESULT_POOL.
+
+   If the state flag specifies that a lock must be used, store the token in LOCK
+   in lock_tokens.
+ */
 static svn_error_t *
 add_committable(svn_client__committables_t *committables,
                 const char *local_abspath,
@@ -205,6 +209,8 @@ add_committable(svn_client__committables
                 const char *copyfrom_relpath,
                 svn_revnum_t copyfrom_rev,
                 apr_byte_t state_flags,
+                apr_hash_t *lock_tokens,
+                const svn_lock_t *lock,
                 apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
 {
@@ -260,6 +266,16 @@ add_committable(svn_client__committables
                APR_HASH_KEY_STRING,
                new_item);
 
+  if (lock
+      && lock_tokens
+      && (state_flags & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN))
+    {
+      apr_hash_set(lock_tokens,
+                   new_item->url,
+                   APR_HASH_KEY_STRING,
+                   apr_pstrdup(result_pool, lock->token));
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -414,6 +430,8 @@ harvest_committables(const char *local_a
 {
   struct harvest_baton baton;
 
+  SVN_ERR_ASSERT((just_locked && lock_tokens) || !just_locked);
+
   baton.root_abspath = local_abspath;
   baton.committables = committables;
   baton.lock_tokens = lock_tokens;
@@ -529,6 +547,7 @@ harvest_not_present_for_copy(svn_wc_cont
                               NULL /* copyfrom_relpath */,
                               SVN_INVALID_REVNUM /* copyfrom_rev */,
                               SVN_CLIENT_COMMIT_ITEM_DELETE,
+                              NULL, NULL,
                               result_pool, scratch_pool));
     }
 
@@ -561,13 +580,11 @@ harvest_status_callback(void *status_bat
   svn_boolean_t is_harvest_root = 
                 (strcmp(baton->root_abspath, local_abspath) == 0);
   svn_client__committables_t *committables = baton->committables;
-  apr_hash_t *lock_tokens = baton->lock_tokens;
   const char *repos_root_url = status->repos_root_url;
   const char *commit_relpath = NULL;
   svn_boolean_t copy_mode_root = (baton->commit_relpath && is_harvest_root);
   svn_boolean_t just_locked = baton->just_locked;
   apr_hash_t *changelists = baton->changelists;
-  apr_hash_t *danglers = baton->danglers;
   svn_wc_notify_func2_t notify_func = baton->notify_func;
   void *notify_baton = baton->notify_baton;
   svn_wc_context_t *wc_ctx = baton->wc_ctx;
@@ -631,7 +648,6 @@ harvest_status_callback(void *status_bat
   SVN_ERR_ASSERT((copy_mode && commit_relpath)
                  || (! copy_mode && ! commit_relpath));
   SVN_ERR_ASSERT((copy_mode_root && copy_mode) || ! copy_mode_root);
-  SVN_ERR_ASSERT((just_locked && lock_tokens) || !just_locked);
 
   /* Save the result for reuse. */
   matches_changelists = ((changelists == NULL)
@@ -829,52 +845,43 @@ harvest_status_callback(void *status_bat
   /* If the entry has a lock token and it is already a commit candidate,
      or the caller wants unmodified locked items to be treated as
      such, note this fact. */
-  if (status->lock && lock_tokens && (state_flags || just_locked))
+  if (status->lock && baton->lock_tokens && (state_flags || just_locked))
     {
       state_flags |= SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN;
     }
 
   /* Now, if this is something to commit, add it to our list. */
-  if (state_flags)
+  if (matches_changelists
+      && state_flags)
     {
-      if (matches_changelists)
-        {
-          /* Finally, add the committable item. */
-          SVN_ERR(add_committable(committables, local_abspath,
-                                  status->kind,
-                                  repos_root_url,
-                                  copy_mode
+      /* Finally, add the committable item. */
+      SVN_ERR(add_committable(committables, local_abspath,
+                              status->kind,
+                              repos_root_url,
+                              copy_mode
                                       ? commit_relpath
                                       : status->repos_relpath,
-                                  copy_mode
+                              copy_mode
                                       ? SVN_INVALID_REVNUM
                                       : node_rev,
-                                  cf_relpath,
-                                  cf_rev,
-                                  state_flags,
-                                  result_pool, scratch_pool));
-          if (state_flags & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN)
-            apr_hash_set(lock_tokens,
-                         svn_path_url_add_component2(
-                             repos_root_url, status->repos_relpath,
-                             result_pool),
-                         APR_HASH_KEY_STRING,
-                         apr_pstrdup(result_pool,
-                                     status->lock->token));
-        }
+                              cf_relpath,
+                              cf_rev,
+                              state_flags,
+                              baton->lock_tokens, status->lock,
+                              result_pool, scratch_pool));
     }
 
     /* Fetch lock tokens for descendants of deleted nodes. */
-  if (lock_tokens
-      && (state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE))
+  if (matches_changelists
+      && (state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
+      && baton->lock_tokens)
     {
       apr_hash_t *local_relpath_tokens;
       apr_hash_index_t *hi;
-      apr_pool_t *token_pool = apr_hash_pool_get(lock_tokens);
 
       SVN_ERR(svn_wc__node_get_lock_tokens_recursive(
                   &local_relpath_tokens, wc_ctx, local_abspath,
-                  token_pool, scratch_pool));
+                  result_pool, scratch_pool));
 
       /* Add tokens to existing hash. */
       for (hi = apr_hash_first(scratch_pool, local_relpath_tokens);
@@ -887,22 +894,35 @@ harvest_status_callback(void *status_bat
 
           apr_hash_this(hi, &key, &klen, &val);
 
-          apr_hash_set(lock_tokens, key, klen, val);
+          apr_hash_set(baton->lock_tokens, key, klen, val);
         }
     }
 
-  /* Make sure we check for dangling children on additions */
-  if (state_flags && is_added && is_harvest_root && danglers)
+  /* Make sure we check for dangling children on additions 
+
+     We perform this operation on the harvest root, and on roots caused by
+     changelist filtering.
+  */
+  if (matches_changelists
+      && (is_harvest_root || baton->changelists)
+      && state_flags
+      && is_added
+      && baton->danglers)
     {
-      /* If a node is added, it's parent must exist in the repository at the
+      /* If a node is added, its parent must exist in the repository at the
          time of committing */
-
+      apr_hash_t *danglers = baton->danglers;
       svn_boolean_t parent_added;
       const char *parent_abspath = svn_dirent_dirname(local_abspath,
                                                       scratch_pool);
 
-      SVN_ERR(svn_wc__node_is_added(&parent_added, wc_ctx, parent_abspath,
-                                    scratch_pool));
+      /* First check if parent is already in the list of commits
+         (Common case for GUI clients that provide a list of commit targets) */
+      if (look_up_committable(committables, parent_abspath, scratch_pool))
+        parent_added = FALSE; /* Skip all expensive checks */
+      else
+        SVN_ERR(svn_wc__node_is_added(&parent_added, wc_ctx, parent_abspath,
+                                      scratch_pool));
 
       if (parent_added)
         {
@@ -930,8 +950,7 @@ harvest_status_callback(void *status_bat
         }
     }
 
-  if ((state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
-      && !(state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
+  if (is_deleted && !is_added)
     {
       /* Skip all descendants */
       if (status->kind == svn_node_dir)

Modified: subversion/branches/ev2-export/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/diff.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/diff.c Wed May 16 14:57:41 2012
@@ -1528,7 +1528,8 @@ resolve_pegged_diff_target_url(const cha
                                     ctx, scratch_pool);
   if (err)
     {
-      if (err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES)
+      if (err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES ||
+          err->apr_err == SVN_ERR_FS_NOT_FOUND)
         {
           svn_error_clear(err);
           *resolved_url = NULL;
@@ -1545,6 +1546,8 @@ resolve_pegged_diff_target_url(const cha
  * Return URLs and peg revisions in *URL1, *REV1 and in *URL2, *REV2.
  * Return suitable anchors in *ANCHOR1 and *ANCHOR2, and targets in
  * *TARGET1 and *TARGET2, based on *URL1 and *URL2.
+ * Indicate the corresponding node kinds in *KIND1 and *KIND2, and verify
+ * that at least one of the diff targets exists.
  * Set *BASE_PATH corresponding to the URL opened in the new *RA_SESSION
  * which is pointing at *ANCHOR1.
  * Use client context CTX. Do all allocations in POOL. */
@@ -1558,6 +1561,8 @@ diff_prepare_repos_repos(const char **ur
                          const char **anchor2,
                          const char **target1,
                          const char **target2,
+                         svn_node_kind_t *kind1,
+                         svn_node_kind_t *kind2,
                          svn_ra_session_t **ra_session,
                          svn_client_ctx_t *ctx,
                          const char *path_or_url1,
@@ -1567,7 +1572,6 @@ diff_prepare_repos_repos(const char **ur
                          const svn_opt_revision_t *peg_revision,
                          apr_pool_t *pool)
 {
-  svn_node_kind_t kind1, kind2;
   const char *abspath_or_url2;
   const char *abspath_or_url1;
 
@@ -1644,18 +1648,18 @@ diff_prepare_repos_repos(const char **ur
   SVN_ERR(svn_client__get_revision_number(rev2, NULL, ctx->wc_ctx,
            (path_or_url2 == *url2) ? NULL : abspath_or_url2,
            *ra_session, revision2, pool));
-  SVN_ERR(svn_ra_check_path(*ra_session, "", *rev2, &kind2, pool));
+  SVN_ERR(svn_ra_check_path(*ra_session, "", *rev2, kind2, pool));
 
   /* Do the same for the first target. */
   SVN_ERR(svn_ra_reparent(*ra_session, *url1, pool));
   SVN_ERR(svn_client__get_revision_number(rev1, NULL, ctx->wc_ctx,
            (strcmp(path_or_url1, *url1) == 0) ? NULL : abspath_or_url1,
            *ra_session, revision1, pool));
-  SVN_ERR(svn_ra_check_path(*ra_session, "", *rev1, &kind1, pool));
+  SVN_ERR(svn_ra_check_path(*ra_session, "", *rev1, kind1, pool));
 
   /* Either both URLs must exist at their respective revisions,
    * or one of them may be missing from one side of the diff. */
-  if (kind1 == svn_node_none && kind2 == svn_node_none)
+  if (*kind1 == svn_node_none && *kind2 == svn_node_none)
     {
       if (strcmp(*url1, *url2) == 0)
         return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
@@ -1669,9 +1673,9 @@ diff_prepare_repos_repos(const char **ur
                                    "'%ld'"),
                                  *url1, *url2, *rev1, *rev2);
     }
-  else if (kind1 == svn_node_none)
+  else if (*kind1 == svn_node_none)
     SVN_ERR(check_diff_target_exists(*url1, *rev2, *rev1, *ra_session, pool));
-  else if (kind2 == svn_node_none)
+  else if (*kind2 == svn_node_none)
     SVN_ERR(check_diff_target_exists(*url2, *rev1, *rev2, *ra_session, pool));
 
   /* Choose useful anchors and targets for our two URLs. */
@@ -1679,57 +1683,9 @@ diff_prepare_repos_repos(const char **ur
   *anchor2 = *url2;
   *target1 = "";
   *target2 = "";
-  if ((kind1 == svn_node_none) || (kind2 == svn_node_none))
-    {
-      svn_node_kind_t kind;
-      const char *repos_root;
-      const char *new_anchor;
-      svn_revnum_t rev;
-
-      /* The diff target does not exist on one side of the diff.
-       * This can happen if the target was added or deleted within the
-       * revision range being diffed.
-       * However, we don't know how deep within a added/deleted subtree the
-       * diff target is. Find a common parent that exists on both sides of
-       * the diff and use it as anchor for the diff operation.
-       *
-       * ### This can fail due to authz restrictions (like in issue #3242).
-       * ### But it is the only option we have right now to try to get
-       * ### a usable diff in this situation. */
-
-      SVN_ERR(svn_ra_get_repos_root2(*ra_session, &repos_root, pool));
-
-      /* Since we already know that one of the URLs does exist,
-       * look for an existing parent of the URL which doesn't exist. */
-      new_anchor = (kind1 == svn_node_none ? *anchor1 : *anchor2);
-      rev = (kind1 == svn_node_none ? *rev1 : *rev2);
-      do
-        {
-          if (strcmp(new_anchor, repos_root) != 0)
-            {
-              new_anchor = svn_path_uri_decode(svn_uri_dirname(new_anchor,
-                                                               pool),
-                                               pool);
-              if (*base_path)
-                *base_path = svn_dirent_dirname(*base_path, pool);
-            }
-
-          SVN_ERR(svn_ra_reparent(*ra_session, new_anchor, pool));
-          SVN_ERR(svn_ra_check_path(*ra_session, "", rev, &kind, pool));
 
-        }
-      while (kind != svn_node_dir);
-      *anchor1 = *anchor2 = new_anchor;
-      /* Diff targets must be relative to the new anchor. */
-      *target1 = svn_uri_skip_ancestor(new_anchor, *url1, pool);
-      *target2 = svn_uri_skip_ancestor(new_anchor, *url2, pool);
-      SVN_ERR_ASSERT(*target1 && *target2);
-      if (kind1 == svn_node_none)
-        kind1 = svn_node_dir;
-      else
-        kind2 = svn_node_dir;
-    }
-  else if ((kind1 == svn_node_file) || (kind2 == svn_node_file))
+  /* If one of the targets is a file, use the parent directory as anchor. */
+  if (*kind1 == svn_node_file || *kind2 == svn_node_file)
     {
       svn_uri_split(anchor1, target1, *url1, pool);
       svn_uri_split(anchor2, target2, *url2, pool);
@@ -2334,6 +2290,299 @@ diff_wc_wc(const char *path1,
   return SVN_NO_ERROR;
 }
 
+/* Create an array of regular properties in PROP_HASH, filtering entry-props
+ * and wc-props. Allocate the returned array in RESULT_POOL.
+ * Use SCRATCH_POOL for temporary allocations. */
+static apr_array_header_t *
+make_regular_props_array(apr_hash_t *prop_hash,
+                         apr_pool_t *result_pool,
+                         apr_pool_t *scratch_pool)
+{
+  apr_array_header_t *regular_props;
+  apr_hash_index_t *hi;
+
+  regular_props = apr_array_make(result_pool, 0, sizeof(svn_prop_t));
+  for (hi = apr_hash_first(scratch_pool, prop_hash); hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *name = svn__apr_hash_index_key(hi);
+      svn_string_t *value = svn__apr_hash_index_val(hi);
+      svn_prop_kind_t prop_kind = svn_property_kind2(name);
+
+      if (prop_kind == svn_prop_regular_kind)
+        {
+          svn_prop_t *prop = apr_palloc(scratch_pool, sizeof(svn_prop_t));
+
+          prop->name = name;
+          prop->value = value;
+          APR_ARRAY_PUSH(regular_props, svn_prop_t) = *prop;
+        }
+    }
+
+  return regular_props;
+}
+
+/* Create a hash of regular properties from PROP_HASH, filtering entry-props
+ * and wc-props. Allocate the returned hash in RESULT_POOL.
+ * Use SCRATCH_POOL for temporary allocations. */
+static apr_hash_t *
+make_regular_props_hash(apr_hash_t *prop_hash,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
+{
+  apr_hash_t *regular_props;
+  apr_hash_index_t *hi;
+
+  regular_props = apr_hash_make(result_pool);
+  for (hi = apr_hash_first(scratch_pool, prop_hash); hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *name = svn__apr_hash_index_key(hi);
+      svn_string_t *value = svn__apr_hash_index_val(hi);
+      svn_prop_kind_t prop_kind = svn_property_kind2(name);
+
+      if (prop_kind == svn_prop_regular_kind)
+        apr_hash_set(regular_props, name, APR_HASH_KEY_STRING, value);
+    }
+
+  return regular_props;
+}
+
+/* Handle an added or deleted diff target file for a repos<->repos diff.
+ *
+ * Using the provided diff CALLBACKS and the CALLBACK_BATON, show the file
+ * TARGET@PEG_REVISION as added or deleted, depending on SHOW_DELETION.
+ * TARGET is a path relative to RA_SESSION's URL.
+ * REV1 and REV2 are the revisions being compared.
+ * Use SCRATCH_POOL for temporary allocations. */
+static svn_error_t *
+diff_repos_repos_added_or_deleted_file(const char *target,
+                                       svn_revnum_t peg_revision,
+                                       svn_revnum_t rev1,
+                                       svn_revnum_t rev2,
+                                       svn_boolean_t show_deletion,
+                                      const char *empty_file,
+                                       const svn_wc_diff_callbacks4_t
+                                         *callbacks,
+                                       struct diff_cmd_baton *callback_baton,
+                                       svn_ra_session_t *ra_session,
+                                       apr_pool_t *scratch_pool)
+{
+  const char *file_abspath;
+  svn_stream_t *content;
+  apr_hash_t *prop_hash;
+
+  SVN_ERR(svn_stream_open_unique(&content, &file_abspath, NULL,
+                                 svn_io_file_del_on_pool_cleanup,
+                                 scratch_pool, scratch_pool));
+  SVN_ERR(svn_ra_get_file(ra_session, target, peg_revision, content, NULL,
+                          &prop_hash, scratch_pool));
+  SVN_ERR(svn_stream_close(content));
+
+  if (show_deletion)
+    {
+      SVN_ERR(callbacks->file_deleted(NULL, NULL,
+                                      target, file_abspath, empty_file,
+                                      apr_hash_get(prop_hash,
+                                                   SVN_PROP_MIME_TYPE,
+                                                   APR_HASH_KEY_STRING),
+                                      NULL,
+                                      make_regular_props_hash(
+                                        prop_hash, scratch_pool, scratch_pool),
+                                      callback_baton, scratch_pool));
+    }
+  else
+    {
+      SVN_ERR(callbacks->file_added(NULL, NULL, NULL,
+                                    target, empty_file, file_abspath,
+                                    rev1, rev2, NULL,
+                                    apr_hash_get(prop_hash, SVN_PROP_MIME_TYPE,
+                                                 APR_HASH_KEY_STRING),
+                                    NULL, SVN_INVALID_REVNUM,
+                                    make_regular_props_array(prop_hash,
+                                                             scratch_pool,
+                                                             scratch_pool),
+                                    NULL, callback_baton, scratch_pool));
+    }
+    
+  return SVN_NO_ERROR;
+}
+
+/* Handle an added or deleted diff target directory for a repos<->repos diff.
+ *
+ * Using the provided diff CALLBACKS and the CALLBACK_BATON, show the
+ * directory TARGET@PEG_REVISION, and all of its children, as added or deleted,
+ * depending on SHOW_DELETION. TARGET is a path relative to RA_SESSION's URL.
+ * REV1 and REV2 are the revisions being compared.
+ * Use SCRATCH_POOL for temporary allocations. */
+static svn_error_t *
+diff_repos_repos_added_or_deleted_dir(const char *target,
+                                      svn_revnum_t revision,
+                                      svn_revnum_t rev1,
+                                      svn_revnum_t rev2,
+                                      svn_boolean_t show_deletion,
+                                      const char *empty_file,
+                                      const svn_wc_diff_callbacks4_t
+                                        *callbacks,
+                                      struct diff_cmd_baton *callback_baton,
+                                      svn_ra_session_t *ra_session,
+                                      apr_pool_t *scratch_pool)
+{
+  apr_hash_t *dirents;
+  apr_hash_t *props;
+  apr_pool_t *iterpool;
+  apr_hash_index_t *hi;
+
+  SVN_ERR(svn_ra_get_dir2(ra_session, &dirents, NULL, &props,
+                          target, revision, SVN_DIRENT_KIND,
+                          scratch_pool));
+
+  if (show_deletion)
+    SVN_ERR(callbacks->dir_deleted(NULL, NULL, target, callback_baton,
+                                   scratch_pool));
+  else
+    SVN_ERR(callbacks->dir_added(NULL, NULL, NULL, NULL,
+                                 target, revision,
+                                 NULL, SVN_INVALID_REVNUM,
+                                 callback_baton, scratch_pool));
+  if (props)
+    {
+      if (show_deletion)
+        SVN_ERR(callbacks->dir_props_changed(NULL, NULL, target, FALSE,
+                                             apr_array_make(scratch_pool, 0,
+                                                            sizeof(svn_prop_t)),
+                                             make_regular_props_hash(
+                                               props, scratch_pool,
+                                               scratch_pool),
+                                             callback_baton, scratch_pool));
+      else
+        SVN_ERR(callbacks->dir_props_changed(NULL, NULL, target, TRUE,
+                                             make_regular_props_array(
+                                               props, scratch_pool,
+                                               scratch_pool),
+                                             NULL,
+                                             callback_baton, scratch_pool));
+    }
+
+  iterpool = svn_pool_create(scratch_pool);
+  for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi))
+    {
+      const char *name = svn__apr_hash_index_key(hi);
+      svn_dirent_t *dirent = svn__apr_hash_index_val(hi);
+      const char *child_target;
+
+      svn_pool_clear(iterpool);
+
+      child_target = svn_relpath_join(target, name, iterpool);
+
+      if (dirent->kind == svn_node_dir)
+        SVN_ERR(diff_repos_repos_added_or_deleted_dir(child_target,
+                                                      revision, rev1, rev2,
+                                                      show_deletion,
+                                                      empty_file,
+                                                      callbacks,
+                                                      callback_baton,
+                                                      ra_session,
+                                                      iterpool));
+      else if (dirent->kind == svn_node_file)
+        SVN_ERR(diff_repos_repos_added_or_deleted_file(child_target,
+                                                       revision, rev1, rev2,
+                                                       show_deletion,
+                                                       empty_file,
+                                                       callbacks,
+                                                       callback_baton,
+                                                       ra_session,
+                                                       iterpool));
+    }
+  svn_pool_destroy(iterpool);
+
+  if (!show_deletion)
+    SVN_ERR(callbacks->dir_closed(NULL, NULL, NULL, target, TRUE,
+                                  callback_baton, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
+/* Handle an added or deleted diff target for a repos<->repos diff.
+ *
+ * Using the provided diff CALLBACKS and the CALLBACK_BATON, show
+ * TARGET@PEG_REVISION, and all of its children, if any, as added or deleted.
+ * TARGET is a path relative to RA_SESSION's URL.
+ * REV1 and REV2 are the revisions being compared.
+ * Use SCRATCH_POOL for temporary allocations. */
+static svn_error_t *
+diff_repos_repos_added_or_deleted_target(const char *target1,
+                                         const char *target2,
+                                         svn_revnum_t rev1,
+                                         svn_revnum_t rev2,
+                                         svn_node_kind_t kind1,
+                                         svn_node_kind_t kind2,
+                                         const svn_wc_diff_callbacks4_t
+                                           *callbacks,
+                                         struct diff_cmd_baton *callback_baton,
+                                         svn_ra_session_t *ra_session,
+                                         apr_pool_t *scratch_pool)
+{
+  const char *existing_target;
+  svn_revnum_t existing_rev;
+  svn_node_kind_t existing_kind;
+  svn_boolean_t show_deletion;
+  const char *empty_file;
+
+  SVN_ERR_ASSERT(kind1 == svn_node_none || kind2 == svn_node_none);
+
+  /* Are we showing an addition or deletion? */
+  show_deletion = (kind2 == svn_node_none);
+
+  /* Which target is being added/deleted? Is it a file or a directory? */
+  if (show_deletion)
+    {
+      existing_target = target1;
+      existing_rev = rev1;
+      existing_kind = kind1;
+    }
+  else
+    {
+      existing_target = target2;
+      existing_rev = rev2;
+      existing_kind = kind2;
+    }
+
+  /* All file content will be diffed against the empty file. */
+  SVN_ERR(svn_io_open_unique_file3(NULL, &empty_file, NULL,
+                                   svn_io_file_del_on_pool_cleanup,
+                                   scratch_pool, scratch_pool));
+
+  if (existing_kind == svn_node_file)
+    {
+      /* Get file content and show a diff against the empty file. */
+      SVN_ERR(diff_repos_repos_added_or_deleted_file(existing_target,
+                                                     existing_rev,
+                                                     rev1, rev2,
+                                                     show_deletion,
+                                                     empty_file,
+                                                     callbacks,
+                                                     callback_baton,
+                                                     ra_session,
+                                                     scratch_pool));
+    }
+  else
+    {
+      /* Walk the added/deleted tree and show a diff for each child. */
+      SVN_ERR(diff_repos_repos_added_or_deleted_dir(existing_target,
+                                                    existing_rev,
+                                                    rev1, rev2,
+                                                    show_deletion,
+                                                    empty_file,
+                                                    callbacks,
+                                                    callback_baton,
+                                                    ra_session,
+                                                    scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
 
 /* Perform a diff between two repository paths.
 
@@ -2370,6 +2619,8 @@ diff_repos_repos(const svn_wc_diff_callb
   const char *base_path;
   svn_revnum_t rev1;
   svn_revnum_t rev2;
+  svn_node_kind_t kind1;
+  svn_node_kind_t kind2;
   const char *anchor1;
   const char *anchor2;
   const char *target1;
@@ -2379,7 +2630,8 @@ diff_repos_repos(const svn_wc_diff_callb
   /* Prepare info for the repos repos diff. */
   SVN_ERR(diff_prepare_repos_repos(&url1, &url2, &base_path, &rev1, &rev2,
                                    &anchor1, &anchor2, &target1, &target2,
-                                   &ra_session, ctx, path_or_url1, path_or_url2,
+                                   &kind1, &kind2, &ra_session,
+                                   ctx, path_or_url1, path_or_url2,
                                    revision1, revision2, peg_revision,
                                    pool));
 
@@ -2394,6 +2646,21 @@ diff_repos_repos(const svn_wc_diff_callb
   callback_baton->ra_session = ra_session;
   callback_baton->anchor = base_path;
 
+  if (kind1 == svn_node_none || kind2 == svn_node_none)
+    {
+      /* One side of the diff does not exist.
+       * Walk the tree that does exist, showing a series of additions
+       * or deletions. */
+      SVN_ERR(diff_repos_repos_added_or_deleted_target(target1, target2,
+                                                       rev1, rev2,
+                                                       kind1, kind2,
+                                                       callbacks,
+                                                       callback_baton,
+                                                       ra_session,
+                                                       pool));
+      return SVN_NO_ERROR;
+    }
+
   /* Now, we open an extra RA session to the correct anchor
      location for URL1.  This is used during the editor calls to fetch file
      contents.  */
@@ -2741,6 +3008,8 @@ diff_summarize_repos_repos(svn_client_di
   const char *base_path;
   svn_revnum_t rev1;
   svn_revnum_t rev2;
+  svn_node_kind_t kind1;
+  svn_node_kind_t kind2;
   const char *anchor1;
   const char *anchor2;
   const char *target1;
@@ -2752,10 +3021,29 @@ diff_summarize_repos_repos(svn_client_di
   /* Prepare info for the repos repos diff. */
   SVN_ERR(diff_prepare_repos_repos(&url1, &url2, &base_path, &rev1, &rev2,
                                    &anchor1, &anchor2, &target1, &target2,
-                                   &ra_session, ctx,
-                                   path_or_url1, path_or_url2, revision1, revision2,
+                                   &kind1, &kind2, &ra_session,
+                                   ctx, path_or_url1, path_or_url2,
+                                   revision1, revision2,
                                    peg_revision, pool));
 
+  if (kind1 == svn_node_none || kind2 == svn_node_none)
+    {
+      /* One side of the diff does not exist.
+       * Walk the tree that does exist, showing a series of additions
+       * or deletions. */
+      SVN_ERR(svn_client__get_diff_summarize_callbacks(
+                &callbacks, &callback_baton, target1,
+                summarize_func, summarize_baton, pool));
+      SVN_ERR(diff_repos_repos_added_or_deleted_target(target1, target2,
+                                                       rev1, rev2,
+                                                       kind1, kind2,
+                                                       callbacks,
+                                                       callback_baton,
+                                                       ra_session,
+                                                       pool));
+      return SVN_NO_ERROR;
+    }
+
   SVN_ERR(svn_client__get_diff_summarize_callbacks(
             &callbacks, &callback_baton,
             target1, summarize_func, summarize_baton, pool));

Modified: subversion/branches/ev2-export/subversion/libsvn_client/export.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/export.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/export.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/export.c Wed May 16 14:57:41 2012
@@ -957,20 +957,19 @@ svn_client_export5(svn_revnum_t *result_
 
   if (from_is_url || ! SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind))
     {
-      svn_revnum_t revnum;
-      const char *url;
+      svn_client__pathrev_t *loc;
       svn_ra_session_t *ra_session;
       svn_node_kind_t kind;
       struct edit_baton *eb = apr_pcalloc(pool, sizeof(*eb));
 
       /* Get the RA connection. */
-      SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum,
-                                               &url, from_path_or_url, NULL,
-                                               peg_revision,
-                                               revision, ctx, pool));
+      SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
+                                                from_path_or_url, NULL,
+                                                peg_revision,
+                                                revision, ctx, pool));
 
       eb->root_path = to_path;
-      eb->root_url = url;
+      eb->root_url = loc->url;
       eb->force = overwrite;
       eb->target_revision = &edit_revision;
       eb->externals = apr_hash_make(pool);
@@ -981,7 +980,7 @@ svn_client_export5(svn_revnum_t *result_
       eb->notify_func = ctx->notify_func2;
       eb->notify_baton = ctx->notify_baton2;
 
-      SVN_ERR(svn_ra_check_path(ra_session, "", revnum, &kind, pool));
+      SVN_ERR(svn_ra_check_path(ra_session, "", loc->rev, &kind, pool));
 
       if (kind == svn_node_file)
         {
@@ -1020,7 +1019,7 @@ svn_client_export5(svn_revnum_t *result_
 
           tmp_stream = svn_stream_buffered(pool);
 
-          SVN_ERR(svn_ra_get_file(ra_session, "", revnum,
+          SVN_ERR(svn_ra_get_file(ra_session, "", loc->rev,
                                   tmp_stream, NULL, &props, pool));
 
           /* Since you cannot actually root an editor at a file, we
@@ -1042,13 +1041,13 @@ svn_client_export5(svn_revnum_t *result_
           /* Manufacture a basic 'report' to the update reporter. */
           SVN_ERR(svn_ra_do_update2(ra_session,
                                     &reporter, &report_baton,
-                                    revnum,
+                                    loc->rev,
                                     "", /* no sub-target */
                                     depth,
                                     FALSE, /* don't want copyfrom-args */
                                     export_editor, edit_baton, pool));
 
-          SVN_ERR(reporter->set_path(report_baton, "", revnum,
+          SVN_ERR(reporter->set_path(report_baton, "", loc->rev,
                                      /* Depth is irrelevant, as we're
                                         passing start_empty=TRUE anyway. */
                                      svn_depth_infinity,

Modified: subversion/branches/ev2-export/subversion/libsvn_client/list.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/list.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/list.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/list.c Wed May 16 14:57:41 2012
@@ -237,9 +237,8 @@ svn_client_list2(const char *path_or_url
                  apr_pool_t *pool)
 {
   svn_ra_session_t *ra_session;
-  svn_revnum_t rev;
+  svn_client__pathrev_t *loc;
   svn_dirent_t *dirent;
-  const char *url;
   const char *fs_path;
   svn_error_t *err;
   apr_hash_t *locks;
@@ -249,20 +248,19 @@ svn_client_list2(const char *path_or_url
   dirent_fields |= SVN_DIRENT_KIND;
 
   /* Get an RA plugin for this filesystem object. */
-  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &rev,
-                                           &url, path_or_url, NULL,
-                                           peg_revision,
-                                           revision, ctx, pool));
+  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
+                                            path_or_url, NULL,
+                                            peg_revision,
+                                            revision, ctx, pool));
 
-  SVN_ERR(svn_ra__get_fspath_relative_to_root(ra_session, &fs_path, url,
-                                              pool));
+  fs_path = svn_client__pathrev_fspath(loc, pool);
 
-  SVN_ERR(ra_stat_compatible(ra_session, rev, &dirent, dirent_fields,
+  SVN_ERR(ra_stat_compatible(ra_session, loc->rev, &dirent, dirent_fields,
                              ctx, pool));
   if (! dirent)
     return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
                              _("URL '%s' non-existent in revision %ld"),
-                             url, rev);
+                             loc->url, loc->rev);
 
   /* Maybe get all locks under url. */
   if (fetch_locks)
@@ -292,7 +290,7 @@ svn_client_list2(const char *path_or_url
       && (depth == svn_depth_files
           || depth == svn_depth_immediates
           || depth == svn_depth_infinity))
-    SVN_ERR(get_dir_contents(dirent_fields, "", rev, ra_session, locks,
+    SVN_ERR(get_dir_contents(dirent_fields, "", loc->rev, ra_session, locks,
                              fs_path, depth, ctx, list_func, baton, pool));
 
   return SVN_NO_ERROR;

Modified: subversion/branches/ev2-export/subversion/libsvn_client/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/log.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/log.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/log.c Wed May 16 14:57:41 2012
@@ -101,23 +101,22 @@ svn_client__get_copy_source(const char *
   copyfrom_info_t copyfrom_info = { 0 };
   apr_pool_t *sesspool = svn_pool_create(pool);
   svn_ra_session_t *ra_session;
-  svn_revnum_t at_rev;
-  const char *at_url;
+  svn_client__pathrev_t *at_loc;
 
   copyfrom_info.is_first = TRUE;
   copyfrom_info.path = NULL;
   copyfrom_info.rev = SVN_INVALID_REVNUM;
   copyfrom_info.pool = pool;
 
-  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &at_rev, &at_url,
-                                           path_or_url, NULL,
-                                           revision, revision,
-                                           ctx, sesspool));
+  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &at_loc,
+                                            path_or_url, NULL,
+                                            revision, revision,
+                                            ctx, sesspool));
 
   /* Find the copy source.  Walk the location segments to find the revision
      at which this node was created (copied or added). */
 
-  err = svn_ra_get_location_segments(ra_session, "", at_rev, at_rev,
+  err = svn_ra_get_location_segments(ra_session, "", at_loc->rev, at_loc->rev,
                                      SVN_INVALID_REVNUM,
                                      copyfrom_info_receiver, &copyfrom_info,
                                      pool);
@@ -281,7 +280,6 @@ svn_client_log5(const apr_array_header_t
   svn_ra_session_t *ra_session;
   const char *url_or_path;
   svn_boolean_t has_log_revprops;
-  const char *actual_url;
   apr_array_header_t *condensed_targets;
   svn_opt_revision_t session_opt_rev;
   const char *ra_target;
@@ -474,6 +472,8 @@ svn_client_log5(const apr_array_header_t
 
 
   {
+    svn_client__pathrev_t *actual_loc;
+
     /* If this is a revision type that requires access to the working copy,
      * we use our initial target path to figure out where to root the RA
      * session, otherwise we use our URL. */
@@ -483,7 +483,7 @@ svn_client_log5(const apr_array_header_t
     else
       ra_target = url_or_path;
 
-    SVN_ERR(svn_client__ra_session_from_path(&ra_session, NULL, &actual_url,
+    SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &actual_loc,
                                              ra_target, NULL,
                                              &peg_rev, &session_opt_rev,
                                              ctx, pool));
@@ -497,7 +497,7 @@ svn_client_log5(const apr_array_header_t
 
       /* Create ra session on first use */
       rb.ra_session_pool = pool;
-      rb.ra_session_url = actual_url;
+      rb.ra_session_url = actual_loc->url;
     }
   }