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/09 14:18:15 UTC
svn commit: r1540299 - in /subversion/branches/invoke-diff-merge-feature: ./
subversion/include/ subversion/libsvn_client/ subversion/libsvn_subr/
subversion/libsvn_wc/ subversion/svn/
Author: gbg
Date: Sat Nov 9 13:18:14 2013
New Revision: 1540299
URL: http://svn.apache.org/r1540299
Log:
On the invoke-diff-cmd-feature branch: Checkpoint commit (ignore, trivial).
Modified:
subversion/branches/invoke-diff-merge-feature/BRANCH-README
subversion/branches/invoke-diff-merge-feature/subversion/include/svn_config.h
subversion/branches/invoke-diff-merge-feature/subversion/include/svn_io.h
subversion/branches/invoke-diff-merge-feature/subversion/include/svn_wc.h
subversion/branches/invoke-diff-merge-feature/subversion/libsvn_client/merge.c
subversion/branches/invoke-diff-merge-feature/subversion/libsvn_subr/config_file.c
subversion/branches/invoke-diff-merge-feature/subversion/libsvn_subr/io.c
subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/deprecated.c
subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/merge.c
subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/wc.h
subversion/branches/invoke-diff-merge-feature/subversion/svn/cl.h
subversion/branches/invoke-diff-merge-feature/subversion/svn/conflict-callbacks.c
subversion/branches/invoke-diff-merge-feature/subversion/svn/svn.c
subversion/branches/invoke-diff-merge-feature/subversion/svn/util.c
Modified: subversion/branches/invoke-diff-merge-feature/BRANCH-README
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/BRANCH-README?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/BRANCH-README (original)
+++ subversion/branches/invoke-diff-merge-feature/BRANCH-README Sat Nov 9 13:18:14 2013
@@ -43,11 +43,36 @@ TBD
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.
+
+& Users can specify the following mutually exclusive options:
+
+ --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-merge-cmd,
+ --diff-cmd are invoked.
+
Changes to the existing code structure:
=======================================
-TBD
+None.
+
+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-diff3-cmd feature, and any errors could cause
+many users a lot of problems.
+
+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
=====
@@ -80,12 +105,7 @@ kdiff3: 0.9.97 (32 bit)
TODO:
====
- * add invoke-merge-cmd to svn.c
- # plug in opt_get_invoke-merge-cmd
- # UI checks:
- write decision matrix
- write checking code
- # write help info
+ * write help info
* Create the UI for the interactive dialogue in
subversion/svn/conflict-callbacks.
@@ -97,11 +117,8 @@ TODO:
(3i) - interactively select diff3 tool now to resolve conflict
* make list of where else in svn to add the invoke-merge-cmd.
+ - svn cleanup
- * add routing for invoke-merge-cmd.
-
- * add new function to io.c that copies svn_io_run_diff3_3().
-
* config file service:
plug in config file service into io.c
add new entry in config file
Modified: subversion/branches/invoke-diff-merge-feature/subversion/include/svn_config.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/subversion/include/svn_config.h?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/subversion/include/svn_config.h (original)
+++ subversion/branches/invoke-diff-merge-feature/subversion/include/svn_config.h Sat Nov 9 13:18:14 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_MERGE_CMD "invoke-merge-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-diff-merge-feature/subversion/include/svn_io.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/subversion/include/svn_io.h?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/subversion/include/svn_io.h (original)
+++ subversion/branches/invoke-diff-merge-feature/subversion/include/svn_io.h Sat Nov 9 13:18:14 2013
@@ -2426,6 +2426,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-diff-merge-feature/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/subversion/include/svn_wc.h?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/subversion/include/svn_wc.h (original)
+++ subversion/branches/invoke-diff-merge-feature/subversion/include/svn_wc.h Sat Nov 9 13:18:14 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-diff-merge-feature/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/subversion/libsvn_client/merge.c?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/invoke-diff-merge-feature/subversion/libsvn_client/merge.c Sat Nov 9 13:18:14 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,
Modified: subversion/branches/invoke-diff-merge-feature/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/subversion/libsvn_subr/config_file.c?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/invoke-diff-merge-feature/subversion/libsvn_subr/config_file.c Sat Nov 9 13:18:14 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-diff-merge-feature/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/subversion/libsvn_subr/io.c?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/invoke-diff-merge-feature/subversion/libsvn_subr/io.c Sat Nov 9 13:18:14 2013
@@ -3150,6 +3150,7 @@ svn_io_run_external_diff(const char *dir
return SVN_NO_ERROR;
}
+
svn_error_t *
svn_io_run_diff2(const char *dir,
const char *const *user_args,
@@ -3331,6 +3332,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 = __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-diff-merge-feature/subversion/libsvn_wc/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/deprecated.c?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/deprecated.c (original)
+++ subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/deprecated.c Sat Nov 9 13:18:14 2013
@@ -4402,6 +4402,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 +4863,98 @@ svn_wc__conflict_description2_dup(const
return new_conflict;
}
+
+/*
+ Prepare to merge a file content change into the working copy.
+
+ This does not merge properties; see svn_wc__merge_props() for that.
+ This does not necessarily change the file TARGET_ABSPATH on disk; it
+ may instead return work items that will replace the file on disk when
+ they are run. ### Can we be more consistent about this?
+
+ Merge the difference between LEFT_ABSPATH and RIGHT_ABSPATH into
+ TARGET_ABSPATH.
+
+ Set *WORK_ITEMS to the appropriate work queue operations.
+
+ If there are any conflicts, append a conflict description to
+ *CONFLICT_SKEL. (First allocate *CONFLICT_SKEL from RESULT_POOL if
+ it is initially NULL. CONFLICT_SKEL itself must not be NULL.)
+ Also, unless it is considered to be a 'binary' file, mark any
+ conflicts in the text of the file TARGET_ABSPATH using LEFT_LABEL,
+ RIGHT_LABEL and TARGET_LABEL.
+
+ Set *MERGE_OUTCOME to indicate the result.
+
+ 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.
+
+ When MERGE_OPTIONS are specified, they are used by the internal
+ diff3 routines, or passed to the external diff3 tool.
+
+ WRI_ABSPATH describes in which working copy information should be
+ retrieved. (Interesting for merging file externals).
+
+ OLD_ACTUAL_PROPS is the set of actual properties before merging; used for
+ detranslating the file before merging. This is necessary because, in
+ the case of updating, the update can have sent new properties, so we
+ cannot simply fetch and use the current actual properties.
+
+ ### Is OLD_ACTUAL_PROPS still necessary, now that we first prepare the
+ content change and property change and then apply them both to
+ the WC together?
+
+ Property changes sent by the update are provided in PROP_DIFF.
+
+ For a complete description, see svn_wc_merge5() for which this is
+ the (loggy) implementation.
+
+ *WORK_ITEMS will be allocated in RESULT_POOL. All temporary allocations
+ will be performed in SCRATCH_POOL.
+*/
+svn_error_t *
+svn_wc__internal_merge(svn_skel_t **work_items,
+ svn_skel_t **conflict_skel,
+ enum svn_wc_merge_outcome_t *merge_outcome,
+ svn_wc__db_t *db,
+ const char *left_abspath,
+ const char *right_abspath,
+ const char *target_abspath,
+ const char *wri_abspath,
+ const char *left_label,
+ const char *right_label,
+ const char *target_label,
+ apr_hash_t *old_actual_props,
+ svn_boolean_t dry_run,
+ const char *diff3_cmd,
+ const apr_array_header_t *merge_options,
+ const apr_array_header_t *prop_diff,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_wc__internal_merge1(work_items,
+ conflict_skel,
+ merge_outcome,
+ db,
+ left_abspath,
+ right_abspath,
+ target_abspath,
+ wri_abspath,
+ left_label,
+ right_label,
+ target_label,
+ old_actual_props,
+ dry_run,
+ diff3_cmd,
+ NULL,
+ merge_options,
+ prop_diff,
+ cancel_func,
+ cancel_baton,
+ result_pool,
+ scratch_pool);
+}
Modified: subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/merge.c?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/merge.c (original)
+++ subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/merge.c Sat Nov 9 13:18:14 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,
@@ -1066,7 +1079,7 @@ merge_binary_file(svn_skel_t **work_item
}
svn_error_t *
-svn_wc__internal_merge(svn_skel_t **work_items,
+svn_wc__internal_merge1(svn_skel_t **work_items,
svn_skel_t **conflict_skel,
enum svn_wc_merge_outcome_t *merge_outcome,
svn_wc__db_t *db,
@@ -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,8 @@ 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 +1137,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 +1211,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 +1224,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,
@@ -1333,22 +1352,23 @@ svn_wc_merge5(enum svn_wc_merge_outcome_
}
/* Merge the text. */
- SVN_ERR(svn_wc__internal_merge(&work_items,
- &conflict_skel,
- merge_content_outcome,
- wc_ctx->db,
- left_abspath,
- right_abspath,
- target_abspath,
- target_abspath,
- left_label, right_label, target_label,
- old_actual_props,
- dry_run,
- diff3_cmd,
- merge_options,
- prop_diff,
- cancel_func, cancel_baton,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__internal_merge1(&work_items,
+ &conflict_skel,
+ merge_content_outcome,
+ wc_ctx->db,
+ left_abspath,
+ right_abspath,
+ target_abspath,
+ target_abspath,
+ left_label, right_label, target_label,
+ old_actual_props,
+ dry_run,
+ diff3_cmd,
+ invoke_diff3_cmd,
+ merge_options,
+ prop_diff,
+ cancel_func, cancel_baton,
+ scratch_pool, scratch_pool));
/* If this isn't a dry run, then update the DB, run the work, and
* call the conflict resolver callback. */
Modified: subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/wc.h?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/invoke-diff-merge-feature/subversion/libsvn_wc/wc.h Sat Nov 9 13:18:14 2013
@@ -440,6 +440,31 @@ svn_wc__internal_file_modified_p(svn_boo
will be performed in SCRATCH_POOL.
*/
svn_error_t *
+svn_wc__internal_merge1(svn_skel_t **work_items,
+ svn_skel_t **conflict_skel,
+ enum svn_wc_merge_outcome_t *merge_outcome,
+ svn_wc__db_t *db,
+ const char *left_abspath,
+ const char *right_abspath,
+ const char *target_abspath,
+ const char *wri_abspath,
+ const char *left_label,
+ const char *right_label,
+ 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,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/* As svn_wc__internal_merge but without the invoke_diff3_cmd parameter. */
+SVN_DEPRECATED
+svn_error_t *
svn_wc__internal_merge(svn_skel_t **work_items,
svn_skel_t **conflict_skel,
enum svn_wc_merge_outcome_t *merge_outcome,
@@ -461,6 +486,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 *
Modified: subversion/branches/invoke-diff-merge-feature/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/subversion/svn/cl.h?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/subversion/svn/cl.h (original)
+++ subversion/branches/invoke-diff-merge-feature/subversion/svn/cl.h Sat Nov 9 13:18:14 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,19 @@ 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_file_externally(const char *base_path,
+ const char *their_path,
+ const char *my_path,
+ const char *merged_path,
+ const char *wc_path,
+ apr_hash_t *config,
+ svn_boolean_t *remains_in_conflict,
+ 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-diff-merge-feature/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/subversion/svn/conflict-callbacks.c?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/subversion/svn/conflict-callbacks.c (original)
+++ subversion/branches/invoke-diff-merge-feature/subversion/svn/conflict-callbacks.c Sat Nov 9 13:18:14 2013
@@ -458,6 +458,18 @@ 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 },
+ { "3c", N_("invoke-diff3-cmd given on command line"),
+ N_("use invoke-diff3 tool defined in the "
+ "commandline to resolve conflict "
+ "[invoke-diff3-cmd]"), -1 },
+ { "3i", 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 },
@@ -735,6 +747,10 @@ handle_text_conflict(svn_wc_conflict_res
*next_option++ = "e";
*next_option++ = "m";
+ *next_option++ = "3f";
+ *next_option++ = "3c";
+ *next_option++ = "3i";
+
if (knows_something)
*next_option++ = "r";
@@ -813,7 +829,9 @@ handle_text_conflict(svn_wc_conflict_res
knows_something = TRUE;
}
else if (strcmp(opt->code, "m") == 0 || strcmp(opt->code, ":-g") == 0 ||
- strcmp(opt->code, "=>-") == 0 || strcmp(opt->code, ":>.") == 0)
+ strcmp(opt->code, "=>-") == 0 || strcmp(opt->code, ":>.") == 0 ||
+ strcmp(opt->code, "3f") == 0 || strcmp(opt->code, "3c") == 0 ||
+ strcmp(opt->code, "3i") == 0)
{
svn_boolean_t remains_in_conflict;
svn_error_t *err;
@@ -1294,6 +1312,56 @@ 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_file_externally(desc->base_abspath,
+ desc->their_abspath,
+ desc->my_abspath,
+ desc->merged_file,
+ desc->local_abspath,
+ b->config,
+ &remains_in_conflict,
+ 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-diff2-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-diff-merge-feature/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/subversion/svn/svn.c?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/subversion/svn/svn.c (original)
+++ subversion/branches/invoke-diff-merge-feature/subversion/svn/svn.c Sat Nov 9 13:18:14 2013
@@ -95,6 +95,7 @@ typedef enum svn_cl__longopt_t {
opt_ignore_externals,
opt_incremental,
opt_merge_cmd,
+ opt_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_diff_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")},
@@ -545,7 +564,7 @@ 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_merge_cmd, opt_diff3_cmd, opt_remove_unversioned, opt_remove_ignored,
opt_include_externals, 'q'} },
{ "commit", svn_cl__commit, {"ci"},
@@ -1139,8 +1158,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_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"
@@ -1603,8 +1622,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_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")}}
},
@@ -1662,9 +1682,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_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"
@@ -2173,6 +2193,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_diff3_cmd:
+ opt_state.invoke_diff3_cmd = apr_pstrdup(pool, opt_arg);
+ break;
case opt_record_only:
opt_state.record_only = TRUE;
break;
@@ -2610,6 +2633,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)
@@ -2829,8 +2862,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);
@@ -2954,6 +2994,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-diff-merge-feature/subversion/svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-merge-feature/subversion/svn/util.c?rev=1540299&r1=1540298&r2=1540299&view=diff
==============================================================================
--- subversion/branches/invoke-diff-merge-feature/subversion/svn/util.c (original)
+++ subversion/branches/invoke-diff-merge-feature/subversion/svn/util.c Sat Nov 9 13:18:14 2013
@@ -173,6 +173,104 @@ svn_cl__merge_file_externally(const char
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_cl__invoke_diff3_cmd_file_externally(const char *base_path,
+ const char *their_path,
+ const char *my_path,
+ const char *merged_path,
+ const char *wc_path,
+ apr_hash_t *config,
+ svn_boolean_t *remains_in_conflict,
+ apr_pool_t *pool)
+{
+ char *invoke_diff3_cmd;
+ /* Error if there is no editor specified */
+ /* not sure how or where to set this, but it loads on fail... so... FIXME? */
+ 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_MERGE_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"));
+
+ {
+ 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);
+
+ /* doppelt gemoppelt... FIXME */
+ if (0 == strlen(invoke_diff3_cmd))
+ return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, NULL);
+
+ /* cmd = __create_custom_diff_cmd(mine_label, yours_label, older_label, */
+ /* mine, yours, older, */
+ /* invoke_diff3_cmd, scratch_pool); */
+ cmd = __create_custom_diff_cmd(my_path, their_path, base_path,
+ my_path, merged_path, wc_path,
+ 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(). */