Author: julianfoad
Date: Mon Aug 22 11:11:50 2011
New Revision: 1160204

URL: http://svn.apache.org/viewvc?rev=1160204&view=rev
Log:
Extend 'svn diff --summarize' to support WC-WC diffs. Before this it only
supported repo-repo diffs.

* subversion/libsvn_client/diff.c
  (diff_summarize_wc_wc): New function.
  (do_diff_summarize): Call it. Update the error message. Accept a
    'changelists' parameter and use it for these WC-WC diffs.
  (svn_client_diff_summarize2, svn_client_diff_summarize_peg2): Pass the
    'changelists' parameter, which was previously unused, to
    do_diff_summarize().

* subversion/libsvn_wc/diff_local.c
  (diff_status_callback): Call the dir_added, dir_deleted, dir_opened and
    dir_closed callbacks at the appropriate times.

* subversion/tests/cmdline/diff_tests.py
  (diff_summarize_xml): Test a WC-WC diff instead of checking that such a
    request would fail.

* subversion/tests/cmdline/input_validation_tests.py
  (invalid_diff_targets): Don't expect a WC-WC summarizing diff to fail.

Modified:
    subversion/trunk/subversion/libsvn_client/diff.c
    subversion/trunk/subversion/libsvn_wc/diff_local.c
    subversion/trunk/subversion/tests/cmdline/diff_tests.py
    subversion/trunk/subversion/tests/cmdline/input_validation_tests.py

Modified: subversion/trunk/subversion/libsvn_client/diff.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff.c?rev=1160204&r1=1160203&r2=1160204&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff.c Mon Aug 22 11:11:50 2011
@@ -2007,6 +2007,73 @@ do_diff(const svn_wc_diff_callbacks4_t *
   return SVN_NO_ERROR;
 }
 
+/* Perform a summary diff between two working-copy paths.
+
+   PATH1 and PATH2 are both working copy paths.  REVISION1 and
+   REVISION2 are their respective revisions.
+
+   All other options are the same as those passed to svn_client_diff5(). */
+static svn_error_t *
+diff_summarize_wc_wc(svn_client_diff_summarize_func_t summarize_func,
+                     void *summarize_baton,
+                     const char *path1,
+                     const svn_opt_revision_t *revision1,
+                     const char *path2,
+                     const svn_opt_revision_t *revision2,
+                     svn_depth_t depth,
+                     svn_boolean_t ignore_ancestry,
+                     svn_boolean_t use_git_diff_format,
+                     const apr_array_header_t *changelists,
+                     svn_client_ctx_t *ctx,
+                     apr_pool_t *pool)
+{
+  svn_wc_diff_callbacks4_t *callbacks;
+  void *callback_baton;
+  const char *abspath1, *anchor1, *target1;
+  svn_node_kind_t kind;
+
+  SVN_ERR_ASSERT(! svn_path_is_url(path1));
+  SVN_ERR_ASSERT(! svn_path_is_url(path2));
+
+  /* Currently we support only the case where path1 and path2 are the
+     same path. */
+  if ((strcmp(path1, path2) != 0)
+      || (! ((revision1->kind == svn_opt_revision_base)
+             && (revision2->kind == svn_opt_revision_working))))
+    return unsupported_diff_error
+      (svn_error_create
+       (SVN_ERR_INCORRECT_PARAMS, NULL,
+        _("Only diffs between a path's text-base "
+          "and its working files are supported at this time")));
+
+  /* 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_kind(&kind, ctx->wc_ctx, abspath1, FALSE, pool));
+  if (kind == svn_node_dir)
+    {
+      anchor1 = path1;
+      target1 = "";
+    }
+  else
+    {
+      svn_dirent_split(&anchor1, &target1, path1, pool);
+    }
+  SVN_ERR(svn_client__get_diff_summarize_callbacks(
+            &callbacks, &callback_baton, target1,
+            summarize_func, summarize_baton, pool));
+
+  SVN_ERR(svn_wc_diff6(ctx->wc_ctx,
+                       abspath1,
+                       callbacks, callback_baton,
+                       depth,
+                       ignore_ancestry, FALSE /* show_copies_as_adds */,
+                       /* FALSE */ use_git_diff_format, changelists,
+                       ctx->cancel_func, ctx->cancel_baton,
+                       pool));
+  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,
@@ -2094,6 +2161,7 @@ do_diff_summarize(svn_client_diff_summar
                   const svn_opt_revision_t *peg_revision,
                   svn_depth_t depth,
                   svn_boolean_t ignore_ancestry,
+                  const apr_array_header_t *changelists,
                   apr_pool_t *pool)
 {
   svn_boolean_t is_repos1;
@@ -2108,10 +2176,17 @@ do_diff_summarize(svn_client_diff_summar
                                       path1, path2, revision1, revision2,
                                       peg_revision, depth, ignore_ancestry,
                                       pool);
+  else if (! is_repos1 && ! is_repos2)
+    return diff_summarize_wc_wc(summarize_func, summarize_baton,
+                                path1, revision1, path2, revision2,
+                                depth, ignore_ancestry,
+                                FALSE /* use_git_diff_format */,
+                                changelists, ctx, pool);
   else
-    return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-                            _("Summarizing diff can only compare repository "
-                              "to repository"));
+   return unsupported_diff_error(
+            svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                             _("Summarizing diff cannot compare repository "
+                               "to WC")));
 }
 
 
@@ -2341,10 +2416,9 @@ svn_client_diff_summarize2(const char *p
   svn_opt_revision_t peg_revision;
   peg_revision.kind = svn_opt_revision_unspecified;
 
-  /* ### CHANGELISTS parameter isn't used */
   return do_diff_summarize(summarize_func, summarize_baton, ctx,
                            path1, path2, revision1, revision2, &peg_revision,
-                           depth, ignore_ancestry, pool);
+                           depth, ignore_ancestry, changelists, pool);
 }
 
 svn_error_t *
@@ -2360,10 +2434,10 @@ svn_client_diff_summarize_peg2(const cha
                                svn_client_ctx_t *ctx,
                                apr_pool_t *pool)
 {
-  /* ### CHANGELISTS parameter isn't used */
   return do_diff_summarize(summarize_func, summarize_baton, ctx,
                            path, path, start_revision, end_revision,
-                           peg_revision, depth, ignore_ancestry, pool);
+                           peg_revision,
+                           depth, ignore_ancestry, changelists, pool);
 }
 
 svn_client_diff_summarize_t *

Modified: subversion/trunk/subversion/libsvn_wc/diff_local.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/diff_local.c?rev=1160204&r1=1160203&r2=1160204&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/diff_local.c (original)
+++ subversion/trunk/subversion/libsvn_wc/diff_local.c Mon Aug 22 11:11:50 2011
@@ -474,8 +474,29 @@ diff_status_callback(void *baton,
           SVN_ERR(file_diff(eb, local_abspath, path, scratch_pool));
         }
     }
-  else
+  else  /* it's a directory */
     {
+      const char *path = svn_dirent_skip_ancestor(eb->anchor_abspath,
+                                                  local_abspath);
+
+      /* Report the directory as deleted and/or opened or added. */
+      if (status->node_status == svn_wc_status_deleted
+          || status->node_status == svn_wc_status_replaced)
+        SVN_ERR(eb->callbacks->dir_deleted(NULL, NULL, path,
+                                           eb->callback_baton, scratch_pool));
+
+      if (status->node_status == svn_wc_status_added
+          || status->node_status == svn_wc_status_replaced)
+        SVN_ERR(eb->callbacks->dir_added(NULL, NULL, NULL, NULL,
+                                         path, status->revision,
+                                         path, status->revision /* ### ? */,
+                                         eb->callback_baton, scratch_pool));
+      else
+        SVN_ERR(eb->callbacks->dir_opened(NULL, NULL, NULL,
+                                          path, status->revision,
+                                          eb->callback_baton, scratch_pool));
+
+      /* Report the prop change. */
       /* ### This case should probably be extended for git-diff, but this
              is what the old diff code provided */
       if (status->node_status == svn_wc_status_deleted
@@ -484,9 +505,6 @@ diff_status_callback(void *baton,
         {
           apr_array_header_t *propchanges;
           apr_hash_t *baseprops;
-          const char *path = svn_dirent_skip_ancestor(eb->anchor_abspath,
-                                                      local_abspath);
-
 
           SVN_ERR(svn_wc__internal_propdiff(&propchanges, &baseprops,
                                             eb->db, local_abspath,
@@ -498,6 +516,15 @@ diff_status_callback(void *baton,
                                                    eb->callback_baton,
                                                    scratch_pool));
         }
+
+      /* Close the dir.
+       * ### This should be done after all children have been processed, not
+       *     yet.  The current Subversion-internal callers don't care. */
+      SVN_ERR(eb->callbacks->dir_closed(
+                        NULL, NULL, NULL, path,
+                        (status->node_status == svn_wc_status_added
+                         || status->node_status == svn_wc_status_replaced),
+                        eb->callback_baton, scratch_pool));
     }
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/tests/cmdline/diff_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/diff_tests.py?rev=1160204&r1=1160203&r2=1160204&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/diff_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/diff_tests.py Mon Aug 22 11:11:50 
2011
@@ -3184,6 +3184,16 @@ def diff_summarize_xml(sbox):
                         wc_rev=2)
   expected_status.remove("A/B/lambda")
 
+  # 3) Test working copy summarize
+  paths = ['A/mu', 'iota', 'A/D/G/tau', 'newfile', 'A/B/lambda',
+           'newdir',]
+  items = ['modified', 'none', 'modified', 'added', 'deleted', 'added',]
+  kinds = ['file','file','file','file','file', 'dir',]
+  props = ['none', 'modified', 'modified', 'none', 'none', 'none',]
+
+  svntest.actions.run_and_verify_diff_summarize_xml(
+    [], wc_dir, paths, items, props, kinds, wc_dir)
+
   svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                         expected_status, None, wc_dir)
 
@@ -3197,38 +3207,21 @@ def diff_summarize_xml(sbox):
     ".*No such revision 5555555",
     None, wc_dir, None, None, None, '-r0:5555555', wc_dir)
 
-  # 3) Test working copy summarize
-  svntest.actions.run_and_verify_diff_summarize_xml(
-    ".*Summarizing diff can only compare repository to repository",
-    None, wc_dir, None, None, wc_dir)
-
   # 4) Test --summarize --xml on -c2
-  paths = ['iota',]
-  items = ['none',]
-  kinds = ['file',]
-  props = ['modified',]
+  paths_iota = ['iota',]
+  items_iota = ['none',]
+  kinds_iota = ['file',]
+  props_iota = ['modified',]
 
   svntest.actions.run_and_verify_diff_summarize_xml(
-    [], wc_dir, paths, items, props, kinds, '-c2',
+    [], wc_dir, paths_iota, items_iota, props_iota, kinds_iota, '-c2',
     os.path.join(wc_dir, 'iota'))
 
   # 5) Test --summarize --xml on -r1:2
-  paths = ['A/mu', 'iota', 'A/D/G/tau', 'newfile', 'A/B/lambda',
-           'newdir',]
-  items = ['modified', 'none', 'modified', 'added', 'deleted', 'added',]
-  kinds = ['file','file','file','file','file', 'dir',]
-  props = ['none', 'modified', 'modified', 'none', 'none', 'none',]
-
   svntest.actions.run_and_verify_diff_summarize_xml(
     [], wc_dir, paths, items, props, kinds, '-r1:2', wc_dir)
 
   # 6) Same as test #5 but ran against a URL instead of a WC path
-  paths = ['A/mu', 'iota', 'A/D/G/tau', 'newfile', 'A/B/lambda',
-           'newdir',]
-  items = ['modified', 'none', 'modified', 'added', 'deleted', 'added',]
-  kinds = ['file','file','file','file','file', 'dir',]
-  props = ['none', 'modified', 'modified', 'none', 'none', 'none',]
-
   svntest.actions.run_and_verify_diff_summarize_xml(
     [], sbox.repo_url, paths, items, props, kinds, '-r1:2', sbox.repo_url)
 

Modified: subversion/trunk/subversion/tests/cmdline/input_validation_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/input_validation_tests.py?rev=1160204&r1=1160203&r2=1160204&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/input_validation_tests.py 
(original)
+++ subversion/trunk/subversion/tests/cmdline/input_validation_tests.py Mon Aug 
22 11:11:50 2011
@@ -120,9 +120,6 @@ def invalid_diff_targets(sbox):
   for (target1, target2) in [("iota", "^/"), ("file://", "iota")]:
     run_and_verify_svn_in_wc(sbox, "svn: E205000: Cannot mix repository and 
working "
                              "copy targets", 'diff', target1, target2)
-  run_and_verify_svn_in_wc(sbox, "svn: E200007: Summarizing diff can only 
compare "
-                           "repository to repository",
-                           'diff', '--summarize', "iota", "A")
 
 def invalid_export_targets(sbox):
   "invalid targets for 'export'"


Reply via email to