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 2014/02/19 15:30:52 UTC

svn commit: r1569756 - in /subversion/trunk/subversion/libsvn_client: client.h diff.c diff_summarize.c

Author: rhuijben
Date: Wed Feb 19 14:30:52 2014
New Revision: 1569756

URL: http://svn.apache.org/r1569756
Log:
Use the diff tree processor for hooking the diff --summarize handler in
libsvn_client.

* subversion/libsvn_client/client.h
  (svn_client__get_diff_summarize_callbacks): Update api to return a diff
    processor instead of diff callbacks. Remove reverse option as that
    can be applied by the caller by reversing the tree.

* subversion/libsvn_client/diff.c
  (diff_wc_wc): Implement proper result and scratch pool.
  (diff_repos_repos): Calculate anchor path. Use result/scratch pool. Make
    text delta handling optional.
  (diff_repos_wc): Calculate anchor path. Use result/scratch pool.

  (do_diff): Add anchor_path output argument. Add result pool. Update caller.

  (diff_summarize_repos_wc): Wrap diff processor when we need reverse logic
    Update caller. Remove logic that calculates anchor, which is now an
    output argument of called function.

   diff_summarize_wc_wc): Update caller. Remove logic that calculates
    anchor, which is now an output argument of called function.

  (diff_summarize_repos_repos): Remove now unused function.

  (do_diff_summarize): Update diff_repos_repos instead of
    diff_summarize_repos_repos. Remove target calculation for
      svn_client__arbitrary_nodes_diff.

  (svn_client_diff6,
   svn_client_diff_peg6): Update caller.

* subversion/libsvn_client/diff_summarize.c
  (includes): Add svn_path.h and private/svn_wc_private.h.
  (summarize_baton_t): Add variables.
  (ensure_skip_relpath): New function.
  (send_summary): Update caller. Update patch calculation.
  (cb_dir_closed): Update patch calculation.

  (svn_client__get_diff_summarize_callbacks): Fetch a diff tree processor
    here.

Modified:
    subversion/trunk/subversion/libsvn_client/client.h
    subversion/trunk/subversion/libsvn_client/diff.c
    subversion/trunk/subversion/libsvn_client/diff_summarize.c

Modified: subversion/trunk/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=1569756&r1=1569755&r2=1569756&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Wed Feb 19 14:30:52 2014
@@ -709,24 +709,28 @@ svn_client__get_diff_editor2(const svn_d
 
 /*** Editor for diff summary ***/
 
-/* Set *CALLBACKS and *CALLBACK_BATON to a set of diff callbacks that will
-   report a diff summary, i.e. only providing information about the changed
-   items without the text deltas.
+/* Set *DIFF_PROCESSOR to a diff processor that will report a diff summary
+   to SUMMARIZE_FUNC.
 
-   TARGET is the target path, relative to the anchor, of the diff.
+   ANCHOR_PATH will return a pointer to a string that must be set to the
+   anchor of the operation before the processor is called.
+
+   ORIGINAL_PATH specifies the original path and will be used with
+   **ANCHOR_PATH to create paths as the user originally provided them
+   to the diff function.
 
    SUMMARIZE_FUNC is called with SUMMARIZE_BATON as parameter by the
    created callbacks for each changed item.
 */
 svn_error_t *
 svn_client__get_diff_summarize_callbacks(
-                        svn_wc_diff_callbacks4_t **callbacks,
-                        void **callback_baton,
-                        const char *target,
-                        svn_boolean_t reversed,
+                        const svn_diff_tree_processor_t **diff_processor,
+                        const char ***anchor_path,
                         svn_client_diff_summarize_func_t summarize_func,
                         void *summarize_baton,
-                        apr_pool_t *pool);
+                        const char *original_target,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool);
 
 /* ---------------------------------------------------------------- */
 

Modified: subversion/trunk/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff.c?rev=1569756&r1=1569755&r2=1569756&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff.c Wed Feb 19 14:30:52 2014
@@ -1633,7 +1633,8 @@ diff_wc_wc(const char **anchor_path,
            struct diff_cmd_baton *callback_baton,
            const svn_diff_tree_processor_t *diff_processor,
            svn_client_ctx_t *ctx,
-           apr_pool_t *pool)
+           apr_pool_t *result_pool,
+           apr_pool_t *scratch_pool)
 {
   const char *abspath1;
   svn_error_t *err;
@@ -1641,7 +1642,7 @@ diff_wc_wc(const char **anchor_path,
   SVN_ERR_ASSERT(! svn_path_is_url(path1));
   SVN_ERR_ASSERT(! svn_path_is_url(path2));
 
-  SVN_ERR(svn_dirent_get_absolute(&abspath1, path1, pool));
+  SVN_ERR(svn_dirent_get_absolute(&abspath1, path1, scratch_pool));
 
   /* Currently we support only the case where path1 and path2 are the
      same path. */
@@ -1658,7 +1659,7 @@ diff_wc_wc(const char **anchor_path,
   /* Resolve named revisions to real numbers. */
   err = svn_client__get_revision_number(&callback_baton->revnum1, NULL,
                                         ctx->wc_ctx, abspath1, NULL,
-                                        revision1, pool);
+                                        revision1, scratch_pool);
 
   /* In case of an added node, we have no base rev, and we show a revision
    * number of 0. Note that this code is currently always asking for
@@ -1679,17 +1680,17 @@ diff_wc_wc(const char **anchor_path,
       /* ### Eventually we want to get rid of this wrapping as it loses
              information that we might need for some cases */
       diff_processor = svn_diff__tree_processor_copy_as_changed_create(
-                                  diff_processor, pool);
+                                  diff_processor, scratch_pool);
     }
 
   {
     svn_node_kind_t kind;
 
     SVN_ERR(svn_wc_read_kind2(&kind, ctx->wc_ctx, abspath1,
-                            TRUE, FALSE, pool));
+                            TRUE, FALSE, scratch_pool));
 
     if (kind != svn_node_dir)
-      callback_baton->anchor = svn_dirent_dirname(path1, pool);
+      callback_baton->anchor = svn_dirent_dirname(path1, scratch_pool);
     else
       callback_baton->anchor = path1;
   }
@@ -1704,7 +1705,7 @@ diff_wc_wc(const char **anchor_path,
                         ignore_ancestry, changelists,
                         diff_processor,
                         ctx->cancel_func, ctx->cancel_baton,
-                        pool, pool));
+                        result_pool, scratch_pool));
   return SVN_NO_ERROR;
 }
 
@@ -1718,7 +1719,8 @@ diff_wc_wc(const char **anchor_path,
 
    All other options are the same as those passed to svn_client_diff6(). */
 static svn_error_t *
-diff_repos_repos(struct diff_cmd_baton *callback_baton,
+diff_repos_repos(const char **anchor_path_or_url,
+                 struct diff_cmd_baton *callback_baton,
                  const char *path_or_url1,
                  const char *path_or_url2,
                  const svn_opt_revision_t *revision1,
@@ -1726,9 +1728,11 @@ diff_repos_repos(struct diff_cmd_baton *
                  const svn_opt_revision_t *peg_revision,
                  svn_depth_t depth,
                  svn_boolean_t ignore_ancestry,
+                 svn_boolean_t text_deltas,
                  const svn_diff_tree_processor_t *diff_processor,
                  svn_client_ctx_t *ctx,
-                 apr_pool_t *pool)
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
 {
   svn_ra_session_t *extra_ra_session;
 
@@ -1758,27 +1762,30 @@ diff_repos_repos(struct diff_cmd_baton *
                                    &kind1, &kind2, &ra_session,
                                    ctx, path_or_url1, path_or_url2,
                                    revision1, revision2, peg_revision,
-                                   pool));
+                                   scratch_pool));
 
   /* Find a WC path for the ra session */
   if (!svn_path_is_url(path_or_url1))
-    SVN_ERR(svn_dirent_get_absolute(&wri_abspath, path_or_url1, pool));
+    SVN_ERR(svn_dirent_get_absolute(&wri_abspath, path_or_url1, scratch_pool));
   else if (!svn_path_is_url(path_or_url2))
-    SVN_ERR(svn_dirent_get_absolute(&wri_abspath, path_or_url2, pool));
+    SVN_ERR(svn_dirent_get_absolute(&wri_abspath, path_or_url2, scratch_pool));
 
   /* Set up the repos_diff editor on BASE_PATH, if available.
      Otherwise, we just use "". */
 
-  /* Get actual URLs. */
-  callback_baton->orig_path_1 = url1;
-  callback_baton->orig_path_2 = url2;
-
-  /* Get numeric revisions. */
-  callback_baton->revnum1 = rev1;
-  callback_baton->revnum2 = rev2;
+  if (callback_baton)
+    {
+      /* Get actual URLs. */
+      callback_baton->orig_path_1 = url1;
+      callback_baton->orig_path_2 = url2;
+
+      /* Get numeric revisions. */
+      callback_baton->revnum1 = rev1;
+      callback_baton->revnum2 = rev2;
 
-  callback_baton->ra_session = ra_session;
-  callback_baton->anchor = base_path;
+      callback_baton->ra_session = ra_session;
+      callback_baton->anchor = base_path;
+    }
 
   /* The repository can bring in a new working copy, but not delete
      everything. Luckily our new diff handler can just be reversed. */
@@ -1804,45 +1811,65 @@ diff_repos_repos(struct diff_cmd_baton *
       target1 = str_tmp;
 
       diff_processor = svn_diff__tree_processor_reverse_create(diff_processor,
-                                                               NULL, pool);
+                                                               NULL,
+                                                               scratch_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);
+    diff_processor = svn_diff__tree_processor_filter_create(
+                                      diff_processor, target1, scratch_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.  */
   SVN_ERR(svn_ra_dup_session(&extra_ra_session, ra_session, anchor1,
-                             pool, pool));
+                             scratch_pool, scratch_pool));
+
+  if (anchor_path_or_url)
+    {
+      if (base_path)
+        {
+          *anchor_path_or_url = apr_pstrdup(result_pool, base_path);
+        }
+      else
+        {
+          SVN_ERR(svn_ra_get_session_url(ra_session, anchor_path_or_url,
+                                         scratch_pool));
+
+          *anchor_path_or_url = svn_path_url_add_component2(
+                                                  *anchor_path_or_url,
+                                                  target1,
+                                                  result_pool);
+        }
+    }
 
   SVN_ERR(svn_client__get_diff_editor2(
                 &diff_editor, &diff_edit_baton,
                 extra_ra_session, depth,
                 rev1,
-                TRUE /* text_deltas */,
+                text_deltas,
                 diff_processor,
                 ctx->cancel_func, ctx->cancel_baton,
-                pool));
+                scratch_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));
+                          depth, ignore_ancestry, text_deltas,
+                          url2, diff_editor, diff_edit_baton, scratch_pool));
 
   /* Drive the reporter; do the diff. */
   SVN_ERR(reporter->set_path(reporter_baton, "", rev1,
                              svn_depth_infinity,
                              FALSE, NULL,
-                             pool));
+                             scratch_pool));
 
-  return svn_error_trace(reporter->finish_report(reporter_baton, pool));
+  return svn_error_trace(
+                  reporter->finish_report(reporter_baton, scratch_pool));
 }
 
 /* Perform a diff between a repository path and a working-copy path.
@@ -1856,7 +1883,8 @@ diff_repos_repos(struct diff_cmd_baton *
 
    All other options are the same as those passed to svn_client_diff6(). */
 static svn_error_t *
-diff_repos_wc(const char *path_or_url1,
+diff_repos_wc(const char **anchor_path,
+              const char *path_or_url1,
               const svn_opt_revision_t *revision1,
               const svn_opt_revision_t *peg_revision,
               const char *path2,
@@ -1870,6 +1898,7 @@ diff_repos_wc(const char *path_or_url1,
               struct diff_cmd_baton *cmd_baton,
               const svn_diff_tree_processor_t *diff_processor,
               svn_client_ctx_t *ctx,
+              apr_pool_t *result_pool,
               apr_pool_t *scratch_pool)
 {
   apr_pool_t *pool = scratch_pool;
@@ -2014,6 +2043,9 @@ diff_repos_wc(const char *path_or_url1,
   else
     diff_depth = svn_depth_unknown;
 
+  if (anchor_path)
+    *anchor_path = apr_pstrdup(result_pool, anchor_abspath);
+
   if (is_copy)
     {
       const char *copyfrom_parent_url;
@@ -2106,7 +2138,8 @@ diff_repos_wc(const char *path_or_url1,
 
 /* This is basically just the guts of svn_client_diff[_peg]6(). */
 static svn_error_t *
-do_diff(const svn_wc_diff_callbacks4_t *callbacks,
+do_diff(const char **anchor_path,
+        const svn_wc_diff_callbacks4_t *callbacks,
         struct diff_cmd_baton *callback_baton,
         svn_client_ctx_t *ctx,
         const char *path_or_url1,
@@ -2119,7 +2152,8 @@ do_diff(const svn_wc_diff_callbacks4_t *
         svn_boolean_t show_copies_as_adds,
         svn_boolean_t use_git_diff_format,
         const apr_array_header_t *changelists,
-        apr_pool_t *pool)
+        apr_pool_t *result_pool,
+        apr_pool_t *scratch_pool)
 {
   svn_boolean_t is_repos1;
   svn_boolean_t is_repos2;
@@ -2132,39 +2166,46 @@ do_diff(const svn_wc_diff_callbacks4_t *
   SVN_ERR(svn_wc__wrap_diff_callbacks(&diff_processor,
                                       callbacks, callback_baton,
                                       TRUE /* walk_deleted_dirs */,
-                                      pool, pool));
+                                      scratch_pool, scratch_pool));
 
   if (is_repos1)
     {
       if (is_repos2)
         {
           /* ### Ignores 'show_copies_as_adds'. */
-          SVN_ERR(diff_repos_repos(callback_baton,
+          SVN_ERR(diff_repos_repos(anchor_path,
+                                   callback_baton,
                                    path_or_url1, path_or_url2,
                                    revision1, revision2,
                                    peg_revision, depth, ignore_ancestry,
-                                   diff_processor, ctx, pool));
+                                   TRUE /* text_deltas */,
+                                   diff_processor, ctx,
+                                   result_pool, scratch_pool));
         }
       else /* path_or_url2 is a working copy path */
         {
-          SVN_ERR(diff_repos_wc(path_or_url1, revision1, peg_revision,
+          SVN_ERR(diff_repos_wc(anchor_path,
+                                path_or_url1, revision1, peg_revision,
                                 path_or_url2, revision2, FALSE, depth,
                                 ignore_ancestry, show_copies_as_adds,
                                 use_git_diff_format, changelists,
                                 callback_baton,
-                                diff_processor, ctx, pool));
+                                diff_processor, ctx,
+                                result_pool, scratch_pool));
         }
     }
   else /* path_or_url1 is a working copy path */
     {
       if (is_repos2)
         {
-          SVN_ERR(diff_repos_wc(path_or_url2, revision2, peg_revision,
+          SVN_ERR(diff_repos_wc(anchor_path,
+                                path_or_url2, revision2, peg_revision,
                                 path_or_url1, revision1, TRUE, depth,
                                 ignore_ancestry, show_copies_as_adds,
                                 use_git_diff_format, changelists,
                                 callback_baton,
-                                diff_processor, ctx, pool));
+                                diff_processor, ctx,
+                                result_pool, scratch_pool));
         }
       else /* path_or_url2 is a working copy path */
         {
@@ -2174,21 +2215,26 @@ do_diff(const svn_wc_diff_callbacks4_t *
               const char *abspath1;
               const char *abspath2;
 
-              SVN_ERR(svn_dirent_get_absolute(&abspath1, path_or_url1, pool));
-              SVN_ERR(svn_dirent_get_absolute(&abspath2, path_or_url2, pool));
+              SVN_ERR(svn_dirent_get_absolute(&abspath1, path_or_url1,
+                                              scratch_pool));
+              SVN_ERR(svn_dirent_get_absolute(&abspath2, path_or_url2, 
+                                              scratch_pool));
 
-              SVN_ERR(svn_client__arbitrary_nodes_diff(NULL, abspath1, abspath2,
+              SVN_ERR(svn_client__arbitrary_nodes_diff(anchor_path,
+                                                       abspath1, abspath2,
                                                        depth,
                                                        diff_processor,
-                                                       ctx, pool, pool));
+                                                       ctx,
+                                                       result_pool, scratch_pool));
             }
           else
-            SVN_ERR(diff_wc_wc(NULL,
+            SVN_ERR(diff_wc_wc(anchor_path,
                                path_or_url1, revision1,
                                path_or_url2, revision2,
                                depth, ignore_ancestry, show_copies_as_adds,
                                use_git_diff_format, changelists,
-                               callback_baton, diff_processor, ctx, pool));
+                               callback_baton, diff_processor, ctx,
+                               result_pool, scratch_pool));
         }
     }
 
@@ -2220,31 +2266,27 @@ diff_summarize_repos_wc(svn_client_diff_
                         svn_client_ctx_t *ctx,
                         apr_pool_t *pool)
 {
-  const char *anchor, *target;
-  svn_wc_diff_callbacks4_t *callbacks;
-  void *callback_baton;
   struct diff_cmd_baton cmd_baton;
   const svn_diff_tree_processor_t *diff_processor;
+  const char **anchor_path;
 
   SVN_ERR_ASSERT(! svn_path_is_url(path2));
 
-  SVN_ERR(svn_wc_get_actual_target2(&anchor, &target,
-                                    ctx->wc_ctx, path2,
-                                    pool, pool));
-
   SVN_ERR(svn_client__get_diff_summarize_callbacks(
-            &callbacks, &callback_baton, target, reverse,
-            summarize_func, summarize_baton, pool));
+                          &diff_processor, &anchor_path,
+                          summarize_func, summarize_baton,
+                          path2, pool, pool));
 
-  SVN_ERR(svn_wc__wrap_diff_callbacks(&diff_processor,
-                                      callbacks, callback_baton, TRUE,
-                                      pool, pool));
+  if (reverse)
+    diff_processor = svn_diff__tree_processor_reverse_create(
+                              diff_processor, NULL, pool);
 
-  SVN_ERR(diff_repos_wc(path_or_url1, revision1, peg_revision,
+  SVN_ERR(diff_repos_wc(anchor_path,
+                        path_or_url1, revision1, peg_revision,
                         path2, revision2, reverse,
                         depth, FALSE, TRUE, FALSE, changelists,
                         &cmd_baton,
-                        diff_processor, ctx, pool));
+                        diff_processor, ctx, pool, pool));
   return SVN_NO_ERROR;
 }
 
@@ -2267,11 +2309,9 @@ diff_summarize_wc_wc(svn_client_diff_sum
                      svn_client_ctx_t *ctx,
                      apr_pool_t *pool)
 {
-  svn_wc_diff_callbacks4_t *callbacks;
-  void *callback_baton;
-  const char *abspath1, *target1;
-  svn_node_kind_t kind;
+  const char *abspath1;
   const svn_diff_tree_processor_t *diff_processor;
+  const char **anchor_path;
 
   SVN_ERR_ASSERT(! svn_path_is_url(path1));
   SVN_ERR_ASSERT(! svn_path_is_url(path2));
@@ -2290,18 +2330,13 @@ diff_summarize_wc_wc(svn_client_diff_sum
   /* Find the node kind of PATH1 so that we know whether the diff drive will
      be anchored at PATH1 or its parent dir. */
   SVN_ERR(svn_dirent_get_absolute(&abspath1, path1, pool));
-  SVN_ERR(svn_wc_read_kind2(&kind, ctx->wc_ctx, abspath1,
-                            TRUE, FALSE, pool));
-  target1 = (kind == svn_node_dir) ? "" : svn_dirent_basename(path1, pool);
-  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,
+  SVN_ERR(svn_client__get_diff_summarize_callbacks(
+                                      &diff_processor, &anchor_path,
+                                      summarize_func, summarize_baton, path1,
                                       pool, pool));
 
-  SVN_ERR(svn_wc__diff7(NULL,
+  SVN_ERR(svn_wc__diff7(anchor_path,
                         ctx->wc_ctx,
                         abspath1,
                         depth, ignore_ancestry, changelists,
@@ -2311,119 +2346,6 @@ diff_summarize_wc_wc(svn_client_diff_sum
   return SVN_NO_ERROR;
 }
 
-/* Perform a diff summary between two repository paths. */
-static svn_error_t *
-diff_summarize_repos_repos(svn_client_diff_summarize_func_t summarize_func,
-                           void *summarize_baton,
-                           svn_client_ctx_t *ctx,
-                           const char *path_or_url1,
-                           const char *path_or_url2,
-                           const svn_opt_revision_t *revision1,
-                           const svn_opt_revision_t *revision2,
-                           const svn_opt_revision_t *peg_revision,
-                           svn_depth_t depth,
-                           svn_boolean_t ignore_ancestry,
-                           apr_pool_t *pool)
-{
-  svn_ra_session_t *extra_ra_session;
-
-  const svn_ra_reporter3_t *reporter;
-  void *reporter_baton;
-
-  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;
-  svn_revnum_t rev1;
-  svn_revnum_t rev2;
-  svn_node_kind_t kind1;
-  svn_node_kind_t kind2;
-  const char *anchor1;
-  const char *anchor2;
-  const char *target1;
-  const char *target2;
-  svn_ra_session_t *ra_session;
-  svn_wc_diff_callbacks4_t *callbacks;
-  void *callback_baton;
-
-  /* Prepare info for the repos repos diff. */
-  SVN_ERR(diff_prepare_repos_repos(&url1, &url2, &base_path, &rev1, &rev2,
-                                   &anchor1, &anchor2, &target1, &target2,
-                                   &kind1, &kind2, &ra_session,
-                                   ctx, path_or_url1, path_or_url2,
-                                   revision1, revision2,
-                                   peg_revision, pool));
-
-  /* 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 deleted path information.  */
-  SVN_ERR(svn_ra_dup_session(&extra_ra_session, ra_session, anchor1,
-                             pool, 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
-          (ra_session, &reporter, &reporter_baton, rev2, target1,
-           depth, ignore_ancestry,
-           FALSE /* do not create text delta */, 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 svn_error_trace(reporter->finish_report(reporter_baton, pool));
-}
-
 /* This is basically just the guts of svn_client_diff_summarize[_peg]2(). */
 static svn_error_t *
 do_diff_summarize(svn_client_diff_summarize_func_t summarize_func,
@@ -2440,6 +2362,7 @@ do_diff_summarize(svn_client_diff_summar
                   apr_pool_t *pool)
 {
   const svn_diff_tree_processor_t *diff_processor;
+  const char **anchor_path;
   svn_boolean_t is_repos1;
   svn_boolean_t is_repos2;
 
@@ -2450,11 +2373,22 @@ do_diff_summarize(svn_client_diff_summar
   if (is_repos1)
     {
       if (is_repos2)
-        SVN_ERR(diff_summarize_repos_repos(summarize_func, summarize_baton, ctx,
-                                           path_or_url1, path_or_url2,
-                                           revision1, revision2,
-                                           peg_revision, depth, ignore_ancestry,
-                                           pool));
+        {
+
+          SVN_ERR(svn_client__get_diff_summarize_callbacks(
+                        &diff_processor,
+                        &anchor_path,
+                        summarize_func, summarize_baton,
+                        path_or_url1,
+                        pool, pool));
+        SVN_ERR(diff_repos_repos(anchor_path, NULL,
+                                 path_or_url1, path_or_url2,
+                                 revision1, revision2,
+                                 peg_revision, depth, ignore_ancestry,
+                                 FALSE /* text_deltas */,
+                                 diff_processor, ctx,
+                                 pool, pool));
+        }
       else
         SVN_ERR(diff_summarize_repos_wc(summarize_func, summarize_baton,
                                         path_or_url1, revision1,
@@ -2483,31 +2417,17 @@ do_diff_summarize(svn_client_diff_summar
            {
              const char *abspath1;
              const char *abspath2;
-             svn_wc_diff_callbacks4_t *callbacks;
-             void *callback_baton;
-             const char *target;
-             svn_node_kind_t kind;
-
              SVN_ERR(svn_dirent_get_absolute(&abspath1, path_or_url1, pool));
              SVN_ERR(svn_dirent_get_absolute(&abspath2, path_or_url2, pool));
 
-             SVN_ERR(svn_io_check_resolved_path(abspath1, &kind, pool));
-
-             if (kind == svn_node_dir)
-               target = "";
-             else
-               target = svn_dirent_basename(path_or_url1, NULL);
-
              SVN_ERR(svn_client__get_diff_summarize_callbacks(
-                     &callbacks, &callback_baton, target, FALSE,
-                     summarize_func, summarize_baton, pool));
-
-             SVN_ERR(svn_wc__wrap_diff_callbacks(&diff_processor,
-                                                 callbacks, callback_baton,
-                                                 TRUE /* walk_deleted*/,
-                                                 pool, pool));
+                     &diff_processor, &anchor_path,
+                     summarize_func, summarize_baton,
+                     path_or_url1,
+                     pool, pool));
 
-             SVN_ERR(svn_client__arbitrary_nodes_diff(NULL, abspath1, abspath2,
+             SVN_ERR(svn_client__arbitrary_nodes_diff(anchor_path,
+                                                      abspath1, abspath2,
                                                       depth,
                                                       diff_processor,
                                                       ctx, pool, pool));
@@ -2685,11 +2605,11 @@ svn_client_diff6(const apr_array_header_
   diff_cmd_baton.ra_session = NULL;
   diff_cmd_baton.anchor = NULL;
 
-  return do_diff(&diff_callbacks, &diff_cmd_baton, ctx,
+  return do_diff(NULL, &diff_callbacks, &diff_cmd_baton, ctx,
                  path_or_url1, path_or_url2, revision1, revision2,
                  &peg_revision,
                  depth, ignore_ancestry, show_copies_as_adds,
-                 use_git_diff_format, changelists, pool);
+                 use_git_diff_format, changelists, pool, pool);
 }
 
 svn_error_t *
@@ -2748,11 +2668,11 @@ svn_client_diff_peg6(const apr_array_hea
   diff_cmd_baton.ra_session = NULL;
   diff_cmd_baton.anchor = NULL;
 
-  return do_diff(&diff_callbacks, &diff_cmd_baton, ctx,
+  return do_diff(NULL, &diff_callbacks, &diff_cmd_baton, ctx,
                  path_or_url, path_or_url, start_revision, end_revision,
                  peg_revision,
                  depth, ignore_ancestry, show_copies_as_adds,
-                 use_git_diff_format, changelists, pool);
+                 use_git_diff_format, changelists, pool, pool);
 }
 
 svn_error_t *

Modified: subversion/trunk/subversion/libsvn_client/diff_summarize.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff_summarize.c?rev=1569756&r1=1569755&r2=1569756&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff_summarize.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff_summarize.c Wed Feb 19 14:30:52 2014
@@ -25,23 +25,27 @@
 #include "svn_private_config.h"
 #include "svn_dirent_uri.h"
 #include "svn_hash.h"
+#include "svn_path.h"
 #include "svn_props.h"
 #include "svn_pools.h"
 
+#include "private/svn_wc_private.h"
+
 #include "client.h"
 
 
 /* Diff callbacks baton.  */
 struct summarize_baton_t {
+  apr_pool_t *baton_pool; /* For allocating skip_path */
+
   /* The target path of the diff, relative to the anchor; "" if target == anchor. */
-  const char *target;
+  const char *original_target;
+  const char *anchor_path;
+  const char *skip_relpath;
 
   /* The summarize callback passed down from the API */
   svn_client_diff_summarize_func_t summarize_func;
 
-  /* Is the diff handling reversed? (add<->delete) */
-  svn_boolean_t reversed;
-
   /* The summarize callback baton */
   void *summarize_func_baton;
 
@@ -50,6 +54,28 @@ struct summarize_baton_t {
   apr_hash_t *prop_changes;
 };
 
+/* Calculate skip_relpath from original_target and anchor_path */
+static APR_INLINE void
+ensure_skip_relpath(struct summarize_baton_t *b)
+{
+  if (b->skip_relpath)
+    return;
+
+  if (svn_path_is_url(b->original_target))
+    {
+      b->skip_relpath = svn_uri_skip_ancestor(b->anchor_path,
+                                              b->original_target,
+                                              b->baton_pool);
+    }
+  else
+    {
+      b->skip_relpath = svn_dirent_skip_ancestor(b->anchor_path,
+                                                 b->original_target);
+    }
+
+  if (!b->skip_relpath)
+    b->skip_relpath = "";
+}
 
 /* Call B->summarize_func with B->summarize_func_baton, passing it a
  * summary object composed from PATH (but made to be relative to the target
@@ -68,24 +94,11 @@ send_summary(struct summarize_baton_t *b
   SVN_ERR_ASSERT(summarize_kind != svn_client_diff_summarize_kind_normal
                  || prop_changed);
 
-  if (b->reversed)
-    {
-      switch(summarize_kind)
-        {
-          case svn_client_diff_summarize_kind_added:
-            summarize_kind = svn_client_diff_summarize_kind_deleted;
-            break;
-          case svn_client_diff_summarize_kind_deleted:
-            summarize_kind = svn_client_diff_summarize_kind_added;
-            break;
-          default:
-            break;
-        }
-    }
-
   /* PATH is relative to the anchor of the diff, but SUM->path needs to be
      relative to the target of the diff. */
-  sum->path = svn_relpath_skip_ancestor(b->target, path);
+  ensure_skip_relpath(b);
+
+  sum->path = svn_relpath_skip_ancestor(b->skip_relpath, path);
   sum->summarize_kind = summarize_kind;
   if (summarize_kind == svn_client_diff_summarize_kind_modified
       || summarize_kind == svn_client_diff_summarize_kind_normal)
@@ -183,7 +196,8 @@ cb_dir_closed(svn_wc_notify_state_t *con
   struct summarize_baton_t *b = diff_baton;
   svn_boolean_t prop_change;
 
-  if (! svn_relpath_skip_ancestor(b->target, path))
+  ensure_skip_relpath(b);
+  if (! svn_relpath_skip_ancestor(b->skip_relpath, path))
     return SVN_NO_ERROR;
 
   prop_change = svn_hash_gets(b->prop_changes, path) != NULL;
@@ -283,22 +297,23 @@ cb_dir_props_changed(svn_wc_notify_state
 
 svn_error_t *
 svn_client__get_diff_summarize_callbacks(
-                        svn_wc_diff_callbacks4_t **callbacks,
-                        void **callback_baton,
-                        const char *target,
-                        svn_boolean_t reversed,
+                        const svn_diff_tree_processor_t **diff_processor,
+                        const char ***anchor_path,
                         svn_client_diff_summarize_func_t summarize_func,
                         void *summarize_baton,
-                        apr_pool_t *pool)
+                        const char *original_target,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
 {
-  svn_wc_diff_callbacks4_t *cb = apr_palloc(pool, sizeof(*cb));
-  struct summarize_baton_t *b = apr_palloc(pool, sizeof(*b));
+  svn_wc_diff_callbacks4_t *cb = apr_palloc(result_pool, sizeof(*cb));
+  struct summarize_baton_t *b = apr_pcalloc(result_pool, sizeof(*b));
 
-  b->target = target;
+  *anchor_path = &b->anchor_path;
+  b->baton_pool = result_pool;
   b->summarize_func = summarize_func;
   b->summarize_func_baton = summarize_baton;
-  b->prop_changes = apr_hash_make(pool);
-  b->reversed = reversed;
+  b->original_target = apr_pstrdup(result_pool, original_target);
+  b->prop_changes = apr_hash_make(result_pool);
 
   cb->file_opened = cb_file_opened;
   cb->file_changed = cb_file_changed;
@@ -310,8 +325,8 @@ svn_client__get_diff_summarize_callbacks
   cb->dir_props_changed = cb_dir_props_changed;
   cb->dir_closed = cb_dir_closed;
 
-  *callbacks = cb;
-  *callback_baton = b;
+  SVN_ERR(svn_wc__wrap_diff_callbacks(diff_processor, cb, b, TRUE,
+                                      result_pool, scratch_pool));
 
   return SVN_NO_ERROR;
 }