зеркало из https://github.com/microsoft/git.git
merge-ort: store more specific conflict information
It is all fine and dandy for a regular Git command that is intended to be run interactively to produce a bunch of messages upon an error. However, in `merge-ort`'s case, we want to call the command e.g. in server-side software, where the actual error messages are not quite as interesting as machine-readable, immutable terms that describe the exact nature of any given conflict. With this patch, the `merge-ort` machinery records the exact type (as specified via an `enum` value) as well as the involved path(s) together with the conflict's message. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
2715e8a931
Коммит
cb2607759e
253
merge-ort.c
253
merge-ort.c
|
@ -483,6 +483,100 @@ struct conflict_info {
|
|||
unsigned match_mask:3;
|
||||
};
|
||||
|
||||
enum conflict_and_info_types {
|
||||
/* "Simple" conflicts and informational messages */
|
||||
INFO_AUTO_MERGING = 0,
|
||||
CONFLICT_CONTENTS, /* text file that failed to merge */
|
||||
CONFLICT_BINARY,
|
||||
CONFLICT_FILE_DIRECTORY,
|
||||
CONFLICT_DISTINCT_MODES,
|
||||
CONFLICT_MODIFY_DELETE,
|
||||
CONFLICT_PRESENT_DESPITE_SKIPPED,
|
||||
|
||||
/* Regular rename */
|
||||
CONFLICT_RENAME_RENAME, /* same file renamed differently */
|
||||
CONFLICT_RENAME_COLLIDES, /* rename/add or two files renamed to 1 */
|
||||
CONFLICT_RENAME_DELETE,
|
||||
|
||||
/* Basic directory rename */
|
||||
CONFLICT_DIR_RENAME_SUGGESTED,
|
||||
INFO_DIR_RENAME_APPLIED,
|
||||
|
||||
/* Special directory rename cases */
|
||||
INFO_DIR_RENAME_SKIPPED_DUE_TO_RERENAME,
|
||||
CONFLICT_DIR_RENAME_FILE_IN_WAY,
|
||||
CONFLICT_DIR_RENAME_COLLISION,
|
||||
CONFLICT_DIR_RENAME_SPLIT,
|
||||
|
||||
/* Basic submodule */
|
||||
INFO_SUBMODULE_FAST_FORWARDING,
|
||||
CONFLICT_SUBMODULE_FAILED_TO_MERGE,
|
||||
|
||||
/* Special submodule cases broken out from FAILED_TO_MERGE */
|
||||
CONFLICT_SUBMODULE_FAILED_TO_MERGE_BUT_POSSIBLE_RESOLUTION,
|
||||
CONFLICT_SUBMODULE_NOT_INITIALIZED,
|
||||
CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE,
|
||||
CONFLICT_SUBMODULE_MAY_HAVE_REWINDS,
|
||||
|
||||
/* Keep this entry _last_ in the list */
|
||||
NB_CONFLICT_TYPES,
|
||||
};
|
||||
|
||||
/*
|
||||
* Short description of conflict type, relied upon by external tools.
|
||||
*
|
||||
* We can add more entries, but DO NOT change any of these strings. Also,
|
||||
* Order MUST match conflict_info_and_types.
|
||||
*/
|
||||
static const char *type_short_descriptions[] = {
|
||||
/*** "Simple" conflicts and informational messages ***/
|
||||
[INFO_AUTO_MERGING] = "Auto-merging",
|
||||
[CONFLICT_CONTENTS] = "CONFLICT (contents)",
|
||||
[CONFLICT_BINARY] = "CONFLICT (binary)",
|
||||
[CONFLICT_FILE_DIRECTORY] = "CONFLICT (file/directory)",
|
||||
[CONFLICT_DISTINCT_MODES] = "CONFLICT (distinct modes)",
|
||||
[CONFLICT_MODIFY_DELETE] = "CONFLICT (modify/delete)",
|
||||
[CONFLICT_PRESENT_DESPITE_SKIPPED] =
|
||||
"CONFLICT (upgrade your version of git)",
|
||||
|
||||
/*** Regular rename ***/
|
||||
[CONFLICT_RENAME_RENAME] = "CONFLICT (rename/rename)",
|
||||
[CONFLICT_RENAME_COLLIDES] = "CONFLICT (rename involved in collision)",
|
||||
[CONFLICT_RENAME_DELETE] = "CONFLICT (rename/delete)",
|
||||
|
||||
/*** Basic directory rename ***/
|
||||
[CONFLICT_DIR_RENAME_SUGGESTED] =
|
||||
"CONFLICT (directory rename suggested)",
|
||||
[INFO_DIR_RENAME_APPLIED] = "Path updated due to directory rename",
|
||||
|
||||
/*** Special directory rename cases ***/
|
||||
[INFO_DIR_RENAME_SKIPPED_DUE_TO_RERENAME] =
|
||||
"Directory rename skipped since directory was renamed on both sides",
|
||||
[CONFLICT_DIR_RENAME_FILE_IN_WAY] =
|
||||
"CONFLICT (file in way of directory rename)",
|
||||
[CONFLICT_DIR_RENAME_COLLISION] = "CONFLICT(directory rename collision)",
|
||||
[CONFLICT_DIR_RENAME_SPLIT] = "CONFLICT(directory rename unclear split)",
|
||||
|
||||
/*** Basic submodule ***/
|
||||
[INFO_SUBMODULE_FAST_FORWARDING] = "Fast forwarding submodule",
|
||||
[CONFLICT_SUBMODULE_FAILED_TO_MERGE] = "CONFLICT (submodule)",
|
||||
|
||||
/*** Special submodule cases broken out from FAILED_TO_MERGE ***/
|
||||
[CONFLICT_SUBMODULE_FAILED_TO_MERGE_BUT_POSSIBLE_RESOLUTION] =
|
||||
"CONFLICT (submodule with possible resolution)",
|
||||
[CONFLICT_SUBMODULE_NOT_INITIALIZED] =
|
||||
"CONFLICT (submodule not initialized)",
|
||||
[CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE] =
|
||||
"CONFLICT (submodule history not available)",
|
||||
[CONFLICT_SUBMODULE_MAY_HAVE_REWINDS] =
|
||||
"CONFLICT (submodule may have rewinds)",
|
||||
};
|
||||
|
||||
struct logical_conflict_info {
|
||||
enum conflict_and_info_types type;
|
||||
struct strvec paths;
|
||||
};
|
||||
|
||||
/*** Function Grouping: various utility functions ***/
|
||||
|
||||
/*
|
||||
|
@ -571,6 +665,11 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
|
|||
/* Release and free each strbuf found in output */
|
||||
strmap_for_each_entry(&opti->conflicts, &iter, e) {
|
||||
struct string_list *list = e->value;
|
||||
for (int i = 0; i < list->nr; i++) {
|
||||
struct logical_conflict_info *info =
|
||||
list->items[i].util;
|
||||
strvec_clear(&info->paths);
|
||||
}
|
||||
/*
|
||||
* While strictly speaking we don't need to
|
||||
* free(conflicts) here because we could pass
|
||||
|
@ -629,31 +728,56 @@ static void format_commit(struct strbuf *sb,
|
|||
strbuf_addch(sb, '\n');
|
||||
}
|
||||
|
||||
__attribute__((format (printf, 4, 5)))
|
||||
__attribute__((format (printf, 8, 9)))
|
||||
static void path_msg(struct merge_options *opt,
|
||||
const char *path,
|
||||
enum conflict_and_info_types type,
|
||||
int omittable_hint, /* skippable under --remerge-diff */
|
||||
const char *primary_path,
|
||||
const char *other_path_1, /* may be NULL */
|
||||
const char *other_path_2, /* may be NULL */
|
||||
struct string_list *other_paths, /* may be NULL */
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
struct string_list *path_conflicts;
|
||||
struct logical_conflict_info *info;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct strbuf *dest;
|
||||
struct strbuf tmp = STRBUF_INIT;
|
||||
|
||||
/* Sanity checks */
|
||||
assert(omittable_hint ==
|
||||
!starts_with(type_short_descriptions[type], "CONFLICT") ||
|
||||
type == CONFLICT_DIR_RENAME_SUGGESTED ||
|
||||
type == CONFLICT_PRESENT_DESPITE_SKIPPED);
|
||||
if (opt->record_conflict_msgs_as_headers && omittable_hint)
|
||||
return; /* Do not record mere hints in headers */
|
||||
if (opt->priv->call_depth && opt->verbosity < 5)
|
||||
return; /* Ignore messages from inner merges */
|
||||
|
||||
/* Ensure path_conflicts (ptr to array of logical_conflict) allocated */
|
||||
path_conflicts = strmap_get(&opt->priv->conflicts, path);
|
||||
path_conflicts = strmap_get(&opt->priv->conflicts, primary_path);
|
||||
if (!path_conflicts) {
|
||||
path_conflicts = xmalloc(sizeof(*path_conflicts));
|
||||
string_list_init_dup(path_conflicts);
|
||||
strmap_put(&opt->priv->conflicts, path, path_conflicts);
|
||||
strmap_put(&opt->priv->conflicts, primary_path, path_conflicts);
|
||||
}
|
||||
|
||||
/* Add a logical_conflict at the end to store info from this call */
|
||||
info = xcalloc(1, sizeof(*info));
|
||||
info->type = type;
|
||||
strvec_init(&info->paths);
|
||||
|
||||
/* Handle the list of paths */
|
||||
strvec_push(&info->paths, primary_path);
|
||||
if (other_path_1)
|
||||
strvec_push(&info->paths, other_path_1);
|
||||
if (other_path_2)
|
||||
strvec_push(&info->paths, other_path_2);
|
||||
if (other_paths)
|
||||
for (int i = 0; i < other_paths->nr; i++)
|
||||
strvec_push(&info->paths, other_paths->items[i].string);
|
||||
|
||||
/* Handle message and its format, in normal case */
|
||||
dest = (opt->record_conflict_msgs_as_headers ? &tmp : &buf);
|
||||
|
||||
|
@ -690,7 +814,8 @@ static void path_msg(struct merge_options *opt,
|
|||
|
||||
strbuf_release(&tmp);
|
||||
}
|
||||
string_list_append_nodup(path_conflicts, strbuf_detach(&buf, NULL));
|
||||
string_list_append_nodup(path_conflicts, strbuf_detach(&buf, NULL))
|
||||
->util = info;
|
||||
}
|
||||
|
||||
static struct diff_filespec *pool_alloc_filespec(struct mem_pool *pool,
|
||||
|
@ -1632,7 +1757,8 @@ static int merge_submodule(struct merge_options *opt,
|
|||
return 0;
|
||||
|
||||
if (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) {
|
||||
path_msg(opt, path, 0,
|
||||
path_msg(opt, CONFLICT_SUBMODULE_NOT_INITIALIZED, 0,
|
||||
path, NULL, NULL, NULL,
|
||||
_("Failed to merge submodule %s (not checked out)"),
|
||||
path);
|
||||
return 0;
|
||||
|
@ -1641,7 +1767,8 @@ static int merge_submodule(struct merge_options *opt,
|
|||
if (!(commit_o = lookup_commit_reference(&subrepo, o)) ||
|
||||
!(commit_a = lookup_commit_reference(&subrepo, a)) ||
|
||||
!(commit_b = lookup_commit_reference(&subrepo, b))) {
|
||||
path_msg(opt, path, 0,
|
||||
path_msg(opt, CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE, 0,
|
||||
path, NULL, NULL, NULL,
|
||||
_("Failed to merge submodule %s (commits not present)"),
|
||||
path);
|
||||
goto cleanup;
|
||||
|
@ -1650,7 +1777,8 @@ static int merge_submodule(struct merge_options *opt,
|
|||
/* check whether both changes are forward */
|
||||
if (!repo_in_merge_bases(&subrepo, commit_o, commit_a) ||
|
||||
!repo_in_merge_bases(&subrepo, commit_o, commit_b)) {
|
||||
path_msg(opt, path, 0,
|
||||
path_msg(opt, CONFLICT_SUBMODULE_MAY_HAVE_REWINDS, 0,
|
||||
path, NULL, NULL, NULL,
|
||||
_("Failed to merge submodule %s "
|
||||
"(commits don't follow merge-base)"),
|
||||
path);
|
||||
|
@ -1660,7 +1788,8 @@ static int merge_submodule(struct merge_options *opt,
|
|||
/* Case #1: a is contained in b or vice versa */
|
||||
if (repo_in_merge_bases(&subrepo, commit_a, commit_b)) {
|
||||
oidcpy(result, b);
|
||||
path_msg(opt, path, 1,
|
||||
path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1,
|
||||
path, NULL, NULL, NULL,
|
||||
_("Note: Fast-forwarding submodule %s to %s"),
|
||||
path, oid_to_hex(b));
|
||||
ret = 1;
|
||||
|
@ -1668,7 +1797,8 @@ static int merge_submodule(struct merge_options *opt,
|
|||
}
|
||||
if (repo_in_merge_bases(&subrepo, commit_b, commit_a)) {
|
||||
oidcpy(result, a);
|
||||
path_msg(opt, path, 1,
|
||||
path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1,
|
||||
path, NULL, NULL, NULL,
|
||||
_("Note: Fast-forwarding submodule %s to %s"),
|
||||
path, oid_to_hex(a));
|
||||
ret = 1;
|
||||
|
@ -1691,13 +1821,16 @@ static int merge_submodule(struct merge_options *opt,
|
|||
&merges);
|
||||
switch (parent_count) {
|
||||
case 0:
|
||||
path_msg(opt, path, 0, _("Failed to merge submodule %s"), path);
|
||||
path_msg(opt, CONFLICT_SUBMODULE_FAILED_TO_MERGE, 0,
|
||||
path, NULL, NULL, NULL,
|
||||
_("Failed to merge submodule %s"), path);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
format_commit(&sb, 4, &subrepo,
|
||||
(struct commit *)merges.objects[0].item);
|
||||
path_msg(opt, path, 0,
|
||||
path_msg(opt, CONFLICT_SUBMODULE_FAILED_TO_MERGE_BUT_POSSIBLE_RESOLUTION, 0,
|
||||
path, NULL, NULL, NULL,
|
||||
_("Failed to merge submodule %s, but a possible merge "
|
||||
"resolution exists: %s"),
|
||||
path, sb.buf);
|
||||
|
@ -1707,7 +1840,8 @@ static int merge_submodule(struct merge_options *opt,
|
|||
for (i = 0; i < merges.nr; i++)
|
||||
format_commit(&sb, 4, &subrepo,
|
||||
(struct commit *)merges.objects[i].item);
|
||||
path_msg(opt, path, 0,
|
||||
path_msg(opt, CONFLICT_SUBMODULE_FAILED_TO_MERGE_BUT_POSSIBLE_RESOLUTION, 0,
|
||||
path, NULL, NULL, NULL,
|
||||
_("Failed to merge submodule %s, but multiple "
|
||||
"possible merges exist:\n%s"), path, sb.buf);
|
||||
strbuf_release(&sb);
|
||||
|
@ -1833,7 +1967,8 @@ static int merge_3way(struct merge_options *opt,
|
|||
&src1, name1, &src2, name2,
|
||||
&opt->priv->attr_index, &ll_opts);
|
||||
if (merge_status == LL_MERGE_BINARY_CONFLICT)
|
||||
path_msg(opt, path, 0,
|
||||
path_msg(opt, CONFLICT_BINARY, 0,
|
||||
path, NULL, NULL, NULL,
|
||||
"warning: Cannot merge binary files: %s (%s vs. %s)",
|
||||
path, name1, name2);
|
||||
|
||||
|
@ -1945,7 +2080,8 @@ static int handle_content_merge(struct merge_options *opt,
|
|||
if (ret)
|
||||
return -1;
|
||||
clean &= (merge_status == 0);
|
||||
path_msg(opt, path, 1, _("Auto-merging %s"), path);
|
||||
path_msg(opt, INFO_AUTO_MERGING, 1, path, NULL, NULL, NULL,
|
||||
_("Auto-merging %s"), path);
|
||||
} else if (S_ISGITLINK(a->mode)) {
|
||||
int two_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));
|
||||
clean = merge_submodule(opt, pathnames[0],
|
||||
|
@ -2083,20 +2219,23 @@ static char *handle_path_level_conflicts(struct merge_options *opt,
|
|||
c_info->reported_already = 1;
|
||||
strbuf_add_separated_string_list(&collision_paths, ", ",
|
||||
&c_info->source_files);
|
||||
path_msg(opt, new_path, 0,
|
||||
_("CONFLICT (implicit dir rename): Existing file/dir "
|
||||
"at %s in the way of implicit directory rename(s) "
|
||||
"putting the following path(s) there: %s."),
|
||||
path_msg(opt, CONFLICT_DIR_RENAME_FILE_IN_WAY, 0,
|
||||
new_path, NULL, NULL, &c_info->source_files,
|
||||
_("CONFLICT (implicit dir rename): Existing "
|
||||
"file/dir at %s in the way of implicit "
|
||||
"directory rename(s) putting the following "
|
||||
"path(s) there: %s."),
|
||||
new_path, collision_paths.buf);
|
||||
clean = 0;
|
||||
} else if (c_info->source_files.nr > 1) {
|
||||
c_info->reported_already = 1;
|
||||
strbuf_add_separated_string_list(&collision_paths, ", ",
|
||||
&c_info->source_files);
|
||||
path_msg(opt, new_path, 0,
|
||||
_("CONFLICT (implicit dir rename): Cannot map more "
|
||||
"than one path to %s; implicit directory renames "
|
||||
"tried to put these paths there: %s"),
|
||||
path_msg(opt, CONFLICT_DIR_RENAME_COLLISION, 0,
|
||||
new_path, NULL, NULL, &c_info->source_files,
|
||||
_("CONFLICT (implicit dir rename): Cannot map "
|
||||
"more than one path to %s; implicit directory "
|
||||
"renames tried to put these paths there: %s"),
|
||||
new_path, collision_paths.buf);
|
||||
clean = 0;
|
||||
}
|
||||
|
@ -2151,12 +2290,13 @@ static void get_provisional_directory_renames(struct merge_options *opt,
|
|||
continue;
|
||||
|
||||
if (bad_max == max) {
|
||||
path_msg(opt, source_dir, 0,
|
||||
path_msg(opt, CONFLICT_DIR_RENAME_SPLIT, 0,
|
||||
source_dir, NULL, NULL, NULL,
|
||||
_("CONFLICT (directory rename split): "
|
||||
"Unclear where to rename %s to; it was "
|
||||
"renamed to multiple other directories, with "
|
||||
"no destination getting a majority of the "
|
||||
"files."),
|
||||
"renamed to multiple other directories, "
|
||||
"with no destination getting a majority of "
|
||||
"the files."),
|
||||
source_dir);
|
||||
*clean = 0;
|
||||
} else {
|
||||
|
@ -2305,7 +2445,8 @@ static char *check_for_directory_rename(struct merge_options *opt,
|
|||
*/
|
||||
otherinfo = strmap_get_entry(dir_rename_exclusions, new_dir);
|
||||
if (otherinfo) {
|
||||
path_msg(opt, rename_info->key, 1,
|
||||
path_msg(opt, INFO_DIR_RENAME_SKIPPED_DUE_TO_RERENAME, 1,
|
||||
rename_info->key, path, new_dir, NULL,
|
||||
_("WARNING: Avoiding applying %s -> %s rename "
|
||||
"to %s, because %s itself was renamed."),
|
||||
rename_info->key, new_dir, path, new_dir);
|
||||
|
@ -2445,14 +2586,16 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
|
|||
if (opt->detect_directory_renames == MERGE_DIRECTORY_RENAMES_TRUE) {
|
||||
/* Notify user of updated path */
|
||||
if (pair->status == 'A')
|
||||
path_msg(opt, new_path, 1,
|
||||
path_msg(opt, INFO_DIR_RENAME_APPLIED, 1,
|
||||
new_path, old_path, NULL, NULL,
|
||||
_("Path updated: %s added in %s inside a "
|
||||
"directory that was renamed in %s; moving "
|
||||
"it to %s."),
|
||||
old_path, branch_with_new_path,
|
||||
branch_with_dir_rename, new_path);
|
||||
else
|
||||
path_msg(opt, new_path, 1,
|
||||
path_msg(opt, INFO_DIR_RENAME_APPLIED, 1,
|
||||
new_path, old_path, NULL, NULL,
|
||||
_("Path updated: %s renamed to %s in %s, "
|
||||
"inside a directory that was renamed in %s; "
|
||||
"moving it to %s."),
|
||||
|
@ -2465,7 +2608,8 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
|
|||
*/
|
||||
ci->path_conflict = 1;
|
||||
if (pair->status == 'A')
|
||||
path_msg(opt, new_path, 1,
|
||||
path_msg(opt, CONFLICT_DIR_RENAME_SUGGESTED, 1,
|
||||
new_path, old_path, NULL, NULL,
|
||||
_("CONFLICT (file location): %s added in %s "
|
||||
"inside a directory that was renamed in %s, "
|
||||
"suggesting it should perhaps be moved to "
|
||||
|
@ -2473,7 +2617,8 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
|
|||
old_path, branch_with_new_path,
|
||||
branch_with_dir_rename, new_path);
|
||||
else
|
||||
path_msg(opt, new_path, 1,
|
||||
path_msg(opt, CONFLICT_DIR_RENAME_SUGGESTED, 1,
|
||||
new_path, old_path, NULL, NULL,
|
||||
_("CONFLICT (file location): %s renamed to %s "
|
||||
"in %s, inside a directory that was renamed "
|
||||
"in %s, suggesting it should perhaps be "
|
||||
|
@ -2629,7 +2774,8 @@ static int process_renames(struct merge_options *opt,
|
|||
* and remove the setting of base->path_conflict to 1.
|
||||
*/
|
||||
base->path_conflict = 1;
|
||||
path_msg(opt, oldpath, 0,
|
||||
path_msg(opt, CONFLICT_RENAME_RENAME, 0,
|
||||
pathnames[0], pathnames[1], pathnames[2], NULL,
|
||||
_("CONFLICT (rename/rename): %s renamed to "
|
||||
"%s in %s and to %s in %s."),
|
||||
pathnames[0],
|
||||
|
@ -2724,7 +2870,8 @@ static int process_renames(struct merge_options *opt,
|
|||
memcpy(&newinfo->stages[target_index], &merged,
|
||||
sizeof(merged));
|
||||
if (!clean) {
|
||||
path_msg(opt, newpath, 0,
|
||||
path_msg(opt, CONFLICT_RENAME_COLLIDES, 0,
|
||||
newpath, oldpath, NULL, NULL,
|
||||
_("CONFLICT (rename involved in "
|
||||
"collision): rename of %s -> %s has "
|
||||
"content conflicts AND collides "
|
||||
|
@ -2743,7 +2890,8 @@ static int process_renames(struct merge_options *opt,
|
|||
*/
|
||||
|
||||
newinfo->path_conflict = 1;
|
||||
path_msg(opt, newpath, 0,
|
||||
path_msg(opt, CONFLICT_RENAME_DELETE, 0,
|
||||
newpath, oldpath, NULL, NULL,
|
||||
_("CONFLICT (rename/delete): %s renamed "
|
||||
"to %s in %s, but deleted in %s."),
|
||||
oldpath, newpath, rename_branch, delete_branch);
|
||||
|
@ -2767,7 +2915,8 @@ static int process_renames(struct merge_options *opt,
|
|||
} else if (source_deleted) {
|
||||
/* rename/delete */
|
||||
newinfo->path_conflict = 1;
|
||||
path_msg(opt, newpath, 0,
|
||||
path_msg(opt, CONFLICT_RENAME_DELETE, 0,
|
||||
newpath, oldpath, NULL, NULL,
|
||||
_("CONFLICT (rename/delete): %s renamed"
|
||||
" to %s in %s, but deleted in %s."),
|
||||
oldpath, newpath,
|
||||
|
@ -3688,7 +3837,8 @@ static void process_entry(struct merge_options *opt,
|
|||
path = unique_path(opt, path, branch);
|
||||
strmap_put(&opt->priv->paths, path, new_ci);
|
||||
|
||||
path_msg(opt, path, 0,
|
||||
path_msg(opt, CONFLICT_FILE_DIRECTORY, 0,
|
||||
path, old_path, NULL, NULL,
|
||||
_("CONFLICT (file/directory): directory in the way "
|
||||
"of %s from %s; moving it to %s instead."),
|
||||
old_path, branch, path);
|
||||
|
@ -3764,15 +3914,23 @@ static void process_entry(struct merge_options *opt,
|
|||
rename_b = 1;
|
||||
}
|
||||
|
||||
if (rename_a)
|
||||
a_path = unique_path(opt, path, opt->branch1);
|
||||
if (rename_b)
|
||||
b_path = unique_path(opt, path, opt->branch2);
|
||||
|
||||
if (rename_a && rename_b) {
|
||||
path_msg(opt, path, 0,
|
||||
path_msg(opt, CONFLICT_DISTINCT_MODES, 0,
|
||||
path, a_path, b_path, NULL,
|
||||
_("CONFLICT (distinct types): %s had "
|
||||
"different types on each side; "
|
||||
"renamed both of them so each can "
|
||||
"be recorded somewhere."),
|
||||
path);
|
||||
} else {
|
||||
path_msg(opt, path, 0,
|
||||
path_msg(opt, CONFLICT_DISTINCT_MODES, 0,
|
||||
path, rename_a ? a_path : b_path,
|
||||
NULL, NULL,
|
||||
_("CONFLICT (distinct types): %s had "
|
||||
"different types on each side; "
|
||||
"renamed one of them so each can be "
|
||||
|
@ -3809,14 +3967,10 @@ static void process_entry(struct merge_options *opt,
|
|||
|
||||
/* Insert entries into opt->priv_paths */
|
||||
assert(rename_a || rename_b);
|
||||
if (rename_a) {
|
||||
a_path = unique_path(opt, path, opt->branch1);
|
||||
if (rename_a)
|
||||
strmap_put(&opt->priv->paths, a_path, ci);
|
||||
}
|
||||
|
||||
if (rename_b)
|
||||
b_path = unique_path(opt, path, opt->branch2);
|
||||
else
|
||||
if (!rename_b)
|
||||
b_path = path;
|
||||
strmap_put(&opt->priv->paths, b_path, new_ci);
|
||||
|
||||
|
@ -3867,7 +4021,8 @@ static void process_entry(struct merge_options *opt,
|
|||
reason = _("add/add");
|
||||
if (S_ISGITLINK(merged_file.mode))
|
||||
reason = _("submodule");
|
||||
path_msg(opt, path, 0,
|
||||
path_msg(opt, CONFLICT_CONTENTS, 0,
|
||||
path, NULL, NULL, NULL,
|
||||
_("CONFLICT (%s): Merge conflict in %s"),
|
||||
reason, path);
|
||||
}
|
||||
|
@ -3911,7 +4066,8 @@ static void process_entry(struct merge_options *opt,
|
|||
* since the contents were not modified.
|
||||
*/
|
||||
} else {
|
||||
path_msg(opt, path, 0,
|
||||
path_msg(opt, CONFLICT_MODIFY_DELETE, 0,
|
||||
path, NULL, NULL, NULL,
|
||||
_("CONFLICT (modify/delete): %s deleted in %s "
|
||||
"and modified in %s. Version %s of %s left "
|
||||
"in tree."),
|
||||
|
@ -4207,7 +4363,8 @@ static int record_conflicted_index_entries(struct merge_options *opt)
|
|||
path,
|
||||
"cruft");
|
||||
|
||||
path_msg(opt, path, 1,
|
||||
path_msg(opt, CONFLICT_PRESENT_DESPITE_SKIPPED, 1,
|
||||
path, NULL, NULL, NULL,
|
||||
_("Note: %s not up to date and in way of checking out conflicted version; old copy renamed to %s"),
|
||||
path, new_name);
|
||||
errs |= rename(path, new_name);
|
||||
|
|
Загрузка…
Ссылка в новой задаче