Hello, attached is a patch against the current subversion trunk state (revision 1611327) that fixes a problem when using external diff programs that's also been described years ago here:
http://svn.haxx.se/users/archive-2008-10/0664.shtml ---- When passing the new diff command line option --no-normalization then svn diff won't create and pass on a temporary, normalized version of a file for local working copy files. This normalization is the default behaviour when svn diff encounters files that have the svn:keywords or svn:eol-style properties set, such that the base version and the working copy version of the file have the same format. This makes it impossible to edit diffed files when using an external --diff-cmd that supports editing, because the file passed to the external tool is a temporary file that will be deleted afterwards, instead of the original working copy file. When passing --no-normalization the original file is passed to the diff tool instead. External tools that can ignore whitespace differences (present due to svn:eol-style) can still display decent diffs and the benefit of editing the diffed files in place is helpful. ---- Best regards, Matthias Gerstner -- Matthias Gerstner, Dipl.-Wirtsch.-Inf. (FH) Entwicklung NCP engineering GmbH Dombühler Straße 2, D-90449, Nürnberg Geschäftsführer Peter Söll, HRB-Nr: 77 86 Nürnberg Telefon: +49 911 9968-153, Fax: +49 911 9968-229 E-Mail: matthias.gerst...@ncp-e.com Internet: http://www.ncp-e.com
Index: subversion/include/private/svn_wc_private.h =================================================================== --- subversion/include/private/svn_wc_private.h (revision 1611312) +++ subversion/include/private/svn_wc_private.h (working copy) @@ -1845,6 +1845,7 @@ const char *local_abspath, svn_depth_t depth, svn_boolean_t ignore_ancestry, + svn_boolean_t no_normalization, const apr_array_header_t *changelist_filter, const svn_diff_tree_processor_t *diff_processor, svn_cancel_func_t cancel_func, Index: subversion/include/svn_client.h =================================================================== --- subversion/include/svn_client.h (revision 1611312) +++ subversion/include/svn_client.h (working copy) @@ -2994,6 +2994,41 @@ * @{ */ +/** Just like svn_client_diff6() but with an added parameter @a + * no_normalization. + * + * If @a no_normalization is TRUE, then local diffs in the working copy + * won't be made against a potentially normalized, temporary version of the + * working copy version of the file. This is normally done if the file in + * question has got the svn:keywords or svn:eol-style property set. However, + * this makes it impossible to edit diffed files in an external diff tool, + * therefore setting @a no_normalization sacrifices normalization in favor + * of being able to edit the working copy file from the differ. + **/ +svn_error_t * +svn_client_diff7(const apr_array_header_t *diff_options, + const char *path_or_url1, + const svn_opt_revision_t *revision1, + const char *path_or_url2, + const svn_opt_revision_t *revision2, + const char *relative_to_dir, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t no_diff_added, + svn_boolean_t no_diff_deleted, + svn_boolean_t show_copies_as_adds, + svn_boolean_t no_normalization, + svn_boolean_t ignore_content_type, + svn_boolean_t ignore_properties, + svn_boolean_t properties_only, + svn_boolean_t use_git_diff_format, + const char *header_encoding, + svn_stream_t *outstream, + svn_stream_t *errstream, + const apr_array_header_t *changelists, + svn_client_ctx_t *ctx, + apr_pool_t *pool); + /** * Produce diff output which describes the delta between * @a path_or_url1/@a revision1 and @a path_or_url2/@a revision2. Print Index: subversion/libsvn_client/deprecated.c =================================================================== --- subversion/libsvn_client/deprecated.c (revision 1611312) +++ subversion/libsvn_client/deprecated.c (working copy) @@ -914,6 +914,41 @@ /*** From diff.c ***/ svn_error_t * +svn_client_diff6(const apr_array_header_t *diff_options, + const char *path_or_url1, + const svn_opt_revision_t *revision1, + const char *path_or_url2, + const svn_opt_revision_t *revision2, + const char *relative_to_dir, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t no_diff_added, + svn_boolean_t no_diff_deleted, + svn_boolean_t show_copies_as_adds, + svn_boolean_t ignore_content_type, + svn_boolean_t ignore_properties, + svn_boolean_t properties_only, + svn_boolean_t use_git_diff_format, + const char *header_encoding, + svn_stream_t *outstream, + svn_stream_t *errstream, + const apr_array_header_t *changelists, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_diff7(diff_options, path_or_url1, revision1, path_or_url2, + revision2, relative_to_dir, depth, + ignore_ancestry, no_diff_added, + no_diff_deleted, show_copies_as_adds, + FALSE /* no normalization */, + ignore_content_type, ignore_properties, + properties_only, use_git_diff_format, + header_encoding, + outstream, errstream, changelists, ctx, pool); + +} + +svn_error_t * svn_client_diff5(const apr_array_header_t *diff_options, const char *path1, const svn_opt_revision_t *revision1, Index: subversion/libsvn_client/diff.c =================================================================== --- subversion/libsvn_client/diff.c (revision 1611312) +++ subversion/libsvn_client/diff.c (working copy) @@ -564,6 +564,12 @@ /* Set this if you want diff output even for binary files. */ svn_boolean_t force_binary; + /* Set this if you don't want to get temporary version of files during local + * diff, because svn:eol_style or svn:keywords are set on the old/new file. + * This allows to always edit the working file when invoking external diff + * commands. */ + svn_boolean_t no_normalization; + /* The directory that diff target paths should be considered as relative to for output generation (see issue #2723). */ const char *relative_to_dir; @@ -1638,6 +1644,7 @@ apr_pool_t *scratch_pool) { const char *abspath1; + diff_writer_info_t *dwi = (diff_writer_info_t*)diff_processor->baton; SVN_ERR_ASSERT(! svn_path_is_url(path1)); SVN_ERR_ASSERT(! svn_path_is_url(path2)); @@ -1670,8 +1677,8 @@ SVN_ERR(svn_wc__diff7(root_relpath, root_is_dir, ctx->wc_ctx, abspath1, depth, - ignore_ancestry, changelists, - diff_processor, + ignore_ancestry, dwi->no_normalization, + changelists, diff_processor, ctx->cancel_func, ctx->cancel_baton, result_pool, scratch_pool)); return SVN_NO_ERROR; @@ -2328,7 +2335,7 @@ * These cases require server communication. */ svn_error_t * -svn_client_diff6(const apr_array_header_t *options, +svn_client_diff7(const apr_array_header_t *options, const char *path_or_url1, const svn_opt_revision_t *revision1, const char *path_or_url2, @@ -2339,6 +2346,7 @@ svn_boolean_t no_diff_added, svn_boolean_t no_diff_deleted, svn_boolean_t show_copies_as_adds, + svn_boolean_t no_normalization, svn_boolean_t ignore_content_type, svn_boolean_t ignore_properties, svn_boolean_t properties_only, @@ -2382,6 +2390,7 @@ dwi.no_diff_added = no_diff_added; dwi.no_diff_deleted = no_diff_deleted; dwi.show_copies_as_adds = show_copies_as_adds; + dwi.no_normalization = no_normalization; dwi.cancel_func = ctx->cancel_func; dwi.cancel_baton = ctx->cancel_baton; Index: subversion/libsvn_wc/diff.h =================================================================== --- subversion/libsvn_wc/diff.h (revision 1611312) +++ subversion/libsvn_wc/diff.h (working copy) @@ -136,6 +136,7 @@ const svn_diff_tree_processor_t *processor, void *processor_dir_baton, svn_boolean_t diff_pristine, + svn_boolean_t no_normalization, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool); Index: subversion/libsvn_wc/diff_editor.c =================================================================== --- subversion/libsvn_wc/diff_editor.c (revision 1611312) +++ subversion/libsvn_wc/diff_editor.c (working copy) @@ -396,6 +396,7 @@ const svn_diff_tree_processor_t *processor, void *processor_dir_baton, svn_boolean_t diff_pristine, + svn_boolean_t no_normalization, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) @@ -505,7 +506,7 @@ db, local_abspath, working_checksum, scratch_pool, scratch_pool)); - else if (! (had_props || props_mod)) + else if (! (had_props || props_mod) || (!files_same && no_normalization) ) local_file = local_abspath; else if (files_same) local_file = pristine_file; @@ -817,6 +818,7 @@ eb->changelist_hash, eb->processor, dir_baton, eb->diff_pristine, + FALSE /* no normalization */, eb->cancel_func, eb->cancel_baton, scratch_pool)); Index: subversion/libsvn_wc/diff_local.c =================================================================== --- subversion/libsvn_wc/diff_local.c (revision 1611312) +++ subversion/libsvn_wc/diff_local.c (working copy) @@ -88,6 +88,9 @@ /* Should this diff ignore node ancestry? */ svn_boolean_t ignore_ancestry; + + /* don't perform normalization even if eol_style or keywords are set */ + svn_boolean_t no_normalization; /* Hash whose keys are const char * changelist names. */ apr_hash_t *changelist_hash; @@ -364,6 +367,7 @@ ? eb->cur->baton : NULL, FALSE, + eb->no_normalization, eb->cancel_func, eb->cancel_baton, scratch_pool)); @@ -435,6 +439,7 @@ const char *local_abspath, svn_depth_t depth, svn_boolean_t ignore_ancestry, + svn_boolean_t no_normalization, const apr_array_header_t *changelist_filter, const svn_diff_tree_processor_t *diff_processor, svn_cancel_func_t cancel_func, @@ -454,6 +459,7 @@ scratch_pool)); eb.anchor_abspath = local_abspath; + eb.no_normalization = no_normalization; if (root_relpath) { @@ -564,6 +570,7 @@ wc_ctx, local_abspath, depth, ignore_ancestry, + FALSE, /* no normalization */ changelist_filter, processor, cancel_func, cancel_baton, Index: subversion/svn/cl.h =================================================================== --- subversion/svn/cl.h (revision 1611312) +++ subversion/svn/cl.h (working copy) @@ -188,6 +188,7 @@ svn_boolean_t no_diff_added; /* do not show diffs for deleted files */ svn_boolean_t no_diff_deleted; /* do not show diffs for deleted files */ svn_boolean_t show_copies_as_adds; /* do not diff copies with their source */ + svn_boolean_t no_normalization; /* do not use temporary, normalized files */ svn_boolean_t notice_ancestry; /* notice ancestry for diff-y operations */ svn_boolean_t summarize; /* create a summary of a diff */ svn_boolean_t use_git_diff_format; /* Use git's extended diff format */ Index: subversion/svn/diff-cmd.c =================================================================== --- subversion/svn/diff-cmd.c (revision 1611312) +++ subversion/svn/diff-cmd.c (working copy) @@ -404,7 +404,7 @@ ctx, iterpool)); } else - SVN_ERR(svn_client_diff6( + SVN_ERR(svn_client_diff7( options, target1, &(opt_state->start_revision), @@ -416,6 +416,7 @@ opt_state->diff.no_diff_added, opt_state->diff.no_diff_deleted, show_copies_as_adds, + opt_state->diff.no_normalization, ignore_content_type, ignore_properties, opt_state->diff.properties_only, Index: subversion/svn/svn.c =================================================================== --- subversion/svn/svn.c (revision 1611312) +++ subversion/svn/svn.c (working copy) @@ -79,6 +79,7 @@ opt_no_diff_added, opt_no_diff_deleted, opt_show_copies_as_adds, + opt_no_normalization, opt_notice_ancestry, opt_summarize, opt_use_git_diff_format, @@ -352,6 +353,14 @@ N_("do not print differences for deleted files")}, {"show-copies-as-adds", opt_show_copies_as_adds, 0, N_("don't diff copied or moved files with their source")}, + {"no-normalization", opt_no_normalization, 0, + N_("don't pass temporary, normalized files to the diff\n" + " " + "tool but the local working copy file. This is otherwise\n" + " " + "done if the svn:keywords or svn:eol-style property is set\n" + " " + "on the file")}, {"notice-ancestry", opt_notice_ancestry, 0, N_("diff unrelated nodes as delete and add")}, {"summarize", opt_summarize, 0, N_("show a summary of the results")}, @@ -636,7 +645,8 @@ {'r', 'c', opt_old_cmd, opt_new_cmd, 'N', opt_depth, opt_diff_cmd, opt_internal_diff, 'x', opt_no_diff_added, opt_no_diff_deleted, opt_ignore_properties, opt_properties_only, - opt_show_copies_as_adds, opt_notice_ancestry, opt_summarize, opt_changelist, + opt_show_copies_as_adds, opt_no_normalization, opt_notice_ancestry, + opt_summarize, opt_changelist, opt_force, opt_xml, opt_use_git_diff_format, opt_patch_compatible} }, { "export", svn_cl__export, {0}, N_ ("Create an unversioned copy of a tree.\n" @@ -2136,6 +2146,9 @@ case opt_show_copies_as_adds: opt_state.diff.show_copies_as_adds = TRUE; break; + case opt_no_normalization: + opt_state.diff.no_normalization = TRUE; + break; case opt_notice_ancestry: opt_state.diff.notice_ancestry = TRUE; break;
signature.asc
Description: Digital signature