subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From g..@apache.org
Subject svn commit: r1542514 [2/3] - in /subversion/branches/invoke-diff3-feature: ./ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_subr/ subversion/libsvn_wc/ subversion/svn/ subversion/tests/cmdline/getopt_tests_...
Date Sat, 16 Nov 2013 14:36:47 GMT

Modified: subversion/branches/invoke-diff3-feature/BRANCH-README
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/BRANCH-README?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/BRANCH-README (original)
+++ subversion/branches/invoke-diff3-feature/BRANCH-README Sat Nov 16 14:36:46 2013
@@ -1,4 +1,11 @@
-This branch implements the 'invoke-diff-cmd' feature and is located at 
+This branch implements the 'invoke-diff3-cmd' feature and is located
+at:
+
+https://svn.apache.org/repos/asf/subversion/branches/invoke-diff3-feature/
+
+It is a continuation of the invoke-diff-cmd-feature branch r1541740,
+which is located here:
+
 https://svn.apache.org/repos/asf/subversion/branches/invoke-diff-cmd-feature/
 
 It is a feature branch, receiving regular sync merges from /trunk, and
@@ -7,1259 +14,1832 @@ expected to be reintegrated back thereto
 See: http://subversion.tigris.org/issues/show_bug.cgi?id=2044 for the
 original motivation for this project.
 
+Index:
+======
 
-======================================================================
-        INVOKE-DIFF-CMD SECTION
-======================================================================
-
---invoke-diff-cmd allows command line selection of an external diff
-program and will be extended to cover the existing diff3 option with a
-similar --invoke-diff3-cmd option.
+1. Introduction
+2. What --invoke-diff3-cmd provides
+3. Structure of the feature
+   API components 
+   UI components 
+4. Changes to the existing code structure
+5. Known Problems
+6. Tests
+   Automatic tests
+   Manual tests passed
+   Working copy functionality test
+7. TODO
+8. Log messages
+9. DIFF from invoke-diff-cmd branch 1541740
 
-Currently this capability is provided by user written shell scripts
-which are passed as the diff program via the svn config file.
 
---invoke-diff-cmd is currently implemented for 'diff', 'log',
-'svnlook' and the config file.
+1. Introduction:    
+================
 
+--invoke-diff3-cmd allows command line, config file and interactive
+selection of an external diff3 program.
 
-What --invoke-diff-cmd provides
-===============================
+Currently this capability is provided by user written shell scripts
+which are passed as the merge program via the svn config file, and on
+the command line via the --diff3_cmd and the -x extensions.
 
-Users can type 'free-style' command lines for their selected
-diff/merge program, and optionally select a diff command file that
-applies stored commands to selected files.  If the file diffed is not
-in the list, the given command will be used instead.  
-
-from 'svn help diff':
-
-  --invoke-diff-cmd ARG:
-
-       use ARG as format string for external diff command     
-        invocation. 
-                    
-        Substitutions: %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_new_label \      
-             --L2 "Custom Label" '                          
-        Substitution variables may be embedded in strings:
-        +%svn_new, %svn_new- and file=%svn_label_new+
 
+2. What --invoke-diff3-cmd provides
+===================================
 
-Structure of the feature:
-=========================
+Users can type 'free-style' command lines for their selected diff3
+program, define a default command in the config file and also,
+interactively select a diff3 program during the merge conflict
+dialogue.
 
-API components 
---------------
-
-   ./subversion/libsvn_subr/io.c __create_custom_diff_cmd()
- 
-   transforms the user input 'invoke-diff-cmd' into a command line
-   call by substitution the labels and file names(where defined),
-   whilst leaving everything else untouched.  This is more of an
-   internal routine and probably not well placed in the public API.
-   It will be reused for the merge part of this project.
 
+3. Structure of the feature:
+============================
 
-   ./subversion/libsvn_subr/io.c svn_io_run_external_diff()
+API components 
+--------------
 
-   calls __create_custom_diff_cmd() and does all the error checking
-   required, before routing the result to the actual call to the APR
-   routine that makes it.
+* svn_merge5() has been deprecated to svn_merge6().
 
 
 UI components
 -------------
 
   --invoke-diff-cmd and its user interface components for the command
-  line have been installed everywhere where --diff-cmd is available,
-  in svnlook.c, svn.c, svnlog.c.
+  line have been installed everywhere where --diff-cmd is available.
+
 
   Users can specify the following mutually exclusive options:
 
-  --invoke-diff-cmd, --diff-cmd and --internal-diff-cmd, and also
-  define what diff program to use via the ./svn/config file, using the
-  new config file parameter "invoke-diff-cmd"..
-
-  The selection first defaults to the internal diff program, then to
-  the config file entry (if defined) which in turn is overridden when
-  one of --invoke-diff-cmd, --diff-cmd or --internal-diff-cmd are
-  invoked.
+  --invoke-merge-cmd, --diff3-cmd , and also define what diff3 program
+  to use via the ./svn/config file, using the new config file
+  parameter "invoke-merge-cmd"..
+
+  The selection first defaults to the config file entry (if defined)
+  which in turn is overridden when one of --invoke-diff3-cmd,
+  --diff-cmd are invoked.
+  
+  The interactive merge section has 2 new options: Interactive
+  selection of the config file define, and an input option for a
+  invoke-diff3-cmd command style instruction.
 
 
-Changes to the existing code structure:
-=======================================
+4. Changes to the existing code structure:
+==========================================
 
 None.
 
-The existing --diff-cmd has been in use for years and is best left
+The existing --diff3-cmd has been in use for years and is best left
 untouched, since many users will not require the extra services
-offered by the --invoke-diff-cmd feature, and any errors could cause
+offered by the --invoke-diff3-cmd feature, and any errors could cause
 many users a lot of problems.  
 
-Moreover, the nature of --invoke-diff-cmd and --diff-cmd are quite
-different; --diff-cmd is tailored for GNU diff and carefully checks the
-user's input of switches, whereas --invoke-diff-cmd is a
+Moreover, the nature of --invoke-diff3-cmd and --diff-cmd are quite
+different; --diff-3 is tailored for GNU diff3 and carefully checks the
+user's input of switches, whereas --invoke-diff3-cmd is a
 free-style-anything-goes-including-shooting-your-foot creation.
 
 
-Tests
-=====
+Known Problems
+==============
+
+The error trace back in subversion/svn/conflict-callbacks.c is
+defective in general since the response to a user error is 'traced
+call' instead of the actual error being displayed.  I've kept the
+current shape to match the 'l' option, since I think that is a
+seperate bug outside the scope of this patch.
+
+see line 902 ('l' option)
+and line 940 ('i' option)
+
+Merge of 'subversion/libsvn_client/diff.c' aborted.
+Select: (p) postpone, (df) show diff, (e) edit file, (m) merge,
+        (i) interactive invoke-diff3-cmd selection,
+        (mc) my side of conflict, (tc) their side of conflict,
+        (s) show all options: l
+l
+traced call
+Select: (p) postpone, (df) show diff, (e) edit file, (m) merge,
+        (i) interactive invoke-diff3-cmd selection,
+        (mc) my side of conflict, (tc) their side of conflict,
+        (s) show all options: i
+i
+Enter the invoke-diff3-cmd: flobble
+flobble
+traced call
+Select: (p) postpone, (df) show diff, (e) edit file, (m) merge,
+        (i) interactive invoke-diff3-cmd selection,
+        (mc) my side of conflict, (tc) their side of conflict,
+        (s) show all options: 
+
+
+6. Tests
+========
+
+Automatic tests
+---------------
+
+I could not find a pre-existing test for the --diff3-cmd option and so
+I omitted writing an automated test for now.  
+
+
+Manual tests passed
+-------------------
+
+* config file selection '--invoke-diff3-cmd' invocation works.
+  overrides interactive invoke-diff3-cmd selection.
 
-The test for the 'invoke-diff-cmd' feature is
+* --invoke-diff3-cmd commandline invocation works.
+  overrides config file selection.
 
-  /subversion/tests/cmdline/diff_tests.py diff_invoke_external_diffcmd
+* interactive --invoke-diff3-cmd commandline invocation works.
 
+* --diff3-cmd and --invoke-diff3-cmd mututally exclusive.
 
 
-Log messages 
-=============
+Working copy functionality test
+-------------------------------
 
-* subversion/include/private/svn_io_private.h
+Create a suitable conflict to test the UI part of the feature:
+       
+    mkdir conflict
+    svn co -r r1526439  https://svn.apache.org/repos/asf/subversion/trunk/ trunk
+    svn co -r r1502389 https://svn.apache.org/repos/asf/subversion/branches//invoke-diff-cmd-feature branch
+    cd branch
+    svn /home/g/conflict/trunk 
+    revert -R .
 
-  (svn_io__create_custom_diff_cmd): New function declaration.
+The above produces 2 conflicts using the native svn merge command, and
+30 conflicts when kdiff3 is used.
 
+$ kdiff3 --version
+Qt: 4.8.4
+KDE Development Platform: 4.10.5
+kdiff3: 0.9.97 (32 bit)
 
-* 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.
+7. TODO:
+========
 
-  (svn_client_diff6, svn_client_diff_peg_6): Deprecate. 
+ * Dear Reviwer: please ensure I got the left and right merges the
+   correct way round.  I think I have, but given that the left thumb
+   points to where the right hand is... %-)
+
+ * Decide which smiley character to choose: ./subversion/svn/conflict-callbacks.c:122
+
+
+8. Log messages
+===============
+
+* BRANCH-README
+  (*)  Description of Branch.
+
+
+* subversion/include/private/svn_wc_private.h
+
+  (svn_wc__get_file_external_editor,
+  (svn_wc__get_update_editor,
+  (svn_wc__get_switch_editor): New parameter:
+     const char *invoke_diff3_cmd.
 
 
 * subversion/include/svn_config.h
 
-  (SVN_CONFIG_OPTION_INVOKE_DIFF_CMD): New definition.
+  (): New definition: SVN_CONFIG_OPTION_INVOKE_DIFF3_CMD.
 
 
 * subversion/include/svn_error_codes.h
 
-  (SVN_CLIENT_DIFF_CMD): New macro.
+  (command-line client errors): New definition:
+    SVN_ERR_CL_NO_EXTERNAL_DIFF3_TOOL.
 
+  (SVN_ERR_CL_ERROR_PROCESSING_EXTERNALS): Adjust numbering in order
+    to retain a logical grouping.
 
 * subversion/include/svn_io.h
 
-   (svn_io_run_external_diff): New function.
+  (svn_io_run_invoke_diff3): New function.
+
+
+* subversion/include/svn_wc.h
+ 
+  (svn_wc_merge6):  New function.
+
+  (svn_wc_merge5):  Deprecate.
+  
 
+* subversion/libsvn_client/externals.c
 
-* subversion/libsvn_client/deprecated.c
+  (switch_file_external): New variable: const char *invoke_diff3_cmd.
+    Initialize diff3_cmd to NULL.  Add precedence logic and read the
+    config file to populate invoke_diff3_cmd.  Add invoke_diff3_cmd in
+    call to svn_wc__get_file_external_editor().
 
-  (svn_client_diff6, svn_client_diff_peg6): New deprecation wrappers.
 
+* subversion/libsvn_client/merge.c
 
-* subversion/libsvn_client/diff.c
+  (merge_cmd_baton_t): New member *invoke_diff3_cmd.  Adjust comment.
 
-  (*): Update all comments mentioning 'svn_client_diff6' to
-    'svn_client_diff7'.
+  (merge_file_changed): Replace call to svn_wc_merge5 with call to
+    svn_wc_merge6.
 
-  (diff_cmd_baton): New member: 'invoke_diff_cmd'. 
+  (do_merge): New variable: const char *invoke_diff3_cmd. Initialize
+    diff3_cmd to NULL.  Adjust comment. Add precedence logic and read
+    the config file to populate invoke_diff3_cmd. Add invoke_diff3_cmd
+    to merge_baton.
 
-  (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.
 
-  (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.
+* subversion/libsvn_client/switch.c
 
-  (svn_client_diff_peg_7): Rename and update from
-    svn_client_diff_peg_6.  Add new parameter: invoke_diff_cmd.
+  (switch_internal): New variable: const char *invoke_diff3_cmd.  Add
+    precedence logic and read the config file to populate
+    invoke_diff3_cmd.  Add invoke_diff3_cmd in call to
+    svn_wc__get_switch_editor().
 
-  (svn_client_diff7): Rename and update from svn_client_diff6, add
-    new parameter 'invoke_diff_cmd'.  
 
+* subversion/libsvn_client/update.c
 
-* subversion/libsvn_subr/config_file.c
+  (update_internal): Initialize diff3_cmd to NULL.  New variable:
+    *invoke_diff3_cmd.  Adjust comment, add precedence logic and read
+    the config file to populate invoke_diff3_cmd.  Add
+    invoke_diff3_cmd in call to svn_wc__get_update_editor().
 
-  (svn_config_ensure,"invoke-diff-cmd"): New entry: invoke-diff-cmd.
-    Add help info.
+
+* subversion/libsvn_subr/config_file.c 
+ 
+  (svn_config_ensure): Add entry for invoke-diff3-cmd.
 
 
 * subversion/libsvn_subr/io.c
 
-  (svn_io__create_custom_diff_cmd): New function.
+  (svn_io_run_invoke_diff3): New function.
 
-  (svn_io_run_external_diff): New function.
 
-  (svn_io_run_diff2):  Add test location information.
+* subversion/libsvn_wc/deprecated.c
 
+  (svn_wc_get_update_editor4): Add invoke-diff3-cmd as NULL to call to
+    svn_wc__get_update_editor().
 
-* subversion/svn/cl.h
+  (svn_wc_get_switch_editor4): Add invoke-diff3-cmd as NULL to call to
+    svn_wc__get_switch_editor().
 
-  (struct svn_cl__opt_state_t.diff): New member: 'invoke_diff_cmd'.
+  (svn_wc_merge5): New  function.
 
 
-* subversion/svn/diff-cmd.c
+* subversion/libsvn_wc/externals.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.
+  (struct edit_baton): Rename diff3cmd to diff3_cmd.  New member
+    variable: const char *invoke_diff3_cmd.
 
+  (close_file): Rename diff3cmd to diff3_cmd and add invoke_diff3_cmd
+    in call to svn_wc__perform_file_merge().
 
-* subversion/svn/log-cmd.c
+  (svn_wc__get_file_external_editor): New parameter: const char
+    *invoke_diff3_cmd.  Rename diff3cmd to diff3_cmd in eb
+    assignment and assign invoke_diff3_cmd to struct edit_baton eb.
 
-  (log_receiver_baton): New struct member invoke_diff_cmd.
 
-  (display_diff): New parameter 'invoke_diff_cmd' . Update call to
-    svn_client_peg_diff7.  Pass invoke_diff_cmd parameter into
-    svn_client_diff_peg7().
+* subversion/libsvn_wc/merge.c 
 
-  (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.
+  (merge_target_t): Adjust comment for old_actual_props.  New member
+    variable: invoke_diff3_cmd.
 
+  (do_text_merge_external): New parameter: const char
+    invoke_diff3_cmd.  Add if condition to route call to newly added
+    svn_io_run_invoke_diff3().  Add clarifying braces around
+    A = (B == C) type assignment.
 
-* subversion/svnlook/svnlook.c
+  (merge_text_file): Adjust if condition to route call to
+    do_text_merge_external() and add invoke_diff3_cmd to call to
+    do_text_merge_external().
 
-  (enum): New variable svnlook__invoke_diff_cmd.
+  (svn_wc__internal_merge): New parameter: const char
+    *invoke_diff3_cmd.  Assign invoke_diff3_cmd to mt. Add
+    invoke_diff3_cmd as a conditional variable in to call to
+    detranslate_wc_file().
 
-  (options_table[]): New entry 'invoke-diff-cmd'.
+  (svn_wc_merge6): Declare new API.
 
-  (cmd_tablcmd[]): Add svnlook__invoke_diff_cmd to diff cmd table
-    entry.
 
-  (svnlook_opt_state): New member variable "invoke_diff_cmd".
+* subversion/libsvn_wc/update_editor.c
 
-  (svnlook_ctxt_t): New member variable "invoke_diff_cmd".
+  (struct edit_baton): New member const char *invoke_diff3_cmd.
 
-  (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().
+  (svn_wc__perform_file_merge): New parameter: const char
+    *invoke_diff3_cmd.  Add invoke_diff3_cmd to
+    svn_wc__internal_merge(). 
 
-  (get_ctxt_baton): Assign invoke_diff_cmd data.
+  (merge_file): Add invoke_diff3_cmd to svn_wc__internal_merge().
 
-  (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.
+  (make_editor): New parameter: const char *invoke_diff3_cmd.  Assign
+    invoke_diff3_cmd to eb.
 
+  (svn_wc__get_update_editor, svn_wc__get_switch_editor): New
+    parameter: const char *invoke_diff3_cmd. Add invoke_diff3_cmd to
+    call to make_editor().
 
-* subversion/svn/svn.c
 
-  (svn_cl__longopt_t): New enum opt_invoke_diff_cmd.              
- 
-  (svn_cl__options "invoke-diff-cmd"): Add help information.  Add new
-    variable 'opt_invoke_diff_cmd'.
+* subversion/libsvn_wc/wc.h
 
-  (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.
+  (svn_wc__internal_merge): Adjust function comment.  New parameter:
+    const char *invoke_diff3_cmd.  Add newline to conform to general
+    formatting in this file.
 
+  (svn_wc__perform_file_merge): New parameter: const char
+    *invoke_diff3_cmd.
 
-  (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_wc/wc_db_update_move.c
 
-* subversion/tests/cmdline/diff_tests.py
+  (update_working_file): Add invoke_diff3_cmd in call to
+    svn_wc__perform_file_merge() as NULL.  Adjust other comments for
+    neatness.
 
-  (diff_invoke_external_diffcmd): New function.
 
-  (test_list): Add new entry 'diff_invoke_external_diffcmd'.
+* subversion/svn/cl.h
 
+  (svn_cl__accept_t): New commented member:
+    svn_cl__accept_invoke_diff3_config.
+  
+  ():  New definition: SVN_CL__ACCEPT_INVOKE_DIFF3_CONFIG.
 
-* subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
+  (svn_cl__opt_state_t): New member const char* invoke_diff3_cmd.
 
-  (--invoke-diff-cmd): Add new entry to 'help' output data.
+  (svn_cl__invoke_diff3_cmd_externally): New function.
 
 
-Diff file for this branch
-=========================
+* subversion/svn/conflict-callbacks.c
 
-*** /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);
-+ 
-+ 
+  (svn_cl__accept_from_word): Add SVN_CL__ACCEPT_INVOKE_DIFF3_CONFIG
+    to if condition returns svn_cl__accept_launch.
 
-================================================================================
+  (invoke_diff3_resolver): New routing function that calls
+    svn_cl__invoke_diff3_cmd_externally().
 
-*** /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")
-+ 
+  (text_conflict_options): Add "3f" option for invoke-diff3-cmd tool
+    selection and add 'i' option for interactive invoke-diff3-cmd
+    input.
 
-================================================================================
+  (handle_text_conflict): Add interactive selection code for
+    invoke-diff3-cmd input ("i" section) and invoke-diff3-cmd tool
+    ("3f" section) to if condition.  Add '3f' and 'i' to next_option.
+    Adjust general indentation(2 entries). 
 
-*** /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
-+   */
-+ 
+  (conflict_func_interactive): Add cases for "i" and "3f" selection.
+    Adjust general indentation.  Add case
+    'svn_cl__accept_invoke_diff3_config'.
 
-================================================================================
 
-*** /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 "
+* subversion/svn/svn.c
+
+  (svn_cl__longopt_t): New member 'opt_diff3_cmd'.
+
+  (svn_cl__options): Add 'invoke-diff3-cmd' entry plus help text.
+
+  (svn_cl__cmd_table,"cleanup","merge","switch","update"): Add
+    opt_invoke_diff3_cmd.
+
+  (sub_main): Add case opt_invoke_diff3_cmd.  Ensure murutal
+    exclusiveness of diff3-cmd and invoke-diff3-cmd.  Add call to
+    svn_config_set().  Add error check for
+    svn_cl__accept_invoke_diff3_config.
+
+
+* subversion/svn/util.c
+
+  (): Include svn_io_private.h
+
+  (svn_cl__invoke_diff3_cmd_externally): New function.
+
+
+* subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
+
+  (): Update help output.
+
+
+
+9. DIFF from invoke-diff-cmd branch 1541740:
+============================================
+
+Index: subversion/include/private/svn_wc_private.h
+===================================================================
+--- subversion/include/private/svn_wc_private.h	(revision 1542103)
++++ subversion/include/private/svn_wc_private.h	(working copy)
+@@ -77,6 +77,7 @@ svn_wc__get_file_external_editor(const svn_delta_e
+                                  apr_array_header_t *iprops,
+                                  svn_boolean_t use_commit_times,
+                                  const char *diff3_cmd,
++                                 const char *invoke_diff3_cmd,
+                                  const apr_array_header_t *preserved_exts,
+                                  const char *record_ancestor_abspath,
+                                  const char *recorded_url,
+@@ -1507,6 +1508,7 @@ svn_wc__get_update_editor(const svn_delta_editor_t
+                           svn_boolean_t server_performs_filtering,
+                           svn_boolean_t clean_checkout,
+                           const char *diff3_cmd,
++                          const char *invoke_diff3_cmd,
+                           const apr_array_header_t *preserved_exts,
+                           svn_wc_dirents_func_t fetch_dirents_func,
+                           void *fetch_dirents_baton,
+@@ -1549,6 +1551,7 @@ svn_wc__get_switch_editor(const svn_delta_editor_t
+                           svn_boolean_t allow_unver_obstructions,
+                           svn_boolean_t server_performs_filtering,
+                           const char *diff3_cmd,
++                          const char *invoke_diff3_cmd,
+                           const apr_array_header_t *preserved_exts,
+                           svn_wc_dirents_func_t fetch_dirents_func,
+                           void *fetch_dirents_baton,
+Index: subversion/include/svn_config.h
+===================================================================
+--- subversion/include/svn_config.h	(revision 1542103)
++++ subversion/include/svn_config.h	(working copy)
+@@ -116,6 +116,8 @@ typedef struct svn_config_t svn_config_t;
+ #define SVN_CONFIG_OPTION_DIFF3_HAS_PROGRAM_ARG     "diff3-has-program-arg"
+ /** @since New in 1.9. */
+ #define SVN_CONFIG_OPTION_INVOKE_DIFF_CMD           "invoke-diff-cmd"
++/** @since New in 1.9. */
++#define SVN_CONFIG_OPTION_INVOKE_DIFF3_CMD          "invoke-diff3-cmd"
+ #define SVN_CONFIG_OPTION_MERGE_TOOL_CMD            "merge-tool-cmd"
+ #define SVN_CONFIG_SECTION_MISCELLANY           "miscellany"
+ #define SVN_CONFIG_OPTION_GLOBAL_IGNORES            "global-ignores"
+Index: subversion/include/svn_error_codes.h
+===================================================================
+--- subversion/include/svn_error_codes.h	(revision 1542103)
++++ subversion/include/svn_error_codes.h	(working copy)
+@@ -1451,8 +1451,13 @@ SVN_ERROR_START
+              SVN_ERR_CL_CATEGORY_START + 10,
+              "No external merge tool available")
+ 
++  /** @since New in 1.9. */
++  SVN_ERRDEF(SVN_ERR_CL_NO_EXTERNAL_DIFF3_TOOL,
++             SVN_ERR_CL_CATEGORY_START + 11,
++             "No external invoke-diff3 tool available")
++
+   SVN_ERRDEF(SVN_ERR_CL_ERROR_PROCESSING_EXTERNALS,
+-             SVN_ERR_CL_CATEGORY_START + 11,
++             SVN_ERR_CL_CATEGORY_START + 12,
+              "Failed processing one or more externals definitions")
+ 
+   /* ra_svn errors */
+Index: subversion/include/svn_io.h
+===================================================================
+--- subversion/include/svn_io.h	(revision 1542103)
++++ subversion/include/svn_io.h	(working copy)
+@@ -2378,6 +2378,25 @@ svn_io_run_external_diff(const char *dir,
+                          const char *external_diff_cmd,
+                          apr_pool_t *scratch_pool);
+ 
++/** Run the external merge command defined by the invoke-diff3-cmd
++ *  option.
++ *  
++ *  @since New in 1.9.
++ */
++svn_error_t *
++svn_io_run_invoke_diff3(int *exitcode,
++                        const char *dir,
++                        const char *mine,
++                        const char *older,
++                        const char *yours,
++                        const char *mine_label,
++                        const char *older_label,
++                        const char *yours_label,
++                        apr_file_t *merged,
++                        const char *diff3_cmd,
++                        apr_pool_t *pool);
++
++
+ #ifdef __cplusplus
+ }
+ #endif /* __cplusplus */
+Index: subversion/include/svn_wc.h
+===================================================================
+--- subversion/include/svn_wc.h	(revision 1542103)
++++ subversion/include/svn_wc.h	(working copy)
+@@ -7011,6 +7011,35 @@ typedef enum svn_wc_merge_outcome_t
+  * @since New in 1.8.
+  */
+ svn_error_t *
++svn_wc_merge6(enum svn_wc_merge_outcome_t *merge_content_outcome,
++              enum svn_wc_notify_state_t *merge_props_state,
++              svn_wc_context_t *wc_ctx,
++              const char *left_abspath,
++              const char *right_abspath,
++              const char *target_abspath,
++              const char *left_label,
++              const char *right_label,
++              const char *target_label,
++              const svn_wc_conflict_version_t *left_version,
++              const svn_wc_conflict_version_t *right_version,
++              svn_boolean_t dry_run,
++              const char *diff3_cmd,
++              const char *invoke_diff3_cmd,
++              const apr_array_header_t *merge_options,
++              apr_hash_t *original_props,
++              const apr_array_header_t *prop_diff,
++              svn_wc_conflict_resolver_func2_t conflict_func,
++              void *conflict_baton,
++              svn_cancel_func_t cancel_func,
++              void *cancel_baton,
++              apr_pool_t *scratch_pool);
++
++/** Similar to svn_wc_merge6() but with @a invoke_diff3_cmd.
++ *
++ * @since New in 1.9.
++ */
++SVN_DEPRECATED
++svn_error_t *
+ svn_wc_merge5(enum svn_wc_merge_outcome_t *merge_content_outcome,
+               enum svn_wc_notify_state_t *merge_props_state,
+               svn_wc_context_t *wc_ctx,
+Index: subversion/libsvn_client/externals.c
+===================================================================
+--- subversion/libsvn_client/externals.c	(revision 1542103)
++++ subversion/libsvn_client/externals.c	(working copy)
+@@ -364,7 +364,8 @@ switch_file_external(const char *local_abspath,
+                       ? svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG)
+                       : NULL;
+   svn_boolean_t use_commit_times;
+-  const char *diff3_cmd;
++  const char *diff3_cmd = NULL;
++  const char *invoke_diff3_cmd = NULL;
+   const char *preserved_exts_str;
+   const apr_array_header_t *preserved_exts;
+   svn_node_kind_t kind, external_kind;
+@@ -376,13 +377,23 @@ switch_file_external(const char *local_abspath,
+                               SVN_CONFIG_SECTION_MISCELLANY,
+                               SVN_CONFIG_OPTION_USE_COMMIT_TIMES, FALSE));
+ 
+-  /* Get the external diff3, if any. */
++  /* Get the external *_diff3_cmd, if any. 
++     Precedence: If there is no invoke_diff3_cmd on the cmd line,
++     check if there is a diff3-cmd in the config file.  If there is,
++     do not check invoke_diff3_cmd in the config file.*/
+   svn_config_get(cfg, &diff3_cmd, SVN_CONFIG_SECTION_HELPERS,
+                  SVN_CONFIG_OPTION_DIFF3_CMD, NULL);
+ 
+   if (diff3_cmd != NULL)
+     SVN_ERR(svn_path_cstring_to_utf8(&diff3_cmd, diff3_cmd, scratch_pool));
+-
++  else
++    {
++      svn_config_get(cfg, &invoke_diff3_cmd, SVN_CONFIG_SECTION_HELPERS,
++                     SVN_CONFIG_OPTION_INVOKE_DIFF3_CMD, NULL);
++      if (invoke_diff3_cmd != NULL)
++        SVN_ERR(svn_path_cstring_to_utf8(&invoke_diff3_cmd, 
++                                         invoke_diff3_cmd, scratch_pool));
++    }
+   /* See which files the user wants to preserve the extension of when
+      conflict files are made. */
+   svn_config_get(cfg, &preserved_exts_str, SVN_CONFIG_SECTION_MISCELLANY,
+@@ -483,7 +494,8 @@ switch_file_external(const char *local_abspath,
+                                              switch_loc->repos_uuid,
+                                              inherited_props,
+                                              use_commit_times,
+-                                             diff3_cmd, preserved_exts,
++                                             diff3_cmd, invoke_diff3_cmd,
++                                             preserved_exts,
+                                              def_dir_abspath,
+                                              url, peg_revision, revision,
+                                              ctx->conflict_func2,
+Index: subversion/libsvn_client/merge.c
+===================================================================
+--- subversion/libsvn_client/merge.c	(revision 1542103)
++++ subversion/libsvn_client/merge.c	(working copy)
+@@ -316,10 +316,13 @@ typedef struct merge_cmd_baton_t {
+   /* A list of tree conflict victim absolute paths which may be NULL. */
+   apr_hash_t *tree_conflicted_abspaths;
+ 
+-  /* The diff3_cmd in ctx->config, if any, else null.  We could just
+-     extract this as needed, but since more than one caller uses it,
+-     we just set it up when this baton is created. */
++  /* The diff3_cmd and invoke_diff3_cmd in ctx->config, if any, else
++     null.  We could just extract this as needed, but since more than
++     one caller uses it, we just set it up when this baton is
++     created. */
+   const char *diff3_cmd;
++  const char *invoke_diff3_cmd;
++
+   const apr_array_header_t *merge_options;
+ 
+   /* RA sessions used throughout a merge operation.  Opened/re-parented
+@@ -2040,11 +2043,13 @@ merge_file_changed(const char *relpath,
+ 
+       /* Do property merge and text merge in one step so that keyword expansion
+          takes into account the new property values. */
+-      SVN_ERR(svn_wc_merge5(&content_outcome, &property_state, ctx->wc_ctx,
++      SVN_ERR(svn_wc_merge6(&content_outcome, &property_state, ctx->wc_ctx,
+                             left_file, right_file, local_abspath,
+                             left_label, right_label, target_label,
+                             left, right,
+-                            merge_b->dry_run, merge_b->diff3_cmd,
++                            merge_b->dry_run, 
++                            merge_b->diff3_cmd,
++                            merge_b->invoke_diff3_cmd,
+                             merge_b->merge_options,
+                             left_props, prop_changes,
+                             NULL, NULL,
+@@ -9667,7 +9672,8 @@ do_merge(apr_hash_t **modified_subtrees,
+ {
+   merge_cmd_baton_t merge_cmd_baton = { 0 };
+   svn_config_t *cfg;
+-  const char *diff3_cmd;
++  const char *diff3_cmd = NULL;
++  const char *invoke_diff3_cmd = NULL;
+   int i;
+   svn_boolean_t checked_mergeinfo_capability = FALSE;
+   svn_ra_session_t *ra_session1 = NULL, *ra_session2 = NULL;
+@@ -9718,7 +9724,11 @@ do_merge(apr_hash_t **modified_subtrees,
+   if (depth == svn_depth_unknown)
+     depth = svn_depth_infinity;
+ 
+-  /* Set up the diff3 command, so various callers don't have to. */
++ /* Get the external *_diff3_cmd, if any. 
++     Precedence: If there is no invoke_diff3_cmd on the cmd line,
++     check if there is a diff3-cmd in the config file.  If there is,
++     do not check invoke_diff3_cmd in the config file.*/
++
+   cfg = ctx->config
+         ? svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG)
+         : NULL;
+@@ -9727,6 +9737,14 @@ do_merge(apr_hash_t **modified_subtrees,
+ 
+   if (diff3_cmd != NULL)
+     SVN_ERR(svn_path_cstring_to_utf8(&diff3_cmd, diff3_cmd, scratch_pool));
++  else
++    {
++      svn_config_get(cfg, &invoke_diff3_cmd, SVN_CONFIG_SECTION_HELPERS,
++                     SVN_CONFIG_OPTION_INVOKE_DIFF3_CMD, NULL);
++      if (invoke_diff3_cmd != NULL)
++        SVN_ERR(svn_path_cstring_to_utf8(&invoke_diff3_cmd, 
++                                         invoke_diff3_cmd, scratch_pool));
++    }
+ 
+   /* Build the merge context baton (or at least the parts of it that
+      don't need to be reset for each merge source).  */
+@@ -9743,6 +9761,7 @@ do_merge(apr_hash_t **modified_subtrees,
+   merge_cmd_baton.pool = iterpool;
+   merge_cmd_baton.merge_options = merge_options;
+   merge_cmd_baton.diff3_cmd = diff3_cmd;
++  merge_cmd_baton.invoke_diff3_cmd = invoke_diff3_cmd;
+   merge_cmd_baton.use_sleep = use_sleep;
+ 
+   /* Do we already know the specific subtrees with mergeinfo we want
+Index: subversion/libsvn_client/switch.c
+===================================================================
+--- subversion/libsvn_client/switch.c	(revision 1542103)
++++ subversion/libsvn_client/switch.c	(working copy)
+@@ -106,6 +106,7 @@ switch_internal(svn_revnum_t *result_rev,
+   svn_ra_session_t *ra_session;
+   svn_revnum_t revnum;
+   const char *diff3_cmd;
++  const char *invoke_diff3_cmd;
+   apr_hash_t *wcroot_iprops;
+   apr_array_header_t *inherited_props;
+   svn_boolean_t use_commit_times;
+@@ -134,7 +135,18 @@ switch_internal(svn_revnum_t *result_rev,
+ 
+   if (diff3_cmd != NULL)
+     SVN_ERR(svn_path_cstring_to_utf8(&diff3_cmd, diff3_cmd, pool));
++  else
++    /* Get the external invoke_diff3_cmd, if any. */
++    svn_config_get(cfg, &invoke_diff3_cmd, SVN_CONFIG_SECTION_HELPERS,
++                   SVN_CONFIG_OPTION_INVOKE_DIFF3_CMD, NULL);
+ 
++  if (diff3_cmd != NULL)
++    SVN_ERR(svn_path_cstring_to_utf8(&diff3_cmd, diff3_cmd, pool));
++  else
++    if (invoke_diff3_cmd != NULL)
++      SVN_ERR(svn_path_cstring_to_utf8(&invoke_diff3_cmd, invoke_diff3_cmd, pool));
++
++
+   /* See if the user wants last-commit timestamps instead of current ones. */
+   SVN_ERR(svn_config_get_bool(cfg, &use_commit_times,
+                               SVN_CONFIG_SECTION_MISCELLANY,
+@@ -312,7 +324,8 @@ switch_internal(svn_revnum_t *result_rev,
+                                     use_commit_times, depth,
+                                     depth_is_sticky, allow_unver_obstructions,
+                                     server_supports_depth,
+-                                    diff3_cmd, preserved_exts,
++                                    diff3_cmd, invoke_diff3_cmd,
++                                    preserved_exts,
+                                     svn_client__dirent_fetcher, &dfb,
+                                     conflicted_paths ? record_conflict : NULL,
+                                     conflicted_paths,
+Index: subversion/libsvn_client/update.c
+===================================================================
+--- subversion/libsvn_client/update.c	(revision 1542103)
++++ subversion/libsvn_client/update.c	(working copy)
+@@ -226,7 +226,8 @@ update_internal(svn_revnum_t *result_rev,
+   svn_revnum_t revnum;
+   svn_boolean_t use_commit_times;
+   svn_boolean_t clean_checkout = FALSE;
+-  const char *diff3_cmd;
++  const char *diff3_cmd = NULL;
++  const char *invoke_diff3_cmd = NULL;
+   apr_hash_t *wcroot_iprops;
+   svn_opt_revision_t opt_rev;
+   svn_ra_session_t *ra_session;
+@@ -332,13 +333,24 @@ update_internal(svn_revnum_t *result_rev,
+   /* check whether the "clean c/o" optimization is applicable */
+   SVN_ERR(is_empty_wc(&clean_checkout, local_abspath, anchor_abspath, pool));
+ 
+-  /* Get the external diff3, if any. */
++ /* Get the external *_diff3_cmd, if any. 
++     Precedence: If there is no invoke_diff3_cmd on the cmd line,
++     check if there is a diff3-cmd in the config file.  If there is,
++     do not check invoke_diff3_cmd in the config file.*/
+   svn_config_get(cfg, &diff3_cmd, SVN_CONFIG_SECTION_HELPERS,
+                  SVN_CONFIG_OPTION_DIFF3_CMD, NULL);
+ 
+   if (diff3_cmd != NULL)
+     SVN_ERR(svn_path_cstring_to_utf8(&diff3_cmd, diff3_cmd, pool));
+-
++  else
++    {
++      svn_config_get(cfg, &invoke_diff3_cmd, SVN_CONFIG_SECTION_HELPERS,
++                     SVN_CONFIG_OPTION_INVOKE_DIFF3_CMD, NULL);
++      if (invoke_diff3_cmd != NULL)
++        SVN_ERR(svn_path_cstring_to_utf8(&invoke_diff3_cmd, 
++                                         invoke_diff3_cmd, pool));
++    }
++ 
+   /* See if the user wants last-commit timestamps instead of current ones. */
+   SVN_ERR(svn_config_get_bool(cfg, &use_commit_times,
+                               SVN_CONFIG_SECTION_MISCELLANY,
+@@ -429,7 +441,8 @@ update_internal(svn_revnum_t *result_rev,
+                                     adds_as_modification,
+                                     server_supports_depth,
+                                     clean_checkout,
+-                                    diff3_cmd, preserved_exts,
++                                    diff3_cmd, invoke_diff3_cmd,
++                                    preserved_exts,
+                                     svn_client__dirent_fetcher, &dfb,
+                                     conflicted_paths ? record_conflict : NULL,
+                                     conflicted_paths,
+Index: subversion/libsvn_subr/config_file.c
+===================================================================
+--- subversion/libsvn_subr/config_file.c	(revision 1542103)
++++ subversion/libsvn_subr/config_file.c	(working copy)
+@@ -1192,6 +1192,11 @@ svn_config_ensure(const char *config_dir, apr_pool
+         "###   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
++        "### Set invoke-diff3-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 merge implementation."                  NL
++        "# invoke-diff3-cmd = (see svn help merge for examples)"             NL
+         "### Set merge-tool-cmd to the command used to invoke your external" NL
+         "### merging tool of choice. Subversion will pass 5 arguments to"    NL
+         "### the specified command: base theirs mine merged wcfile"          NL
+Index: subversion/libsvn_subr/io.c
+===================================================================
+--- subversion/libsvn_subr/io.c	(revision 1542103)
++++ subversion/libsvn_subr/io.c	(working copy)
+@@ -3371,7 +3371,60 @@ svn_io_run_diff3_3(int *exitcode,
+   return SVN_NO_ERROR;
+ }
+ 
++svn_error_t *
++svn_io_run_invoke_diff3(int *exitcode,
++                        const char *dir,
++                        const char *mine,
++                        const char *older,
++                        const char *yours,
++                        const char *mine_label,
++                        const char *older_label,
++                        const char *yours_label,
++                        apr_file_t *merged,
++                        const char *invoke_diff3_cmd,
++                        apr_pool_t *pool)
++{
+ 
++  const char ** cmd;
++
++  apr_pool_t *scratch_pool = svn_pool_create(pool); 
++
++  if (0 == strlen(invoke_diff3_cmd)) 
++     return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, NULL);
++
++  cmd = svn_io__create_custom_diff_cmd(mine_label, yours_label, older_label, 
++                                       mine, yours, older, 
++                                       invoke_diff3_cmd, scratch_pool);
++  
++  SVN_ERR(svn_io_run_cmd(dir, cmd[0], cmd, exitcode, NULL, TRUE,
++                         NULL, merged, NULL, scratch_pool));
++
++
++  /* According to the diff3 docs, a '0' means the merge was clean, and
++     '1' means conflict markers were found.  Anything else is real
++     error. */
++  if ((*exitcode != 0) && (*exitcode != 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"),
++                               invoke_diff3_cmd,
++                               failed_command,
++                               *exitcode);
++    }
++  else
++    svn_pool_destroy(scratch_pool);
++
++  return SVN_NO_ERROR;
++}
++
+ /* Canonicalize a string for hashing.  Modifies KEY in place. */
+ static APR_INLINE char *
+ fileext_tolower(char *key)
+Index: subversion/libsvn_wc/deprecated.c
+===================================================================
+--- subversion/libsvn_wc/deprecated.c	(revision 1542103)
++++ subversion/libsvn_wc/deprecated.c	(working copy)
+@@ -3492,6 +3492,7 @@ svn_wc_get_update_editor4(const svn_delta_editor_t
+                               server_performs_filtering,
+                               clean_checkout,
+                               diff3_cmd,
++                              NULL,
+                               preserved_exts,
+                               fetch_dirents_func, fetch_dirents_baton,
+                               conflict_func, conflict_baton,
+@@ -3676,6 +3677,7 @@ svn_wc_get_switch_editor4(const svn_delta_editor_t
+                               allow_unver_obstructions,
+                               server_performs_filtering,
+                               diff3_cmd,
++                              NULL,
+                               preserved_exts,
+                               fetch_dirents_func, fetch_dirents_baton,
+                               conflict_func, conflict_baton,
+@@ -4402,6 +4404,53 @@ svn_wc_copy(const char *src_path,
+ /*** From merge.c ***/
+ 
+ svn_error_t *
++svn_wc_merge5(enum svn_wc_merge_outcome_t *merge_content_outcome,
++              enum svn_wc_notify_state_t *merge_props_outcome,
++              svn_wc_context_t *wc_ctx,
++              const char *left_abspath,
++              const char *right_abspath,
++              const char *target_abspath,
++              const char *left_label,
++              const char *right_label,
++              const char *target_label,
++              const svn_wc_conflict_version_t *left_version,
++              const svn_wc_conflict_version_t *right_version,
++              svn_boolean_t dry_run,
++              const char *diff3_cmd,
++              const apr_array_header_t *merge_options,
++              apr_hash_t *original_props,
++              const apr_array_header_t *prop_diff,
++              svn_wc_conflict_resolver_func2_t conflict_func,
++              void *conflict_baton,
++              svn_cancel_func_t cancel_func,
++              void *cancel_baton,
++              apr_pool_t *scratch_pool)
++{
++  return  svn_wc_merge6(merge_content_outcome,
++                        merge_props_outcome,
++                        wc_ctx,
++                        left_abspath,
++                        right_abspath,
++                        target_abspath,
++                        left_label,
++                        right_label,
++                        target_label,
++                        left_version,
++                        right_version,
++                        dry_run,
++                        diff3_cmd,
++                        NULL,
++                        merge_options,
++                        original_props,
++                        prop_diff,
++                        conflict_func,
++                        conflict_baton,
++                        cancel_func,
++                        cancel_baton,
++                        scratch_pool);
++}
++
++svn_error_t *
+ svn_wc_merge4(enum svn_wc_merge_outcome_t *merge_outcome,
+               svn_wc_context_t *wc_ctx,
+               const char *left_abspath,
+@@ -4816,3 +4865,4 @@ svn_wc__conflict_description2_dup(const svn_wc_con
+ 
+   return new_conflict;
+ }
++
+Index: subversion/libsvn_wc/externals.c
+===================================================================
+--- subversion/libsvn_wc/externals.c	(revision 1542103)
++++ subversion/libsvn_wc/externals.c	(working copy)
+@@ -402,7 +402,8 @@ struct edit_baton
+   /* Information from the caller */
+   svn_boolean_t use_commit_times;
+   const apr_array_header_t *ext_patterns;
+-  const char *diff3cmd;
++  const char *diff3_cmd;
++  const char *invoke_diff3_cmd;
+ 
+   const char *url;
+   const char *repos_root_url;
+@@ -813,7 +814,8 @@ close_file(void *file_baton,
+                                                    eb->original_revision,
+                                                    *eb->target_revision,
+                                                    eb->propchanges,
+-                                                   eb->diff3cmd,
++                                                   eb->diff3_cmd,
++                                                   eb->invoke_diff3_cmd,
+                                                    eb->cancel_func,
+                                                    eb->cancel_baton,
+                                                    pool, pool));
+@@ -984,6 +986,7 @@ svn_wc__get_file_external_editor(const svn_delta_e
+                                  apr_array_header_t *iprops,
+                                  svn_boolean_t use_commit_times,
+                                  const char *diff3_cmd,
++                                 const char *invoke_diff3_cmd,
+                                  const apr_array_header_t *preserved_exts,
+                                  const char *record_ancestor_abspath,
+                                  const char *recorded_url,
+@@ -1021,7 +1024,8 @@ svn_wc__get_file_external_editor(const svn_delta_e
+ 
+   eb->use_commit_times = use_commit_times;
+   eb->ext_patterns = preserved_exts;
+-  eb->diff3cmd = diff3_cmd;
++  eb->diff3_cmd = diff3_cmd;
++  eb->invoke_diff3_cmd = invoke_diff3_cmd;
+ 
+   eb->record_ancestor_abspath = apr_pstrdup(edit_pool,record_ancestor_abspath);
+   eb->recorded_repos_relpath = svn_uri_skip_ancestor(repos_root_url, recorded_url,
+Index: subversion/libsvn_wc/merge.c
+===================================================================
+--- subversion/libsvn_wc/merge.c	(revision 1542103)
++++ subversion/libsvn_wc/merge.c	(working copy)
+@@ -45,11 +45,12 @@ typedef struct merge_target_t
+   const char *local_abspath;                /* The absolute path to target */
+   const char *wri_abspath;                  /* The working copy of target */
+ 
+-  apr_hash_t *old_actual_props;                 /* The set of actual properties
++  apr_hash_t *old_actual_props;             /* The set of actual properties
+                                                before merging */
+   const apr_array_header_t *prop_diff;      /* The property changes */
+ 
+   const char *diff3_cmd;                    /* The diff3 command and options */
++  const char *invoke_diff3_cmd;             /* The invoke_diff3_cmd command  */
+   const apr_array_header_t *merge_options;
+ 
+ } merge_target_t;
+@@ -437,6 +438,7 @@ static svn_error_t *
+ do_text_merge_external(svn_boolean_t *contains_conflicts,
+                        apr_file_t *result_f,
+                        const char *diff3_cmd,
++                       const char *invoke_diff3_cmd,
+                        const apr_array_header_t *merge_options,
+                        const char *detranslated_target,
+                        const char *left_abspath,
+@@ -448,17 +450,26 @@ do_text_merge_external(svn_boolean_t *contains_con
+ {
+   int exit_code;
+ 
+-  SVN_ERR(svn_io_run_diff3_3(&exit_code, ".",
+-                             detranslated_target, left_abspath, right_abspath,
+-                             target_label, left_label, right_label,
+-                             result_f, diff3_cmd,
+-                             merge_options, scratch_pool));
++  if (diff3_cmd)
++    SVN_ERR(svn_io_run_diff3_3(&exit_code, ".",
++                               detranslated_target, left_abspath, right_abspath,
++                               target_label, left_label, right_label,
++                               result_f, diff3_cmd,
++                               merge_options, scratch_pool));
++  else 
++    SVN_ERR(svn_io_run_invoke_diff3(&exit_code, ".",
++                                    detranslated_target, 
++                                    left_abspath, right_abspath,
++                                    target_label, left_label, right_label,
++                                    result_f, invoke_diff3_cmd,
++                                    scratch_pool));
++  
++  *contains_conflicts = (exit_code == 1);
+ 
+-  *contains_conflicts = exit_code == 1;
+-
+   return SVN_NO_ERROR;
+ }
+ 
++
+ /* Preserve the three pre-merge files.
+ 
+    Create three empty files, with unique names that each include the
+@@ -843,11 +854,13 @@ merge_text_file(svn_skel_t **work_items,
+                                      temp_dir, base_name, ".tmp",
+                                      svn_io_file_del_none, pool, pool));
+ 
+-  /* Run the external or internal merge, as requested. */
+-  if (mt->diff3_cmd)
++  /* Run the external (old-style or new-style) or internal merge, as
++     requested. */
++  if (mt->diff3_cmd || mt->invoke_diff3_cmd)
+       SVN_ERR(do_text_merge_external(&contains_conflicts,
+                                      result_f,
+                                      mt->diff3_cmd,
++                                     mt->invoke_diff3_cmd,
+                                      mt->merge_options,
+                                      detranslated_target_abspath,
+                                      left_abspath,
+@@ -1080,6 +1093,7 @@ svn_wc__internal_merge(svn_skel_t **work_items,
+                        apr_hash_t *old_actual_props,
+                        svn_boolean_t dry_run,
+                        const char *diff3_cmd,
++                       const char *invoke_diff3_cmd,
+                        const apr_array_header_t *merge_options,
+                        const apr_array_header_t *prop_diff,
+                        svn_cancel_func_t cancel_func,
+@@ -1106,6 +1120,7 @@ svn_wc__internal_merge(svn_skel_t **work_items,
+   mt.old_actual_props = old_actual_props;
+   mt.prop_diff = prop_diff;
+   mt.diff3_cmd = diff3_cmd;
++  mt.invoke_diff3_cmd = invoke_diff3_cmd;
+   mt.merge_options = merge_options;
+ 
+   /* Decide if the merge target is a text or binary file. */
+@@ -1121,7 +1136,9 @@ svn_wc__internal_merge(svn_skel_t **work_items,
+     }
+ 
+   SVN_ERR(detranslate_wc_file(&detranslated_target_abspath, &mt,
+-                              (! is_binary) && diff3_cmd != NULL,
++                              (! is_binary) 
++                              && diff3_cmd != NULL 
++                              && invoke_diff3_cmd != NULL,
+                               target_abspath,
+                               cancel_func, cancel_baton,
+                               scratch_pool, scratch_pool));
+@@ -1193,7 +1210,7 @@ svn_wc__internal_merge(svn_skel_t **work_items,
+ 
+ 
+ svn_error_t *
+-svn_wc_merge5(enum svn_wc_merge_outcome_t *merge_content_outcome,
++svn_wc_merge6(enum svn_wc_merge_outcome_t *merge_content_outcome,
+               enum svn_wc_notify_state_t *merge_props_outcome,
+               svn_wc_context_t *wc_ctx,
+               const char *left_abspath,
+@@ -1206,6 +1223,7 @@ svn_error_t *
+               const svn_wc_conflict_version_t *right_version,
+               svn_boolean_t dry_run,
+               const char *diff3_cmd,
++              const char *invoke_diff3_cmd,
+               const apr_array_header_t *merge_options,
+               apr_hash_t *original_props,
+               const apr_array_header_t *prop_diff,
+@@ -1345,6 +1363,7 @@ svn_error_t *
+                                  old_actual_props,
+                                  dry_run,
+                                  diff3_cmd,
++                                 invoke_diff3_cmd,
+                                  merge_options,
+                                  prop_diff,
+                                  cancel_func, cancel_baton,
+Index: subversion/libsvn_wc/update_editor.c
+===================================================================
+--- subversion/libsvn_wc/update_editor.c	(revision 1542103)
++++ subversion/libsvn_wc/update_editor.c	(working copy)
+@@ -223,6 +223,10 @@ struct edit_baton
+      internal merge code is used). */
+   const char *diff3_cmd;
+ 
++  /* External custom invoke diff3 to use for merges (can be null, in
++     which case internal merge code is used). */
++  const char *invoke_diff3_cmd;
++
+   /* Externals handler */
+   svn_wc_external_update_t external_func;
+   void *external_baton;
+@@ -3900,6 +3904,7 @@ svn_wc__perform_file_merge(svn_skel_t **work_items
+                            svn_revnum_t target_revision,
+                            const apr_array_header_t *propchanges,
+                            const char *diff3_cmd,
++                           const char *invoke_diff3_cmd,
+                            svn_cancel_func_t cancel_func,
+                            void *cancel_baton,
+                            apr_pool_t *result_pool,
+@@ -3977,7 +3982,8 @@ svn_wc__perform_file_merge(svn_skel_t **work_items
+                                  oldrev_str, newrev_str, mine_str,
+                                  old_actual_props,
+                                  FALSE /* dry_run */,
+-                                 diff3_cmd, NULL, propchanges,
++                                 diff3_cmd, invoke_diff3_cmd,
++                                 NULL, propchanges,
+                                  cancel_func, cancel_baton,
+                                  result_pool, scratch_pool));
+ 
+@@ -4138,6 +4144,7 @@ merge_file(svn_skel_t **work_items,
+                                          *eb->target_revision,
+                                          fb->propchanges,
+                                          eb->diff3_cmd,
++                                         eb->invoke_diff3_cmd,
+                                          eb->cancel_func, eb->cancel_baton,
+                                          result_pool, scratch_pool));
+     } /* end: working file exists and has mods */
+@@ -4831,6 +4838,7 @@ make_editor(svn_revnum_t *target_revision,
+             svn_wc_external_update_t external_func,
+             void *external_baton,
+             const char *diff3_cmd,
++            const char *invoke_diff3_cmd,
+             const apr_array_header_t *preserved_exts,
+             const svn_delta_editor_t **editor,
+             void **edit_baton,
+@@ -4901,6 +4909,7 @@ make_editor(svn_revnum_t *target_revision,
+   eb->external_func            = external_func;
+   eb->external_baton           = external_baton;
+   eb->diff3_cmd                = diff3_cmd;
++  eb->invoke_diff3_cmd         = invoke_diff3_cmd;
+   eb->cancel_func              = cancel_func;
+   eb->cancel_baton             = cancel_baton;
+   eb->conflict_func            = conflict_func;
+@@ -5107,6 +5116,7 @@ svn_wc__get_update_editor(const svn_delta_editor_t
+                           svn_boolean_t server_performs_filtering,
+                           svn_boolean_t clean_checkout,
+                           const char *diff3_cmd,
++                          const char *invoke_diff3_cmd,
+                           const apr_array_header_t *preserved_exts,
+                           svn_wc_dirents_func_t fetch_dirents_func,
+                           void *fetch_dirents_baton,
+@@ -5131,7 +5141,8 @@ svn_wc__get_update_editor(const svn_delta_editor_t
+                      fetch_dirents_func, fetch_dirents_baton,
+                      conflict_func, conflict_baton,
+                      external_func, external_baton,
+-                     diff3_cmd, preserved_exts, editor, edit_baton,
++                     diff3_cmd, invoke_diff3_cmd,
++                     preserved_exts, editor, edit_baton,
+                      result_pool, scratch_pool);
+ }
+ 
+@@ -5150,6 +5161,7 @@ svn_wc__get_switch_editor(const svn_delta_editor_t
+                           svn_boolean_t allow_unver_obstructions,
+                           svn_boolean_t server_performs_filtering,
+                           const char *diff3_cmd,
++                          const char *invoke_diff3_cmd,
+                           const apr_array_header_t *preserved_exts,
+                           svn_wc_dirents_func_t fetch_dirents_func,
+                           void *fetch_dirents_baton,
+@@ -5178,7 +5190,8 @@ svn_wc__get_switch_editor(const svn_delta_editor_t
+                      fetch_dirents_func, fetch_dirents_baton,
+                      conflict_func, conflict_baton,
+                      external_func, external_baton,
+-                     diff3_cmd, preserved_exts,
++                     diff3_cmd, invoke_diff3_cmd,
++                     preserved_exts,
+                      editor, edit_baton,
+                      result_pool, scratch_pool);
+ }
+Index: subversion/libsvn_wc/wc.h
+===================================================================
+--- subversion/libsvn_wc/wc.h	(revision 1542103)
++++ subversion/libsvn_wc/wc.h	(working copy)
+@@ -413,8 +413,8 @@ svn_wc__internal_file_modified_p(svn_boolean_t *mo
+ 
+    When DRY_RUN is true, no actual changes are made to the working copy.
+ 
+-   If DIFF3_CMD is specified, the given external diff3 tool will
+-   be used instead of our built in diff3 routines.
++   If DIFF3_CMD or INVOKE_DIFF3_CMD is specified, the given external
++   diff3 tool will be used instead of our built in diff3 routines.
+ 
+    When MERGE_OPTIONS are specified, they are used by the internal
+    diff3 routines, or passed to the external diff3 tool.
+@@ -453,6 +453,7 @@ svn_wc__internal_merge(svn_skel_t **work_items,
+                        const char *target_label,
+                        apr_hash_t *old_actual_props,
+                        svn_boolean_t dry_run,
++                       const char *invoke_diff3_cmd,
+                        const char *diff3_cmd,
+                        const apr_array_header_t *merge_options,
+                        const apr_array_header_t *prop_diff,
+@@ -461,6 +462,7 @@ svn_wc__internal_merge(svn_skel_t **work_items,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool);
+ 
++
+ /* A default error handler for svn_wc_walk_entries3().  Returns ERR in
+    all cases. */
+ svn_error_t *
+@@ -730,6 +732,7 @@ svn_wc__perform_file_merge(svn_skel_t **work_items
+                            svn_revnum_t target_revision,
+                            const apr_array_header_t *propchanges,
+                            const char *diff3_cmd,
++                           const char *invoke_diff3_cmd,
+                            svn_cancel_func_t cancel_func,

[... 870 lines stripped ...]


Mime
View raw message