[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH] Issue 2015, diff summarize solution?

From: Martin Hauner <hauner_at_web.de>
Date: 2005-06-01 20:40:28 CEST

Hi,

i created a partial patch for diff summarize, Issue 2015.

This patch is far from finished and a little dirty at some places.
It could be a starting point if this is an acceptable solution.

'svn diff -s .' will print the summarize for modified files
(adds and deletes are not implemented).

It doesn't make much sense for this case (being nearly the same as
svn status) but i think it is enough for demonstration of the
general idea.

I created a new api function svn_client_diff_summarize with a
callback function that prints the summarize to the command line.

svn_client_diff_summarize calls do_diff with svn_wc_diff_callbacks2_t
functions that delegate back to the summarize callback.

To make it cleaner the diff_cmd_baton would need new members to
propagate the summarize callback and its baton to the
svn_wc_diff_callbacks2_t functions.

Another topic is that #2015 wants to list the author. The
svn_wc_diff_callbacks2_t functions don't take an author parameter.
That would have to be added.

I wonder if the author is really necessary. A normal diff doesn't
output an author so why should summarize?

But maybe adding the author to the diff output is interesting too?

-- 
Martin
Subcommander, http://subcommander.tigris.org
a x-platform Win32/Unix/Linux/MacOSX svn gui client & a text diff/merge tool.

Index: subversion/include/svn_client.h
===================================================================
--- subversion/include/svn_client.h (revision 14883)
+++ subversion/include/svn_client.h (working copy)
@@ -1111,6 +1111,70 @@
                                   svn_client_ctx_t *ctx,
                                   apr_pool_t *pool);
 
+/**
+ * svn diff summarize
+ */
+
+typedef enum svn_diff_summarize_kind
+{
+ /** an added item */
+ svn_diff_summarize_kind_add,
+
+ /** a modified item */
+ svn_diff_summarize_kind_modified,
+
+ /** a deleted item */
+ svn_diff_summarize_kind_deleted
+
+} svn_diff_summarize_kind_t;
+
+
+typedef struct svn_diff_summarize_t
+{
+ /** item path, relative to svn_client_diff_summarize path1/path2 */
+ const char* path;
+
+ /** file or dir */
+ svn_node_kind_t node_kind;
+
+ /** change kind */
+ svn_diff_summarize_kind_t sum_kind;
+
+ /** revision prior to changes */
+ svn_revnum_t prior_revision;
+
+ /** revision after all changes */
+ svn_revnum_t after_revision;
+
+ /** properties changed? */
+ svn_boolean_t props_changed;
+
+ /** pool */
+ apr_pool_t* pool;
+
+} svn_diff_summarize_t;
+
+
+typedef void (*svn_diff_summarize_func_t) (void *summarize_baton,
+ svn_diff_summarize_t *diff);
+
+
+svn_error_t *
+svn_client_diff_summarize (const apr_array_header_t *options,
+ const char *path1,
+ const svn_opt_revision_t *revision1,
+ const char *path2,
+ const svn_opt_revision_t *revision2,
+ svn_boolean_t recurse,
+ svn_boolean_t ignore_ancestry,
+ svn_boolean_t no_diff_deleted,
+ svn_boolean_t ignore_content_type,
+ svn_diff_summarize_func_t summarize_func,
+ void *summarize_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool);
+
+
 /** Merge changes from @a source1/@a revision1 to @a source2/@a revision2 into
  * the working-copy path @a target_wcpath.
  *
Index: subversion/libsvn_client/diff.c
===================================================================
--- subversion/libsvn_client/diff.c (revision 14883)
+++ subversion/libsvn_client/diff.c (working copy)
@@ -2628,3 +2628,181 @@
 
   return SVN_NO_ERROR;
 }
+
+/*-----------------------------------------------------------------*/
+
+/*** possible solution for svn diff summarize ***/
+
+/* A svn_wc_diff_callbacks2_t function. Used for both file and directory
+ property merges. */
+static svn_error_t *
+summarize_props_changed (svn_wc_adm_access_t *adm_access,
+ svn_wc_notify_state_t *state,
+ const char *path,
+ const apr_array_header_t *propchanges,
+ apr_hash_t *original_props,
+ void *baton)
+{
+ return SVN_NO_ERROR;
+}
+
+/* A svn_wc_diff_callbacks2_t function. */
+static svn_error_t *
+summarize_file_changed (svn_wc_adm_access_t *adm_access,
+ svn_wc_notify_state_t *content_state,
+ svn_wc_notify_state_t *prop_state,
+ const char *mine,
+ const char *older,
+ const char *yours,
+ svn_revnum_t older_rev,
+ svn_revnum_t yours_rev,
+ const char *mimetype1,
+ const char *mimetype2,
+ const apr_array_header_t *prop_changes,
+ apr_hash_t *original_props,
+ void *baton)
+{
+ struct diff_cmd_baton* diff_cmd_baton = baton;
+
+ svn_diff_summarize_func_t summarize_func = (svn_diff_summarize_func_t)diff_cmd_baton->outfile;
+ void* summarize_baton = diff_cmd_baton->errfile;
+
+ svn_diff_summarize_t summarize;
+
+ summarize.node_kind = svn_node_file;
+ summarize.sum_kind = svn_diff_summarize_kind_modified;
+ summarize.prior_revision = older_rev;
+ summarize.after_revision = yours_rev;
+ summarize.path = mine;
+ summarize.props_changed = prop_changes->nelts > 0 ? TRUE : FALSE;
+ summarize.pool = diff_cmd_baton->pool;
+
+
+
+ summarize_func( diff_cmd_baton->errfile, &summarize );
+
+ return SVN_NO_ERROR;
+}
+
+/* A svn_wc_diff_callbacks2_t function. */
+static svn_error_t *
+summarize_file_added (svn_wc_adm_access_t *adm_access,
+ svn_wc_notify_state_t *content_state,
+ svn_wc_notify_state_t *prop_state,
+ const char *mine,
+ const char *older,
+ const char *yours,
+ svn_revnum_t rev1,
+ svn_revnum_t rev2,
+ const char *mimetype1,
+ const char *mimetype2,
+ const apr_array_header_t *prop_changes,
+ apr_hash_t *original_props,
+ void *baton)
+{
+ return SVN_NO_ERROR;
+}
+
+/* A svn_wc_diff_callbacks2_t function. */
+static svn_error_t *
+summarize_file_deleted_no_diff (svn_wc_adm_access_t *adm_access,
+ svn_wc_notify_state_t *state,
+ const char *mine,
+ const char *older,
+ const char *yours,
+ const char *mimetype1,
+ const char *mimetype2,
+ apr_hash_t *original_props,
+ void *baton)
+{
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+summarize_file_deleted_with_diff (svn_wc_adm_access_t *adm_access,
+ svn_wc_notify_state_t *state,
+ const char *mine,
+ const char *older,
+ const char *yours,
+ const char *mimetype1,
+ const char *mimetype2,
+ apr_hash_t *original_props,
+ void *baton)
+{
+ return SVN_NO_ERROR;
+}
+
+
+/* A svn_wc_diff_callbacks2_t function. */
+static svn_error_t *
+summarize_dir_added (svn_wc_adm_access_t *adm_access,
+ svn_wc_notify_state_t *state,
+ const char *path,
+ svn_revnum_t rev,
+ void *baton)
+{
+ return SVN_NO_ERROR;
+}
+
+/* A svn_wc_diff_callbacks2_t function. */
+static svn_error_t *
+summarize_dir_deleted (svn_wc_adm_access_t *adm_access,
+ svn_wc_notify_state_t *state,
+ const char *path,
+ void *baton)
+{
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_client_diff_summarize ( const apr_array_header_t *options,
+ const char *path1,
+ const svn_opt_revision_t *revision1,
+ const char *path2,
+ const svn_opt_revision_t *revision2,
+ svn_boolean_t recurse,
+ svn_boolean_t ignore_ancestry,
+ svn_boolean_t no_diff_deleted,
+ svn_boolean_t ignore_content_type,
+ svn_diff_summarize_func_t summarize_func,
+ void *summarize_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ struct diff_cmd_baton summarize_cmd_baton;
+ svn_wc_diff_callbacks2_t summarize_callbacks;
+
+ summarize_callbacks.file_changed = summarize_file_changed;
+ summarize_callbacks.file_added = summarize_file_added;
+ summarize_callbacks.file_deleted = no_diff_deleted
+ ? summarize_file_deleted_no_diff
+ : summarize_file_deleted_with_diff;
+
+ summarize_callbacks.dir_added = summarize_dir_added;
+ summarize_callbacks.dir_deleted = summarize_dir_deleted;
+ summarize_callbacks.dir_props_changed = summarize_props_changed;
+
+ summarize_cmd_baton.orig_path_1 = path1;
+ summarize_cmd_baton.orig_path_2 = path2;
+
+ summarize_cmd_baton.options = options;
+ summarize_cmd_baton.pool = pool;
+ summarize_cmd_baton.outfile = (apr_file_t*)summarize_func;
+ summarize_cmd_baton.errfile = summarize_baton;
+ summarize_cmd_baton.revnum1 = SVN_INVALID_REVNUM;
+ summarize_cmd_baton.revnum2 = SVN_INVALID_REVNUM;
+
+ summarize_cmd_baton.config = ctx->config;
+ summarize_cmd_baton.force_empty = FALSE;
+ summarize_cmd_baton.force_binary = ignore_content_type;
+
+ return do_diff (options,
+ path1, revision1,
+ path2, revision2,
+ recurse,
+ ignore_ancestry,
+ &summarize_callbacks, &summarize_cmd_baton,
+ ctx,
+ pool);
+}
Index: subversion/clients/cmdline/cl.h
===================================================================
--- subversion/clients/cmdline/cl.h (revision 14883)
+++ subversion/clients/cmdline/cl.h (working copy)
@@ -141,6 +141,7 @@
   svn_boolean_t autoprops; /* enable automatic properties */
   svn_boolean_t no_autoprops; /* disable automatic properties */
   const char *native_eol; /* override system standard eol marker */
+ svn_boolean_t summarize; /* show a diff summarize */
 } svn_cl__opt_state_t;
 
 
Index: subversion/clients/cmdline/diff-cmd.c
===================================================================
--- subversion/clients/cmdline/diff-cmd.c (revision 14883)
+++ subversion/clients/cmdline/diff-cmd.c (working copy)
@@ -22,6 +22,7 @@
 
 /*** Includes. ***/
 
+#include "svn_cmdline.h"
 #include "svn_pools.h"
 #include "svn_client.h"
 #include "svn_string.h"
@@ -35,6 +36,51 @@
 
 /*** Code. ***/
 
+static char
+generate_summarize_code (enum svn_diff_summarize_kind kind)
+{
+ switch (kind)
+ {
+ case svn_diff_summarize_kind_add: return 'A';
+ case svn_diff_summarize_kind_modified: return 'M';
+ case svn_diff_summarize_kind_deleted: return 'D';
+ default: return '?';
+ }
+}
+
+void summarize_func( void *summarize_baton, svn_diff_summarize_t *diff )
+{
+ const char *prior_rev;
+ const char *after_rev;
+
+ if ( SVN_IS_VALID_REVNUM(diff->prior_revision) )
+ {
+ prior_rev = apr_psprintf (diff->pool, "%ld", diff->prior_revision);
+ }
+ else
+ {
+ prior_rev = "?";
+ }
+
+ if ( SVN_IS_VALID_REVNUM(diff->after_revision) )
+ {
+ after_rev = apr_psprintf (diff->pool, "%ld", diff->after_revision);
+ }
+ else
+ {
+ after_rev = "?";
+ }
+
+ /*SVN_ERR*/ (svn_cmdline_printf (diff->pool, "%c%c%c %6s %6s %s\n",
+ generate_summarize_code(diff->sum_kind),
+ diff->props_changed ? 'M' : ' ',
+ diff->node_kind == svn_node_dir ? 'F' : ' ',
+ prior_rev,
+ after_rev,
+ diff->path));
+}
+
+
 /* An svn_opt_subcommand_t to handle the 'diff' command.
    This implements the `svn_opt_subcommand_t' interface. */
 svn_error_t *
@@ -182,20 +228,39 @@
           svn_pool_clear (subpool);
           target1 = svn_path_join (old_target, path, subpool);
           target2 = svn_path_join (new_target, path, subpool);
-
- SVN_ERR (svn_client_diff2 (options,
- target1,
- &(opt_state->start_revision),
- target2,
- &(opt_state->end_revision),
- opt_state->nonrecursive ? FALSE : TRUE,
- opt_state->notice_ancestry ? FALSE : TRUE,
- opt_state->no_diff_deleted,
- opt_state->force,
- outfile,
- errfile,
- ((svn_cl__cmd_baton_t *)baton)->ctx,
- pool));
+
+ if (! opt_state->summarize)
+ {
+ SVN_ERR (svn_client_diff2 (options,
+ target1,
+ &(opt_state->start_revision),
+ target2,
+ &(opt_state->end_revision),
+ opt_state->nonrecursive ? FALSE : TRUE,
+ opt_state->notice_ancestry ? FALSE : TRUE,
+ opt_state->no_diff_deleted,
+ opt_state->force,
+ outfile,
+ errfile,
+ ((svn_cl__cmd_baton_t *)baton)->ctx,
+ pool));
+ }
+ else
+ {
+ SVN_ERR (svn_client_diff_summarize
+ (options,
+ target1,
+ &(opt_state->start_revision),
+ target2,
+ &(opt_state->end_revision),
+ opt_state->nonrecursive ? FALSE : TRUE,
+ opt_state->notice_ancestry ? FALSE : TRUE,
+ opt_state->no_diff_deleted,
+ opt_state->force,
+ summarize_func,0,
+ ((svn_cl__cmd_baton_t *)baton)->ctx,
+ pool));
+ }
         }
       else
         {
Index: subversion/clients/cmdline/main.c
===================================================================
--- subversion/clients/cmdline/main.c (revision 14883)
+++ subversion/clients/cmdline/main.c (working copy)
@@ -149,6 +149,8 @@
                       N_("maximum number of log entries")},
     {"no-unlock", svn_cl__no_unlock_opt, 0,
                       N_("don't unlock the targets")},
+ {"summarize", 's', 0,
+ N_("summarize diffs")},
     {0, 0, 0, 0}
   };
 
@@ -300,7 +302,7 @@
     {'r', svn_cl__old_cmd_opt, svn_cl__new_cmd_opt, 'N',
      svn_cl__diff_cmd_opt, 'x', svn_cl__no_diff_deleted,
      svn_cl__notice_ancestry_opt, svn_cl__force_opt, SVN_CL__AUTH_OPTIONS,
- svn_cl__config_dir_opt} },
+ svn_cl__config_dir_opt, 's'} },
 
   { "export", svn_cl__export, {0},
     N_("Create an unversioned copy of a tree.\n"
@@ -1104,6 +1106,8 @@
       case svn_cl__no_unlock_opt:
         opt_state.no_unlock = TRUE;
         break;
+ case 's':
+ opt_state.summarize = TRUE;
       default:
         /* Hmmm. Perhaps this would be a good place to squirrel away
            opts that commands like svn diff might need. Hmmm indeed. */

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Wed Jun 1 21:12:29 2005

This is an archived mail posted to the Subversion Dev mailing list.