Hi,

my branch has grown into a veritable forest, and so, I thought that
it would be convenient to present the net code changes in a file called
'entire-branch-code' (attached).

This is generated like so:

1) Merge trunk to branch

2) run this bash command:

svn log --stop-on-copy | grep '^*\ subversion' |\
 awk '{gsub(/^ +| +$/,"")} {print $0}' | cut -d '*' -f 2 |\
 sort --unique | while read line; do echo $line | if [ -a $line ];\
 then echo ""; echo \
"================================================================================";\
 echo "";\
 diff -p --context=0 -b -B -w "$HOME/trunk/$line" "$PWD/$line"; fi;\
 done > entire-branch-code

Is this useful?  Can this be improved?

thanks,

Gabriela
================================================================================

*** /home/g/trunk/subversion/include/svn_client.h       2013-09-24 
21:40:40.306770699 +0100
--- /home/g/branches/invoke-diff-cmd-feature/subversion/include/svn_client.h    
2013-09-26 13:50:43.967821533 +0100
*************** svn_client_blame(const char *path_or_url
*** 3023 ****
--- 3024,3028 ----
+  * @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
*** 3053 ****
--- 3059,3087 ----
+  * @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 with @a invoke_diff_cmd.
+  *
+  * @deprecated Provided for backward compatibility with the 1.8 API.
*************** svn_client_blame(const char *path_or_url
*** 3055 ****
--- 3090 ----
+ SVN_DEPRECATED
*************** svn_client_diff(const apr_array_header_t
*** 3213 ****
!  * identically to svn_client_diff6(), using @a path_or_url for both of that
--- 3248 ----
!  * identically to svn_client_diff7(), using @a path_or_url for both of that 
*************** svn_client_diff(const apr_array_header_t
*** 3216 ****
!  * All other options are handled identically to svn_client_diff6().
--- 3251 ----
!  * All other options are handled identically to svn_client_diff7().
*************** svn_client_diff(const apr_array_header_t
*** 3217 ****
--- 3253,3285 ----
+  * @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 with @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
*** 3219 ****
--- 3288 ----
+ SVN_DEPRECATED
*************** svn_client_diff_peg6(const apr_array_hea
*** 3243 ****
! /** Similar to svn_client_diff6_peg6(), but with @a outfile and @a errfile,
--- 3312,3313 ----
! /**
!  * Similar to svn_client_diff6_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-08-07 20:56:48.269221179 
+0100
--- /home/g/branches/invoke-diff-cmd-feature/subversion/include/svn_io.h        
2013-10-12 14:15:01.434000142 +0100
*************** svn_io_run_cmd(const char *path,
*** 1824,1825 ****
!  * @since New in 1.6.0.
!  */
--- 1824 ----
!  * @since New in 1.6.0. */
*************** svn_io_file_readline(apr_file_t *file,
*** 2348 ****
--- 2348,2412 ----
+ 
+ /** 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 (;l1) refers to the label of @a tmpfile1 (;f1) which is
+  *  the pristine copy.
+  *
+  *  @a label2 (;l2) refers to the label of @a tmpfile2 (;f2) 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 (;l3) refers to the label of @a base (;f3) which is
+  *  the 'base' copy.
+  *
+  *  A parse token can be escaped by prefixing a ';'.  Any other
+  *  strings containing ';' are not affected.
+  *
+  *  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 **
+ __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);
+ 
+ 
+ /** 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-08-21 15:18:31.626301687 +0100
*************** 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 {
*** 567 ****
!      svn_client_diff6(), either may be SVN_INVALID_REVNUM.  We need these
--- 567 ----
!      svn_client_diff7(), either may be SVN_INVALID_REVNUM.  We need these
*************** struct diff_cmd_baton {
*** 614 ****
--- 615,618 ----
+ 
+   /* external custom diff command */
+   const char *invoke_diff_cmd;
+ 
*************** 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_
*** 2469 ****
!       svn_config_t *cfg = svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG);
--- 2487,2490 ----
!       svn_config_t *cfg;
!       
!       cfg = svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG);
!       
*************** 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));
--- 2507,2508 ----
!     SVN_ERR(svn_path_cstring_to_utf8(&diff_cmd_baton->diff_cmd, 
!                                    diff_cmd, pool));
*************** set_up_diff_cmd_and_options(struct diff_
*** 2488 ****
--- 2510,2515 ----
+     {
+       if (config) /* check if there is a invoke_diff_cmd in the config file */
+       {
+         svn_config_t *cfg;
+           
+           cfg = svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG);
*************** set_up_diff_cmd_and_options(struct diff_
*** 2489 ****
--- 2517,2526 ----
+         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_
*** 2494,2495 ****
!       const char **argv = NULL;
!       int argc = options->nelts;
--- 2531,2535 ----
!       const char **argv;
!       int argc;
! 
!       argc = options->nelts;
!       argv = NULL;
*************** set_up_diff_cmd_and_options(struct diff_
*** 2502 ****
!                       APR_ARRAY_IDX(options, i, const char *), pool));
--- 2543,2545 ----
!                                             APR_ARRAY_IDX(options, i, 
!                                                           const char *), 
!                                             pool));
*************** svn_error_t *
*** 2555 ****
! svn_client_diff6(const apr_array_header_t *options,
--- 2598 ----
! svn_client_diff7(const apr_array_header_t *options,
*************** svn_client_diff6(const apr_array_header_
*** 2573 ****
--- 2617 ----
+                  const char *invoke_diff_cmd,
*************** svn_client_diff6(const apr_array_header_
*** 2590 ****
--- 2635 ----
+   diff_cmd_baton.invoke_diff_cmd = invoke_diff_cmd;
*************** svn_error_t *
*** 2622 ****
! svn_client_diff_peg6(const apr_array_header_t *options,
--- 2667 ----
! svn_client_diff_peg7(const apr_array_header_t *options,
*************** svn_client_diff_peg6(const apr_array_hea
*** 2640 ****
--- 2686 ----
+                      const char *invoke_diff_cmd,
*************** svn_client_diff_peg6(const apr_array_hea
*** 2653 ****
--- 2700 ----
+   diff_cmd_baton.invoke_diff_cmd = invoke_diff_cmd;

================================================================================

*** /home/g/trunk/subversion/libsvn_subr/config_file.c  2013-07-12 
22:06:43.862072458 +0100
--- 
/home/g/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/config_file.c   
    2013-08-21 15:12:45.828586973 +0100
*************** svn_config_ensure(const char *config_dir
*** 1120 ****
--- 1121,1125 ----
+         "### 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 = \"diff -y --label ;l1 ;f1 --label ;l2 ;f2\""    
NL

================================================================================


================================================================================

*** /home/g/trunk/subversion/libsvn_subr/io.c   2013-10-12 21:38:58.478086111 
+0100
--- /home/g/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/io.c        
2013-10-12 16:52:34.768876699 +0100
*************** svn_io_run_cmd(const char *path,
*** 3029,3034 ****
! 
! svn_error_t *
! svn_io_run_diff2(const char *dir,
!                  const char *const *user_args,
!                  int num_user_args,
!                  const char *label1,
--- 3029,3030 ----
! const char **
! __create_custom_diff_cmd(const char *label1,
*************** svn_io_run_diff2(const char *dir,
*** 3035 ****
--- 3032 ----
+                          const char *label3,
*************** svn_io_run_diff2(const char *dir,
*** 3038,3041 ****
!                  int *pexitcode,
!                  apr_file_t *outfile,
!                  apr_file_t *errfile,
!                  const char *diff_cmd,
--- 3035,3036 ----
!                          const char *base,
!                          const char *cmd,
*************** svn_io_run_diff2(const char *dir,
*** 3044,3048 ****
!   const char **args;
!   int i;
!   int exitcode;
!   int nargs = 4; /* the diff command itself, two paths, plus a trailing NULL 
*/
!   apr_pool_t *subpool = svn_pool_create(pool);
--- 3039,3042 ----
!   /* 
!      This function can be tested with:
!      /subversion/tests/cmdline/diff_tests.py diff_invoke_external_diffcmd
!   */
*************** svn_io_run_diff2(const char *dir,
*** 3050,3051 ****
!   if (pexitcode == NULL)
!     pexitcode = &exitcode;
--- 3044,3047 ----
!   apr_array_header_t *words;
!   const char ** result;
!   size_t argv, item, i, delimiters = 6;
!   apr_pool_t *scratch_pool = svn_pool_create(pool); 
*************** svn_io_run_diff2(const char *dir,
*** 3053,3056 ****
!   if (user_args != NULL)
!     nargs += num_user_args;
!   else
!     nargs += 1; /* -u */
--- 3049,3061 ----
!   struct replace_tokens_tab
!   {
!     const char *delimiter;
!     const char *replace;
!   } tokens_tab[] = { 
!     { ";l1", label1 },
!     { ";l2", label2 },
!     { ";l3", label3 },
!     { ";f1", from },  
!     { ";f2", to },    
!     { ";f3", base },    
!     { NULL, NULL }
!   };
*************** svn_io_run_diff2(const char *dir,
*** 3058,3061 ****
!   if (label1 != NULL)
!     nargs += 2; /* the -L and the label itself */
!   if (label2 != NULL)
!     nargs += 2; /* the -L and the label itself */
--- 3063 ----
!   words = svn_cstring_split(cmd, " ", TRUE, scratch_pool);
*************** svn_io_run_diff2(const char *dir,
*** 3063 ****
!   args = apr_palloc(subpool, nargs * sizeof(char *));
--- 3065,3066 ----
!   result = apr_palloc(pool, 
!                       (words->nelts+1) * words->elt_size * sizeof(char *) );
*************** svn_io_run_diff2(const char *dir,
*** 3065,3066 ****
!   i = 0;
!   args[i++] = diff_cmd;
--- 3068,3070 ----
!   for (item = 0, argv = 0; item < words->nelts; argv++, item++)
!     {
!       svn_stringbuf_t *word;
*************** svn_io_run_diff2(const char *dir,
*** 3068 ****
!   if (user_args != NULL)
--- 3072,3076 ----
!       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_io_run_diff2(const char *dir,
*** 3070,3072 ****
!       int j;
!       for (j = 0; j < num_user_args; ++j)
!         args[i++] = user_args[j];
--- 3078,3090 ----
!           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;
*************** svn_io_run_diff2(const char *dir,
*** 3075,3077 ****
-     args[i++] = "-u"; /* assume -u if the user didn't give us any args */
- 
-   if (label1 != NULL)
--- 3092 ----
*************** svn_io_run_diff2(const char *dir,
*** 3079,3080 ****
!       args[i++] = "-L";
!       args[i++] = label1;
--- 3094,3095 ----
!                   svn_stringbuf_appendcstr(complete, " ");
!                   item++;
*************** svn_io_run_diff2(const char *dir,
*** 3082 ****
!   if (label2 != NULL)
--- 3097,3114 ----
!             }
!         }
! 
!       for (i = 0; i < delimiters; i++)
!         {
!           char *found = strstr(word->data, tokens_tab[i].delimiter);
!           int len;
! 
!           if (!found)
!             continue;
!             
!           len = word->len - strlen(found) - 1;
!             
!           /* if we find a protective semi-colon in front of this, consume it 
*/
!           if ( (len >= 0) 
!                && (word->data[len] == ';') )
!             svn_stringbuf_remove(word, len, 1);
!           else
*************** svn_io_run_diff2(const char *dir,
*** 3084,3085 ****
!       args[i++] = "-L";
!       args[i++] = label2;
--- 3116,3120 ----
!               svn_stringbuf_replace(word, found - word->data,
!                                     strlen(tokens_tab[i].delimiter),
!                                     tokens_tab[i].replace,
!                                     strlen(tokens_tab[i].replace));
!               i = delimiters;
*************** svn_io_run_diff2(const char *dir,
*** 3086 ****
--- 3122,3125 ----
+         }
+       result[argv] = word->data;
+     }  
+   result[argv] = NULL;
*************** svn_io_run_diff2(const char *dir,
*** 3088,3090 ****
!   args[i++] = svn_dirent_local_style(from, subpool);
!   args[i++] = svn_dirent_local_style(to, subpool);
!   args[i++] = NULL;
--- 3127,3129 ----
!   svn_pool_destroy(scratch_pool);
!   return result;
! }
*************** svn_io_run_diff2(const char *dir,
*** 3092 ****
!   SVN_ERR_ASSERT(i == nargs);
--- 3131,3144 ----
! 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;
*************** svn_io_run_diff2(const char *dir,
*** 3094,3095 ****
!   SVN_ERR(svn_io_run_cmd(dir, diff_cmd, args, pexitcode, NULL, TRUE,
!                          NULL, outfile, errfile, subpool));
--- 3146,3147 ----
!   if (0 == strlen(external_diff_cmd)) 
!      return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, NULL);
*************** svn_io_run_diff2(const char *dir,
*** 3097 ****
!   /* The man page for (GNU) diff describes the return value as:
--- 3149,3153 ----
!   cmd = __create_custom_diff_cmd(label1, label2, NULL, 
!                                  tmpfile1, tmpfile2, NULL, 
!                                  external_diff_cmd, pool);
!   if (pexitcode == NULL)
!      pexitcode = &exitcode;
*************** svn_io_run_diff2(const char *dir,
*** 3099,3100 ****
!        "An exit status of 0 means no differences were found, 1 means
!         some differences were found, and 2 means trouble."
--- 3155,3156 ----
!   SVN_ERR(svn_io_run_cmd(dir, cmd[0], cmd, pexitcode, NULL, TRUE,
!                          NULL, outfile, errfile, pool));
*************** svn_io_run_diff2(const char *dir,
*** 3102,3106 ****
-      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.
-    */
--- 3157 ----
*************** svn_io_run_diff2(const char *dir,
*** 3107 ****
--- 3159,3166 ----
+     {
+       int i;
+       const char *failed_command = "";
+ 
+       for (i = 0; cmd[i]; ++i)
+           failed_command = apr_pstrcat(pool, failed_command, 
+                                        cmd[i], " ", (char*) NULL);
+ 
*************** svn_io_run_diff2(const char *dir,
*** 3109,3110 ****
!                              _("'%s' returned %d"),
!                              svn_dirent_local_style(diff_cmd, pool),
--- 3168,3170 ----
!                                _("'%s' was expanded to '%s' and returned %d"),
!                                external_diff_cmd,
!                                failed_command,
*************** svn_io_run_diff2(const char *dir,
*** 3111 ****
--- 3172,3174 ----
+     }
+   return SVN_NO_ERROR;
+ }
*************** svn_io_run_diff2(const char *dir,
*** 3113 ****
!   svn_pool_destroy(subpool);
--- 3176,3197 ----
! svn_error_t *
! svn_io_run_diff2(const char *dir,
!                  const char *const *user_args,
!                  int num_user_args,
!                  const char *label1,
!                  const char *label2,
!                  const char *from,
!                  const char *to,
!                  int *pexitcode,
!                  apr_file_t *outfile,
!                  apr_file_t *errfile,
!                  const char *diff_cmd,
!                  apr_pool_t *pool)
! {
!   /* 
!   This function can be tested by using the test 
!   /subversion/tests/cmdline/diff_tests.py diff_external_diffcmd
!   */
!   svn_stringbuf_t *com;
!   com = svn_stringbuf_create_empty(pool);
!   svn_stringbuf_appendcstr(com, diff_cmd);
!   svn_stringbuf_appendcstr(com, " ");
*************** svn_io_run_diff2(const char *dir,
*** 3115 ****
!   return SVN_NO_ERROR;
--- 3199,3206 ----
!   if (user_args != NULL)
!     {
!       int j;
!       for (j = 0; j < num_user_args; ++j) 
!         {
!           svn_stringbuf_appendcstr(com, user_args[j]);
!           svn_stringbuf_appendcstr(com, " ");
!         }
*************** svn_io_run_diff2(const char *dir,
*** 3116 ****
--- 3208,3209 ----
+   else /* assume -u if the user didn't give us any args */
+     svn_stringbuf_appendcstr(com, "-u "); 
*************** svn_io_run_diff2(const char *dir,
*** 3117 ****
--- 3211,3229 ----
+   if (label1 != NULL)
+     svn_stringbuf_appendcstr(com,"-L ;l1 ");
+ 
+   if (label2 != NULL)
+     svn_stringbuf_appendcstr(com,"-L ;l2 ");
+ 
+   svn_stringbuf_appendcstr(com,";f1 ;f2 "); 
+ 
+   return svn_io_run_external_diff(dir,
+                                   label1,
+                                   label2,
+                                   from,
+                                   to,
+                                   pexitcode,
+                                   outfile,
+                                   errfile,
+                                   com->data,
+                                   pool);
+ }

================================================================================

*** /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-09-26 13:50:36.815786068 +0100
*************** 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-09-26 13:50:47.043836786 +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-10-12 14:55:38.646085624 +0100
*************** typedef enum svn_cl__longopt_t {
*** 85 ****
--- 86 ----
+   opt_invoke_diff_cmd,
*************** const apr_getopt_option_t svn_cl__option
*** 346 ****
--- 348,374 ----
+   {"invoke-diff-cmd",      opt_invoke_diff_cmd, 1, 
+                    N_("use ARG as format string for external diff command\n"
+                       "                             "
+                       "invocation. \n                                         
\n" 
+                       "                             "
+                       "Substitutions: ;f1 original file                       
\n"
+                       "                             "
+                       "               ;f2 changed file                        
\n"
+                       "                             "
+                       "               ;l1 label of the original file          
\n"
+                       "                             "
+                       "               ;l2 label of the changed file           
\n"
+                       "                             "
+                       "Examples: --invoke-diff-cmd=\"diff -y ;f1 ;f2\"        
\n"          
+                       "                             "
+                       "   --invoke-diff-cmd=\"kdiff3 -auto -o /home/u/log \\  
\n"
+                       "                             "
+                       "     +;f1 ;l2 --L1 ;l1 --L2 \"Custom Label\" \"        
\n"
+                       "                             "
+                       "The delimiter ';' can be escaped by adding a ';', 
which\n"
+                       "                             "
+                       "will be consumed in the process.  The delimiter can    
\n"
+                       "                             "
+                       "appear anywhere in the string, ie, file=;f1 will 
expand\n"
+                       "                             "
+                       "as expected and file=;;f1 will be rendered as 
file=;f1.\n"
+      )},
*************** const svn_opt_subcommand_desc2_t svn_cl_
*** 613 ****
!      opt_force, opt_xml, opt_use_git_diff_format, opt_patch_compatible} },
--- 641,642 ----
!      opt_force, opt_xml, opt_use_git_diff_format, opt_patch_compatible,
!      opt_invoke_diff_cmd} },
*************** sub_main(int argc, const char *argv[], a
*** 2140 ****
--- 2170,2172 ----
+       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,2556 ****
!   /* Disallow simultaneous use of both --diff-cmd and
!      --internal-diff.  */
--- 2587,2588 ----
!   /* Disallow simultaneous use of both --diff-cmd, --invoke-diff-cmd
!      and --internal-diff.  */
*************** sub_main(int argc, const char *argv[], a
*** 2564 ****
--- 2597,2612 ----
+   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 ****
--- 2828,2830 ----
+   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-08-21 
14:38:53.038506909 +0100
--- 
/home/g/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/diff_tests.py 
    2013-10-12 14:34:04.175666692 +0100
*************** def diff_wrong_extension_type(sbox):
*** 3225 ****
--- 3226 ----
+ #----------------------------------------------------------------------
*************** def diff_external_diffcmd(sbox):
*** 3262 ****
--- 3264,3312 ----
+ # 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 ;l1 -> label 1
+       "iota   (revision 1)\n",   
+ 
+       # correct file ;f1 -> file1
+       os.path.abspath(svntest.wc.text_base_path("iota")) + "\n",
+ 
+       # correct label ;l2 -> label 2
+       "iota   (working copy)\n",
+ 
+       # correct file ;f2 -> file2
+       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 "+;f2+" -> "+" + file2 + "+"
+       "+" + os.path.abspath("iota") + "+\n",
+ 
+       # removal of protective ';' ";;f1" -> ";f1"
+       ";f1\n",
+       ])
+   
+   svntest.actions.run_and_verify_svn(None, expected_output, [],
+    'diff',
+    '--invoke-diff-cmd='+diff_script_path+
+    ' ;l1 ;f1 ;l2 ;f2 \"X Y Z\" +;f2+ ;;f1',
+   iota_path)
+ 
*************** test_list = [ None,
*** 4690 ****
--- 4741 ----
+               diff_invoke_external_diffcmd,

Reply via email to