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/03 20:24:06 UTC

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

Author: rhuijben
Date: Thu Jan  3 19:24:06 2013
New Revision: 1428561

URL: http://svn.apache.org/viewvc?rev=1428561&view=rev
Log:
Make 'svn diff --summarize' handle repos-wc diffs to make its implementation
match all the capabilities of the normal 'svn diff'.

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

* subversion/libsvn_client/diff.c
  (diff_repos_wc): Allow passing a separate cmd baton and callback baton to
    allow calling this function for summarize support.
  (do_diff): Update caller.
  (diff_summarize_repos_wc): New function, wrapping diff_repos_wc with a
    summarizer diff handler.
  (diff_summarize_wc_wc,
   diff_summarize_repos_repos): Update caller.

  (do_diff_summarize): Handle repos<->wc diffs.

* subversion/libsvn_client/diff_summarize.c
  (summarize_baton_t): Add reversed boolean.
  (send_summary): Reverse add and delete when requested.
  (svn_client__get_diff_summarize_callbacks): Copy boolean into baton.

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=1428561&r1=1428560&r2=1428561&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Thu Jan  3 19:24:06 2013
@@ -744,6 +744,7 @@ svn_client__get_diff_summarize_callbacks
                         svn_wc_diff_callbacks4_t **callbacks,
                         void **callback_baton,
                         const char *target,
+                        svn_boolean_t reversed,
                         svn_client_diff_summarize_func_t summarize_func,
                         void *summarize_baton,
                         apr_pool_t *pool);

Modified: subversion/trunk/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff.c?rev=1428561&r1=1428560&r2=1428561&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff.c Thu Jan  3 19:24:06 2013
@@ -2228,7 +2228,8 @@ diff_repos_wc(const char *path_or_url1,
               svn_boolean_t use_git_diff_format,
               const apr_array_header_t *changelists,
               const svn_wc_diff_callbacks4_t *callbacks,
-              struct diff_cmd_baton *callback_baton,
+              void *callback_baton,
+              struct diff_cmd_baton *cmd_baton,
               svn_client_ctx_t *ctx,
               apr_pool_t *pool)
 {
@@ -2289,15 +2290,15 @@ diff_repos_wc(const char *path_or_url1,
                                           ctx, pool));
       if (!reverse)
         {
-          callback_baton->orig_path_1 = url1;
-          callback_baton->orig_path_2 =
+          cmd_baton->orig_path_1 = url1;
+          cmd_baton->orig_path_2 =
             svn_path_url_add_component2(anchor_url, target, pool);
         }
       else
         {
-          callback_baton->orig_path_1 =
+          cmd_baton->orig_path_1 =
             svn_path_url_add_component2(anchor_url, target, pool);
-          callback_baton->orig_path_2 = url1;
+          cmd_baton->orig_path_2 = url1;
         }
     }
 
@@ -2315,13 +2316,13 @@ diff_repos_wc(const char *path_or_url1,
   /* Figure out the node kind of the local target. */
   SVN_ERR(svn_io_check_resolved_path(abspath2, &kind2, pool));
 
-  callback_baton->ra_session = ra_session;
-  callback_baton->anchor = anchor;
+  cmd_baton->ra_session = ra_session;
+  cmd_baton->anchor = anchor;
 
   if (!reverse)
-    callback_baton->revnum1 = rev;
+    cmd_baton->revnum1 = rev;
   else
-    callback_baton->revnum2 = rev;
+    cmd_baton->revnum2 = rev;
 
   /* Check if our diff target is a copied node. */
   SVN_ERR(svn_wc__node_get_origin(&is_copy, 
@@ -2382,8 +2383,8 @@ diff_repos_wc(const char *path_or_url1,
       const char *copyfrom_basename;
       svn_depth_t copy_depth;
 
-      callback_baton->repos_wc_diff_target_is_copy = TRUE;
-      
+      cmd_baton->repos_wc_diff_target_is_copy = TRUE;
+
       /* We're diffing a locally copied/moved directory.
        * Describe the copy source to the reporter instead of the copy itself.
        * Doing the latter would generate a single add_directory() call to the
@@ -2486,7 +2487,8 @@ do_diff(const svn_wc_diff_callbacks4_t *
                                 path_or_url2, revision2, FALSE, depth,
                                 ignore_ancestry, show_copies_as_adds,
                                 use_git_diff_format, changelists,
-                                callbacks, callback_baton, ctx, pool));
+                                callbacks, callback_baton, callback_baton,
+                                ctx, pool));
         }
     }
   else /* path_or_url1 is a working copy path */
@@ -2497,7 +2499,8 @@ do_diff(const svn_wc_diff_callbacks4_t *
                                 path_or_url1, revision1, TRUE, depth,
                                 ignore_ancestry, show_copies_as_adds,
                                 use_git_diff_format, changelists,
-                                callbacks, callback_baton, ctx, pool));
+                                callbacks, callback_baton, callback_baton,
+                                ctx, pool));
         }
       else /* path_or_url2 is a working copy path */
         {
@@ -2527,6 +2530,54 @@ do_diff(const svn_wc_diff_callbacks4_t *
   return SVN_NO_ERROR;
 }
 
+/* Perform a diff between a repository path and a working-copy path.
+
+   PATH_OR_URL1 may be either a URL or a working copy path.  PATH2 is a
+   working copy path.  REVISION1 and REVISION2 are their respective
+   revisions.  If REVERSE is TRUE, the diff will be done in reverse.
+   If PEG_REVISION is specified, then PATH_OR_URL1 is the path in the peg
+   revision, and the actual repository path to be compared is
+   determined by following copy history.
+
+   All other options are the same as those passed to svn_client_diff6(). */
+static svn_error_t *
+diff_summarize_repos_wc(svn_client_diff_summarize_func_t summarize_func,
+                        void *summarize_baton,
+                        const char *path_or_url1,
+                        const svn_opt_revision_t *revision1,
+                        const svn_opt_revision_t *peg_revision,
+                        const char *path2,
+                        const svn_opt_revision_t *revision2,
+                        svn_boolean_t reverse,
+                        svn_depth_t depth,
+                        svn_boolean_t ignore_ancestry,
+                        const apr_array_header_t *changelists,
+                        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;
+
+  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));
+
+  SVN_ERR(diff_repos_wc(path_or_url1, revision1, peg_revision,
+                        path2, revision2, reverse,
+                        depth, FALSE, TRUE, FALSE, changelists,
+                        callbacks, callback_baton, &cmd_baton,
+                        ctx, pool));
+  return SVN_NO_ERROR;
+}
+
 /* Perform a summary diff between two working-copy paths.
 
    PATH1 and PATH2 are both working copy paths.  REVISION1 and
@@ -2571,7 +2622,7 @@ diff_summarize_wc_wc(svn_client_diff_sum
   SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, abspath1, FALSE, pool));
   target1 = (kind == svn_node_dir) ? "" : svn_dirent_basename(path1, pool);
   SVN_ERR(svn_client__get_diff_summarize_callbacks(
-            &callbacks, &callback_baton, target1,
+            &callbacks, &callback_baton, target1, FALSE,
             summarize_func, summarize_baton, pool));
 
   SVN_ERR(svn_wc_diff6(ctx->wc_ctx,
@@ -2636,7 +2687,7 @@ diff_summarize_repos_repos(svn_client_di
        * 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,
+                &callbacks, &callback_baton, target1, FALSE, 
                 summarize_func, summarize_baton, pool));
       SVN_ERR(diff_repos_repos_added_or_deleted_target(target1, target2,
                                                        rev1, rev2,
@@ -2650,7 +2701,7 @@ diff_summarize_repos_repos(svn_client_di
 
   SVN_ERR(svn_client__get_diff_summarize_callbacks(
             &callbacks, &callback_baton,
-            target1, summarize_func, summarize_baton, pool));
+            target1, FALSE, summarize_func, summarize_baton, 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.  */
@@ -2703,57 +2754,76 @@ do_diff_summarize(svn_client_diff_summar
   SVN_ERR(check_paths(&is_repos1, &is_repos2, path_or_url1, path_or_url2,
                       revision1, revision2, peg_revision));
 
-  if (is_repos1 && is_repos2)
-    return diff_summarize_repos_repos(summarize_func, summarize_baton, ctx,
-                                      path_or_url1, path_or_url2,
-                                      revision1, revision2,
-                                      peg_revision, depth, ignore_ancestry,
-                                      pool);
-  else if (! is_repos1 && ! is_repos2)
+  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));
+      else
+        SVN_ERR(diff_summarize_repos_wc(summarize_func, summarize_baton,
+                                        path_or_url1, revision1,
+                                        peg_revision,
+                                        path_or_url2, revision2,
+                                        FALSE, depth,
+                                        ignore_ancestry,
+                                        changelists,
+                                        ctx, pool));
+    }
+  else /* ! is_repos1 */
     {
-      if (revision1->kind == svn_opt_revision_working
-          && revision2->kind == svn_opt_revision_working)
+      if (is_repos2)
+        SVN_ERR(diff_summarize_repos_wc(summarize_func, summarize_baton,
+                                        path_or_url2, revision2,
+                                        peg_revision,
+                                        path_or_url1, revision1,
+                                        TRUE, depth,
+                                        ignore_ancestry,
+                                        changelists,
+                                        ctx, pool));
+      else
         {
-          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 = "";
+          if (revision1->kind == svn_opt_revision_working
+              && revision2->kind == svn_opt_revision_working)
+           {
+             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_client__arbitrary_nodes_diff(abspath1, abspath2,
+                                                      callbacks,
+                                                      callback_baton,
+                                                      ctx, pool));
+           }
           else
-            target = svn_dirent_basename(path_or_url1, NULL);
-
-          SVN_ERR(svn_client__get_diff_summarize_callbacks(
-                  &callbacks, &callback_baton, target,
-                  summarize_func, summarize_baton, pool));
-
-          SVN_ERR(svn_client__arbitrary_nodes_diff(abspath1, abspath2,
-                                                   callbacks,
-                                                   callback_baton,
-                                                   ctx, pool));
-        }
-      else
-        SVN_ERR(diff_summarize_wc_wc(summarize_func, summarize_baton,
-                                     path_or_url1, revision1,
-                                     path_or_url2, revision2,
-                                     depth, ignore_ancestry,
-                                     changelists, ctx, pool));
-
-      return SVN_NO_ERROR;
+            SVN_ERR(diff_summarize_wc_wc(summarize_func, summarize_baton,
+                                         path_or_url1, revision1,
+                                         path_or_url2, revision2,
+                                         depth, ignore_ancestry,
+                                         changelists, ctx, pool));
+      }
     }
-  else
-   return unsupported_diff_error(
-            svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-                             _("Summarizing diff cannot compare repository "
-                               "to WC")));
+
+  return SVN_NO_ERROR;
 }
 
 

Modified: subversion/trunk/subversion/libsvn_client/diff_summarize.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff_summarize.c?rev=1428561&r1=1428560&r2=1428561&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff_summarize.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff_summarize.c Thu Jan  3 19:24:06 2013
@@ -38,6 +38,9 @@ struct summarize_baton_t {
   /* 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;
 
@@ -64,6 +67,19 @@ 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;
+        }
+    }
+
   /* 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);
@@ -310,6 +326,7 @@ svn_client__get_diff_summarize_callbacks
                         svn_wc_diff_callbacks4_t **callbacks,
                         void **callback_baton,
                         const char *target,
+                        svn_boolean_t reversed,
                         svn_client_diff_summarize_func_t summarize_func,
                         void *summarize_baton,
                         apr_pool_t *pool)
@@ -321,6 +338,7 @@ svn_client__get_diff_summarize_callbacks
   b->summarize_func = summarize_func;
   b->summarize_func_baton = summarize_baton;
   b->prop_changes = apr_hash_make(pool);
+  b->reversed = reversed;
 
   cb->file_opened = cb_file_opened;
   cb->file_changed = cb_file_changed;



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

Posted by Mark Phippard <ma...@gmail.com>.
On Thu, Jan 3, 2013 at 2:24 PM,  <rh...@apache.org> wrote:
> Author: rhuijben
> Date: Thu Jan  3 19:24:06 2013
> New Revision: 1428561
>
> URL: http://svn.apache.org/viewvc?rev=1428561&view=rev
> Log:
> Make 'svn diff --summarize' handle repos-wc diffs to make its implementation
> match all the capabilities of the normal 'svn diff'.

Sweet!  Wanted this for a long time.  Do you know if the existing
JavaHL summarize method should now work?

I also seem to recall there was a tree conflict feature that needed
this in order to be implemented.

-- 
Thanks

Mark Phippard
http://markphip.blogspot.com/