diff options
Diffstat (limited to 'tools/diff/diff3.c')
-rw-r--r-- | tools/diff/diff3.c | 153 |
1 files changed, 141 insertions, 12 deletions
diff --git a/tools/diff/diff3.c b/tools/diff/diff3.c index 63d7dec..5502254 100644 --- a/tools/diff/diff3.c +++ b/tools/diff/diff3.c @@ -28,11 +28,19 @@ #include "svn_pools.h" #include "svn_diff.h" #include "svn_io.h" +#include "svn_opt.h" +#include "private/svn_token.h" static svn_error_t * do_diff3(svn_stream_t *ostream, - const char *original, const char *modified, const char *latest, + const char *original, + const char *modified, + const char *latest, + const char *conflict_original, + const char *conflict_modified, + const char *conflict_latest, + svn_diff_conflict_display_style_t conflict_style, svn_boolean_t *has_changes, apr_pool_t *pool) { @@ -43,38 +51,129 @@ do_diff3(svn_stream_t *ostream, *has_changes = svn_diff_contains_diffs(diff); - SVN_ERR(svn_diff_file_output_merge2(ostream, diff, + SVN_ERR(svn_diff_file_output_merge3(ostream, diff, original, modified, latest, - NULL, NULL, NULL, NULL, - svn_diff_conflict_display_modified_latest, + conflict_original, + conflict_modified, + conflict_latest, + "=======", + conflict_style, + NULL, NULL, /* cancel */ pool)); return NULL; } -int main(int argc, char *argv[]) +int main(int argc, const char *argv[]) { apr_pool_t *pool; svn_stream_t *ostream; int rc; - svn_error_t *svn_err; + svn_error_t *svn_err = SVN_NO_ERROR; + apr_getopt_t *opts; + svn_boolean_t help = FALSE; + + enum { + conflict_style_opt = SVN_OPT_FIRST_LONGOPT_ID + }; + static const apr_getopt_option_t options[] = { + {"conflict-style", conflict_style_opt, 1, ""}, + {"label", 'L', 1, ""}, + {"show-overlap", 'E', 0, ""}, + {"merge", 'm', 0, ""}, + {"help", 'h', 0, ""}, + {NULL, '?', 0, ""}, + {NULL, 0, 0, NULL} + }; + svn_diff_conflict_display_style_t conflict_style + = svn_diff_conflict_display_modified_latest; + const svn_token_map_t style_map[] = { + { "modified-latest", + svn_diff_conflict_display_modified_latest }, + { "resolved-modified-latest", + svn_diff_conflict_display_resolved_modified_latest }, + { "modified-original-latest", + svn_diff_conflict_display_modified_original_latest }, + { "modified", + svn_diff_conflict_display_modified }, + { "latest", + svn_diff_conflict_display_latest }, + { "only-conflicts", + svn_diff_conflict_display_only_conflicts }, + {NULL, 0} + }; + const char *conflict_original = NULL; + const char *conflict_modified = NULL; + const char *conflict_latest = NULL; apr_initialize(); pool = svn_pool_create(NULL); - svn_err = svn_stream_for_stdout(&ostream, pool); + apr_getopt_init(&opts, pool, argc, argv); + opts->interleave = 1; + while (!svn_err) + { + int opt; + const char *arg; + apr_status_t status = apr_getopt_long(opts, options, &opt, &arg); + + if (APR_STATUS_IS_EOF(status)) + break; + if (status != APR_SUCCESS) + { + svn_err = svn_error_wrap_apr(status, "getopt failure"); + break; + } + switch (opt) + { + case conflict_style_opt: + { + int val; + svn_err = svn_token__from_word_err(&val, style_map, arg); + conflict_style = val; + break; + } + case 'L': + if (!conflict_modified) + conflict_modified = apr_pstrcat(pool, "<<<<<<< ", arg, SVN_VA_NULL); + else if (!conflict_original) + conflict_original = apr_pstrcat(pool, "||||||| ", arg, SVN_VA_NULL); + else if (!conflict_latest) + conflict_latest = apr_pstrcat(pool, ">>>>>>> ", arg, SVN_VA_NULL); + else + svn_err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + "too many labels"); + break; + case 'E': + case 'm': + /* These are allowed and ignored so that all the options + passed when invoking --diff3-cmd are accepted as that + makes it easier to use this as an external diff3 + program. */ + break; + case 'h': + case '?': + help = TRUE; + break; + } + } + + if (!svn_err) + svn_err = svn_stream_for_stdout(&ostream, pool); if (svn_err) { svn_handle_error2(svn_err, stdout, FALSE, "diff3: "); + svn_error_clear(svn_err); rc = 2; } - else if (argc == 4) + else if (argc - opts->ind == 3 && !help) { svn_boolean_t has_changes; - svn_err = do_diff3(ostream, argv[2], argv[1], argv[3], - &has_changes, pool); + svn_err = do_diff3(ostream, argv[argc-2], argv[argc-3], argv[argc-1], + conflict_original, conflict_modified, conflict_latest, + conflict_style, &has_changes, pool); if (svn_err == NULL) { rc = has_changes ? 1 : 0; @@ -88,8 +187,38 @@ int main(int argc, char *argv[]) else { svn_error_clear(svn_stream_printf(ostream, pool, - "Usage: %s <mine> <older> <yours>\n", - argv[0])); + "Usage: %s [options] <mine> <older> <yours>\n" + "Options:\n" + " --conflict-style STYLE\n" + " where STYLE can be:\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + "\n" + " --label [-L] LABEL\n" + " can be repeated up to three times\n" + "\n" + " --merge [-m]\n" + " ignored (present for compatibility)\n" + "\n" + " --show-overlap [-E]\n" + " ignored (present for compatibility)\n", + argv[0], + svn_token__to_word(style_map, + svn_diff_conflict_display_modified_latest), + svn_token__to_word(style_map, + svn_diff_conflict_display_resolved_modified_latest), + svn_token__to_word(style_map, + svn_diff_conflict_display_modified_original_latest), + svn_token__to_word(style_map, + svn_diff_conflict_display_modified), + svn_token__to_word(style_map, + svn_diff_conflict_display_latest), + svn_token__to_word(style_map, + svn_diff_conflict_display_only_conflicts))); rc = 2; } |