You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by gb...@apache.org on 2013/11/16 15:36:47 UTC

svn commit: r1542514 [3/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_...

Modified: subversion/branches/invoke-diff3-feature/subversion/include/private/svn_wc_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/include/private/svn_wc_private.h?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/include/private/svn_wc_private.h (original)
+++ subversion/branches/invoke-diff3-feature/subversion/include/private/svn_wc_private.h Sat Nov 16 14:36:46 2013
@@ -77,6 +77,7 @@ svn_wc__get_file_external_editor(const s
                                  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_delt
                           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_delt
                           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,

Modified: subversion/branches/invoke-diff3-feature/subversion/include/svn_config.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/include/svn_config.h?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/include/svn_config.h (original)
+++ subversion/branches/invoke-diff3-feature/subversion/include/svn_config.h Sat Nov 16 14:36:46 2013
@@ -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"

Modified: subversion/branches/invoke-diff3-feature/subversion/include/svn_error_codes.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/include/svn_error_codes.h?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/include/svn_error_codes.h (original)
+++ subversion/branches/invoke-diff3-feature/subversion/include/svn_error_codes.h Sat Nov 16 14:36:46 2013
@@ -1451,8 +1451,13 @@ SVN_ERROR_START
              SVN_ERR_CL_CATEGORY_START + 10,
              "No external merge tool available")
 
-  SVN_ERRDEF(SVN_ERR_CL_ERROR_PROCESSING_EXTERNALS,
+  /** @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 + 12,
              "Failed processing one or more externals definitions")
 
   /* ra_svn errors */

Modified: subversion/branches/invoke-diff3-feature/subversion/include/svn_io.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/include/svn_io.h?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/include/svn_io.h (original)
+++ subversion/branches/invoke-diff3-feature/subversion/include/svn_io.h Sat Nov 16 14:36:46 2013
@@ -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 */

Modified: subversion/branches/invoke-diff3-feature/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/include/svn_wc.h?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/include/svn_wc.h (original)
+++ subversion/branches/invoke-diff3-feature/subversion/include/svn_wc.h Sat Nov 16 14:36:46 2013
@@ -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,

Modified: subversion/branches/invoke-diff3-feature/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/libsvn_client/externals.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/libsvn_client/externals.c Sat Nov 16 14:36:46 2013
@@ -364,7 +364,8 @@ switch_file_external(const char *local_a
                       ? 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_a
                               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_a
                                              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,

Modified: subversion/branches/invoke-diff3-feature/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/libsvn_client/merge.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/libsvn_client/merge.c Sat Nov 16 14:36:46 2013
@@ -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

Modified: subversion/branches/invoke-diff3-feature/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/libsvn_client/switch.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/libsvn_client/switch.c Sat Nov 16 14:36:46 2013
@@ -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,6 +135,17 @@ 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,
@@ -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,

Modified: subversion/branches/invoke-diff3-feature/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/libsvn_client/update.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/libsvn_client/update.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/libsvn_client/update.c Sat Nov 16 14:36:46 2013
@@ -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,

Modified: subversion/branches/invoke-diff3-feature/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/libsvn_subr/config_file.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/libsvn_subr/config_file.c Sat Nov 16 14:36:46 2013
@@ -1192,6 +1192,11 @@ svn_config_ensure(const char *config_dir
         "###   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

Modified: subversion/branches/invoke-diff3-feature/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/libsvn_subr/io.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/libsvn_subr/io.c Sat Nov 16 14:36:46 2013
@@ -3371,6 +3371,59 @@ 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 *

Modified: subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/deprecated.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/deprecated.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/deprecated.c Sat Nov 16 14:36:46 2013
@@ -3492,6 +3492,7 @@ svn_wc_get_update_editor4(const svn_delt
                               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_delt
                               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 
 
   return new_conflict;
 }
+

Modified: subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/externals.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/externals.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/externals.c Sat Nov 16 14:36:46 2013
@@ -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 s
                                  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 s
 
   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,

Modified: subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/merge.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/merge.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/merge.c Sat Nov 16 14:36:46 2013
@@ -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 *co
 {
   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));
-
-  *contains_conflicts = exit_code == 1;
+  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);
 
   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
                        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
   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
     }
 
   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
 
 
 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_wc_merge5(enum svn_wc_merge_outcome_
               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_wc_merge5(enum svn_wc_merge_outcome_
                                  old_actual_props,
                                  dry_run,
                                  diff3_cmd,
+                                 invoke_diff3_cmd,
                                  merge_options,
                                  prop_diff,
                                  cancel_func, cancel_baton,

Modified: subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/update_editor.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/update_editor.c Sat Nov 16 14:36:46 2013
@@ -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 **
                            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 **
                                  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_revisio
             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_revisio
   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_delt
                           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_delt
                      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_delt
                           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_delt
                      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);
 }

Modified: subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/wc.h?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/wc.h Sat Nov 16 14:36:46 2013
@@ -413,8 +413,8 @@ svn_wc__internal_file_modified_p(svn_boo
 
    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
                        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
                        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 **
                            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,

Modified: subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/wc_db_update_move.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/libsvn_wc/wc_db_update_move.c Sat Nov 16 14:36:46 2013
@@ -961,8 +961,9 @@ update_working_file(const char *local_re
                                          NULL, NULL, NULL, /* diff labels */
                                          actual_props,
                                          FALSE, /* dry-run */
-                                         NULL, /* diff3-cmd */
-                                         NULL, /* merge options */
+                                         NULL,  /* diff3-cmd */
+                                         NULL,  /* invoke-diff3-cmd */
+                                         NULL,  /* merge options */
                                          propchanges,
                                          NULL, NULL, /* cancel_func + baton */
                                          scratch_pool, scratch_pool));

Modified: subversion/branches/invoke-diff3-feature/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/svn/cl.h?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/svn/cl.h (original)
+++ subversion/branches/invoke-diff3-feature/subversion/svn/cl.h Sat Nov 16 14:36:46 2013
@@ -83,7 +83,11 @@ typedef enum svn_cl__accept_t
   svn_cl__accept_edit,
 
   /* Launch user's resolver and resolve conflict with edited file. */
-  svn_cl__accept_launch
+  svn_cl__accept_launch,
+
+  /* Launch user's resolver with the invoke_diff3_cmd in the config
+     file and resolve conflict with edited file. */
+  svn_cl__accept_invoke_diff3_config
 
 } svn_cl__accept_t;
 
@@ -97,6 +101,7 @@ typedef enum svn_cl__accept_t
 #define SVN_CL__ACCEPT_THEIRS_FULL "theirs-full"
 #define SVN_CL__ACCEPT_EDIT "edit"
 #define SVN_CL__ACCEPT_LAUNCH "launch"
+#define SVN_CL__ACCEPT_INVOKE_DIFF3_CONFIG "invoke-diff3-config"
 
 /* Return the svn_cl__accept_t value corresponding to WORD, using exact
  * case-sensitive string comparison. Return svn_cl__accept_invalid if WORD
@@ -204,6 +209,9 @@ typedef struct svn_cl__opt_state_t
   svn_boolean_t revprop;         /* operate on a revision property */
   const char *merge_cmd;         /* the external merge command to use
                                     (not converted to UTF-8) */
+  const char *invoke_diff3_cmd;  /* the format string for the external
+                                    merge command to use (not
+                                    converted to UTF-8) */
   const char *editor_cmd;        /* the external editor command to use
                                     (not converted to UTF-8) */
   svn_boolean_t record_only;     /* whether to record mergeinfo */
@@ -531,6 +539,21 @@ svn_cl__merge_file_externally(const char
                               svn_boolean_t *remains_in_conflict,
                               apr_pool_t *pool);
 
+/* As svn_cl__merge_file_externally, but for the invoke_diff3_cmd
+   selected merge tool  */
+svn_error_t *
+svn_cl__invoke_diff3_cmd_externally(const char *base_label,
+                                    const char *their_label,
+                                    const char *my_label,
+                                    const char *base_file,
+                                    const char *their_file,
+                                    const char *my_file,
+                                    apr_hash_t *config,
+                                    svn_boolean_t *remains_in_conflict,
+                                    const char *opt_code,
+                                    apr_pool_t *pool);
+
+
 /* Like svn_cl__merge_file_externally, but using a built-in merge tool
  * with help from an external editor specified by EDITOR_CMD. */
 svn_error_t *

Modified: subversion/branches/invoke-diff3-feature/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/svn/conflict-callbacks.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/svn/conflict-callbacks.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/svn/conflict-callbacks.c Sat Nov 16 14:36:46 2013
@@ -118,6 +118,11 @@ svn_cl__accept_from_word(const char *wor
   if (strcmp(word, SVN_CL__ACCEPT_LAUNCH) == 0
       || strcmp(word, "l") == 0 || strcmp(word, ":-l") == 0)
     return svn_cl__accept_launch;
+  if (strcmp(word, SVN_CL__ACCEPT_INVOKE_DIFF3_CONFIG) == 0
+      /* FIX ME:  Which smiley to select? */
+      || strcmp(word, "3f") == 0 || strcmp(word, ":-?") == 0)
+    return svn_cl__accept_launch;
+
   /* word is an invalid action. */
   return svn_cl__accept_invalid;
 }
@@ -409,6 +414,37 @@ launch_resolver(svn_boolean_t *performed
   return SVN_NO_ERROR;
 }
 
+/* Run an external merge tool, passing it the 'base', 'their', 'my' and
+ * 'merged' files in DESC. The tool to use is determined by B->config and
+ * environment variables; see svn_cl__merge_file_externally() for details.
+ *
+ * If the tool runs, set *PERFORMED_EDIT to true; if a tool is not
+ * configured or cannot run, do not touch *PERFORMED_EDIT, report the error
+ * on stderr, and return SVN_NO_ERROR; if any other error is encountered,
+ * return that error.  */
+static svn_error_t *
+invoke_diff3_resolver(svn_boolean_t *performed_edit,
+                      const svn_wc_conflict_description2_t *desc,
+                      svn_cl__interactive_conflict_baton_t *b,
+                      const char *opt_code,
+                      apr_pool_t *pool)
+{
+
+  SVN_ERR(svn_cl__invoke_diff3_cmd_externally("BASE",
+                                              "OLD",
+                                              "NEW",
+                                              desc->base_abspath,
+                                              desc->their_abspath,
+                                              desc->my_abspath,
+                                              b->config, NULL,
+                                              opt_code,
+                                              pool));
+  if (performed_edit)
+    *performed_edit = TRUE;
+
+  return SVN_NO_ERROR;
+}
+
 
 /* Maximum line length for the prompt string. */
 #define MAX_PROMPT_WIDTH 70
@@ -458,6 +494,15 @@ static const resolver_option_t text_conf
                                      -1 },
   { "l",  N_("launch tool"),      N_("launch external tool to resolve "
                                      "conflict  [launch]"), -1 },
+  { "3f", N_("invoke-diff3-cmd given in config file"), 
+                                  N_("use invoke-diff3 command defined in "
+                                     "the config file to resolve conflict "
+                                     "[invoke-diff3-config]"), -1 },
+
+  { "i", N_("interactive invoke-diff3-cmd selection"), 
+                                  N_("interactively select tool now to "
+                                     "resolve conflict"), -1 },
+
   { "p",  N_("postpone"),         N_("mark the conflict to be resolved later"
                                      "  [postpone]"),
                                   svn_wc_conflict_choose_postpone },
@@ -734,6 +779,8 @@ handle_text_conflict(svn_wc_conflict_res
           *next_option++ = "df";
           *next_option++ = "e";
           *next_option++ = "m";
+          *next_option++ = "3f";
+          *next_option++ = "i";
 
           if (knows_something)
             *next_option++ = "r";
@@ -798,8 +845,8 @@ handle_text_conflict(svn_wc_conflict_res
           if (! diff_allowed)
             {
               SVN_ERR(svn_cmdline_fprintf(stderr, iterpool,
-                             _("Invalid option; there's no "
-                                "merged version to diff.\n\n")));
+                                          _("Invalid option; there's no "
+                                            "merged version to diff.\n\n")));
               continue;
             }
 
@@ -887,8 +934,79 @@ handle_text_conflict(svn_wc_conflict_res
                 {
                   SVN_ERR(svn_cmdline_fprintf(stderr, iterpool, "%s\n",
                                               err->message ? err->message :
-                                         _("Error running merge tool, "
-                                           "try '(m) merge' instead.")));
+                                              _("Error running merge tool, "
+                                                "try '(m) merge' instead.")));
+                  svn_error_clear(err);
+                }
+              else if (err)
+                return svn_error_trace(err);
+
+              if (performed_edit)
+                knows_something = TRUE;
+            }
+          else
+            SVN_ERR(svn_cmdline_fprintf(stderr, iterpool,
+                                        _("Invalid option.\n\n")));
+        }
+      else if (strcmp(opt->code, "i") == 0)
+        { /* interactively get the invoke-diff3-cmd */
+              
+          if (desc->base_abspath && desc->their_abspath &&
+              desc->my_abspath && desc->merged_file)
+            {
+              const char *answer;
+              svn_error_t *err;
+              
+              SVN_ERR(svn_cmdline_prompt_user2(&answer, 
+                                               "Enter the invoke-diff3-cmd: ", 
+                                               b->pb, iterpool));
+              err = invoke_diff3_resolver(&performed_edit, desc, b, answer, iterpool);
+              
+              if (err && err->apr_err == SVN_ERR_EXTERNAL_PROGRAM)
+                {
+                  SVN_ERR(svn_cmdline_fprintf(stderr, iterpool, "%s\n",
+                                              err->message ? err->message :
+                                              _("Error executing the interactive, "
+                                                "invoke-diff3-cmd.\n")));
+                  svn_error_clear(err);
+                }
+              else if (err)
+                return svn_error_trace(err);
+              
+              if (performed_edit)
+                knows_something = TRUE;
+            }
+          else
+            SVN_ERR(svn_cmdline_fprintf(stderr, iterpool,
+                                        _("Invalid option.\n\n")));
+        }
+      else if (strcmp(opt->code, "3f") == 0)
+        {
+          if (desc->base_abspath && desc->their_abspath &&
+              desc->my_abspath && desc->merged_file)
+            {
+
+              svn_error_t *err;
+              /* ### This check should be earlier as it's nasty to offer an option
+               *     and then when the user chooses it say 'Invalid option'. */
+              /* ### 'merged_file' shouldn't be necessary *before* we launch the
+               *     resolver: it should be the *result* of doing so. */
+
+              err = invoke_diff3_resolver(&performed_edit, desc, b, opt->code, iterpool);
+              if (err && err->apr_err == SVN_ERR_CL_NO_EXTERNAL_DIFF3_TOOL)
+                {
+                  SVN_ERR(svn_cmdline_fprintf(stderr, iterpool, "%s\n",
+                                              err->message ? err->message :
+                                              _("No invoke-diff3 tool found, "
+                                                "try '(m) merge' instead.\n")));
+                  svn_error_clear(err);
+                }
+              else if (err && err->apr_err == SVN_ERR_EXTERNAL_PROGRAM)
+                {
+                  SVN_ERR(svn_cmdline_fprintf(stderr, iterpool, "%s\n",
+                                              err->message ? err->message :
+                                              _("Error running invoke-diff3 tool, "
+                                                "try '(m) merge' instead.")));
                   svn_error_clear(err);
                 }
               else if (err)
@@ -921,9 +1039,9 @@ handle_text_conflict(svn_wc_conflict_res
               && ! knows_something)
             {
               SVN_ERR(svn_cmdline_fprintf(
-                        stderr, iterpool,
-                        _("Invalid option; use diff/edit/merge/launch "
-                          "before choosing 'mark resolved'.\n\n")));
+                                          stderr, iterpool,
+                                          _("Invalid option; use diff/edit/merge/launch "
+                                            "before choosing 'mark resolved'.\n\n")));
               continue;
             }
 
@@ -1294,6 +1412,57 @@ conflict_func_interactive(svn_wc_conflic
         }
       /* else, fall through to prompting. */
       break;
+    case svn_cl__accept_invoke_diff3_config:
+      if (desc->base_abspath && desc->their_abspath
+          && desc->my_abspath && desc->merged_file)
+        {
+          svn_boolean_t remains_in_conflict;
+
+          if (b->external_failed)
+            {
+              (*result)->choice = svn_wc_conflict_choose_postpone;
+              return SVN_NO_ERROR;
+            }
+          err = svn_cl__invoke_diff3_cmd_externally("BASE",
+                                                    "NEW",
+                                                    "OLD",
+                                                    desc->base_abspath,
+                                                    desc->their_abspath,
+                                                    desc->my_abspath,
+                                                    b->config,
+                                                    &remains_in_conflict,
+                                                    "3f",
+                                                    scratch_pool);
+          if (err && err->apr_err == SVN_ERR_CL_NO_EXTERNAL_MERGE_TOOL)
+            {
+              SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n",
+                                          err->message ? err->message :
+                                          _("No invoke-diff3-cmd tool found;"
+                                            " leaving all conflicts.")));
+              b->external_failed = TRUE;
+              return svn_error_trace(err);
+            }
+          else if (err && err->apr_err == SVN_ERR_EXTERNAL_PROGRAM)
+            {
+              SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n",
+                                          err->message ? err->message :
+                                          _("Error running invoke-diff3-cmd tool;"
+                                            " leaving all conflicts.")));
+              b->external_failed = TRUE;
+              return svn_error_trace(err);
+            }
+          else if (err)
+            return svn_error_trace(err);
+
+          if (remains_in_conflict)
+            (*result)->choice = svn_wc_conflict_choose_postpone;
+          else
+            (*result)->choice = svn_wc_conflict_choose_merged;
+          return SVN_NO_ERROR;
+        }
+      /* else, fall through to prompting. */
+      break;
+
     }
 
   /* Print a summary of conflicts before starting interactive resolution */

Modified: subversion/branches/invoke-diff3-feature/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/svn/svn.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/svn/svn.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/svn/svn.c Sat Nov 16 14:36:46 2013
@@ -95,6 +95,7 @@ typedef enum svn_cl__longopt_t {
   opt_ignore_externals,
   opt_incremental,
   opt_merge_cmd,
+  opt_invoke_diff3_cmd,
   opt_native_eol,
   opt_new_cmd,
   opt_no_auth_cache,
@@ -250,6 +251,24 @@ const apr_getopt_option_t svn_cl__option
   {"ignore-externals", opt_ignore_externals, 0,
                     N_("ignore externals definitions")},
   {"diff3-cmd",     opt_merge_cmd, 1, N_("use ARG as merge command")},
+  {"invoke-diff3-cmd", opt_invoke_diff3_cmd, 1, 
+                    N_("use ARG as format string for external merge program\n"
+                      "                             "
+                      "invocation.  Substitutions: \n" 
+                      "                             "
+                      "  %svn_mine  'mine' file\n"
+                      "                             "
+                      "  %svn_yours 'yours' file\n"
+                      "                             "
+                      "  %svn_base  'base' file\n"
+                      "                             "
+                      "  %svn_label_mine   label of the 'mine file\n"
+                      "                             "
+                      "  %svn_label_yours  label of the 'yours' file\n"
+                      "                             "
+                      "  %svn_label_base   label of the 'mine file\n"
+                      "                             "
+                      "See 'help diff' for example usage.")},
   {"editor-cmd",    opt_editor_cmd, 1, N_("use ARG as external editor")},
   {"record-only",   opt_record_only, 0,
                     N_("merge only mergeinfo differences")},
@@ -546,8 +565,8 @@ const svn_opt_subcommand_desc2_t svn_cl_
      "  for writing by another Subversion client.\n"
      "  Note that the 'svn status' command shows unversioned items as '?',\n"
      "  and ignored items as 'I' if the --no-ignore option is given to it.\n"),
-    {opt_merge_cmd, opt_remove_unversioned, opt_remove_ignored,
-     opt_include_externals, 'q'} },
+    {opt_merge_cmd, opt_invoke_diff3_cmd, opt_remove_unversioned, 
+     opt_remove_ignored, opt_include_externals, 'q'} },
 
   { "commit", svn_cl__commit, {"ci"},
     N_("Send changes from your working copy to the repository.\n"
@@ -1140,8 +1159,8 @@ const svn_opt_subcommand_desc2_t svn_cl_
 "  target. Also, merge-tracking is not supported for merges from foreign\n"
 "  repositories.\n"),
     {'r', 'c', 'N', opt_depth, 'q', opt_force, opt_dry_run, opt_merge_cmd,
-     opt_record_only, 'x', opt_ignore_ancestry, opt_accept, opt_reintegrate,
-     opt_allow_mixed_revisions, 'v'} },
+     opt_invoke_diff3_cmd, opt_record_only, 'x', opt_ignore_ancestry, 
+     opt_accept, opt_reintegrate, opt_allow_mixed_revisions, 'v'} },
 
   { "mergeinfo", svn_cl__mergeinfo, {0}, N_
     ("Display merge-related information.\n"
@@ -1604,8 +1623,9 @@ const svn_opt_subcommand_desc2_t svn_cl_
      "    svn switch --relocate http:// svn://\n"
      "    svn switch --relocate http://www.example.com/repo/project \\\n"
      "                          svn://svn.example.com/repo/project\n"),
-    { 'r', 'N', opt_depth, opt_set_depth, 'q', opt_merge_cmd, opt_relocate,
-      opt_ignore_externals, opt_ignore_ancestry, opt_force, opt_accept},
+    { 'r', 'N', opt_depth, opt_set_depth, 'q', opt_merge_cmd, 
+      opt_invoke_diff3_cmd, opt_relocate, opt_ignore_externals, 
+      opt_ignore_ancestry, opt_force, opt_accept},
     {{opt_ignore_ancestry,
       N_("allow switching to a node with no common ancestor")}}
   },
@@ -1663,9 +1683,9 @@ const svn_opt_subcommand_desc2_t svn_cl_
      "\n"
      "  Use the --set-depth option to set a new working copy depth on the\n"
      "  targets of this operation.\n"),
-    {'r', 'N', opt_depth, opt_set_depth, 'q', opt_merge_cmd, opt_force,
-     opt_ignore_externals, opt_changelist, opt_editor_cmd, opt_accept,
-     opt_parents} },
+    {'r', 'N', opt_depth, opt_set_depth, 'q', opt_merge_cmd, 
+     opt_invoke_diff3_cmd, opt_force, opt_ignore_externals, opt_changelist, 
+     opt_editor_cmd, opt_accept, opt_parents} },
 
   { "upgrade", svn_cl__upgrade, {0}, N_
     ("Upgrade the metadata storage format for a working copy.\n"
@@ -2174,6 +2194,9 @@ sub_main(int argc, const char *argv[], a
       case opt_merge_cmd:
         opt_state.merge_cmd = apr_pstrdup(pool, opt_arg);
         break;
+      case opt_invoke_diff3_cmd:
+        opt_state.invoke_diff3_cmd = apr_pstrdup(pool, opt_arg);
+        break;
       case opt_record_only:
         opt_state.record_only = TRUE;
         break;
@@ -2611,6 +2634,16 @@ sub_main(int argc, const char *argv[], a
       return EXIT_ERROR(err);
     }
 
+  /* Check for mutually exclusive args --diff3-cmd and
+     --invoke-diff3-cmd */
+  if (opt_state.merge_cmd && opt_state.invoke_diff3_cmd)
+    {
+      err = svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
+                             _("--diff3-cmd  and --invoke-diff3-cmd are "
+                               "mutually exclusive"));
+      return EXIT_ERROR(err);
+    }
+
   /* Ensure that 'revision_ranges' has at least one item, and make
      'start_revision' and 'end_revision' match that item. */
   if (opt_state.revision_ranges->nelts == 0)
@@ -2830,8 +2863,15 @@ sub_main(int argc, const char *argv[], a
     svn_config_set(cfg_config, SVN_CONFIG_SECTION_HELPERS,
                    SVN_CONFIG_OPTION_INVOKE_DIFF_CMD, opt_state.diff.invoke_diff_cmd);
   if (opt_state.merge_cmd)
-    svn_config_set(cfg_config, SVN_CONFIG_SECTION_HELPERS,
-                   SVN_CONFIG_OPTION_DIFF3_CMD, opt_state.merge_cmd);
+    {
+      svn_config_set(cfg_config, SVN_CONFIG_SECTION_HELPERS,
+                     SVN_CONFIG_OPTION_DIFF3_CMD, opt_state.merge_cmd);
+    }
+  if (opt_state.invoke_diff3_cmd) 
+    {
+      svn_config_set(cfg_config, SVN_CONFIG_SECTION_HELPERS,
+                   SVN_CONFIG_OPTION_INVOKE_DIFF3_CMD, opt_state.invoke_diff3_cmd);
+    }
   if (opt_state.diff.internal_diff)
     svn_config_set(cfg_config, SVN_CONFIG_SECTION_HELPERS,
                    SVN_CONFIG_OPTION_DIFF_CMD, NULL);
@@ -2955,6 +2995,12 @@ sub_main(int argc, const char *argv[], a
                                    _("--accept=%s incompatible with"
                                      " --non-interactive"),
                                    SVN_CL__ACCEPT_LAUNCH));
+      if (opt_state.accept_which == svn_cl__accept_invoke_diff3_config)
+        return EXIT_ERROR(
+                 svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                   _("--accept=%s incompatible with"
+                                     " --non-interactive"),
+                                   SVN_CL__ACCEPT_LAUNCH));
 
       /* The default action when we're non-interactive is to postpone
        * conflict resolution. */

Modified: subversion/branches/invoke-diff3-feature/subversion/svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/svn/util.c?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/svn/util.c (original)
+++ subversion/branches/invoke-diff3-feature/subversion/svn/util.c Sat Nov 16 14:36:46 2013
@@ -66,6 +66,7 @@
 #include "private/svn_client_private.h"
 #include "private/svn_cmdline_private.h"
 #include "private/svn_string_private.h"
+#include "private/svn_io_private.h"
 
 
 
@@ -173,6 +174,104 @@ svn_cl__merge_file_externally(const char
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_cl__invoke_diff3_cmd_externally(const char *base_label,
+                                    const char *their_label,
+                                    const char *my_label,
+                                    const char *base_file,
+                                    const char *their_file,
+                                    const char *my_file,
+                                    apr_hash_t *config,
+                                    svn_boolean_t *remains_in_conflict,
+                                    const char *opt_code,
+                                    apr_pool_t *pool)
+{
+  char *invoke_diff3_cmd;
+  const char ** cmd;
+  apr_pool_t *scratch_pool = svn_pool_create(pool); 
+  char *cwd;
+  int exitcode;
+  apr_status_t status = apr_filepath_get(&cwd, APR_FILEPATH_NATIVE, pool);
+
+  if (status != 0)
+    return svn_error_wrap_apr(status, NULL);
+
+  if (0 == strcmp(opt_code,"3f")) /* command in config file */
+    {
+
+      if (apr_env_get(&invoke_diff3_cmd, "SVN_INVOKE_DIFF3_CMD", pool) != APR_SUCCESS)
+        {
+          struct svn_config_t *cfg;
+          invoke_diff3_cmd = NULL;
+          cfg = config ? svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG) : NULL;
+          /* apr_env_get wants char **, this wants const char ** */
+          svn_config_get(cfg, (const char **)&invoke_diff3_cmd,
+                         SVN_CONFIG_SECTION_HELPERS,
+                         SVN_CONFIG_OPTION_INVOKE_DIFF3_CMD, NULL);
+        }
+ 
+      if (invoke_diff3_cmd)
+        {
+          const char *c;
+          for (c = invoke_diff3_cmd; *c; c++)
+            if (!svn_ctype_isspace(*c))
+              break;
+
+          if (! *c)
+            return svn_error_create
+              (SVN_ERR_CL_NO_EXTERNAL_DIFF3_TOOL, NULL,
+               _("The SVN_INVOKE_DIFF3_TOOL environment variable is empty or "
+                 "consists solely of whitespace. Expected a shell command.\n"));
+        }
+      else
+         return svn_error_create
+           (SVN_ERR_CL_NO_EXTERNAL_MERGE_TOOL, NULL,
+           _("The environment variable SVN_INVOKE_DIFF3_TOOL and the invoke-diff3-cmd run-time "
+             "configuration option were not set.\n"));
+    }
+    else
+      {
+        invoke_diff3_cmd = apr_pstrdup(pool, opt_code);
+      }
+
+
+  if (0 == strlen(invoke_diff3_cmd)) 
+    return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, NULL);
+  
+  cmd = svn_io__create_custom_diff_cmd(my_label, their_label, base_label,
+                                      my_file, their_file, base_file,
+                                      invoke_diff3_cmd, scratch_pool);
+    
+  SVN_ERR(svn_io_run_cmd(svn_dirent_internal_style(cwd, pool), 
+                         cmd[0], cmd, &exitcode, NULL, TRUE,
+                         NULL, NULL, 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 if (remains_in_conflict)
+    *remains_in_conflict = exitcode == 1;
+  svn_pool_destroy(scratch_pool);
+
+  return SVN_NO_ERROR;
+}
+
 
 /* A svn_client_ctx_t's log_msg_baton3, for use with
    svn_cl__make_log_msg_baton(). */

Modified: subversion/branches/invoke-diff3-feature/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff3-feature/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout?rev=1542514&r1=1542513&r2=1542514&view=diff
==============================================================================
--- subversion/branches/invoke-diff3-feature/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout (original)
+++ subversion/branches/invoke-diff3-feature/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout Sat Nov 16 14:36:46 2013
@@ -201,6 +201,15 @@ Valid options:
                              'empty', 'files', 'immediates', or 'infinity')
   -q [--quiet]             : print nothing, or only summary information
   --diff3-cmd ARG          : use ARG as merge command
+  --invoke-diff3-cmd ARG   : use ARG as format string for external merge program
+                             invocation.  Substitutions: 
+                               %svn_mine  'mine' file
+                               %svn_yours 'yours' file
+                               %svn_base  'base' file
+                               %svn_label_mine   label of the 'mine file
+                               %svn_label_yours  label of the 'yours' file
+                               %svn_label_base   label of the 'mine file
+                             See 'help diff' for example usage.
   --relocate               : relocate via URL-rewriting
   --ignore-externals       : ignore externals definitions
   --ignore-ancestry        : allow switching to a node with no common ancestor