subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hwri...@apache.org
Subject svn commit: r1449262 [3/25] - in /subversion/branches/ev2-export: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ build/win32/ contrib/server-side/fsfsfixer/fixer/ contrib/server-side/svncutter/ notes/ notes...
Date Sat, 23 Feb 2013 01:25:44 GMT
Modified: subversion/branches/ev2-export/subversion/libsvn_client/cleanup.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/cleanup.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/cleanup.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/cleanup.c Sat Feb 23 01:25:38 2013
@@ -38,7 +38,6 @@
 #include "svn_props.h"
 
 #include "svn_private_config.h"
-#include "private/svn_wc_private.h"
 
 
 /*** Code. ***/
@@ -62,308 +61,3 @@ svn_client_cleanup(const char *path,
   svn_io_sleep_for_timestamps(path, scratch_pool);
   return svn_error_trace(err);
 }
-
-
-/* callback baton for fetch_repos_info */
-struct repos_info_baton
-{
-  apr_pool_t *state_pool;
-  svn_client_ctx_t *ctx;
-  const char *last_repos;
-  const char *last_uuid;
-};
-
-/* svn_wc_upgrade_get_repos_info_t implementation for calling
-   svn_wc_upgrade() from svn_client_upgrade() */
-static svn_error_t *
-fetch_repos_info(const char **repos_root,
-                 const char **repos_uuid,
-                 void *baton,
-                 const char *url,
-                 apr_pool_t *result_pool,
-                 apr_pool_t *scratch_pool)
-{
-  struct repos_info_baton *ri = baton;
-  apr_pool_t *subpool;
-  svn_ra_session_t *ra_session;
-
-  /* The same info is likely to retrieved multiple times (e.g. externals) */
-  if (ri->last_repos && svn_uri__is_ancestor(ri->last_repos, url))
-    {
-      *repos_root = apr_pstrdup(result_pool, ri->last_repos);
-      *repos_uuid = apr_pstrdup(result_pool, ri->last_uuid);
-      return SVN_NO_ERROR;
-    }
-
-  subpool = svn_pool_create(scratch_pool);
-
-  SVN_ERR(svn_client_open_ra_session(&ra_session, url, ri->ctx, subpool));
-
-  SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, result_pool));
-  SVN_ERR(svn_ra_get_uuid2(ra_session, repos_uuid, result_pool));
-
-  /* Store data for further calls */
-  ri->last_repos = apr_pstrdup(ri->state_pool, *repos_root);
-  ri->last_uuid = apr_pstrdup(ri->state_pool, *repos_uuid);
-
-  svn_pool_destroy(subpool);
-
-  return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client_upgrade(const char *path,
-                   svn_client_ctx_t *ctx,
-                   apr_pool_t *scratch_pool)
-{
-  const char *local_abspath;
-  apr_hash_t *externals;
-  apr_hash_index_t *hi;
-  apr_pool_t *iterpool;
-  apr_pool_t *iterpool2;
-  svn_opt_revision_t rev = {svn_opt_revision_unspecified, {0}};
-  struct repos_info_baton info_baton;
-
-  info_baton.state_pool = scratch_pool;
-  info_baton.ctx = ctx;
-  info_baton.last_repos = NULL;
-  info_baton.last_uuid = NULL;
-
-  if (svn_path_is_url(path))
-    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
-                             _("'%s' is not a local path"), path);
-
-  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
-  SVN_ERR(svn_wc_upgrade(ctx->wc_ctx, local_abspath,
-                         fetch_repos_info, &info_baton,
-                         ctx->cancel_func, ctx->cancel_baton,
-                         ctx->notify_func2, ctx->notify_baton2,
-                         scratch_pool));
-
-  /* Now it's time to upgrade the externals too. We do it after the wc
-     upgrade to avoid that errors in the externals causes the wc upgrade to
-     fail. Thanks to caching the performance penalty of walking the wc a
-     second time shouldn't be too severe */
-  SVN_ERR(svn_client_propget5(&externals, NULL, SVN_PROP_EXTERNALS,
-                              local_abspath, &rev, &rev, NULL,
-                              svn_depth_infinity, NULL, ctx,
-                              scratch_pool, scratch_pool));
-
-  iterpool = svn_pool_create(scratch_pool);
-  iterpool2 = svn_pool_create(scratch_pool);
-
-  for (hi = apr_hash_first(scratch_pool, externals); hi;
-       hi = apr_hash_next(hi))
-    {
-      int i;
-      const char *externals_parent_abspath;
-      const char *externals_parent_url;
-      const char *externals_parent_repos_root_url;
-      const char *externals_parent = svn__apr_hash_index_key(hi);
-      svn_string_t *external_desc = svn__apr_hash_index_val(hi);
-      apr_array_header_t *externals_p;
-      svn_error_t *err;
-
-      svn_pool_clear(iterpool);
-      externals_p = apr_array_make(iterpool, 1,
-                                   sizeof(svn_wc_external_item2_t*));
-
-      /* In this loop, an error causes the respective externals definition, or
-       * the external (inner loop), to be skipped, so that upgrade carries on
-       * with the other externals. */
-
-      err = svn_dirent_get_absolute(&externals_parent_abspath,
-                                    externals_parent, iterpool);
-
-      if (!err)
-        err = svn_wc__node_get_url(&externals_parent_url, ctx->wc_ctx,
-                                   externals_parent_abspath,
-                                   iterpool, iterpool);
-      if (!err)
-        err = svn_wc__node_get_repos_info(&externals_parent_repos_root_url,
-                                          NULL,
-                                          ctx->wc_ctx,
-                                          externals_parent_abspath,
-                                          iterpool, iterpool);
-      if (!err)
-        err = svn_wc_parse_externals_description3(
-                  &externals_p, svn_dirent_dirname(path, iterpool),
-                  external_desc->data, FALSE, iterpool);
-      if (err)
-        {
-          svn_wc_notify_t *notify =
-              svn_wc_create_notify(externals_parent,
-                                   svn_wc_notify_failed_external,
-                                   scratch_pool);
-          notify->err = err;
-
-          ctx->notify_func2(ctx->notify_baton2,
-                            notify, scratch_pool);
-
-          svn_error_clear(err);
-
-          /* Next externals definition, please... */
-          continue;
-        }
-
-      for (i = 0; i < externals_p->nelts; i++)
-        {
-          svn_wc_external_item2_t *item;
-          const char *resolved_url;
-          const char *external_abspath;
-          const char *repos_relpath;
-          const char *repos_root_url;
-          const char *repos_uuid;
-          svn_node_kind_t external_kind;
-          svn_revnum_t peg_revision;
-          svn_revnum_t revision;
-
-          item = APR_ARRAY_IDX(externals_p, i, svn_wc_external_item2_t*);
-
-          svn_pool_clear(iterpool2);
-          external_abspath = svn_dirent_join(externals_parent_abspath,
-                                             item->target_dir,
-                                             iterpool2);
-
-          err = svn_wc__resolve_relative_external_url(
-                                              &resolved_url,
-                                              item,
-                                              externals_parent_repos_root_url,
-                                              externals_parent_url,
-                                              scratch_pool, scratch_pool);
-          if (err)
-            goto handle_error;
-
-          /* This is a hack. We only need to call svn_wc_upgrade() on external
-           * dirs, as file externals are upgraded along with their defining
-           * WC.  Reading the kind will throw an exception on an external dir,
-           * saying that the wc must be upgraded.  If it's a file, the lookup
-           * is done in an adm_dir belonging to the defining wc (which has
-           * already been upgraded) and no error is returned.  If it doesn't
-           * exist (external that isn't checked out yet), we'll just get
-           * svn_node_none. */
-          err = svn_wc_read_kind(&external_kind, ctx->wc_ctx,
-                                 external_abspath, FALSE, iterpool2);
-          if (err && err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
-            {
-              svn_error_clear(err);
-
-              err = svn_client_upgrade(external_abspath, ctx, iterpool2);
-              if (err)
-                goto handle_error;
-            }
-          else if (err)
-            goto handle_error;
-
-          /* The upgrade of any dir should be done now, get the now reliable
-           * kind. */
-          err = svn_wc_read_kind(&external_kind, ctx->wc_ctx, external_abspath,
-                                 FALSE, iterpool2);
-          if (err)
-            goto handle_error;
-
-          /* Update the EXTERNALS table according to the root URL,
-           * relpath and uuid known in the upgraded external WC. */
-
-          /* We should probably have a function that provides all three
-           * of root URL, repos relpath and uuid at once, but here goes... */
-
-          /* First get the relpath, as that returns SVN_ERR_WC_PATH_NOT_FOUND
-           * when the node is not present in the file system.
-           * svn_wc__node_get_repos_info() would try to derive the URL. */
-          err = svn_wc__node_get_repos_relpath(&repos_relpath,
-                                               ctx->wc_ctx,
-                                               external_abspath,
-                                               iterpool2, iterpool2);
-          if (! err)
-            {
-              /* We got a repos relpath from a WC. So also get the root. */
-              err = svn_wc__node_get_repos_info(&repos_root_url,
-                                                &repos_uuid,
-                                                ctx->wc_ctx,
-                                                external_abspath,
-                                                iterpool2, iterpool2);
-              if (err)
-                goto handle_error;
-            }
-          else if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
-            {
-              /* The external is not currently checked out. Try to figure out
-               * the URL parts via the defined URL and fetch_repos_info(). */
-              svn_error_clear(err);
-              repos_relpath = NULL;
-              repos_root_url = NULL;
-              repos_uuid = NULL;
-            }
-          else if (err)
-            goto handle_error;
-
-          /* If we haven't got any information from the checked out external,
-           * or if the URL information mismatches the external's definition,
-           * ask fetch_repos_info() to find out the repos root. */
-          if (! repos_relpath || ! repos_root_url
-              || 0 != strcmp(resolved_url,
-                             svn_path_url_add_component2(repos_root_url,
-                                                         repos_relpath,
-                                                         scratch_pool)))
-            {
-              err = fetch_repos_info(&repos_root_url,
-                                     &repos_uuid,
-                                     &info_baton,
-                                     resolved_url,
-                                     scratch_pool, scratch_pool);
-              if (err)
-                goto handle_error;
-
-              repos_relpath = svn_uri_skip_ancestor(repos_root_url,
-                                                    resolved_url,
-                                                    iterpool2);
-
-              /* There's just the URL, no idea what kind the external is.
-               * That's fine, as the external isn't even checked out yet.
-               * The kind will be set during the next 'update'. */
-              external_kind = svn_node_unknown;
-            }
-
-          if (err)
-            goto handle_error;
-
-          peg_revision = (item->peg_revision.kind == svn_opt_revision_number
-                          ? item->peg_revision.value.number
-                          : SVN_INVALID_REVNUM);
-
-          revision = (item->revision.kind == svn_opt_revision_number
-                      ? item->revision.value.number
-                      : SVN_INVALID_REVNUM);
-
-          err = svn_wc__upgrade_add_external_info(ctx->wc_ctx,
-                                                  external_abspath,
-                                                  external_kind,
-                                                  externals_parent,
-                                                  repos_relpath,
-                                                  repos_root_url,
-                                                  repos_uuid,
-                                                  peg_revision,
-                                                  revision,
-                                                  iterpool2);
-handle_error:
-          if (err)
-            {
-              svn_wc_notify_t *notify =
-                  svn_wc_create_notify(external_abspath,
-                                       svn_wc_notify_failed_external,
-                                       scratch_pool);
-              notify->err = err;
-              ctx->notify_func2(ctx->notify_baton2,
-                                notify, scratch_pool);
-              svn_error_clear(err);
-              /* Next external node, please... */
-            }
-        }
-    }
-
-  svn_pool_destroy(iterpool);
-  svn_pool_destroy(iterpool2);
-
-  return SVN_NO_ERROR;
-}

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=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/client.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/client.h Sat Feb 23 01:25:38 2013
@@ -38,6 +38,7 @@
 #include "private/svn_magic.h"
 #include "private/svn_editor.h"
 #include "private/svn_client_private.h"
+#include "private/svn_diff_tree.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -597,58 +598,6 @@ svn_client__switch_internal(svn_revnum_t
 
 /* ---------------------------------------------------------------- */
 
-/*** List ***/
-
-/* List the file/directory entries for PATH_OR_URL at REVISION.
-   The actual node revision selected is determined by the path as 
-   it exists in PEG_REVISION.  
-   
-   If DEPTH is svn_depth_infinity, then list all file and directory entries 
-   recursively.  Else if DEPTH is svn_depth_files, list all files under 
-   PATH_OR_URL (if any), but not subdirectories.  Else if DEPTH is
-   svn_depth_immediates, list all files and include immediate
-   subdirectories (at svn_depth_empty).  Else if DEPTH is
-   svn_depth_empty, just list PATH_OR_URL with none of its entries.
- 
-   DIRENT_FIELDS controls which fields in the svn_dirent_t's are
-   filled in.  To have them totally filled in use SVN_DIRENT_ALL,
-   otherwise simply bitwise OR together the combination of SVN_DIRENT_*
-   fields you care about.
- 
-   If FETCH_LOCKS is TRUE, include locks when reporting directory entries.
- 
-   If INCLUDE_EXTERNALS is TRUE, also list all external items 
-   reached by recursion.  DEPTH value passed to the original list target
-   applies for the externals also.  EXTERNAL_PARENT_URL is url of the 
-   directory which has the externals definitions.  EXTERNAL_TARGET is the
-   target subdirectory of externals definitions.
-
-   Report directory entries by invoking LIST_FUNC/BATON. 
-   Pass EXTERNAL_PARENT_URL and EXTERNAL_TARGET to LIST_FUNC when external
-   items are listed, otherwise both are set to NULL.
- 
-   Use authentication baton cached in CTX to authenticate against the
-   repository.
- 
-   Use POOL for all allocations.
-*/
-svn_error_t *
-svn_client__list_internal(const char *path_or_url,
-                          const svn_opt_revision_t *peg_revision,
-                          const svn_opt_revision_t *revision,
-                          svn_depth_t depth,
-                          apr_uint32_t dirent_fields,
-                          svn_boolean_t fetch_locks,
-                          svn_boolean_t include_externals,
-                          const char *external_parent_url,
-                          const char *external_target,
-                          svn_client_list_func2_t list_func,
-                          void *baton,
-                          svn_client_ctx_t *ctx,
-                          apr_pool_t *pool);
-
-/* ---------------------------------------------------------------- */
-
 /*** Inheritable Properties ***/
 
 /* Convert any svn_prop_inherited_item_t elements in INHERITED_PROPS which
@@ -710,36 +659,27 @@ svn_client__get_inheritable_props(apr_ha
    is being driven. REVISION is the revision number of the 'old' side of
    the diff.
 
-   For each deleted directory, if WALK_DELETED_DIRS is true then just call
-   the 'dir_deleted' callback once, otherwise call the 'file_deleted' or
-   'dir_deleted' callback for each individual node in that subtree.
-
    If TEXT_DELTAS is FALSE, then do not expect text deltas from the edit
    drive, nor send the 'before' and 'after' texts to the diff callbacks;
    instead, send empty files to the diff callbacks if there was a change.
    This must be FALSE if the edit producer is not sending text deltas,
    otherwise the file content checksum comparisons will fail.
 
-   If NOTIFY_FUNC is non-null, invoke it with NOTIFY_BATON for each
-   file and directory operated on during the edit.
+   EDITOR/EDIT_BATON return the newly created editor and baton.
 
-   EDITOR/EDIT_BATON return the newly created editor and baton. */
+   @since New in 1.8.
+   */
 svn_error_t *
-svn_client__get_diff_editor(const svn_delta_editor_t **editor,
-                            void **edit_baton,
-                            svn_depth_t depth,
-                            svn_ra_session_t *ra_session,
-                            svn_revnum_t revision,
-                            svn_boolean_t walk_deleted_dirs,
-                            svn_boolean_t text_deltas,
-                            const svn_wc_diff_callbacks4_t *diff_callbacks,
-                            void *diff_cmd_baton,
-                            svn_cancel_func_t cancel_func,
-                            void *cancel_baton,
-                            svn_wc_notify_func2_t notify_func,
-                            void *notify_baton,
-                            apr_pool_t *result_pool);
-
+svn_client__get_diff_editor2(const svn_delta_editor_t **editor,
+                             void **edit_baton,
+                             svn_ra_session_t *ra_session,
+                             svn_depth_t depth,
+                             svn_revnum_t revision,
+                             svn_boolean_t text_deltas,
+                             const svn_diff_tree_processor_t *processor,
+                             svn_cancel_func_t cancel_func,
+                             void *cancel_baton,
+                             apr_pool_t *result_pool);
 
 /* ---------------------------------------------------------------- */
 
@@ -1094,43 +1034,6 @@ svn_client__export_externals(apr_hash_t 
                              svn_client_ctx_t *ctx,
                              apr_pool_t *pool);
 
-
-/* Perform status operations on each external in EXTERNAL_MAP, a const char *
-   local_abspath of all externals mapping to the const char* defining_abspath.
-   All other options are the same as those passed to svn_client_status().
-
-   If ANCHOR_ABSPATH and ANCHOR-RELPATH are not null, use them to provide
-   properly formatted relative paths
- */
-svn_error_t *
-svn_client__do_external_status(svn_client_ctx_t *ctx,
-                               apr_hash_t *external_map,
-                               svn_depth_t depth,
-                               svn_boolean_t get_all,
-                               svn_boolean_t update,
-                               svn_boolean_t no_ignore,
-                               const char *anchor_abspath,
-                               const char *anchor_relpath,
-                               svn_client_status_func_t status_func,
-                               void *status_baton,
-                               apr_pool_t *scratch_pool);
-
-
-/* List external items defined on each external in EXTERNALS, a const char *
-   externals_parent_url(url of the directory which has the externals
-   definitions) of all externals mapping to the svn_string_t * externals_desc
-   (externals description text). All other options are the same as those 
-   passed to svn_client_list(). */
-svn_error_t * 
-svn_client__list_externals(apr_hash_t *externals, 
-                           svn_depth_t depth,
-                           apr_uint32_t dirent_fields,
-                           svn_boolean_t fetch_locks,
-                           svn_client_list_func2_t list_func,
-                           void *baton,
-                           svn_client_ctx_t *ctx,
-                           apr_pool_t *scratch_pool);
-
 /* Baton for svn_client__dirent_fetcher */
 struct svn_client__dirent_fetcher_baton_t
 {

Modified: subversion/branches/ev2-export/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/commit.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/commit.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/commit.c Sat Feb 23 01:25:38 2013
@@ -848,7 +848,8 @@ svn_client_commit6(const apr_array_heade
                 }
             }
         }
-      else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
+
+      if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
         {
           const char *moved_to_abspath;
           const char *copy_op_root_abspath;

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=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c Sat Feb 23 01:25:38 2013
@@ -495,7 +495,7 @@ harvest_not_present_for_copy(svn_wc_cont
       svn_pool_clear(iterpool);
 
       SVN_ERR(svn_wc__node_is_not_present(&not_present, NULL, NULL, wc_ctx,
-                                          this_abspath, scratch_pool));
+                                          this_abspath, FALSE, scratch_pool));
 
       if (!not_present)
         continue;
@@ -777,7 +777,7 @@ harvest_status_callback(void *status_bat
       svn_revnum_t dir_rev;
 
       if (!copy_mode_root && !status->switched)
-        SVN_ERR(svn_wc__node_get_base(&dir_rev, NULL, NULL, NULL, wc_ctx,
+        SVN_ERR(svn_wc__node_get_base(&dir_rev, NULL, NULL, NULL, NULL, wc_ctx,
                                       svn_dirent_dirname(local_abspath,
                                                          scratch_pool),
                                       scratch_pool, scratch_pool));
@@ -1251,7 +1251,8 @@ harvest_copy_committables(void *baton, v
   /* Read the entry for this SRC. */
   SVN_ERR_ASSERT(svn_dirent_is_absolute(pair->src_abspath_or_url));
 
-  SVN_ERR(svn_wc__node_get_repos_info(&repos_root_url, NULL, btn->ctx->wc_ctx,
+  SVN_ERR(svn_wc__node_get_repos_info(NULL, NULL, &repos_root_url, NULL,
+                                      btn->ctx->wc_ctx,
                                       pair->src_abspath_or_url,
                                       pool, pool));
 

Modified: subversion/branches/ev2-export/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/copy.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/copy.c Sat Feb 23 01:25:38 2013
@@ -412,7 +412,7 @@ verify_wc_dsts(const apr_array_header_t 
 
           SVN_ERR(svn_wc__node_is_not_present(&is_not_present, &is_excluded,
                                               &is_server_excluded, ctx->wc_ctx,
-                                              pair->dst_abspath_or_url,
+                                              pair->dst_abspath_or_url, FALSE,
                                               iterpool));
 
           if (is_excluded || is_server_excluded)
@@ -1440,58 +1440,73 @@ repos_to_wc_copy_single(svn_client__copy
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(dst_abspath));
 
-  if (pair->src_kind == svn_node_dir)
+  if (!same_repositories && ctx->notify_func2)
     {
-      svn_boolean_t sleep_needed = FALSE;
-      const char *tmpdir_abspath, *tmp_abspath;
+      svn_wc_notify_t *notify;
+      notify = svn_wc_create_notify_url(
+                            pair->src_abspath_or_url,
+                            svn_wc_notify_foreign_copy_begin,
+                            pool);
+      notify->kind = pair->src_kind;
+      ctx->notify_func2(ctx->notify_baton2, notify, pool);
 
-      /* Find a temporary location in which to check out the copy source. */
-      SVN_ERR(svn_wc__get_tmpdir(&tmpdir_abspath, ctx->wc_ctx, dst_abspath,
-                                 pool, pool));
-                                 
-      SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_abspath, tmpdir_abspath,
-                                       svn_io_file_del_on_close, pool, pool));
-
-      /* Make a new checkout of the requested source. While doing so,
-       * resolve pair->src_revnum to an actual revision number in case it
-       * was until now 'invalid' meaning 'head'.  Ask this function not to
-       * sleep for timestamps, by passing a sleep_needed output param.
-       * Send notifications for all nodes except the root node, and adjust
-       * them to refer to the destination rather than this temporary path. */
-      {
-        svn_wc_notify_func2_t old_notify_func2 = ctx->notify_func2;
-        void *old_notify_baton2 = ctx->notify_baton2;
-        struct notification_adjust_baton nb;
-        svn_error_t *err;
-
-        nb.inner_func = ctx->notify_func2;
-        nb.inner_baton = ctx->notify_baton2;
-        nb.checkout_abspath = tmp_abspath;
-        nb.final_abspath = dst_abspath;
-        ctx->notify_func2 = notification_adjust_func;
-        ctx->notify_baton2 = &nb;
-
-        err = svn_client__checkout_internal(&pair->src_revnum,
-                                            pair->src_original,
-                                            tmp_abspath,
-                                            &pair->src_peg_revision,
-                                            &pair->src_op_revision,
-                                            svn_depth_infinity,
-                                            ignore_externals, FALSE,
-                                            &sleep_needed, ctx, pool);
+      /* Allow a theoretical cancel to get through. */
+      if (ctx->cancel_func)
+        SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+    }
 
-        ctx->notify_func2 = old_notify_func2;
-        ctx->notify_baton2 = old_notify_baton2;
+  if (pair->src_kind == svn_node_dir)
+    {
+      if (same_repositories)
+        {
+          svn_boolean_t sleep_needed = FALSE;
+          const char *tmpdir_abspath, *tmp_abspath;
 
-        SVN_ERR(err);
-      }
+          /* Find a temporary location in which to check out the copy source. */
+          SVN_ERR(svn_wc__get_tmpdir(&tmpdir_abspath, ctx->wc_ctx, dst_abspath,
+                                     pool, pool));
+                                     
+          SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_abspath, tmpdir_abspath,
+                                           svn_io_file_del_on_close, pool, pool));
+
+          /* Make a new checkout of the requested source. While doing so,
+           * resolve pair->src_revnum to an actual revision number in case it
+           * was until now 'invalid' meaning 'head'.  Ask this function not to
+           * sleep for timestamps, by passing a sleep_needed output param.
+           * Send notifications for all nodes except the root node, and adjust
+           * them to refer to the destination rather than this temporary path. */
+          {
+            svn_wc_notify_func2_t old_notify_func2 = ctx->notify_func2;
+            void *old_notify_baton2 = ctx->notify_baton2;
+            struct notification_adjust_baton nb;
+            svn_error_t *err;
+          
+            nb.inner_func = ctx->notify_func2;
+            nb.inner_baton = ctx->notify_baton2;
+            nb.checkout_abspath = tmp_abspath;
+            nb.final_abspath = dst_abspath;
+            ctx->notify_func2 = notification_adjust_func;
+            ctx->notify_baton2 = &nb;
+          
+            err = svn_client__checkout_internal(&pair->src_revnum,
+                                                pair->src_original,
+                                                tmp_abspath,
+                                                &pair->src_peg_revision,
+                                                &pair->src_op_revision,
+                                                svn_depth_infinity,
+                                                ignore_externals, FALSE,
+                                                &sleep_needed, ctx, pool);
+          
+            ctx->notify_func2 = old_notify_func2;
+            ctx->notify_baton2 = old_notify_baton2;
+
+            SVN_ERR(err);
+          }
 
       /* Schedule dst_path for addition in parent, with copy history.
          Don't send any notification here.
          Then remove the temporary checkout's .svn dir in preparation for
          moving the rest of it into the final destination. */
-      if (same_repositories)
-        {
           SVN_ERR(svn_wc_copy3(ctx->wc_ctx, tmp_abspath, dst_abspath,
                                TRUE /* metadata_only */,
                                ctx->cancel_func, ctx->cancel_baton,
@@ -1510,21 +1525,16 @@ repos_to_wc_copy_single(svn_client__copy
         }
       else
         {
-          /* ### We want to schedule this as a simple add, or even better
-             a copy from a foreign repos, but we don't yet have the
-             WC APIs to do that, so we will just move the whole WC into
-             place as a disjoint, nested WC. */
-
-          /* Move the working copy to where it is expected. */
-          SVN_ERR(svn_wc__rename_wc(ctx->wc_ctx, tmp_abspath, dst_abspath,
-                                    pool));
+          SVN_ERR(svn_client__copy_foreign(pair->src_abspath_or_url,
+                                           dst_abspath,
+                                           &pair->src_peg_revision,
+                                           &pair->src_op_revision,
+                                           svn_depth_infinity,
+                                           FALSE /* make_parents */,
+                                           TRUE /* already_locked */,
+                                           ctx, pool));
 
-          svn_io_sleep_for_timestamps(dst_abspath, pool);
-
-          return svn_error_createf(
-             SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-             _("Source URL '%s' is from foreign repository; "
-               "leaving it as a disjoint WC"), pair->src_abspath_or_url);
+          return SVN_NO_ERROR;
         }
     } /* end directory case */
 
@@ -1542,6 +1552,10 @@ repos_to_wc_copy_single(svn_client__copy
       SVN_ERR(svn_ra_get_file(ra_session, src_rel, pair->src_revnum,
                               new_base_contents,
                               &pair->src_revnum, &new_props, pool));
+
+      if (new_props && ! same_repositories)
+        apr_hash_set(new_props, SVN_PROP_MERGEINFO, APR_HASH_KEY_STRING, NULL);
+
       SVN_ERR(svn_wc_add_repos_file4(
          ctx->wc_ctx, dst_abspath,
          new_base_contents, NULL, new_props, NULL,

Modified: subversion/branches/ev2-export/subversion/libsvn_client/delete.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/delete.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/delete.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/delete.c Sat Feb 23 01:25:38 2013
@@ -79,7 +79,14 @@ find_undeletables(void *baton,
     return svn_error_createf(SVN_ERR_UNVERSIONED_RESOURCE, NULL,
                              _("'%s' is not under version control"),
                              svn_dirent_local_style(local_abspath, pool));
-
+  else if ((status->node_status == svn_wc_status_added
+            || status->node_status == svn_wc_status_replaced)
+           && status->text_status == svn_wc_status_normal
+           && (status->prop_status == svn_wc_status_normal
+               || status->prop_status == svn_wc_status_none))
+    {
+      /* Unmodified copy. Go ahead, remove it */
+    }
   else if (status->node_status != svn_wc_status_normal
            && status->node_status != svn_wc_status_deleted
            && status->node_status != svn_wc_status_missing)

Modified: subversion/branches/ev2-export/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/deprecated.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/deprecated.c Sat Feb 23 01:25:38 2013
@@ -1630,6 +1630,34 @@ svn_client_log(const apr_array_header_t 
 /*** From merge.c ***/
 
 svn_error_t *
+svn_client_merge4(const char *source1,
+                  const svn_opt_revision_t *revision1,
+                  const char *source2,
+                  const svn_opt_revision_t *revision2,
+                  const char *target_wcpath,
+                  svn_depth_t depth,
+                  svn_boolean_t ignore_ancestry,
+                  svn_boolean_t force_delete,
+                  svn_boolean_t record_only,
+                  svn_boolean_t dry_run,
+                  svn_boolean_t allow_mixed_rev,
+                  const apr_array_header_t *merge_options,
+                  svn_client_ctx_t *ctx,
+                  apr_pool_t *pool)
+{
+  SVN_ERR(svn_client_merge5(source1, revision1,
+                            source2, revision2,
+                            target_wcpath,
+                            depth,
+                            ignore_ancestry /*ignore_mergeinfo*/,
+                            ignore_ancestry /*diff_ignore_ancestry*/,
+                            force_delete, record_only,
+                            dry_run, allow_mixed_rev,
+                            merge_options, ctx, pool));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_client_merge3(const char *source1,
                   const svn_opt_revision_t *revision1,
                   const char *source2,
@@ -1690,6 +1718,34 @@ svn_client_merge(const char *source1,
 }
 
 svn_error_t *
+svn_client_merge_peg4(const char *source_path_or_url,
+                      const apr_array_header_t *ranges_to_merge,
+                      const svn_opt_revision_t *source_peg_revision,
+                      const char *target_wcpath,
+                      svn_depth_t depth,
+                      svn_boolean_t ignore_ancestry,
+                      svn_boolean_t force_delete,
+                      svn_boolean_t record_only,
+                      svn_boolean_t dry_run,
+                      svn_boolean_t allow_mixed_rev,
+                      const apr_array_header_t *merge_options,
+                      svn_client_ctx_t *ctx,
+                      apr_pool_t *pool)
+{
+  SVN_ERR(svn_client_merge_peg5(source_path_or_url,
+                                ranges_to_merge,
+                                source_peg_revision,
+                                target_wcpath,
+                                depth,
+                                ignore_ancestry /*ignore_mergeinfo*/,
+                                ignore_ancestry /*diff_ignore_ancestry*/,
+                                force_delete, record_only,
+                                dry_run, allow_mixed_rev,
+                                merge_options, ctx, pool));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_client_merge_peg3(const char *source,
                       const apr_array_header_t *ranges_to_merge,
                       const svn_opt_revision_t *peg_revision,
@@ -2729,7 +2785,8 @@ svn_client_uuid_from_path2(const char **
                            apr_pool_t *scratch_pool)
 {
   return svn_error_trace(
-    svn_wc__node_get_repos_info(NULL, uuid, ctx->wc_ctx, local_abspath,
+      svn_client_get_repos_root(NULL, uuid,
+                                local_abspath, ctx,
                                 result_pool, scratch_pool));
 }
 

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=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/diff.c Sat Feb 23 01:25:38 2013
@@ -50,6 +50,7 @@
 
 #include "private/svn_wc_private.h"
 #include "private/svn_diff_private.h"
+#include "private/svn_subr_private.h"
 
 #include "svn_private_config.h"
 
@@ -92,9 +93,9 @@ make_repos_relpath(const char **repos_re
                                                       scratch_pool),
                                       scratch_pool));
 
-      err = svn_wc__node_get_repos_relpath(repos_relpath, wc_ctx,
-                                           local_abspath,
-                                           result_pool, scratch_pool);
+      err = svn_wc__node_get_repos_info(NULL, repos_relpath, NULL, NULL,
+                                        wc_ctx, local_abspath,
+                                        result_pool, scratch_pool);
 
       if (!ra_session
           || ! err
@@ -594,6 +595,12 @@ struct diff_cmd_baton {
   /* Whether deletion of a file is summarized versus showing a full diff. */
   svn_boolean_t no_diff_deleted;
 
+  /* Whether to ignore copyfrom information when showing adds */
+  svn_boolean_t no_copyfrom_on_add;
+
+  /* Empty files for creating diffs or NULL if not used yet */
+  const char *empty_file;
+
   svn_wc_context_t *wc_ctx;
 
   /* The RA session used during diffs involving the repository. */
@@ -669,7 +676,9 @@ diff_dir_props_changed(svn_wc_notify_sta
   return svn_error_trace(diff_props_changed(diff_relpath,
                                             /* ### These revs be filled
                                              * ### with per node info */
-                                            diff_cmd_baton->revnum1,
+                                            dir_was_added
+                                                ? 0 /* Magic legacy value */
+                                                : diff_cmd_baton->revnum1,
                                             diff_cmd_baton->revnum2,
                                             dir_was_added,
                                             propchanges,
@@ -996,6 +1005,30 @@ diff_file_added(svn_wc_notify_state_t *c
         rev2 = diff_cmd_baton->revnum2;
     }
 
+  if (diff_cmd_baton->no_copyfrom_on_add
+      && (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_revision)))
+    {
+      apr_hash_t *empty_hash = apr_hash_make(scratch_pool);
+      apr_array_header_t *new_changes;
+
+      /* Rebase changes on having no left source. */
+      if (!diff_cmd_baton->empty_file)
+        SVN_ERR(svn_io_open_unique_file3(NULL, &diff_cmd_baton->empty_file,
+                                         NULL, svn_io_file_del_on_pool_cleanup,
+                                         diff_cmd_baton->pool, scratch_pool));
+
+      SVN_ERR(svn_prop_diffs(&new_changes,
+                             svn_prop__patch(original_props, prop_changes,
+                                             scratch_pool),
+                             empty_hash,
+                             scratch_pool));
+
+      tmpfile1 = diff_cmd_baton->empty_file;
+      prop_changes = new_changes;
+      original_props = empty_hash;
+      copyfrom_revision = SVN_INVALID_REVNUM;
+    }
+
   if (diff_cmd_baton->no_diff_added)
     {
       const char *index_path = diff_relpath;
@@ -1192,37 +1225,6 @@ static const svn_wc_diff_callbacks4_t di
    the user specifies two dates that resolve to the same revision.  */
 
 
-
-
-/* Helper function: given a working-copy ABSPATH_OR_URL, return its
-   associated url in *URL, allocated in RESULT_POOL.  If ABSPATH_OR_URL is
-   *already* a URL, that's fine, return ABSPATH_OR_URL allocated in
-   RESULT_POOL.
-
-   Use SCRATCH_POOL for temporary allocations. */
-static svn_error_t *
-convert_to_url(const char **url,
-               svn_wc_context_t *wc_ctx,
-               const char *abspath_or_url,
-               apr_pool_t *result_pool,
-               apr_pool_t *scratch_pool)
-{
-  if (svn_path_is_url(abspath_or_url))
-    {
-      *url = apr_pstrdup(result_pool, abspath_or_url);
-      return SVN_NO_ERROR;
-    }
-
-  SVN_ERR(svn_wc__node_get_url(url, wc_ctx, abspath_or_url,
-                               result_pool, scratch_pool));
-  if (! *url)
-    return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
-                             _("Path '%s' has no URL"),
-                             svn_dirent_local_style(abspath_or_url,
-                                                    scratch_pool));
-  return SVN_NO_ERROR;
-}
-
 /** Check if paths PATH_OR_URL1 and PATH_OR_URL2 are urls and if the
  * revisions REVISION1 and REVISION2 are local. If PEG_REVISION is not
  * unspecified, ensure that at least one of the two revisions is not
@@ -1384,24 +1386,25 @@ diff_prepare_repos_repos(const char **ur
 {
   const char *abspath_or_url2;
   const char *abspath_or_url1;
+  const char *repos_root_url;
 
   if (!svn_path_is_url(path_or_url2))
-    SVN_ERR(svn_dirent_get_absolute(&abspath_or_url2, path_or_url2,
-                                    pool));
+    {
+      SVN_ERR(svn_dirent_get_absolute(&abspath_or_url2, path_or_url2, pool));
+      SVN_ERR(svn_wc__node_get_url(url2, ctx->wc_ctx, abspath_or_url2,
+                                   pool, pool));
+    }
   else
-    abspath_or_url2 = path_or_url2;
+    *url2 = abspath_or_url2 = apr_pstrdup(pool, path_or_url2);
 
   if (!svn_path_is_url(path_or_url1))
-    SVN_ERR(svn_dirent_get_absolute(&abspath_or_url1, path_or_url1,
-                                    pool));
+    {
+      SVN_ERR(svn_dirent_get_absolute(&abspath_or_url1, path_or_url1, pool));
+      SVN_ERR(svn_wc__node_get_url(url1, ctx->wc_ctx, abspath_or_url1,
+                                   pool, pool));
+    }
   else
-    abspath_or_url1 = path_or_url1;
-
-  /* Figure out URL1 and URL2. */
-  SVN_ERR(convert_to_url(url1, ctx->wc_ctx, abspath_or_url1,
-                         pool, pool));
-  SVN_ERR(convert_to_url(url2, ctx->wc_ctx, abspath_or_url2,
-                         pool, pool));
+    *url1 = abspath_or_url1 = apr_pstrdup(pool, path_or_url1);
 
   /* We need exactly one BASE_PATH, so we'll let the BASE_PATH
      calculated for PATH_OR_URL2 override the one for PATH_OR_URL1
@@ -1488,18 +1491,23 @@ diff_prepare_repos_repos(const char **ur
   else if (*kind2 == svn_node_none)
     SVN_ERR(check_diff_target_exists(*url2, *rev1, *rev2, *ra_session, pool));
 
+  SVN_ERR(svn_ra_get_repos_root2(*ra_session, &repos_root_url, pool));
+
   /* Choose useful anchors and targets for our two URLs. */
   *anchor1 = *url1;
   *anchor2 = *url2;
   *target1 = "";
   *target2 = "";
 
-  /* If one of the targets is a file, use the parent directory as anchor. */
-  if (*kind1 == svn_node_file || *kind2 == svn_node_file)
+  /* If none of the targets is the repository root open the parent directory
+     to allow describing replacement of the target itself */
+  if (strcmp(*url1, repos_root_url) != 0
+      && strcmp(*url2, repos_root_url) != 0)
     {
       svn_uri_split(anchor1, target1, *url1, pool);
       svn_uri_split(anchor2, target2, *url2, pool);
-      if (*base_path)
+      if (*base_path
+          && (*kind1 == svn_node_file || *kind2 == svn_node_file))
         *base_path = svn_dirent_dirname(*base_path, pool);
       SVN_ERR(svn_ra_reparent(*ra_session, *anchor1, pool));
     }
@@ -1630,300 +1638,6 @@ 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.
 
    PATH_OR_URL1 and PATH_OR_URL2 may be either URLs or the working copy paths.
@@ -1954,6 +1668,8 @@ diff_repos_repos(const svn_wc_diff_callb
   const svn_delta_editor_t *diff_editor;
   void *diff_edit_baton;
 
+  const svn_diff_tree_processor_t *diff_processor;
+
   const char *url1;
   const char *url2;
   const char *base_path;
@@ -1975,6 +1691,14 @@ diff_repos_repos(const svn_wc_diff_callb
                                    revision1, revision2, peg_revision,
                                    pool));
 
+  /* Set up the repos_diff editor on BASE_PATH, if available.
+     Otherwise, we just use "". */
+
+  SVN_ERR(svn_wc__wrap_diff_callbacks(&diff_processor,
+                                      callbacks, callback_baton,
+                                      TRUE /* walk_deleted_dirs */,
+                                      pool, pool));
+
   /* Get actual URLs. */
   callback_baton->orig_path_1 = url1;
   callback_baton->orig_path_2 = url2;
@@ -1986,21 +1710,41 @@ 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)
+  /* The repository can bring in a new working copy, but not delete
+     everything. Luckily our new diff handler can just be reversed. */
+  if (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;
+      const char *str_tmp;
+      svn_revnum_t rev_tmp;
+
+      str_tmp = url2;
+      url2 = url1;
+      url1 = str_tmp;
+
+      rev_tmp = rev2;
+      rev2 = rev1;
+      rev1 = rev_tmp;
+
+      str_tmp = anchor2;
+      anchor2 = anchor1;
+      anchor1 = str_tmp;
+
+      str_tmp = target2;
+      target2 = target1;
+      target1 = str_tmp;
+
+      diff_processor = svn_diff__tree_processor_reverse_create(diff_processor,
+                                                               NULL, pool);
     }
 
+  /* Filter the first path component using a filter processor, until we fixed
+     the diff processing to handle this directly */
+  if ((kind1 != svn_node_file && kind2 != svn_node_file) && target1[0] != '\0')
+  {
+    diff_processor = svn_diff__tree_processor_filter_create(diff_processor,
+                                                            target1, pool);
+  }
+
   /* 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.  */
@@ -2008,188 +1752,28 @@ diff_repos_repos(const svn_wc_diff_callb
                                                anchor1, NULL, NULL, FALSE,
                                                TRUE, ctx, pool));
 
-  /* Set up the repos_diff editor on BASE_PATH, if available.
-     Otherwise, we just use "". */
-  SVN_ERR(svn_client__get_diff_editor(
+  SVN_ERR(svn_client__get_diff_editor2(
                 &diff_editor, &diff_edit_baton,
-                depth,
-                extra_ra_session, rev1, TRUE /* walk_deleted_dirs */,
+                extra_ra_session, depth,
+                rev1, 
                 TRUE /* text_deltas */,
-                callbacks, callback_baton,
+                diff_processor,
                 ctx->cancel_func, ctx->cancel_baton,
-                NULL /* no notify_func */, NULL /* no notify_baton */,
                 pool));
 
   /* We want to switch our txn into URL2 */
-  SVN_ERR(svn_ra_do_diff3
-          (ra_session, &reporter, &reporter_baton, rev2, target1,
-           depth, ignore_ancestry, TRUE /* text_deltas */,
-           url2, diff_editor, diff_edit_baton, pool));
+  SVN_ERR(svn_ra_do_diff3(ra_session, &reporter, &reporter_baton,
+                          rev2, target1,
+                          depth, ignore_ancestry, TRUE /* text_deltas */,
+                          url2, diff_editor, diff_edit_baton, pool));
 
   /* Drive the reporter; do the diff. */
   SVN_ERR(reporter->set_path(reporter_baton, "", rev1,
                              svn_depth_infinity,
                              FALSE, NULL,
                              pool));
-  return reporter->finish_report(reporter_baton, pool);
-}
-
-
-/* Using CALLBACKS, show a REPOS->WC diff for a file TARGET, which in the
- * working copy is at FILE2_ABSPATH. KIND1 is the node kind of the repository
- * target (either svn_node_file or svn_node_none). REV is the revision the
- * working file is diffed against. RA_SESSION points at the URL of the file
- * in the repository and is used to get the file's repository-version content,
- * if necessary. The other parameters are as in diff_repos_wc(). */
-static svn_error_t *
-diff_repos_wc_file_target(const char *target,
-                          const char *file2_abspath,
-                          svn_node_kind_t kind1,
-                          svn_revnum_t rev,
-                          svn_boolean_t reverse,
-                          svn_boolean_t show_copies_as_adds,
-                          const svn_wc_diff_callbacks4_t *callbacks,
-                          void *callback_baton,
-                          svn_ra_session_t *ra_session,
-                          svn_client_ctx_t *ctx,
-                          apr_pool_t *scratch_pool)
-{
-  const char *file1_abspath;
-  svn_stream_t *file1_content;
-  svn_stream_t *file2_content;
-  apr_hash_t *file1_props = NULL;
-  apr_hash_t *file2_props;
-  svn_boolean_t is_copy = FALSE;
-  apr_hash_t *keywords = NULL;
-  svn_string_t *keywords_prop;
-  svn_subst_eol_style_t eol_style;
-  const char *eol_str;
-
-  /* Get content and props of file 1 (the remote file). */
-  SVN_ERR(svn_stream_open_unique(&file1_content, &file1_abspath, NULL,
-                                 svn_io_file_del_on_pool_cleanup,
-                                 scratch_pool, scratch_pool));
-  if (kind1 == svn_node_file)
-    {
-      if (show_copies_as_adds)
-        SVN_ERR(svn_wc__node_get_origin(&is_copy, 
-                                        NULL, NULL, NULL, NULL, NULL,
-                                        ctx->wc_ctx, file2_abspath,
-                                        FALSE, scratch_pool, scratch_pool));
-      /* If showing copies as adds, diff against the empty file. */
-      if (!(show_copies_as_adds && is_copy))
-        SVN_ERR(svn_ra_get_file(ra_session, "", rev, file1_content,
-                                NULL, &file1_props, scratch_pool));
-    }
-
-  SVN_ERR(svn_stream_close(file1_content));
-
-  SVN_ERR(svn_wc_prop_list2(&file2_props, ctx->wc_ctx, file2_abspath,
-                            scratch_pool, scratch_pool));
-
-  /* We might have to create a normalised version of the working file. */
-  svn_subst_eol_style_from_value(&eol_style, &eol_str,
-                                 apr_hash_get(file2_props,
-                                              SVN_PROP_EOL_STYLE,
-                                              APR_HASH_KEY_STRING));
-  keywords_prop = apr_hash_get(file2_props, SVN_PROP_KEYWORDS,
-                               APR_HASH_KEY_STRING);
-  if (keywords_prop)
-    SVN_ERR(svn_subst_build_keywords2(&keywords, keywords_prop->data,
-                                      NULL, NULL, 0, NULL,
-                                      scratch_pool));
-  if (svn_subst_translation_required(eol_style, SVN_SUBST_NATIVE_EOL_STR,
-                                     keywords, FALSE, TRUE))
-    {
-      svn_stream_t *working_content;
-      svn_stream_t *normalized_content;
-
-      SVN_ERR(svn_stream_open_readonly(&working_content, file2_abspath,
-                                       scratch_pool, scratch_pool));
-
-      /* Create a temporary file and copy normalised data into it. */
-      SVN_ERR(svn_stream_open_unique(&file2_content, &file2_abspath, NULL,
-                                     svn_io_file_del_on_pool_cleanup,
-                                     scratch_pool, scratch_pool));
-      normalized_content = svn_subst_stream_translated(
-                             file2_content, SVN_SUBST_NATIVE_EOL_STR,
-                             TRUE, keywords, FALSE, scratch_pool);
-      SVN_ERR(svn_stream_copy3(working_content, normalized_content,
-                               ctx->cancel_func, ctx->cancel_baton,
-                               scratch_pool));
-    }
 
-  if (kind1 == svn_node_file && !(show_copies_as_adds && is_copy))
-    {
-      SVN_ERR(callbacks->file_opened(NULL, NULL, target,
-                                     reverse ? SVN_INVALID_REVNUM : rev,
-                                     callback_baton, scratch_pool));
-
-      if (reverse)
-        SVN_ERR(callbacks->file_changed(NULL, NULL, NULL, target,
-                                        file2_abspath, file1_abspath,
-                                        SVN_INVALID_REVNUM, rev,
-                                        apr_hash_get(file2_props,
-                                                     SVN_PROP_MIME_TYPE,
-                                                     APR_HASH_KEY_STRING),
-                                        apr_hash_get(file1_props,
-                                                     SVN_PROP_MIME_TYPE,
-                                                     APR_HASH_KEY_STRING),
-                                        make_regular_props_array(
-                                          file1_props, scratch_pool,
-                                          scratch_pool),
-                                        file2_props,
-                                        callback_baton, scratch_pool));
-      else
-        SVN_ERR(callbacks->file_changed(NULL, NULL, NULL, target,
-                                        file1_abspath, file2_abspath,
-                                        rev, SVN_INVALID_REVNUM,
-                                        apr_hash_get(file1_props,
-                                                     SVN_PROP_MIME_TYPE,
-                                                     APR_HASH_KEY_STRING),
-                                        apr_hash_get(file2_props,
-                                                     SVN_PROP_MIME_TYPE,
-                                                     APR_HASH_KEY_STRING),
-                                        make_regular_props_array(
-                                          file2_props, scratch_pool,
-                                          scratch_pool),
-                                        file1_props,
-                                        callback_baton, scratch_pool));
-    }
-  else
-    {
-      if (reverse)
-        {
-          SVN_ERR(callbacks->file_deleted(NULL, NULL,
-                                          target, file2_abspath, file1_abspath,
-                                          apr_hash_get(file2_props,
-                                                       SVN_PROP_MIME_TYPE,
-                                                       APR_HASH_KEY_STRING),
-                                          NULL,
-                                          make_regular_props_hash(
-                                            file2_props, scratch_pool,
-                                            scratch_pool),
-                                          callback_baton, scratch_pool));
-        }
-      else
-        {
-          SVN_ERR(callbacks->file_added(NULL, NULL, NULL, target,
-                                        file1_abspath, file2_abspath,
-                                        rev, SVN_INVALID_REVNUM,
-                                        NULL,
-                                        apr_hash_get(file2_props,
-                                                     SVN_PROP_MIME_TYPE,
-                                                     APR_HASH_KEY_STRING),
-                                        NULL, SVN_INVALID_REVNUM,
-                                        make_regular_props_array(
-                                          file2_props, scratch_pool,
-                                          scratch_pool),
-                                        NULL,
-                                        callback_baton, scratch_pool));
-        }
-    }
-
-  return SVN_NO_ERROR;
+  return svn_error_trace(reporter->finish_report(reporter_baton, pool));
 }
 
 /* Perform a diff between a repository path and a working-copy path.
@@ -2218,8 +1802,9 @@ diff_repos_wc(const char *path_or_url1,
               void *callback_baton,
               struct diff_cmd_baton *cmd_baton,
               svn_client_ctx_t *ctx,
-              apr_pool_t *pool)
+              apr_pool_t *scratch_pool)
 {
+  apr_pool_t *pool = scratch_pool;
   const char *url1, *anchor, *anchor_url, *target;
   svn_revnum_t rev;
   svn_ra_session_t *ra_session;
@@ -2236,22 +1821,27 @@ diff_repos_wc(const char *path_or_url1,
   svn_node_kind_t kind1;
   svn_node_kind_t kind2;
   svn_boolean_t is_copy;
-  svn_revnum_t copyfrom_rev;
-  const char *copy_source_repos_relpath;
-  const char *copy_source_repos_root_url;
+  svn_revnum_t cf_revision;
+  const char *cf_repos_relpath;
+  const char *cf_repos_root_url;
 
   SVN_ERR_ASSERT(! svn_path_is_url(path2));
 
   if (!svn_path_is_url(path_or_url1))
-    SVN_ERR(svn_dirent_get_absolute(&abspath_or_url1, path_or_url1, pool));
+    {
+      SVN_ERR(svn_dirent_get_absolute(&abspath_or_url1, path_or_url1, pool));
+      SVN_ERR(svn_wc__node_get_url(&url1, ctx->wc_ctx, abspath_or_url1,
+                                   pool, pool));
+    }
   else
-    abspath_or_url1 = path_or_url1;
+    {
+      url1 = path_or_url1;
+      abspath_or_url1 = path_or_url1;
+    }
 
   SVN_ERR(svn_dirent_get_absolute(&abspath2, path2, pool));
 
   /* Convert path_or_url1 to a URL to feed to do_diff. */
-  SVN_ERR(convert_to_url(&url1, ctx->wc_ctx, abspath_or_url1, pool, pool));
-
   SVN_ERR(svn_wc_get_actual_target2(&anchor, &target,
                                     ctx->wc_ctx, path2,
                                     pool, pool));
@@ -2260,10 +1850,7 @@ diff_repos_wc(const char *path_or_url1,
   SVN_ERR(svn_dirent_get_absolute(&anchor_abspath, anchor, pool));
   SVN_ERR(svn_wc__node_get_url(&anchor_url, ctx->wc_ctx, anchor_abspath,
                                pool, pool));
-  if (! anchor_url)
-    return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
-                             _("Directory '%s' has no URL"),
-                             svn_dirent_local_style(anchor, pool));
+  SVN_ERR_ASSERT(anchor_url != NULL);
 
   /* If we are performing a pegged diff, we need to find out what our
      actual URLs will be. */
@@ -2301,7 +1888,7 @@ diff_repos_wc(const char *path_or_url1,
   SVN_ERR(svn_ra_check_path(ra_session, "", rev, &kind1, pool));
 
   /* Figure out the node kind of the local target. */
-  SVN_ERR(svn_io_check_resolved_path(abspath2, &kind2, pool));
+  SVN_ERR(svn_wc_read_kind(&kind2, ctx->wc_ctx, abspath2, FALSE, pool));
 
   cmd_baton->ra_session = ra_session;
   cmd_baton->anchor = anchor;
@@ -2312,32 +1899,14 @@ diff_repos_wc(const char *path_or_url1,
     cmd_baton->revnum2 = rev;
 
   /* Check if our diff target is a copied node. */
-  SVN_ERR(svn_wc__node_get_origin(&is_copy, 
-                                  &copyfrom_rev,
-                                  &copy_source_repos_relpath,
-                                  &copy_source_repos_root_url,
+  SVN_ERR(svn_wc__node_get_origin(&is_copy,
+                                  &cf_revision,
+                                  &cf_repos_relpath,
+                                  &cf_repos_root_url,
                                   NULL, NULL,
                                   ctx->wc_ctx, abspath2,
                                   FALSE, pool, pool));
 
-  /* If both diff targets can be diffed as files, fetch the appropriate
-   * file content from the repository and generate a diff against the
-   * local version of the file.
-   * However, if comparing the repository version of the file to the BASE
-   * tree version we can use the diff editor to transmit a delta instead
-   * of potentially huge file content. */
-  if ((!rev2_is_base || is_copy) &&
-      (kind1 == svn_node_file || kind1 == svn_node_none)
-       && kind2 == svn_node_file)
-    {
-      SVN_ERR(diff_repos_wc_file_target(target, abspath2, kind1, rev,
-                                        reverse, show_copies_as_adds,
-                                        callbacks, callback_baton,
-                                        ra_session, ctx, pool));
-
-      return SVN_NO_ERROR;
-    }
-
   /* Use the diff editor to generate the diff. */
   SVN_ERR(svn_ra_has_capability(ra_session, &server_supports_depth,
                                 SVN_RA_CAPABILITY_DEPTH, pool));
@@ -2346,7 +1915,7 @@ diff_repos_wc(const char *path_or_url1,
                                   anchor_abspath,
                                   target,
                                   depth,
-                                  ignore_ancestry,
+                                  ignore_ancestry || is_copy,
                                   show_copies_as_adds,
                                   use_git_diff_format,
                                   rev2_is_base,
@@ -2365,30 +1934,40 @@ diff_repos_wc(const char *path_or_url1,
 
   if (is_copy)
     {
-      const char *copyfrom_url;
       const char *copyfrom_parent_url;
       const char *copyfrom_basename;
       svn_depth_t copy_depth;
 
       cmd_baton->repos_wc_diff_target_is_copy = TRUE;
 
-      /* We're diffing a locally copied/moved directory.
+      /* We're diffing a locally copied/moved node.
        * Describe the copy source to the reporter instead of the copy itself.
        * Doing the latter would generate a single add_directory() call to the
        * diff editor which results in an unexpected diff (the copy would
        * be shown as deleted). */
 
-      copyfrom_url = apr_pstrcat(pool, copy_source_repos_root_url, "/",
-                                 copy_source_repos_relpath, (char *)NULL);
-      svn_uri_split(&copyfrom_parent_url, &copyfrom_basename,
-                    copyfrom_url, pool);
+      if (cf_repos_relpath[0] == '\0')
+        {
+          copyfrom_parent_url = cf_repos_root_url;
+          copyfrom_basename = "";
+        }
+      else
+        {
+          const char *parent_relpath;
+          svn_relpath_split(&parent_relpath, &copyfrom_basename,
+                            cf_repos_relpath, scratch_pool);
+
+          copyfrom_parent_url = svn_path_url_add_component2(cf_repos_root_url,
+                                                            parent_relpath,
+                                                            scratch_pool);
+        }
       SVN_ERR(svn_ra_reparent(ra_session, copyfrom_parent_url, pool));
 
       /* Tell the RA layer we want a delta to change our txn to URL1 */ 
       SVN_ERR(svn_ra_do_diff3(ra_session,
                               &reporter, &reporter_baton,
                               rev,
-                              copyfrom_basename,
+                              target,
                               diff_depth,
                               ignore_ancestry,
                               TRUE,  /* text_deltas */
@@ -2398,9 +1977,23 @@ diff_repos_wc(const char *path_or_url1,
       /* Report the copy source. */
       SVN_ERR(svn_wc__node_get_depth(&copy_depth, ctx->wc_ctx, abspath2,
                                      pool));
-      SVN_ERR(reporter->set_path(reporter_baton, "", copyfrom_rev,
-                                 copy_depth, FALSE, NULL, pool));
-      
+
+      if (copy_depth == svn_depth_unknown)
+        copy_depth = svn_depth_infinity;
+
+      SVN_ERR(reporter->set_path(reporter_baton, "",
+                                 cf_revision,
+                                 copy_depth, FALSE, NULL, scratch_pool));
+
+      if (strcmp(target, copyfrom_basename) != 0)
+        SVN_ERR(reporter->link_path(reporter_baton, target,
+                                    svn_path_url_add_component2(
+                                                cf_repos_root_url,
+                                                cf_repos_relpath,
+                                                scratch_pool),
+                                    cf_revision,
+                                    copy_depth, FALSE, NULL, scratch_pool));
+
       /* Finish the report to generate the diff. */
       SVN_ERR(reporter->finish_report(reporter_baton, pool));
     }
@@ -2501,6 +2094,7 @@ do_diff(const svn_wc_diff_callbacks4_t *
               SVN_ERR(svn_dirent_get_absolute(&abspath2, path_or_url2, pool));
 
               SVN_ERR(svn_client__arbitrary_nodes_diff(abspath1, abspath2,
+                                                       depth,
                                                        callbacks,
                                                        callback_baton,
                                                        ctx, pool));
@@ -2645,6 +2239,8 @@ diff_summarize_repos_repos(svn_client_di
   const svn_delta_editor_t *diff_editor;
   void *diff_edit_baton;
 
+  const svn_diff_tree_processor_t *diff_processor;
+
   const char *url1;
   const char *url2;
   const char *base_path;
@@ -2668,42 +2264,58 @@ diff_summarize_repos_repos(svn_client_di
                                    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, FALSE, 
-                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;
-    }
-
+  /* Set up the repos_diff editor. */
   SVN_ERR(svn_client__get_diff_summarize_callbacks(
             &callbacks, &callback_baton,
             target1, FALSE, summarize_func, summarize_baton, pool));
 
+  SVN_ERR(svn_wc__wrap_diff_callbacks(&diff_processor,
+                                      callbacks, callback_baton,
+                                      TRUE /* walk_deleted_dirs */,
+                                      pool, pool));
+
+
+  /* The repository can bring in a new working copy, but not delete
+     everything. Luckily our new diff handler can just be reversed. */
+  if (kind2 == svn_node_none)
+    {
+      const char *str_tmp;
+      svn_revnum_t rev_tmp;
+
+      str_tmp = url2;
+      url2 = url1;
+      url1 = str_tmp;
+
+      rev_tmp = rev2;
+      rev2 = rev1;
+      rev1 = rev_tmp;
+
+      str_tmp = anchor2;
+      anchor2 = anchor1;
+      anchor1 = str_tmp;
+
+      str_tmp = target2;
+      target2 = target1;
+      target1 = str_tmp;
+
+      diff_processor = svn_diff__tree_processor_reverse_create(diff_processor,
+                                                               NULL, pool);
+    }
+
   /* Now, we open an extra RA session to the correct anchor
      location for URL1.  This is used to get the kind of deleted paths.  */
   SVN_ERR(svn_client__open_ra_session_internal(&extra_ra_session, NULL,
                                                anchor1, NULL, NULL, FALSE,
                                                TRUE, ctx, pool));
 
-  /* Set up the repos_diff editor. */
-  SVN_ERR(svn_client__get_diff_editor(&diff_editor, &diff_edit_baton,
-            depth,
-            extra_ra_session, rev1, TRUE /* walk_deleted_dirs */,
-            FALSE /* text_deltas */,
-            callbacks, callback_baton,
-            ctx->cancel_func, ctx->cancel_baton,
-            NULL /* notify_func */, NULL /* notify_baton */, pool));
+  SVN_ERR(svn_client__get_diff_editor2(&diff_editor, &diff_edit_baton,
+                                       extra_ra_session,
+                                       depth,
+                                       rev1,
+                                       FALSE /* text_deltas */,
+                                       diff_processor,
+                                       ctx->cancel_func, ctx->cancel_baton,
+                                       pool));
 
   /* We want to switch our txn into URL2 */
   SVN_ERR(svn_ra_do_diff3
@@ -2716,7 +2328,7 @@ diff_summarize_repos_repos(svn_client_di
   SVN_ERR(reporter->set_path(reporter_baton, "", rev1,
                              svn_depth_infinity,
                              FALSE, NULL, pool));
-  return reporter->finish_report(reporter_baton, pool);
+  return svn_error_trace(reporter->finish_report(reporter_baton, pool));
 }
 
 /* This is basically just the guts of svn_client_diff_summarize[_peg]2(). */
@@ -2797,6 +2409,7 @@ do_diff_summarize(svn_client_diff_summar
                      summarize_func, summarize_baton, pool));
 
              SVN_ERR(svn_client__arbitrary_nodes_diff(abspath1, abspath2,
+                                                      depth,
                                                       callbacks,
                                                       callback_baton,
                                                       ctx, pool));
@@ -2969,6 +2582,8 @@ svn_client_diff6(const apr_array_header_
   diff_cmd_baton.use_git_diff_format = use_git_diff_format;
   diff_cmd_baton.no_diff_added = no_diff_added;
   diff_cmd_baton.no_diff_deleted = no_diff_deleted;
+  diff_cmd_baton.no_copyfrom_on_add = show_copies_as_adds;
+
   diff_cmd_baton.wc_ctx = ctx->wc_ctx;
   diff_cmd_baton.ra_session = NULL;
   diff_cmd_baton.anchor = NULL;
@@ -3030,6 +2645,8 @@ svn_client_diff_peg6(const apr_array_hea
   diff_cmd_baton.use_git_diff_format = use_git_diff_format;
   diff_cmd_baton.no_diff_added = no_diff_added;
   diff_cmd_baton.no_diff_deleted = no_diff_deleted;
+  diff_cmd_baton.no_copyfrom_on_add = show_copies_as_adds;
+
   diff_cmd_baton.wc_ctx = ctx->wc_ctx;
   diff_cmd_baton.ra_session = NULL;
   diff_cmd_baton.anchor = NULL;



Mime
View raw message