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

[WIP] How create diff headers even if we only have property diffs?

From: Daniel Näslund <daniel_at_longitudo.com>
Date: Fri, 18 Jun 2010 10:46:32 +0200

Hi!

I need to have a diff header even if there's only property changes for
the sake of parsing.

And I want only one diff header per file. Makes it easier to apply the
patch. For each found diff header we create one svn_patch_t object.
Simple and clean.

What to do? I could add a flag to the diff_cmd_baton and reset it
between each call but, as Greg pointed out, that's like using a global
variable.

I could collect all the paths with affected files and create the diff in
something like close_edit() but there's no such call for
svn_wc_diff_callbacks4_t.

One other approach:

[[[
Make 'svn diff' always write out a diff header if there are changes to a
path, no matter if it's property or text changes.

* subversion/libsvn_client/diff.c
  (diff_cmd_baton): New field 'visited_paths' to hold all the paths for
    which a diff header has already been written.
  (display_prop_diff): Add parameter 'show_diff_header'.
  (diff_props_changed): Call display_prop_diffs() with show_diff_header
    set to TRUE if the path has not yet been processed.
  (diff_content_changed): Add the path to 'visited_paths'.
  (svn_client_diff5,
   svn_client_diff_peg5): Initialize diff_cmd_baton->visited_paths.
]]]

Feels kinda ugly. Some obvious way to do it that I'm missing? The
alternatives I can come up with would involve revamping the callback
chain to make property changes and text changes end up in one function.

[[[

Index: subversion/libsvn_client/diff.c
===================================================================
--- subversion/libsvn_client/diff.c (revision 955844)
+++ subversion/libsvn_client/diff.c (arbetskopia)
@@ -200,6 +200,7 @@ display_prop_diffs(const apr_array_header_t *propc
                    const char *encoding,
                    apr_file_t *file,
                    const char *relative_to_dir,
+ svn_boolean_t show_diff_header,
                    apr_pool_t *pool)
 {
   int i;
@@ -294,7 +295,8 @@ display_prop_diffs(const apr_array_header_t *propc
          * UNIX patch could apply the property diff to, so we use "##"
          * instead of "@@" as the default hunk delimiter for property diffs.
          * We also supress the diff header. */
- SVN_ERR(svn_diff_mem_string_output_unified2(os, diff, FALSE, "##",
+ SVN_ERR(svn_diff_mem_string_output_unified2(os, diff, show_diff_header,
+ "##",
                                            svn_dirent_local_style(path, pool),
                                            svn_dirent_local_style(path, pool),
                                            encoding, orig, val, pool));
@@ -451,6 +453,8 @@ struct diff_cmd_baton {
   /* The directory that diff target paths should be considered as
      relative to for output generation (see issue #2723). */
   const char *relative_to_dir;
+
+ apr_hash_t *visited_paths;
 };
 
 /* Generate a label for the diff output for file PATH at revision REVNUM.
@@ -485,15 +489,22 @@ diff_props_changed(const char *local_dir_abspath,
 {
   struct diff_cmd_baton *diff_cmd_baton = diff_baton;
   apr_array_header_t *props;
+ svn_boolean_t show_diff_header;
   apr_pool_t *subpool = svn_pool_create(diff_cmd_baton->pool);
 
   SVN_ERR(svn_categorize_props(propchanges, NULL, NULL, &props, subpool));
 
+ if (apr_hash_get(diff_cmd_baton->visited_paths, path, APR_HASH_KEY_STRING))
+ show_diff_header = FALSE;
+ else
+ show_diff_header = TRUE;
+
   if (props->nelts > 0)
     SVN_ERR(display_prop_diffs(props, original_props, path,
                                diff_cmd_baton->header_encoding,
                                diff_cmd_baton->outfile,
                                diff_cmd_baton->relative_to_dir,
+ show_diff_header,
                                subpool));
 
   if (state)
@@ -750,6 +761,8 @@ diff_content_changed(const char *path,
   /* Destroy the subpool. */
   svn_pool_destroy(subpool);
 
+ apr_hash_set(diff_cmd_baton->visited_paths, path, APR_HASH_KEY_STRING, path);
+
   return SVN_NO_ERROR;
 }
 
@@ -1908,6 +1921,7 @@ svn_client_diff5(const apr_array_header_t *options
   diff_cmd_baton.force_empty = FALSE;
   diff_cmd_baton.force_binary = ignore_content_type;
   diff_cmd_baton.relative_to_dir = relative_to_dir;
+ diff_cmd_baton.visited_paths = apr_hash_make(pool);
 
   return do_diff(&diff_params, &diff_callbacks, &diff_cmd_baton, ctx, pool);
 }
@@ -1974,6 +1988,7 @@ svn_client_diff_peg5(const apr_array_header_t *opt
   diff_cmd_baton.force_empty = FALSE;
   diff_cmd_baton.force_binary = ignore_content_type;
   diff_cmd_baton.relative_to_dir = relative_to_dir;
+ diff_cmd_baton.visited_paths = apr_hash_make(pool);
 
   return do_diff(&diff_params, &diff_callbacks, &diff_cmd_baton, ctx, pool);
 }
]]]

Daniel
Received on 2010-06-18 10:47:18 CEST

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