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+