You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by gb...@apache.org on 2013/11/13 22:22:17 UTC
svn commit: r1541728 -
/subversion/branches/invoke-diff-cmd-feature/BRANCH-README
Author: gbg
Date: Wed Nov 13 21:22:17 2013
New Revision: 1541728
URL: http://svn.apache.org/r1541728
Log:
On the invoke-diff-cmd-feature branch: Update BRANCH-README file.
* BRANCH-README:
(Log messages): Update entries.
(Diff file for this Branch): New entry.
Modified:
subversion/branches/invoke-diff-cmd-feature/BRANCH-README
Modified: subversion/branches/invoke-diff-cmd-feature/BRANCH-README
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/BRANCH-README?rev=1541728&r1=1541727&r2=1541728&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/BRANCH-README (original)
+++ subversion/branches/invoke-diff-cmd-feature/BRANCH-README Wed Nov 13 21:22:17 2013
@@ -117,30 +117,58 @@ The test for the 'invoke-diff-cmd' featu
-Log messages of salient code changes
-====================================
+Log messages
+=============
* subversion/include/private/svn_io_private.h
(svn_io__create_custom_diff_cmd): New function declaration.
+* subversion/include/svn_client.h
+
+ (svn_client_diff7, svn_client_diff_peg7): Declare the new API. Like
+ svn_client_diff[_peg]6 but with invoke_diff_cmd parameter.
+
+ (svn_client_diff6, svn_client_diff_peg_6): Deprecate.
+
+
+* subversion/include/svn_config.h
+
+ (SVN_CONFIG_OPTION_INVOKE_DIFF_CMD): New definition.
+
+
+* subversion/include/svn_error_codes.h
+
+ (SVN_CLIENT_DIFF_CMD): New macro.
+
+
+* subversion/include/svn_io.h
+
+ (svn_io_run_external_diff): New function.
+
+
+* subversion/libsvn_client/deprecated.c
+
+ (svn_client_diff6, svn_client_diff_peg6): New deprecation wrappers.
+
+
* subversion/libsvn_client/diff.c
- (diff_cmd_baton): New member: 'invoke_diff_cmd'. Move declaration of
- invoke_diff_cmd to group with diff_cmd.
+ (*): Update all comments mentioning 'svn_client_diff6' to
+ 'svn_client_diff7'.
- (set_up_diff_cmd_and_options): Apply invoke-diff-cmd option
- preferentially. Old behavior unchanged.
+ (diff_cmd_baton): New member: 'invoke_diff_cmd'.
- (diff_content_changed): Raise an error if both diff_cmd and
- invoke-diff-cmd are set. Add comment explaining the presence of
- non-canonical path in function call. Call
- svn_io_run_external_diff if --invoke-diff-cmd option was
- specified, otherwise retain previous behaviour.
+ (set_up_diff_cmd_and_options): Apply invoke-diff-cmd option
+ preferentially. Note: fucntion has been refactored, but previous
+ behavior regards the old diff_cmd stays unchanged.
- (sub_main): Add guard against concurrent usage of incompatible diff
- options. Remove previous guard code.
+ (diff_content_changed): Raise an error if both diff_cmd and
+ invoke-diff-cmd are set. Add invoke-diff-cmd to if condition.
+ Add comment explaining the presence of non-canonical path in
+ function call. Call svn_io_run_external_diff if --invoke-diff-cmd
+ option was specified, otherwise retain previous behaviour.
(svn_client_diff_peg_7): Rename and update from
svn_client_diff_peg_6. Add new parameter: invoke_diff_cmd.
@@ -148,55 +176,48 @@ Log messages of salient code changes
(svn_client_diff7): Rename and update from svn_client_diff6, add
new parameter 'invoke_diff_cmd'.
- (): Update all comments mentioning 'svn_client_diff6' to
- 'svn_client_diff7'.
-
* subversion/libsvn_subr/config_file.c
- (svn_config_ensure): New entry: invoke-diff-cmd.
-
- (invoke-diff-cmd): Update help info.
+ (svn_config_ensure,"invoke-diff-cmd"): New entry: invoke-diff-cmd.
+ Add help info.
* subversion/libsvn_subr/io.c
(svn_io__create_custom_diff_cmd): New function.
- (svn_io_run_diff2): Add test location information.
-
(svn_io_run_external_diff): New function.
+ (svn_io_run_diff2): Add test location information.
-* subversion/svn/svn.c
-
- (svn_cl__cmd_table[]): New option: 'invoke-diff-cmd'. Add
- opt_invoke_diff_cmd to svn_cl__log entry. Add opt_invoke_diff_cmd
- to the list of valid subcommands.
-
- (svn_cl__options "invoke-diff-cmd"): Add help information. Add new
- variable 'opt_invoke_diff_cmd'.
-
- (sub_main): Prohibit simultaneous usage of --invoke-diff-cmd and
- --internal-diff. Add new opt_state.diff.invoke-diff-cmd option
- to the option selector. Add call to svn_config_set.
+* subversion/svn/cl.h
-* subversion/tests/cmdline/diff_tests.py
+ (struct svn_cl__opt_state_t.diff): New member: 'invoke_diff_cmd'.
- (diff_invoke_external_diffcmd): New function.
- (test_list): Add new entry 'diff_invoke_external_diffcmd'.
+* subversion/svn/diff-cmd.c
+ (svn_cl__diff): Update call to svn_client_diff6 to svn_client_diff7,
+ add invoke_diff_cmd to parameter listing. Update call to svn_client_diff_peg7 to
+ svn_client_diff_peg7, add invoke_diff_cmd to parameter listing.
-* subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
- (--invoke-diff-cmd): Add new entry to help output data.
+* subversion/svn/log-cmd.c
+ (log_receiver_baton): New struct member invoke_diff_cmd.
-* subversion/libsvn_subr/config_file.c
+ (display_diff): New parameter 'invoke_diff_cmd' . Update call to
+ svn_client_peg_diff7. Pass invoke_diff_cmd parameter into
+ svn_client_diff_peg7().
- (invoke-diff-cmd): Add help info.
+ (log_entry_receiver): Pass invoke_diff_cmd into display_diff().
+
+ (svn_cl__log): Ensure mutual exclusions between invoke_diff_cmd and
+ diff-cmd. Require 'diff' option to be set when requesting
+ invoke_diff option. Populate log_receiver_baton member
+ invoke_diff_cmd.
* subversion/svnlook/svnlook.c
@@ -212,69 +233,1033 @@ Log messages of salient code changes
(svnlook_ctxt_t): New member variable "invoke_diff_cmd".
- (print_diff_tree): Modify if condition to include new
+ (print_diff_tree): Modify 'if condition' to include new
invoke_diff_cmd. Add conditional call to
/include/svn_io.c:svn_io_run_external_diff().
(get_ctxt_baton): Assign invoke_diff_cmd data.
- (main): Assign opt_arg to opt_state.invoke_diff_cmd. Add
- exclusiveness test for invoke_diff_cmd and diff_cmd.
-
-
-* subversion/include/svn_error_codes.h
-
- (SVN_CLIENT_DIFF_CMD): New macro.
+ (main): Add case svnlook__invoke_diff_cmd. Assign opt_arg to
+ opt_state.invoke_diff_cmd. Add exclusiveness test for
+ invoke_diff_cmd and diff_cmd.
-* subversion/svn/log-cmd.c
-
- (log_receiver_baton): New struct member invoke_diff_cmd.
-
- (display_diff): New parameter 'invoke_diff_cmd' . Pass
- invoke_diff_cmd parameter into svn_client_diff_peg7().
+* subversion/svn/svn.c
- (log_entry_receiver): Pass invoke_diff_cmd into display_diff().
+ (svn_cl__longopt_t): New enum opt_invoke_diff_cmd.
- (svn_cl__log): Ensure mutual exclusions between invoke_diff_cmd and
- quiet and diff-cmd, require 'diff' option. Populate
- log_receiver_baton member invoke_diff_cmd.
-
- (svn_cl__options): Add help info for invoke-diff-cmd option.
-
- (svn_client_diff_peg7): Update call to svn_client_diff_peg6 to
- svn_client_diff_peg7.
-
-
-* subversion/include/svn_client.h
-
- (svn_client_diff7, svn_client_diff_peg7): Declare the new API. Like
- svn_client_diff[_peg]6 but with invoke_diff_cmd parameter.
-
- (svn_client_diff6, svn_client_diff_peg_6): Deprecate.
-
-
-* subversion/include/svn_config.h
-
- (SVN_CONFIG_OPTION_INVOKE_DIFF_CMD): New definition.
+ (svn_cl__options "invoke-diff-cmd"): Add help information. Add new
+ variable 'opt_invoke_diff_cmd'.
+ (svn_cl__cmd_table[]): New option: 'invoke-diff-cmd', help info. Add
+ opt_invoke_diff_cmd to svn_cl__log entry. Add opt_invoke_diff_cmd
+ to the list of valid subcommands.
-* subversion/include/svn_io.h
- (svn_io_run_external_diff): New function.
+ (sub_main): Add case opt_invoke_diff_cmd. Prohibit simultaneous
+ usage of --invoke-diff-cmd and --internal-diff. Prohibit
+ simultaneous usage of --diff-cmd and --invoke-diff-cmd. Add call
+ to svn_config_set.
-* subversion/libsvn_client/deprecated.c
+* subversion/tests/cmdline/diff_tests.py
- (svn_client_diff6, svn_client_diff_peg6): New deprecation wrappers.
+ (diff_invoke_external_diffcmd): New function.
+ (test_list): Add new entry 'diff_invoke_external_diffcmd'.
-* subversion/svn/cl.h
- (struct svn_cl__opt_state_t.diff): New member: 'invoke_diff_cmd'.
+* subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
+ (--invoke-diff-cmd): Add new entry to 'help' output data.
-* subversion/svn/diff-cmd.c
- (svn_cl__diff): Update call to svn_client_diff6 to svn_client_diff7.
+Diff file for this branch
+=========================
+*** /home/g/trunk/subversion/include/private/svn_io_private.h 2013-07-12 22:06:51.122108458 +0100
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/include/private/svn_io_private.h 2013-11-06 19:06:16.397366843 +0000
+*************** svn_stream__aprfile(svn_stream_t *stream
+*** 98 ****
+--- 99,143 ----
++ /** Parse a user defined command to contain dynamically created labels
++ * and filenames. This function serves both diff and diff3 parsing
++ * requirements.
++ *
++ * When used in a diff context: (responding parse tokens in braces)
++ *
++ * @a label1 (%svn_label_old) refers to the label of @a tmpfile1
++ * (%svn_old) which is the pristine copy.
++ *
++ * @a label2 (%svn_label_new) refers to the label of @a tmpfile2
++ * (%svn_new) which is the altered copy.
++ *
++ * When used in a diff3 context:
++ *
++ * @a label1 refers to the label of @a tmpfile1 which is the 'mine'
++ * copy.
++ *
++ * @a label2 refers to the label of @a tmpfile2 which is the 'older'
++ * copy.
++ *
++ * @a label3 (%svn_label_base) refers to the label of @a base
++ * (%svn_base) which is the 'base' copy.
++ *
++ * In general:
++ *
++ * @a cmd is a user defined string containing 0 or more parse tokens
++ * which are expanded by the required labels and filenames.
++ *
++ * @a pool is used for temporary allocations.
++ *
++ * @return A NULL-terminated character array.
++ *
++ * @since New in 1.9.
++ */
++ const char **
++ svn_io__create_custom_diff_cmd(const char *label1,
++ const char *label2,
++ const char *label3,
++ const char *from,
++ const char *to,
++ const char *base,
++ const char *cmd,
++ apr_pool_t *pool);
++
++
+
+================================================================================
+
+*** /home/g/trunk/subversion/include/svn_client.h 2013-10-15 15:55:28.309189195 +0100
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/include/svn_client.h 2013-11-06 16:28:10.178327223 +0000
+*************** svn_client_blame(const char *path_or_url
+*** 3059 ****
+--- 3060,3064 ----
++ * @a invoke_diff_cmd is used to call an external diff program but may
++ * not be @c NULL. The command line invocation will override the
++ * invoke-diff-cmd invocation entry(if any) in the Subversion
++ * configuration file.
++ *
+*************** svn_client_blame(const char *path_or_url
+*** 3089 ****
+--- 3095,3123 ----
++ * @since New in 1.9.
++ */
++ svn_error_t *
++ 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,
++ 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,
++ const char *invoke_diff_cmd,
++ svn_client_ctx_t *ctx,
++ apr_pool_t *pool);
++
++ /** Similar to svn_client_diff7(), but without @a invoke_diff_cmd.
++ *
++ * @deprecated Provided for backward compatibility with the 1.8 API.
+*************** svn_client_blame(const char *path_or_url
+*** 3091 ****
+--- 3126 ----
++ SVN_DEPRECATED
+*************** svn_client_diff(const apr_array_header_t
+*** 3249 ****
+! * identically to svn_client_diff6(), using @a path_or_url for both of that
+--- 3284 ----
+! * identically to svn_client_diff7(), using @a path_or_url for both of that
+*************** svn_client_diff(const apr_array_header_t
+*** 3252 ****
+! * All other options are handled identically to svn_client_diff6().
+--- 3287 ----
+! * All other options are handled identically to svn_client_diff7().
+*************** svn_client_diff(const apr_array_header_t
+*** 3253 ****
+--- 3289,3321 ----
++ * @since New in 1.9.
++ */
++ svn_error_t *
++ svn_client_diff_peg7(const apr_array_header_t *diff_options,
++ const char *path_or_url,
++ const svn_opt_revision_t *peg_revision,
++ const svn_opt_revision_t *start_revision,
++ const svn_opt_revision_t *end_revision,
++ 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,
++ const char *invoke_diff_cmd,
++ svn_client_ctx_t *ctx,
++ apr_pool_t *pool);
++
++
++ /**
++ * Similar to svn_client_peg7(), but without @a no_diff_added set to
++ * FALSE, @a ignore_properties set to FALSE and @a properties_only set
++ * to FALSE.
++ *
++ * @deprecated Provided for backward compatibility with the 1.7 API.
+*************** svn_client_diff(const apr_array_header_t
+*** 3255 ****
+--- 3324 ----
++ SVN_DEPRECATED
+*************** svn_client_diff_peg6(const apr_array_hea
+*** 3279 ****
+! /** Similar to svn_client_diff6_peg6(), but with @a outfile and @a errfile,
+--- 3348,3349 ----
+! /**
+! * Similar to svn_client_diff_peg6(), but with @a outfile and @a errfile,
+
+================================================================================
+
+*** /home/g/trunk/subversion/include/svn_config.h 2013-08-21 14:38:52.462504050 +0100
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/include/svn_config.h 2013-08-21 15:13:02.172668024 +0100
+*************** typedef struct svn_config_t svn_config_t
+*** 116 ****
+--- 117,118 ----
++ /** @since New in 1.9. */
++ #define SVN_CONFIG_OPTION_INVOKE_DIFF_CMD "invoke-diff-cmd"
+
+================================================================================
+
+*** /home/g/trunk/subversion/include/svn_error_codes.h 2013-09-24 21:40:36.710752868 +0100
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/include/svn_error_codes.h 2013-09-26 13:50:41.575809672 +0100
+*************** SVN_ERROR_START
+*** 1206 ****
+--- 1207,1211 ----
++ /** @since New in 1.9 */
++ SVN_ERRDEF(SVN_ERR_CLIENT_DIFF_CMD,
++ SVN_ERR_CLIENT_CATEGORY_START + 24,
++ "More than one diff command defined")
++
+
+================================================================================
+
+*** /home/g/trunk/subversion/include/svn_io.h 2013-10-15 15:55:28.305189175 +0100
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/include/svn_io.h 2013-11-06 17:13:17.923754208 +0000
+*************** svn_io_file_readline(apr_file_t *file,
+*** 2362 ****
+--- 2363,2379 ----
++
++ /** Run the external diff command defined by the invoke-diff-cmd
++ * option.
++ *
++ * @since New in 1.9.
++ */
++ svn_error_t *
++ svn_io_run_external_diff(const char *dir,
++ const char *label1,
++ const char *label2,
++ const char *tmpfile1,
++ const char *tmpfile2,
++ int *pexitcode,
++ apr_file_t *outfile,
++ apr_file_t *errfile,
++ const char *external_diff_cmd,
++ apr_pool_t *scratch_pool);
+
+================================================================================
+
+*** /home/g/trunk/subversion/libsvn_client/deprecated.c 2013-09-24 21:40:36.722752927 +0100
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/libsvn_client/deprecated.c 2013-09-26 13:50:46.983836489 +0100
+*************** svn_error_t *
+*** 916 ****
+--- 917,963 ----
++ svn_client_diff6(const apr_array_header_t *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(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,
++ ignore_content_type,
++ ignore_properties,
++ properties_only,
++ use_git_diff_format,
++ header_encoding,
++ outstream,
++ errstream,
++ changelists,
++ NULL,
++ ctx,
++ pool);
++ }
++
++ svn_error_t *
+*************** svn_client_diff(const apr_array_header_t
+*** 1035 ****
+--- 1083,1129 ----
++ }
++
++ svn_error_t *
++ svn_client_diff_peg6(const apr_array_header_t *options,
++ const char *path_or_url,
++ const svn_opt_revision_t *peg_revision,
++ const svn_opt_revision_t *start_revision,
++ const svn_opt_revision_t *end_revision,
++ 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_diff_peg7(options,
++ path_or_url,
++ peg_revision,
++ start_revision,
++ end_revision,
++ relative_to_dir,
++ depth,
++ ignore_ancestry,
++ no_diff_added,
++ no_diff_deleted,
++ show_copies_as_adds,
++ ignore_content_type,
++ ignore_properties,
++ properties_only,
++ use_git_diff_format,
++ header_encoding,
++ outstream,
++ errstream,
++ changelists,
++ NULL,
++ ctx,
++ pool);
+
+================================================================================
+
+*** /home/g/trunk/subversion/libsvn_client/diff.c 2013-08-07 20:56:50.881234131 +0100
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/libsvn_client/diff.c 2013-11-06 17:10:30.546924231 +0000
+*************** print_git_diff_header(svn_stream_t *os,
+*** 431 ****
+! passed to svn_client_diff6(), which is probably stdout.
+--- 431 ----
+! passed to svn_client_diff7(), which is probably stdout.
+*************** struct diff_cmd_baton {
+*** 538 ****
+--- 539,541 ----
++ /* external custom diff command */
++ const char *invoke_diff_cmd;
++
+*************** struct diff_cmd_baton {
+*** 567 ****
+! svn_client_diff6(), either may be SVN_INVALID_REVNUM. We need these
+--- 570 ----
+! svn_client_diff7(), either may be SVN_INVALID_REVNUM. We need these
+*************** diff_content_changed(svn_boolean_t *wrot
+*** 788 ****
+--- 793,796 ----
++ if (diff_cmd_baton->diff_cmd && diff_cmd_baton->invoke_diff_cmd)
++ return svn_error_create(SVN_ERR_CLIENT_DIFF_CMD, NULL,
++ _("diff-cmd and invoke-diff-cmd are "
++ "mutually exclusive."));
+*************** diff_content_changed(svn_boolean_t *wrot
+*** 790 ****
+! if (diff_cmd_baton->diff_cmd)
+--- 798 ----
+! if (diff_cmd_baton->diff_cmd || diff_cmd_baton->invoke_diff_cmd)
+*************** diff_content_changed(svn_boolean_t *wrot
+*** 828 ****
+--- 836,837 ----
++ /* "." is a non-canonical path for the diff process's working directory. */
++ if (diff_cmd_baton->diff_cmd)
+*************** diff_content_changed(svn_boolean_t *wrot
+*** 835 ****
+--- 845,853 ----
++ else
++ {
++ SVN_ERR(svn_io_run_external_diff(".",
++ label1, label2,
++ tmpfile1, tmpfile2,
++ &exitcode, outfile, errfile,
++ diff_cmd_baton->invoke_diff_cmd,
++ scratch_pool));
++ }
+*************** diff_prepare_repos_repos(const char **ur
+*** 1537,1538 ****
+! This function is really svn_client_diff6(). If you read the public
+! API description for svn_client_diff6(), it sounds quite Grand. It
+--- 1555,1556 ----
+! This function is really svn_client_diff7(). If you read the public
+! API description for svn_client_diff7(), it sounds quite Grand. It
+*************** diff_prepare_repos_repos(const char **ur
+*** 1562 ****
+! Perhaps someday a brave soul will truly make svn_client_diff6()
+--- 1580 ----
+! Perhaps someday a brave soul will truly make svn_client_diff7()
+*************** unsupported_diff_error(svn_error_t *chil
+*** 1575 ****
+! _("Sorry, svn_client_diff6 was called in a way "
+--- 1593 ----
+! _("Sorry, svn_client_diff7 was called in a way "
+*************** unsupported_diff_error(svn_error_t *chil
+*** 1584 ****
+! All other options are the same as those passed to svn_client_diff6(). */
+--- 1602 ----
+! All other options are the same as those passed to svn_client_diff7(). */
+*************** diff_wc_wc(const char *path1,
+*** 1667 ****
+! All other options are the same as those passed to svn_client_diff6(). */
+--- 1685 ----
+! All other options are the same as those passed to svn_client_diff7(). */
+*************** diff_repos_repos(const svn_wc_diff_callb
+*** 1812 ****
+! All other options are the same as those passed to svn_client_diff6(). */
+--- 1830 ----
+! All other options are the same as those passed to svn_client_diff7(). */
+*************** do_diff(const svn_wc_diff_callbacks4_t *
+*** 2147 ****
+! All other options are the same as those passed to svn_client_diff6(). */
+--- 2165 ----
+! All other options are the same as those passed to svn_client_diff7(). */
+*************** diff_summarize_repos_wc(svn_client_diff_
+*** 2191 ****
+! All other options are the same as those passed to svn_client_diff6(). */
+--- 2209 ----
+! All other options are the same as those passed to svn_client_diff7(). */
+*************** set_up_diff_cmd_and_options(struct diff_
+*** 2466 ****
+! /* See if there is a diff command and/or diff arguments. */
+--- 2484 ----
+! /* old style diff_cmd has precedence in config file */
+*************** set_up_diff_cmd_and_options(struct diff_
+*** 2486,2487 ****
+! SVN_ERR(svn_path_cstring_to_utf8(&diff_cmd_baton->diff_cmd, diff_cmd,
+! pool));
+--- 2505,2506 ----
+! SVN_ERR(svn_path_cstring_to_utf8(&diff_cmd_baton->diff_cmd,
+! diff_cmd, pool));
+*************** set_up_diff_cmd_and_options(struct diff_
+*** 2488 ****
+--- 2508,2511 ----
++ {
++ if (config) /* check if there is a invoke_diff_cmd in the config file */
++ {
++ svn_config_t *cfg = svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG);
+*************** set_up_diff_cmd_and_options(struct diff_
+*** 2489 ****
+--- 2513,2522 ----
++ svn_config_get(cfg, &diff_cmd, SVN_CONFIG_SECTION_HELPERS,
++ SVN_CONFIG_OPTION_INVOKE_DIFF_CMD, NULL);
++ if (diff_cmd)
++ {
++ SVN_ERR(svn_path_cstring_to_utf8(&diff_cmd_baton->invoke_diff_cmd,
++ diff_cmd, pool));
++ return SVN_NO_ERROR;
++ }
++ }
++ }
+*************** set_up_diff_cmd_and_options(struct diff_
+*** 2502 ****
+! APR_ARRAY_IDX(options, i, const char *), pool));
+--- 2537,2539 ----
+! APR_ARRAY_IDX(options, i,
+! const char *),
+! pool));
+*************** svn_error_t *
+*** 2555 ****
+! svn_client_diff6(const apr_array_header_t *options,
+--- 2592 ----
+! svn_client_diff7(const apr_array_header_t *options,
+*************** svn_client_diff6(const apr_array_header_
+*** 2573 ****
+--- 2611 ----
++ const char *invoke_diff_cmd,
+*************** svn_client_diff6(const apr_array_header_
+*** 2590 ****
+--- 2629 ----
++ diff_cmd_baton.invoke_diff_cmd = invoke_diff_cmd;
+*************** svn_error_t *
+*** 2622 ****
+! svn_client_diff_peg6(const apr_array_header_t *options,
+--- 2661 ----
+! svn_client_diff_peg7(const apr_array_header_t *options,
+*************** svn_client_diff_peg6(const apr_array_hea
+*** 2640 ****
+--- 2680 ----
++ const char *invoke_diff_cmd,
+*************** svn_client_diff_peg6(const apr_array_hea
+*** 2653 ****
+--- 2694 ----
++ diff_cmd_baton.invoke_diff_cmd = invoke_diff_cmd;
+
+================================================================================
+
+*** /home/g/trunk/subversion/libsvn_subr/config_file.c 2013-11-04 17:30:37.864042065 +0000
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/config_file.c 2013-11-05 12:39:49.417954357 +0000
+*************** svn_config_ensure(const char *config_dir
+*** 1189 ****
+--- 1190,1194 ----
++ "### Set invoke-diff-cmd to the absolute path of your 'diff'" NL
++ "### program." NL
++ "### This will override the compile-time default, which is to use" NL
++ "### Subversion's internal diff implementation." NL
++ "# invoke-diff-cmd = (see svn help diff for examples)" NL
+
+================================================================================
+
+
+================================================================================
+
+*** /home/g/trunk/subversion/libsvn_subr/io.c 2013-10-31 19:53:47.816899485 +0000
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/io.c 2013-11-06 19:07:58.589873589 +0000
+*************** svn_io_run_cmd(const char *path,
+*** 2995 ****
+--- 2996,3153 ----
++ const char **
++ svn_io__create_custom_diff_cmd(const char *label1,
++ const char *label2,
++ const char *label3,
++ const char *from,
++ const char *to,
++ const char *base,
++ const char *cmd,
++ apr_pool_t *pool)
++ {
++ /*
++ This function can be tested with:
++ /subversion/tests/cmdline/diff_tests.py diff_invoke_external_diffcmd
++ */
++
++ apr_array_header_t *words;
++ const char ** result;
++ size_t argv, item, i, delimiters = 6;
++ apr_pool_t *scratch_pool = svn_pool_create(pool);
++
++ struct replace_tokens_tab
++ {
++ const char *delimiter;
++ const char *replace;
++ } tokens_tab[] = { /* Diff terminology */
++ { "%svn_label_old", label1 },
++ { "%svn_label_new", label2 },
++ { "%svn_label_base", label3 },
++ { "%svn_old", from },
++ { "%svn_new", to },
++ { "%svn_base", base },
++ { NULL, NULL }
++ };
++
++ if (label3) /* Merge terminology */
++ {
++ tokens_tab[0].delimiter = "%svn_label_mine";
++ tokens_tab[1].delimiter = "%svn_label_yours";
++ tokens_tab[3].delimiter = "%svn_mine";
++ tokens_tab[4].delimiter = "%svn_yours";
++ }
++
++ words = svn_cstring_split(cmd, " ", TRUE, scratch_pool);
++
++ result = apr_palloc(pool,
++ (words->nelts+1) * words->elt_size * sizeof(char *) );
++
++ for (item = 0, argv = 0; item < words->nelts; argv++, item++)
++ {
++ svn_stringbuf_t *word;
++
++ word = svn_stringbuf_create_empty(scratch_pool);
++ svn_stringbuf_appendcstr(word, APR_ARRAY_IDX(words, item, char *));
++
++ if ( (word->data[0] == '"') && (word->data[word->len-1] != '"') )
++ {
++ svn_stringbuf_t * complete = svn_stringbuf_create_empty(scratch_pool);
++ int done = 0;
++
++ while( (!done) && item < words->nelts)
++ {
++ svn_stringbuf_appendcstr(complete,
++ APR_ARRAY_IDX(words, item, char *));
++
++ if ( (complete->data[complete->len-1] == '"')
++ || (item == words->nelts - 1) )
++ {
++ word->data = complete->data;
++ done = 1;
++ }
++ else
++ {
++ svn_stringbuf_appendcstr(complete, " ");
++ item++;
++ }
++ }
++ }
++ i = 0;
++ while (i < delimiters)
++ {
++ char *found = strstr(word->data, tokens_tab[i].delimiter);
++
++ if (!found)
++ {
++ i++;
++ continue;
++ }
++
++ svn_stringbuf_replace(word, found - word->data,
++ strlen(tokens_tab[i].delimiter),
++ tokens_tab[i].replace,
++ strlen(tokens_tab[i].replace));
++ }
++ result[argv] = apr_pstrdup(pool,word->data);
++ }
++ result[argv] = NULL;
++ svn_pool_destroy(scratch_pool);
++ return result;
++ }
++
++ svn_error_t *
++ svn_io_run_external_diff(const char *dir,
++ const char *label1,
++ const char *label2,
++ const char *tmpfile1,
++ const char *tmpfile2,
++ int *pexitcode,
++ apr_file_t *outfile,
++ apr_file_t *errfile,
++ const char *external_diff_cmd,
++ apr_pool_t *pool)
++ {
++ int exitcode;
++ const char ** cmd;
++
++ apr_pool_t *scratch_pool = svn_pool_create(pool);
++
++ if (0 == strlen(external_diff_cmd))
++ return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, NULL);
++
++ cmd = svn_io__create_custom_diff_cmd(label1, label2, NULL,
++ tmpfile1, tmpfile2, NULL,
++ external_diff_cmd, scratch_pool);
++ if (pexitcode == NULL)
++ pexitcode = &exitcode;
++
++ SVN_ERR(svn_io_run_cmd(dir, cmd[0], cmd, pexitcode, NULL, TRUE,
++ NULL, outfile, errfile, scratch_pool));
++
++ /* The man page for (GNU) diff describes the return value as:
++
++ "An exit status of 0 means no differences were found, 1 means
++ some differences were found, and 2 means trouble."
++
++ A return value of 2 typically occurs when diff cannot read its input
++ or write to its output, but in any case we probably ought to return an
++ error for anything other than 0 or 1 as the output is likely to be
++ corrupt.
++ */
++ if (*pexitcode != 0 && *pexitcode != 1)
++ {
++ int i;
++ const char *failed_command = "";
++
++ for (i = 0; cmd[i]; ++i)
++ failed_command = apr_pstrcat(pool, failed_command,
++ cmd[i], " ", (char*) NULL);
++ svn_pool_destroy(scratch_pool);
++ return svn_error_createf(SVN_ERR_EXTERNAL_PROGRAM, NULL,
++ _("'%s' was expanded to '%s' and returned %d"),
++ external_diff_cmd,
++ failed_command,
++ *pexitcode);
++ }
++ else
++ svn_pool_destroy(scratch_pool);
++ return SVN_NO_ERROR;
++ }
+*************** svn_io_run_diff2(const char *dir,
+*** 3010 ****
+--- 3169,3173 ----
++ /*
++ This function can be tested by using the test
++ /subversion/tests/cmdline/diff_tests.py diff_external_diffcmd
++ */
++
+
+================================================================================
+
+*** /home/g/trunk/subversion/svn/cl.h 2013-09-24 21:40:35.782748266 +0100
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/svn/cl.h 2013-11-06 19:53:45.955497039 +0000
+*************** typedef struct svn_cl__opt_state_t
+*** 186 ****
+--- 187,188 ----
++ const char *invoke_diff_cmd; /* the format string to specify args */
++ /* for the external diff cmd */
+
+================================================================================
+
+*** /home/g/trunk/subversion/svn/diff-cmd.c 2013-08-07 20:56:48.209220881 +0100
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/svn/diff-cmd.c 2013-08-21 15:12:59.268653617 +0100
+*************** svn_cl__diff(apr_getopt_t *os,
+*** 406 ****
+! SVN_ERR(svn_client_diff6(
+--- 406 ----
+! SVN_ERR(svn_client_diff7(
+*************** svn_cl__diff(apr_getopt_t *os,
+*** 425 ****
+--- 426 ----
++ opt_state->diff.invoke_diff_cmd,
+*************** svn_cl__diff(apr_getopt_t *os,
+*** 457 ****
+! SVN_ERR(svn_client_diff_peg6(
+--- 458 ----
+! SVN_ERR(svn_client_diff_peg7(
+*************** svn_cl__diff(apr_getopt_t *os,
+*** 476 ****
+--- 478 ----
++ opt_state->diff.invoke_diff_cmd,
+
+================================================================================
+
+*** /home/g/trunk/subversion/svn/log-cmd.c 2013-09-24 21:40:35.658747651 +0100
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/svn/log-cmd.c 2013-09-26 13:50:37.027787119 +0100
+*************** struct log_receiver_baton
+*** 69 ****
+--- 70,72 ----
++ /* Custom diff command. */
++ const char *invoke_diff_cmd;
++
+*************** display_diff(const svn_log_entry_t *log_
+*** 104 ****
+--- 108 ----
++ const char *invoke_diff_cmd,
+*************** display_diff(const svn_log_entry_t *log_
+*** 125 ****
+! SVN_ERR(svn_client_diff_peg6(diff_options,
+--- 129 ----
+! SVN_ERR(svn_client_diff_peg7(diff_options,
+*************** display_diff(const svn_log_entry_t *log_
+*** 142 ****
+--- 147 ----
++ invoke_diff_cmd,
+*************** log_entry_receiver(void *baton,
+*** 468 ****
+--- 474 ----
++ lb->invoke_diff_cmd,
+*************** svn_cl__log(apr_getopt_t *os,
+*** 710 ****
+--- 717,721 ----
++ if (opt_state->diff.diff_cmd && opt_state->diff.diff_cmd)
++ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
++ _("'diff-cmd' and 'invoke-diff-cmd' options are "
++ "mutually exclusive"));
++
+*************** svn_cl__log(apr_getopt_t *os,
+*** 727 ****
+--- 742,746 ----
++ if (opt_state->diff.invoke_diff_cmd && (! opt_state->show_diff))
++ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
++ _("'invoke-diff-cmd' option requires 'diff' "
++ "option"));
++
+*************** svn_cl__log(apr_getopt_t *os,
+*** 790 ****
+--- 810 ----
++ lb.invoke_diff_cmd = opt_state->diff.invoke_diff_cmd;
+
+================================================================================
+
+*** /home/g/trunk/subversion/svnlook/svnlook.c 2013-09-24 21:40:37.690757727 +0100
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/svnlook/svnlook.c 2013-10-24 16:04:38.939829801 +0100
+*************** enum
+*** 102 ****
+--- 103 ----
++ svnlook__invoke_diff_cmd,
+*************** static const apr_getopt_option_t options
+*** 137 ****
+--- 139,141 ----
++ {"invoke-diff-cmd", svnlook__invoke_diff_cmd, 1,
++ N_("Customizable diff command (see svn help diff)")},
++
+*************** static const svn_opt_subcommand_desc2_t
+*** 227 ****
+! svnlook__ignore_properties, svnlook__properties_only} },
+--- 231,232 ----
+! svnlook__ignore_properties, svnlook__properties_only,
+! svnlook__invoke_diff_cmd} },
+*************** struct svnlook_opt_state
+*** 332 ****
+--- 338 ----
++ const char *invoke_diff_cmd; /* --invoke-diff-cmd */
+*************** typedef struct svnlook_ctxt_t
+*** 355 ****
+--- 362 ----
++ const char *invoke_diff_cmd;
+*************** print_diff_tree(svn_stream_t *out_stream
+*** 947 ****
+! if (c->diff_cmd)
+--- 954 ----
+! if (c->diff_cmd || c->invoke_diff_cmd)
+*************** print_diff_tree(svn_stream_t *out_stream
+*** 1001 ****
+--- 1009 ----
++ if (c->diff_cmd)
+*************** print_diff_tree(svn_stream_t *out_stream
+*** 1009 ****
+--- 1018,1033 ----
++ else if (c->invoke_diff_cmd)
++ SVN_ERR(svn_io_run_external_diff(".",
++ orig_label,
++ new_label,
++ orig_path,
++ new_path,
++ &exitcode,
++ outfile,
++ errfile,
++ c->invoke_diff_cmd,
++ pool));
++
++ SVN_ERR(svn_io_file_close(outfile, pool));
++ SVN_ERR(svn_io_file_close(errfile, pool));
++
++
+*************** get_ctxt_baton(svnlook_ctxt_t **baton_p,
+*** 2093 ****
+--- 2118 ----
++ baton->invoke_diff_cmd = opt_state->invoke_diff_cmd;
+*************** main(int argc, const char *argv[])
+*** 2611 ****
+--- 2636,2639 ----
++ case svnlook__invoke_diff_cmd:
++ opt_state.invoke_diff_cmd = opt_arg;
++ break;
++
+*************** main(int argc, const char *argv[])
+*** 2636 ****
+--- 2665,2671 ----
++
++ /* The --diff-cmd and --invoke-diff-cmd options may not co-exist. */
++ if (opt_state.diff_cmd && opt_state.invoke_diff_cmd)
++ SVN_INT_ERR(svn_error_create
++ (SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
++ _("Cannot use the '--diff-cmd' option with the "
++ "'--invoke-diff-cmd' option")));
+
+================================================================================
+
+*** /home/g/trunk/subversion/svn/svn.c 2013-09-24 21:40:35.782748266 +0100
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/svn/svn.c 2013-11-06 19:25:49.027181601 +0000
+*************** typedef enum svn_cl__longopt_t {
+*** 85 ****
+--- 86 ----
++ opt_invoke_diff_cmd,
+*************** const apr_getopt_option_t svn_cl__option
+*** 346 ****
+--- 348,375 ----
++ {"invoke-diff-cmd", opt_invoke_diff_cmd, 1,
++ N_("use ARG as format string for external diff command\n"
++ " "
++ "invocation.\n"
++ " "
++ "The following reserved keywords are replaced:\n"
++ " "
++ " %svn_new -- new file\n"
++ " "
++ " %svn_old -- old file\n"
++ " "
++ " %svn_label_new -- label of the new file\n"
++ " "
++ " %svn_label_old -- label of the old file\n"
++ " "
++ "Examples:\n"
++ " "
++ "--invoke-diff-cmd=\'diff -y %svn_new %svn_old\'\n"
++ " "
++ "--invoke-diff-cmd=\"kdiff3 -auto -o /home/u/log \\\n"
++ " "
++ " %svn_new %svn_old --L1 %svn_label_new \\\n"
++ " "
++ " --L2 \"Custom Label\" \'\n"
++ " "
++ "Reserved keywords may be embedded in strings:\n"
++ " "
++ "+%svn_new %svn_new- and file=%svn_label_new+")},
+*************** const svn_opt_subcommand_desc2_t svn_cl_
+*** 613 ****
+! opt_force, opt_xml, opt_use_git_diff_format, opt_patch_compatible} },
+--- 642,643 ----
+! opt_force, opt_xml, opt_use_git_diff_format, opt_patch_compatible,
+! opt_invoke_diff_cmd} },
+*************** const svn_opt_subcommand_desc2_t svn_cl_
+*** 777 ****
+! opt_internal_diff, 'x', opt_search, opt_search_and },
+--- 807 ----
+! opt_internal_diff, 'x', opt_invoke_diff_cmd, opt_search, opt_search_and },
+*************** sub_main(int argc, const char *argv[], a
+*** 2140 ****
+--- 2171,2173 ----
++ case opt_invoke_diff_cmd:
++ opt_state.diff.invoke_diff_cmd = apr_pstrdup(pool, opt_arg);
++ break;
+*************** sub_main(int argc, const char *argv[], a
+*** 2555 ****
+! /* Disallow simultaneous use of both --diff-cmd and
+--- 2588 ----
+! /* Disallow simultaneous use of --diff-cmd, --invoke-diff-cmd and
+*************** sub_main(int argc, const char *argv[], a
+*** 2564 ****
+--- 2598,2613 ----
++ if (opt_state.diff.invoke_diff_cmd && opt_state.diff.internal_diff)
++ {
++ err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
++ _("--invoke-diff-cmd and --internal-diff "
++ "are mutually exclusive"));
++ return EXIT_ERROR(err);
++ }
++
++ if ((opt_state.diff.diff_cmd) && (opt_state.diff.invoke_diff_cmd))
++ {
++ err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
++ _("--invoke-diff-cmd and --diff-cmd "
++ "are mutually exclusive"));
++ return EXIT_ERROR(err);
++ }
++
+*************** sub_main(int argc, const char *argv[], a
+*** 2779 ****
+--- 2829,2831 ----
++ if (opt_state.diff.invoke_diff_cmd)
++ svn_config_set(cfg_config, SVN_CONFIG_SECTION_HELPERS,
++ SVN_CONFIG_OPTION_INVOKE_DIFF_CMD, opt_state.diff.invoke_diff_cmd);
+
+================================================================================
+
+*** /home/g/trunk/subversion/tests/cmdline/diff_tests.py 2013-11-04 17:30:37.880042145 +0000
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/diff_tests.py 2013-11-05 12:39:49.421954377 +0000
+*************** def diff_wrong_extension_type(sbox):
+*** 3239 ****
+--- 3240 ----
++ #----------------------------------------------------------------------
+*************** def diff_external_diffcmd(sbox):
+*** 3276 ****
+--- 3278,3324 ----
++ # Check the correct parsing of arguments for an external diff tool
++ def diff_invoke_external_diffcmd(sbox):
++ "svn diff --invoke-diff-cmd passes correct args"
++
++ diff_script_path = os.path.abspath(".")+"/diff"
++
++ svntest.main.create_python_hook_script(diff_script_path, 'import sys\n'
++ 'for arg in sys.argv[1:]:\n print(arg)\n')
++
++ if sys.platform == 'win32':
++ diff_script_path = "%s.bat" % diff_script_path
++
++ sbox.build(read_only = True)
++ os.chdir(sbox.wc_dir)
++
++ iota_path = 'iota'
++ svntest.main.file_append(iota_path, "new text in iota")
++
++ expected_output = svntest.verify.ExpectedOutput([
++ "Index: iota\n",
++ "===================================================================\n",
++ # correct label %svn_label_old -> label 1
++ "iota (revision 1)\n",
++
++ # correct file %svn_old -> old
++ os.path.abspath(svntest.wc.text_base_path("iota")) + "\n",
++
++ # correct label %svn_label_new -> label 2
++ "iota (working copy)\n",
++
++ # correct file %svn_new -> new
++ os.path.abspath("iota") + "\n",
++
++ # preservation of quoted string "X Y Z"-> "X Y Z"
++ "\"X Y Z\"\n",
++
++ # correct insertion of filename into string "+%svn_new+" -> "+" + new + "+"
++ "+" + os.path.abspath("iota") + "+\n",
++
++ ])
++
++ svntest.actions.run_and_verify_svn(None, expected_output, [],
++ 'diff',
++ '--invoke-diff-cmd='+diff_script_path+
++ ' %svn_label_old %svn_old %svn_label_new %svn_new \"X Y Z\" +%svn_new+',
++ iota_path)
++
+*************** test_list = [ None,
+*** 4724 ****
+--- 4773 ----
++ diff_invoke_external_diffcmd,
+
+================================================================================
+
+*** /home/g/trunk/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout 2013-09-24 21:40:35.638747552 +0100
+--- /home/g/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout 2013-11-06 19:26:55.291510188 +0000
+*************** Valid options:
+*** 113 ****
+--- 114,127 ----
++ --invoke-diff-cmd ARG : use ARG as format string for external diff command
++ invocation.
++ The following reserved keywords are replaced:
++ %svn_new -- new file
++ %svn_old -- old file
++ %svn_label_new -- label of the new file
++ %svn_label_old -- label of the old file
++ Examples:
++ --invoke-diff-cmd='diff -y %svn_new %svn_old'
++ --invoke-diff-cmd="kdiff3 -auto -o /home/u/log \
++ %svn_new %svn_old --L1 %svn_label_new \
++ --L2 "Custom Label" '
++ Reserved keywords may be embedded in strings:
++ +%svn_new %svn_new- and file=%svn_label_new+