You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2013/01/29 22:16:29 UTC

svn commit: r1440139 - in /subversion/trunk/subversion: include/private/svn_wc_private.h libsvn_client/client.h libsvn_client/diff.c libsvn_client/merge.c libsvn_client/repos_diff.c libsvn_wc/diff_editor.c

Author: rhuijben
Date: Tue Jan 29 21:16:29 2013
New Revision: 1440139

URL: http://svn.apache.org/viewvc?rev=1440139&view=rev
Log:
Separate svn_client__get_diff_editor() in a function that takes diff callbacks
and one that takes the new svn_diff_tree_processor_t.

* subversion/include/private/svn_wc_private.h
  (svn_wc__wrap_diff_callbacks): Constify output argument and handle
     walk_deleted_dirs.

* subversion/libsvn_client/client.h
  (includes): Add svn_diff_tree.h.

* subversion/libsvn_client/diff.c
  (svn_client__get_diff_editor2): New function, intended to replace...
  (svn_client__get_diff_editor): ... this function, which is now a wrapper.

* subversion/libsvn_client/merge.c
  (notification_receiver): Remove function.
  (drive_merge_report_editor): Update caller.

* subversion/libsvn_client/repos_diff.c
  (edit_baton): Constify processor. Remove variable.
  (diff_deleted_dir): Only check skip_children for skipping deleted.

* subversion/libsvn_wc/diff_editor.c
  (diff_notify_baton_t): Remove unused variables.
  (diff_state_handle,
   diff_state_close): Remove functions.
  (diff_state_absent): Remove notification.
  (svn_client__get_diff_editor): Rename to ...
  (svn_client__get_diff_editor2): ... this and forward diff processor.
  (svn_client__get_diff_editor): New function around
     svn_client__get_diff_editor2, providing diff callbacks.

Modified:
    subversion/trunk/subversion/include/private/svn_wc_private.h
    subversion/trunk/subversion/libsvn_client/client.h
    subversion/trunk/subversion/libsvn_client/diff.c
    subversion/trunk/subversion/libsvn_client/merge.c
    subversion/trunk/subversion/libsvn_client/repos_diff.c
    subversion/trunk/subversion/libsvn_wc/diff_editor.c

Modified: subversion/trunk/subversion/include/private/svn_wc_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_wc_private.h?rev=1440139&r1=1440138&r2=1440139&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_wc_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_wc_private.h Tue Jan 29 21:16:29 2013
@@ -1716,9 +1716,10 @@ typedef svn_error_t *
  * or ignored if STATE_HANDLER is NULL
  */
 svn_error_t *
-svn_wc__wrap_diff_callbacks(svn_diff_tree_processor_t **diff_processor,
+svn_wc__wrap_diff_callbacks(const svn_diff_tree_processor_t **diff_processor,
                             const svn_wc_diff_callbacks4_t *callbacks,
                             void *callback_baton,
+                            svn_boolean_t walk_deleted_dirs,
                             svn_wc__diff_state_handle_t state_handle,
                             svn_wc__diff_state_close_t state_close,
                             svn_wc__diff_state_absent_t state_absent,

Modified: subversion/trunk/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=1440139&r1=1440138&r2=1440139&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Tue Jan 29 21:16:29 2013
@@ -37,6 +37,7 @@
 
 #include "private/svn_magic.h"
 #include "private/svn_client_private.h"
+#include "private/svn_diff_tree.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -709,23 +710,38 @@ 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.
+
+   @since New in 1.8.
+   */
+svn_error_t *
+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);
+
+/* Like svn_client__get_diff_editor2 but calls DIFF_CALLBACKS with
+   DIFF_CMD_BATON. 
+
+   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 ABSENT_RELPATHS is non-null, collect const char * keys in it with
    the relative paths marked as absent by the diff driver.
-
-   EDITOR/EDIT_BATON return the newly created editor and baton. */
+ */
 svn_error_t *
 svn_client__get_diff_editor(const svn_delta_editor_t **editor,
                             void **edit_baton,
@@ -739,8 +755,6 @@ svn_client__get_diff_editor(const svn_de
                             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);
 
 

Modified: subversion/trunk/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff.c?rev=1440139&r1=1440138&r2=1440139&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff.c Tue Jan 29 21:16:29 2013
@@ -2018,7 +2018,6 @@ diff_repos_repos(const svn_wc_diff_callb
                 NULL /* absent relpaths */,
                 callbacks, callback_baton,
                 ctx->cancel_func, ctx->cancel_baton,
-                NULL /* no notify_func */, NULL /* no notify_baton */,
                 pool));
 
   /* We want to switch our txn into URL2 */
@@ -2705,7 +2704,7 @@ diff_summarize_repos_repos(svn_client_di
             NULL /* absent relpaths */,
             callbacks, callback_baton,
             ctx->cancel_func, ctx->cancel_baton,
-            NULL /* notify_func */, NULL /* notify_baton */, pool));
+            pool));
 
   /* We want to switch our txn into URL2 */
   SVN_ERR(svn_ra_do_diff3

Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1440139&r1=1440138&r2=1440139&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Tue Jan 29 21:16:29 2013
@@ -3252,49 +3252,6 @@ record_operative_merge_action(merge_cmd_
   return SVN_NO_ERROR;
 }
 
-/* Handle a diff notification by calling the client's notification callback
- * and also by recording which paths changed (in BATON->*_abspaths).
- *
- * In some cases, notify that a merge is beginning, if we haven't already
- * done so.  (### TODO: Harmonize this so it handles all cases.)
- *
- * The paths in NOTIFY are relpaths, relative to the root of the diff (the
- * merge source). We convert these to abspaths in the merge target WC before
- * passing the notification structure on to the client.
- *
- * This function is not used for 'starting a merge', 'starting to record
- * mergeinfo' and 'completing a merge' notifications.
- *
- * Implements svn_wc_notify_func2_t.*/
-static void
-notification_receiver(void *baton, const svn_wc_notify_t *notify,
-                      apr_pool_t *pool)
-{
-#ifndef HANDLE_NOTIFY_FROM_MERGE
-  merge_cmd_baton_t *merge_b = baton;
-  const char *notify_abspath;
-
-  /* Skip notifications if this is a --record-only merge that is adding
-     or deleting NOTIFY->PATH, allow only mergeinfo changes and headers.
-     We will already have skipped the actual addition or deletion, but will
-     still get a notification callback for it. */
-  if (merge_b->record_only
-      && notify->action != svn_wc_notify_update_update)
-    return;
-
-  notify_abspath = svn_dirent_join(merge_b->target->abspath,
-                                   notify->path, pool);
-
-  if (merge_b->nrb.wrapped_func)
-    {
-      svn_wc_notify_t notify2 = *notify;
-
-      notify2.path = notify_abspath;
-      merge_b->nrb.wrapped_func(merge_b->nrb.wrapped_baton, &notify2, pool);
-    }
-#endif
-}
-
 /* Set *OUT_RANGELIST to the intersection of IN_RANGELIST with the simple
  * (inheritable) revision range REV1:REV2, according to CONSIDER_INHERITANCE.
  * If REV1 is equal to REV2, the result is an empty rangelist, otherwise
@@ -5250,7 +5207,6 @@ drive_merge_report_editor(const char *ta
                                       &merge_callbacks, merge_b,
                                       merge_b->ctx->cancel_func,
                                       merge_b->ctx->cancel_baton,
-                                      notification_receiver, merge_b,
                                       scratch_pool));
   SVN_ERR(svn_ra_do_diff3(merge_b->ra_session1,
                           &reporter, &report_baton, source->loc2->rev,

Modified: subversion/trunk/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/repos_diff.c?rev=1440139&r1=1440138&r2=1440139&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/repos_diff.c Tue Jan 29 21:16:29 2013
@@ -57,7 +57,7 @@ struct edit_baton {
   svn_depth_t depth;
 
   /* The result processor */
-  svn_diff_tree_processor_t *processor;
+  const svn_diff_tree_processor_t *processor;
 
   /* RA_SESSION is the open session for making requests to the RA layer */
   svn_ra_session_t *ra_session;
@@ -77,10 +77,6 @@ struct edit_baton {
   /* Empty hash used for adds. */
   apr_hash_t *empty_hash;
 
-  /* TRUE if the operation needs to walk deleted dirs on the "old" side.
-     FALSE otherwise. */
-  svn_boolean_t walk_deleted_repos_dirs;
-
   /* Whether to report text deltas */
   svn_boolean_t text_deltas;
 
@@ -528,7 +524,7 @@ diff_deleted_dir(const char *path,
    * crawl it recursively, diffing each file against the empty file.  This
    * is a workaround for issue 2333 "'svn diff URL1 URL2' not reverse of
    * 'svn diff URL2 URL1'". */
-  if (! skip_children && eb->walk_deleted_repos_dirs)
+  if (! skip_children)
     {
       apr_hash_index_t *hi;
 
@@ -1263,214 +1259,10 @@ fetch_base_func(const char **filename,
 /* Baton for diff_state_* functions */
 struct diff_notify_baton_t
 {
-  /* Hash used to check replaced paths. Key is path relative CWD,
-   * Value is *deleted_path_notify_t.
-   * All allocations are from edit_baton's pool. */
-  apr_hash_t *deleted_paths;
-
-  /* If the func is non-null, send notifications of actions. */
-  svn_wc_notify_func2_t notify_func;
-  void *notify_baton;
-
   /* If not NULL collects the absent paths */
   apr_hash_t *absent_relpaths;
-
-  apr_pool_t *pool;
 };
 
-/** Callback for the svn_diff_tree_processor_t wrapper, to allow handling
- *  notifications like how the repos diff in libsvn_client does.
- *
- * Probably only necessary while transitioning to svn_diff_tree_processor_t
- */
-static svn_error_t *
-diff_state_handle(svn_boolean_t tree_conflicted,
-                  svn_wc_notify_state_t *state,
-                  svn_wc_notify_state_t *prop_state,
-                  const char *relpath,
-                  svn_kind_t kind,
-                  svn_boolean_t before_operation,
-                  svn_boolean_t for_add,
-                  svn_boolean_t for_delete,
-                  void *state_baton,
-                  apr_pool_t *scratch_pool)
-{
-  struct diff_notify_baton_t *dnb = state_baton;
-  svn_wc_notify_state_t notify_content_state = svn_wc_notify_state_inapplicable;
-  svn_wc_notify_state_t notify_prop_state = svn_wc_notify_state_inapplicable;
-
-  if (! dnb->notify_func)
-    return SVN_NO_ERROR;
-
-  if ((for_delete && before_operation && !tree_conflicted)
-      || (for_add && kind == svn_kind_dir && !before_operation))
-    return SVN_NO_ERROR;
-
-  if (for_delete)
-    {
-      const char *deleted_path;
-      deleted_path_notify_t *dpn;
-      svn_wc_notify_action_t action;
-
-      deleted_path = apr_pstrdup(dnb->pool, relpath);
-      dpn = apr_pcalloc(dnb->pool, sizeof(*dpn));
-
-      if (!tree_conflicted
-          && state
-             && (*state != svn_wc_notify_state_missing)
-             && (*state != svn_wc_notify_state_obstructed))
-        {
-          action = svn_wc_notify_update_delete;
-        }
-      else
-        action = svn_wc_notify_skip;
-
-      dpn->kind = (kind == svn_kind_dir) ? svn_node_dir : svn_node_file;
-      dpn->action = tree_conflicted ? svn_wc_notify_tree_conflict : action;
-      dpn->state = state ? *state : svn_wc_notify_state_inapplicable;
-      dpn->tree_conflicted = tree_conflicted;
-      apr_hash_set(dnb->deleted_paths, deleted_path, APR_HASH_KEY_STRING, dpn);
-
-      return SVN_NO_ERROR;
-    }
-
-  if (tree_conflicted)
-    {
-      svn_wc_notify_t *notify;
-      deleted_path_notify_t *dpn;
-      svn_node_kind_t notify_kind;
-
-      apr_hash_set(dnb->deleted_paths, relpath,
-                   APR_HASH_KEY_STRING, NULL);
-
-      notify = svn_wc_create_notify(relpath, svn_wc_notify_tree_conflict,
-                                    scratch_pool);
-
-      dpn = apr_hash_get(dnb->deleted_paths, relpath, APR_HASH_KEY_STRING);
-      if (dpn)
-        {
-          /* If any was found, we will handle the pending 'deleted path
-          * notification' (DPN) here. Remove it from the list. */
-          apr_hash_set(dnb->deleted_paths, relpath,
-              APR_HASH_KEY_STRING, NULL);
-
-          /* the pending delete might be on a different node kind. */
-          notify_kind = dpn->kind;
-        }
-
-      notify->kind = notify_kind;
-      (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
-      return SVN_NO_ERROR;
-    }
-
-  if (state)
-    notify_content_state = *state;
-  if (prop_state)
-    notify_prop_state = *prop_state;
-
-  /* These states apply to properties (dirs) and content (files) at the same
-     time, so handle them as the same whatever way we got them. */
-  if (notify_prop_state == svn_wc_notify_state_obstructed
-      || notify_prop_state == svn_wc_notify_state_missing)
-    {
-      notify_content_state = notify_prop_state;
-    }
-
-  if (notify_content_state == svn_wc_notify_state_obstructed
-      || notify_content_state == svn_wc_notify_state_missing)
-    {
-      svn_wc_notify_t *notify;
-
-      notify = svn_wc_create_notify(relpath, svn_wc_notify_skip,
-                                    scratch_pool);
-
-      notify->kind = (kind == svn_kind_dir) ? svn_node_dir : svn_node_file;
-      notify->content_state = notify_content_state;
-      notify->prop_state = notify_prop_state;
-      (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
-      return SVN_NO_ERROR;
-    }
-
-  /* This code is only used from the merge api, and should really be
-     integrated there. */
-
-  {
-    deleted_path_notify_t *dpn;
-    svn_wc_notify_t *notify;
-    svn_wc_notify_action_t action;
-    svn_node_kind_t notify_kind = (kind == svn_kind_dir) ? svn_node_dir
-                                                         : svn_node_file;
-
-    if (for_add)
-      action = svn_wc_notify_update_add;
-    else
-      action = svn_wc_notify_update_update;
-
-    /* Find out if a pending delete notification for this path is
-    * still around. */
-    dpn = apr_hash_get(dnb->deleted_paths, relpath, APR_HASH_KEY_STRING);
-    if (dpn)
-      {
-        /* If any was found, we will handle the pending 'deleted path
-        * notification' (DPN) here. Remove it from the list. */
-        apr_hash_set(dnb->deleted_paths, relpath,
-                     APR_HASH_KEY_STRING, NULL);
-
-        /* the pending delete might be on a different node kind. */
-        notify_kind = dpn->kind;
-        notify_content_state = notify_prop_state = dpn->state;
-
-        if (for_add && dpn->action == svn_wc_notify_update_delete)
-          action = svn_wc_notify_update_replace;
-      }
-
-    notify = svn_wc_create_notify(relpath, action, scratch_pool);
-    notify->kind = notify_kind;
-    notify->content_state = notify_content_state;
-    notify->prop_state = notify_prop_state;
-    (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
-  }
-
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-diff_state_close(const char *relpath,
-                 svn_kind_t kind,
-                 void *state_baton,
-                 apr_pool_t *scratch_pool)
-{
-  struct diff_notify_baton_t *dnb = state_baton;
-  apr_hash_index_t *hi;
-
-  if (! dnb->notify_func)
-    return SVN_NO_ERROR;
-
-  for (hi = apr_hash_first(scratch_pool, dnb->deleted_paths); hi;
-       hi = apr_hash_next(hi))
-    {
-      svn_wc_notify_t *notify;
-      const char *deleted_path = svn__apr_hash_index_key(hi);
-      deleted_path_notify_t *dpn = svn__apr_hash_index_val(hi);
-
-      /* Ignore paths which are not children of bb->path.  (There
-         should be none due to editor ordering constraints, but
-         ra_serf drops the ball here -- see issue #3802 for
-         details.) */
-      if (! svn_relpath_skip_ancestor(relpath, deleted_path))
-        continue;
-
-      notify = svn_wc_create_notify(deleted_path, dpn->action, scratch_pool);
-      notify->kind = dpn->kind;
-      notify->content_state = notify->prop_state = dpn->state;
-      notify->lock_state = svn_wc_notify_lock_state_inapplicable;
-      (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
-      apr_hash_set(dnb->deleted_paths, deleted_path,
-                   APR_HASH_KEY_STRING, NULL);
-    }
-  return SVN_NO_ERROR;
-}
-
 static svn_error_t *
 diff_state_absent(const char *relpath,
                   void *state_baton,
@@ -1478,17 +1270,6 @@ diff_state_absent(const char *relpath,
 {
   struct diff_notify_baton_t *dnb = state_baton;
 
-  if (dnb->notify_func)
-    {
-      svn_wc_notify_t *notify
-        = svn_wc_create_notify(relpath, svn_wc_notify_skip, scratch_pool);
-
-      notify->kind = svn_node_unknown;
-      notify->content_state = notify->prop_state
-        = svn_wc_notify_state_missing;
-      (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
-    }
-
   if (dnb->absent_relpaths)
     apr_hash_set(dnb->absent_relpaths,
                  apr_pstrdup(apr_hash_pool_get(dnb->absent_relpaths), relpath),
@@ -1500,52 +1281,33 @@ diff_state_absent(const char *relpath,
 
 /* Create a repository diff editor and baton.  */
 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,
-                            apr_hash_t *absent_relpaths,
-                            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)
 {
   apr_pool_t *editor_pool = svn_pool_create(result_pool);
   svn_delta_editor_t *tree_editor = svn_delta_default_editor(editor_pool);
   struct edit_baton *eb = apr_pcalloc(editor_pool, sizeof(*eb));
-  struct diff_notify_baton_t *dnb = apr_pcalloc(editor_pool, sizeof(*eb));
   svn_delta_shim_callbacks_t *shim_callbacks =
                                 svn_delta_shim_callbacks_default(editor_pool);
 
   eb->pool = editor_pool;
   eb->depth = depth;
 
-  dnb->pool = editor_pool;
-  dnb->deleted_paths = apr_hash_make(eb->pool);
-  dnb->notify_func = notify_func;
-  dnb->notify_baton = notify_baton;
-  dnb->absent_relpaths = absent_relpaths;
-
-  SVN_ERR(svn_wc__wrap_diff_callbacks(&eb->processor,
-                                      diff_callbacks, diff_cmd_baton,
-                                      diff_state_handle,
-                                      diff_state_close,
-                                      diff_state_absent,
-                                      dnb,
-                                      result_pool, result_pool));
+  eb->processor = processor;
 
   eb->ra_session = ra_session;
 
   eb->revision = revision;
   eb->empty_file = NULL;
   eb->empty_hash = apr_hash_make(eb->pool);
-  eb->walk_deleted_repos_dirs = walk_deleted_dirs;
   eb->text_deltas = text_deltas;
   eb->cancel_func = cancel_func;
   eb->cancel_baton = cancel_baton;
@@ -1582,3 +1344,45 @@ svn_client__get_diff_editor(const svn_de
 
   return SVN_NO_ERROR;
 }
+
+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,
+                            apr_hash_t *absent_relpaths,
+                            const svn_wc_diff_callbacks4_t *diff_callbacks,
+                            void *diff_cmd_baton,
+                            svn_cancel_func_t cancel_func,
+                            void *cancel_baton,
+                            apr_pool_t *result_pool)
+{
+  const svn_diff_tree_processor_t *processor;
+  struct diff_notify_baton_t *dnb = apr_pcalloc(result_pool, sizeof(*dnb));
+
+  dnb->absent_relpaths = absent_relpaths;
+
+  SVN_ERR(svn_wc__wrap_diff_callbacks(&processor,
+                                      diff_callbacks, diff_cmd_baton,
+                                      walk_deleted_dirs,
+                                      NULL,
+                                      NULL,
+                                      diff_state_absent,
+                                      dnb,
+                                      result_pool, result_pool));
+
+  SVN_ERR(svn_client__get_diff_editor2(editor,
+                                       edit_baton,
+                                       ra_session,
+                                       depth,
+                                       revision,
+                                       text_deltas,
+                                       processor,
+                                       cancel_func, cancel_baton,
+                                       result_pool));
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/trunk/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/diff_editor.c?rev=1440139&r1=1440138&r2=1440139&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/diff_editor.c Tue Jan 29 21:16:29 2013
@@ -1967,6 +1967,9 @@ typedef struct wc_diff_wrap_baton_t
 {
   const svn_wc_diff_callbacks4_t *callbacks;
   void *callback_baton;
+
+  svn_boolean_t walk_deleted_dirs;
+
   svn_wc__diff_state_handle_t state_handle;
   svn_wc__diff_state_close_t state_close;
   svn_wc__diff_state_absent_t state_absent;
@@ -2031,6 +2034,9 @@ wrap_dir_opened(void **new_dir_baton,
                                  (right_source == NULL) /* for_delete */,
                                  wb->state_baton,
                                  scratch_pool));
+
+      if (! right_source && !wb->walk_deleted_dirs)
+        *skip_children = TRUE;
     }
   else /* left_source == NULL -> Add */
     {
@@ -2410,9 +2416,10 @@ wrap_node_absent(const char *relpath,
 
 
 svn_error_t *
-svn_wc__wrap_diff_callbacks(svn_diff_tree_processor_t **diff_processor,
+svn_wc__wrap_diff_callbacks(const svn_diff_tree_processor_t **diff_processor,
                             const svn_wc_diff_callbacks4_t *callbacks,
                             void *callback_baton,
+                            svn_boolean_t walk_deleted_dirs,
                             svn_wc__diff_state_handle_t state_handler,
                             svn_wc__diff_state_close_t state_close,
                             svn_wc__diff_state_absent_t state_absent,
@@ -2433,6 +2440,7 @@ svn_wc__wrap_diff_callbacks(svn_diff_tre
   wrap_baton->state_absent = state_absent;
   wrap_baton->state_baton = state_baton;
   wrap_baton->empty_file = NULL;
+  wrap_baton->walk_deleted_dirs = walk_deleted_dirs;
 
   processor = svn_diff__tree_processor_create(wrap_baton, result_pool);