/* diff3.c -- test driver for 3-way text merges * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * ==================================================================== */ #include #include #include #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 *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) { svn_diff_t *diff; SVN_ERR(svn_diff_file_diff3_2(&diff, original, modified, latest, svn_diff_file_options_create(pool), pool)); *has_changes = svn_diff_contains_diffs(diff); SVN_ERR(svn_diff_file_output_merge3(ostream, diff, original, modified, latest, conflict_original, conflict_modified, conflict_latest, "=======", conflict_style, NULL, NULL, /* cancel */ pool)); return NULL; } int main(int argc, const char *argv[]) { apr_pool_t *pool; svn_stream_t *ostream; int rc; 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); 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 - opts->ind == 3 && !help) { svn_boolean_t has_changes; 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; } else { svn_handle_error2(svn_err, stdout, FALSE, "diff3: "); rc = 2; } } else { svn_error_clear(svn_stream_printf(ostream, pool, "Usage: %s [options] \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; } apr_terminate(); return rc; }