📄 merge.c
字号:
/*
* merge.c: merging changes into a working file
*
* ====================================================================
* Copyright (c) 2000-2004 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_config.h"
#include "svn_path.h"
#include "wc.h"
#include "entries.h"
#include "translate.h"
#include "questions.h"
#include "svn_private_config.h"
svn_error_t *
svn_wc_merge (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,
enum svn_wc_merge_outcome_t *merge_outcome,
const char *diff3_cmd,
apr_pool_t *pool)
{
const char *tmp_target, *result_target, *tmp_left, *tmp_right;
const char *mt_pt, *mt_bn;
apr_file_t *tmp_f, *result_f;
svn_boolean_t is_binary;
svn_subst_keywords_t *keywords;
const char *eol;
const svn_wc_entry_t *entry;
svn_boolean_t contains_conflicts, special;
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_file (&tmp_target, merge_target, adm_access,
TRUE, pool));
if (tmp_target == merge_target) /* contraction didn't happen */
{
/* The target is already in repository form, so we just need to
make a verbatim copy of it. */
SVN_ERR (svn_io_open_unique_file (&tmp_f, &tmp_target,
merge_target,
SVN_WC__TMP_EXT,
FALSE, pool));
SVN_ERR (svn_io_file_close (tmp_f, pool));
SVN_ERR (svn_io_copy_file (merge_target,
tmp_target, TRUE, pool));
}
/* Open a second temporary file for writing; this is where diff3
will write the merged results. */
SVN_ERR (svn_io_open_unique_file (&result_f, &result_target,
merge_target, SVN_WC__TMP_EXT,
FALSE, 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_file (&tmp_f, &tmp_left,
tmp_target,
SVN_WC__TMP_EXT,
FALSE, pool));
SVN_ERR (svn_io_file_close (tmp_f, pool));
SVN_ERR (svn_io_open_unique_file (&tmp_f, &tmp_right,
tmp_target,
SVN_WC__TMP_EXT,
FALSE, pool));
SVN_ERR (svn_io_file_close (tmp_f, 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 (".",
tmp_target, tmp_left, tmp_right,
target_label, left_label, right_label,
result_f, &exit_code, diff3_cmd, 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;
ostream = svn_stream_from_aprfile(result_f, pool);
SVN_ERR (svn_diff_file_diff3 (&diff,
tmp_left, tmp_target, tmp_right,
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). */
apr_file_t *lcopy_f, *rcopy_f, *tcopy_f;
const char *left_copy, *right_copy, *target_copy;
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_file (&lcopy_f,
&left_copy,
merge_target,
left_label,
FALSE,
pool));
SVN_ERR (svn_io_file_close (lcopy_f, pool));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -