📄 merge.c
字号:
/* * merge.c: merging changes into a working file * * ==================================================================== * Copyright (c) 2000-2006 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#include "svn_wc.h"#include "svn_diff.h"#include "svn_path.h"#include "wc.h"#include "entries.h"#include "translate.h"#include "questions.h"#include "log.h"#include "svn_private_config.h"svn_error_t *svn_wc__merge_internal(svn_stringbuf_t **log_accum, enum svn_wc_merge_outcome_t *merge_outcome, const char *left, const char *right, const char *merge_target, svn_wc_adm_access_t *adm_access, const char *left_label, const char *right_label, const char *target_label, svn_boolean_t dry_run, const char *diff3_cmd, const apr_array_header_t *merge_options, apr_pool_t *pool){ const char *tmp_target, *result_target, *tmp_left, *tmp_right; const char *mt_pt, *mt_bn; const char *adm_path = svn_wc_adm_access_path(adm_access); const char *log_merge_target = svn_path_is_child(adm_path, merge_target, pool); apr_file_t *result_f; svn_boolean_t is_binary; const svn_wc_entry_t *entry; svn_boolean_t contains_conflicts; svn_path_split(merge_target, &mt_pt, &mt_bn, pool); /* Sanity check: the merge target must be under revision control. */ SVN_ERR(svn_wc_entry(&entry, merge_target, adm_access, FALSE, pool)); if (! entry) { *merge_outcome = svn_wc_merge_no_merge; return SVN_NO_ERROR; } /* Decide if the merge target is a text or binary file. */ SVN_ERR(svn_wc_has_binary_prop(&is_binary, merge_target, adm_access, pool)); if (! is_binary) /* this is a text file */ { /* Make sure a temporary copy of 'target' is available with keywords contracted and line endings in repository-normal (LF) form. This is the file that diff3 will read as the 'mine' file. */ SVN_ERR(svn_wc_translated_file2 (&tmp_target, merge_target, merge_target, adm_access, SVN_WC_TRANSLATE_TO_NF | SVN_WC_TRANSLATE_FORCE_COPY, pool)); /* Open a second temporary file for writing; this is where diff3 will write the merged results. */ SVN_ERR(svn_wc_create_tmp_file2(&result_f, &result_target, adm_path, svn_io_file_del_none, pool)); /* LEFT and RIGHT might be in totally different directories than MERGE_TARGET, and our diff3 command wants them all to be in the same directory. So make temporary copies of LEFT and RIGHT right next to the target. */ SVN_ERR(svn_io_open_unique_file2(NULL, &tmp_left, tmp_target, SVN_WC__TMP_EXT, svn_io_file_del_on_pool_cleanup, pool)); SVN_ERR(svn_io_open_unique_file2(NULL, &tmp_right, tmp_target, SVN_WC__TMP_EXT, svn_io_file_del_on_pool_cleanup, pool)); SVN_ERR(svn_io_copy_file(left, tmp_left, TRUE, pool)); SVN_ERR(svn_io_copy_file(right, tmp_right, TRUE, pool)); /* Run an external merge if requested. */ if (diff3_cmd) { int exit_code; SVN_ERR(svn_io_run_diff3_2(&exit_code, ".", tmp_target, tmp_left, tmp_right, target_label, left_label, right_label, result_f, diff3_cmd, merge_options, pool)); contains_conflicts = exit_code == 1; } else { svn_diff_t *diff; const char *target_marker; const char *left_marker; const char *right_marker; svn_stream_t *ostream; svn_diff_file_options_t *options; ostream = svn_stream_from_aprfile(result_f, pool); options = svn_diff_file_options_create(pool); if (merge_options) SVN_ERR(svn_diff_file_options_parse(options, merge_options, pool)); SVN_ERR(svn_diff_file_diff3_2(&diff, tmp_left, tmp_target, tmp_right, options, pool)); /* Labels fall back to sensible defaults if not specified. */ if (target_label) target_marker = apr_psprintf(pool, "<<<<<<< %s", target_label); else target_marker = "<<<<<<< .working"; if (left_label) left_marker = apr_psprintf(pool, "||||||| %s", left_label); else left_marker = "||||||| .old"; if (right_label) right_marker = apr_psprintf(pool, ">>>>>>> %s", right_label); else right_marker = ">>>>>>> .new"; SVN_ERR(svn_diff_file_output_merge(ostream, diff, tmp_left, tmp_target, tmp_right, left_marker, target_marker, right_marker, "=======", /* seperator */ FALSE, /* display original */ FALSE, /* resolve conflicts */ pool)); SVN_ERR(svn_stream_close(ostream)); contains_conflicts = svn_diff_contains_conflicts(diff); } /* Close the output file */ SVN_ERR(svn_io_file_close(result_f, pool)); if (contains_conflicts && ! dry_run) /* got a conflict */ { /* Preserve the three pre-merge files, and modify the entry (mark as conflicted, track the preserved files). */ const char *left_copy, *right_copy, *target_copy; const char *xtmp_left, *xtmp_right; const char *parentt, *left_base, *right_base, *target_base; svn_wc_adm_access_t *parent_access; svn_wc_entry_t tmp_entry; /* I miss Lisp. */ SVN_ERR(svn_io_open_unique_file2(NULL, &left_copy, merge_target, left_label, svn_io_file_del_none, pool)); /* Have I mentioned how much I miss Lisp? */ SVN_ERR(svn_io_open_unique_file2(NULL, &right_copy, merge_target, right_label, svn_io_file_del_none, pool)); /* Why, how much more pleasant to be forced to unroll my loops. If I'd been writing in Lisp, I might have mapped an inline lambda form over a list, or something equally disgusting. Thank goodness C was here to protect me! */ SVN_ERR(svn_io_open_unique_file2(NULL, &target_copy, merge_target, target_label, svn_io_file_del_none, pool)); /* We preserve all the files with keywords expanded and line endings in local (working) form. */ svn_path_split(target_copy, &parentt, &target_base, pool); SVN_ERR(svn_wc_adm_retrieve(&parent_access, adm_access, parentt, pool)); /* Log files require their paths to be in the subtree relative to the adm_access path they are executed in. Make our LEFT and RIGHT files 'local' if they aren't... */ xtmp_left = svn_path_is_child(adm_path, left, pool);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -