| /* 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 <apr.h> |
| #include <apr_general.h> |
| #include <apr_file_io.h> |
| |
| #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] <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; |
| } |
| |
| apr_terminate(); |
| |
| return rc; |
| } |