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>
Elijah Newren committed
Jun 18, 2022 at 00:20 UTC
cb2607759e27627aca614726dc50e98ac0ba6d19
1 file changed
+212
-55
merge-ort.c
+212
-55
@@ -483,6 +483,100 @@ struct conflict_info {
483
unsigned match_mask:3;
484
};
485
486
+enum conflict_and_info_types {
487
+ /* "Simple" conflicts and informational messages */
488
+ INFO_AUTO_MERGING = 0,
489
+ CONFLICT_CONTENTS, /* text file that failed to merge */
490
+ CONFLICT_BINARY,
491
+ CONFLICT_FILE_DIRECTORY,
492
+ CONFLICT_DISTINCT_MODES,
493
+ CONFLICT_MODIFY_DELETE,
494
+ CONFLICT_PRESENT_DESPITE_SKIPPED,
495
+
496
+ /* Regular rename */
497
+ CONFLICT_RENAME_RENAME, /* same file renamed differently */
498
+ CONFLICT_RENAME_COLLIDES, /* rename/add or two files renamed to 1 */
499
+ CONFLICT_RENAME_DELETE,
500
+
501
+ /* Basic directory rename */
502
+ CONFLICT_DIR_RENAME_SUGGESTED,
503
+ INFO_DIR_RENAME_APPLIED,
504
+
505
+ /* Special directory rename cases */
506
+ INFO_DIR_RENAME_SKIPPED_DUE_TO_RERENAME,
507
+ CONFLICT_DIR_RENAME_FILE_IN_WAY,
508
+ CONFLICT_DIR_RENAME_COLLISION,
509
+ CONFLICT_DIR_RENAME_SPLIT,
510
+
511
+ /* Basic submodule */
512
+ INFO_SUBMODULE_FAST_FORWARDING,
513
+ CONFLICT_SUBMODULE_FAILED_TO_MERGE,
514
+
515
+ /* Special submodule cases broken out from FAILED_TO_MERGE */
516
+ CONFLICT_SUBMODULE_FAILED_TO_MERGE_BUT_POSSIBLE_RESOLUTION,
517
+ CONFLICT_SUBMODULE_NOT_INITIALIZED,
518
+ CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE,
519
+ CONFLICT_SUBMODULE_MAY_HAVE_REWINDS,
520
+
521
+ /* Keep this entry _last_ in the list */
522
+ NB_CONFLICT_TYPES,
523
+};
524
+
525
+/*
526
+ * Short description of conflict type, relied upon by external tools.
527
+ *
528
+ * We can add more entries, but DO NOT change any of these strings. Also,
529
+ * Order MUST match conflict_info_and_types.
530
+ */
531
+static const char *type_short_descriptions[] = {
532
+ /*** "Simple" conflicts and informational messages ***/
533
+ [INFO_AUTO_MERGING] = "Auto-merging",
534
+ [CONFLICT_CONTENTS] = "CONFLICT (contents)",
535
+ [CONFLICT_BINARY] = "CONFLICT (binary)",
536
+ [CONFLICT_FILE_DIRECTORY] = "CONFLICT (file/directory)",
537
+ [CONFLICT_DISTINCT_MODES] = "CONFLICT (distinct modes)",
538
+ [CONFLICT_MODIFY_DELETE] = "CONFLICT (modify/delete)",
539
+ [CONFLICT_PRESENT_DESPITE_SKIPPED] =
540
+ "CONFLICT (upgrade your version of git)",
541
+
542
+ /*** Regular rename ***/
543
+ [CONFLICT_RENAME_RENAME] = "CONFLICT (rename/rename)",
544
+ [CONFLICT_RENAME_COLLIDES] = "CONFLICT (rename involved in collision)",
545
+ [CONFLICT_RENAME_DELETE] = "CONFLICT (rename/delete)",
546
+
547
+ /*** Basic directory rename ***/
548
+ [CONFLICT_DIR_RENAME_SUGGESTED] =
549
+ "CONFLICT (directory rename suggested)",
550
+ [INFO_DIR_RENAME_APPLIED] = "Path updated due to directory rename",
551
+
552
+ /*** Special directory rename cases ***/
553
+ [INFO_DIR_RENAME_SKIPPED_DUE_TO_RERENAME] =
554
+ "Directory rename skipped since directory was renamed on both sides",
555
+ [CONFLICT_DIR_RENAME_FILE_IN_WAY] =
556
+ "CONFLICT (file in way of directory rename)",
557
+ [CONFLICT_DIR_RENAME_COLLISION] = "CONFLICT(directory rename collision)",
558
+ [CONFLICT_DIR_RENAME_SPLIT] = "CONFLICT(directory rename unclear split)",
559
+
560
+ /*** Basic submodule ***/
561
+ [INFO_SUBMODULE_FAST_FORWARDING] = "Fast forwarding submodule",
562
+ [CONFLICT_SUBMODULE_FAILED_TO_MERGE] = "CONFLICT (submodule)",
563
+
564
+ /*** Special submodule cases broken out from FAILED_TO_MERGE ***/
565
+ [CONFLICT_SUBMODULE_FAILED_TO_MERGE_BUT_POSSIBLE_RESOLUTION] =
566
+ "CONFLICT (submodule with possible resolution)",
567
+ [CONFLICT_SUBMODULE_NOT_INITIALIZED] =
568
+ "CONFLICT (submodule not initialized)",
569
+ [CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE] =
570
+ "CONFLICT (submodule history not available)",
571
+ [CONFLICT_SUBMODULE_MAY_HAVE_REWINDS] =
572
+ "CONFLICT (submodule may have rewinds)",
573
+};
574
+
575
+struct logical_conflict_info {
576
+ enum conflict_and_info_types type;
577
+ struct strvec paths;
578
+};
579
+
580
/*** Function Grouping: various utility functions ***/
581
582
/*
@@ -571,6 +665,11 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
665
/* Release and free each strbuf found in output */
666
strmap_for_each_entry(&opti->conflicts, &iter, e) {
667
struct string_list *list = e->value;
668
+ for (int i = 0; i < list->nr; i++) {
669
+ struct logical_conflict_info *info =
670
+ list->items[i].util;
671
+ strvec_clear(&info->paths);
672
+ }
673
/*
674
* While strictly speaking we don't need to
675
* free(conflicts) here because we could pass
@@ -629,31 +728,56 @@ static void format_commit(struct strbuf *sb,
728
strbuf_addch(sb, '\n');
729
}
730
632
-__attribute__((format (printf, 4, 5)))
731
+__attribute__((format (printf, 8, 9)))
732
static void path_msg(struct merge_options *opt,
634
- const char *path,
733
+ enum conflict_and_info_types type,
734
int omittable_hint, /* skippable under --remerge-diff */
735
+ const char *primary_path,
736
+ const char *other_path_1, /* may be NULL */
737
+ const char *other_path_2, /* may be NULL */
738
+ struct string_list *other_paths, /* may be NULL */
739
const char *fmt, ...)
740
{
741
va_list ap;
742
struct string_list *path_conflicts;
743
+ struct logical_conflict_info *info;
744
struct strbuf buf = STRBUF_INIT;
745
struct strbuf *dest;
746
struct strbuf tmp = STRBUF_INIT;
747
748
+ /* Sanity checks */
749
+ assert(omittable_hint ==
750
+ !starts_with(type_short_descriptions[type], "CONFLICT") ||
751
+ type == CONFLICT_DIR_RENAME_SUGGESTED ||
752
+ type == CONFLICT_PRESENT_DESPITE_SKIPPED);
753
if (opt->record_conflict_msgs_as_headers && omittable_hint)
754
return; /* Do not record mere hints in headers */
755
if (opt->priv->call_depth && opt->verbosity < 5)
756
return; /* Ignore messages from inner merges */
757
758
/* Ensure path_conflicts (ptr to array of logical_conflict) allocated */
650
- path_conflicts = strmap_get(&opt->priv->conflicts, path);
759
+ path_conflicts = strmap_get(&opt->priv->conflicts, primary_path);
760
if (!path_conflicts) {
761
path_conflicts = xmalloc(sizeof(*path_conflicts));
762
string_list_init_dup(path_conflicts);
654
- strmap_put(&opt->priv->conflicts, path, path_conflicts);
763
+ strmap_put(&opt->priv->conflicts, primary_path, path_conflicts);
764
}
765
766
+ /* Add a logical_conflict at the end to store info from this call */
767
+ info = xcalloc(1, sizeof(*info));
768
+ info->type = type;
769
+ strvec_init(&info->paths);
770
+
771
+ /* Handle the list of paths */
772
+ strvec_push(&info->paths, primary_path);
773
+ if (other_path_1)
774
+ strvec_push(&info->paths, other_path_1);
775
+ if (other_path_2)
776
+ strvec_push(&info->paths, other_path_2);
777
+ if (other_paths)
778
+ for (int i = 0; i < other_paths->nr; i++)
779
+ strvec_push(&info->paths, other_paths->items[i].string);
780
+
781
/* Handle message and its format, in normal case */
782
dest = (opt->record_conflict_msgs_as_headers ? &tmp : &buf);
783
@@ -690,7 +814,8 @@ static void path_msg(struct merge_options *opt,
814
815
strbuf_release(&tmp);
816
}
693
- string_list_append_nodup(path_conflicts, strbuf_detach(&buf, NULL));
817
+ string_list_append_nodup(path_conflicts, strbuf_detach(&buf, NULL))
818
+ ->util = info;
819
}
820
821
static struct diff_filespec *pool_alloc_filespec(struct mem_pool *pool,
@@ -1632,16 +1757,18 @@ static int merge_submodule(struct merge_options *opt,
1757
return 0;
1758
1759
if (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) {
1635
- path_msg(opt, path, 0,
1636
- _("Failed to merge submodule %s (not checked out)"),
1637
- path);
1760
+ path_msg(opt, CONFLICT_SUBMODULE_NOT_INITIALIZED, 0,
1761
+ path, NULL, NULL, NULL,
1762
+ _("Failed to merge submodule %s (not checked out)"),
1763
+ path);
1764
return 0;
1765
}
1766
1767
if (!(commit_o = lookup_commit_reference(&subrepo, o)) ||
1768
!(commit_a = lookup_commit_reference(&subrepo, a)) ||
1769
!(commit_b = lookup_commit_reference(&subrepo, b))) {
1644
- path_msg(opt, path, 0,
1770
+ path_msg(opt, CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE, 0,
1771
+ path, NULL, NULL, NULL,
1772
_("Failed to merge submodule %s (commits not present)"),
1773
path);
1774
goto cleanup;
@@ -1650,7 +1777,8 @@ static int merge_submodule(struct merge_options *opt,
1777
/* check whether both changes are forward */
1778
if (!repo_in_merge_bases(&subrepo, commit_o, commit_a) ||
1779
!repo_in_merge_bases(&subrepo, commit_o, commit_b)) {
1653
- path_msg(opt, path, 0,
1780
+ path_msg(opt, CONFLICT_SUBMODULE_MAY_HAVE_REWINDS, 0,
1781
+ path, NULL, NULL, NULL,
1782
_("Failed to merge submodule %s "
1783
"(commits don't follow merge-base)"),
1784
path);
@@ -1660,7 +1788,8 @@ static int merge_submodule(struct merge_options *opt,
1788
/* Case #1: a is contained in b or vice versa */
1789
if (repo_in_merge_bases(&subrepo, commit_a, commit_b)) {
1790
oidcpy(result, b);
1663
- path_msg(opt, path, 1,
1791
+ path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1,
1792
+ path, NULL, NULL, NULL,
1793
_("Note: Fast-forwarding submodule %s to %s"),
1794
path, oid_to_hex(b));
1795
ret = 1;
@@ -1668,7 +1797,8 @@ static int merge_submodule(struct merge_options *opt,
1797
}
1798
if (repo_in_merge_bases(&subrepo, commit_b, commit_a)) {
1799
oidcpy(result, a);
1671
- path_msg(opt, path, 1,
1800
+ path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1,
1801
+ path, NULL, NULL, NULL,
1802
_("Note: Fast-forwarding submodule %s to %s"),
1803
path, oid_to_hex(a));
1804
ret = 1;
@@ -1691,13 +1821,16 @@ static int merge_submodule(struct merge_options *opt,
1821
&merges);
1822
switch (parent_count) {
1823
case 0:
1694
- path_msg(opt, path, 0, _("Failed to merge submodule %s"), path);
1824
+ path_msg(opt, CONFLICT_SUBMODULE_FAILED_TO_MERGE, 0,
1825
+ path, NULL, NULL, NULL,
1826
+ _("Failed to merge submodule %s"), path);
1827
break;
1828
1829
case 1:
1830
format_commit(&sb, 4, &subrepo,
1831
(struct commit *)merges.objects[0].item);
1700
- path_msg(opt, path, 0,
1832
+ path_msg(opt, CONFLICT_SUBMODULE_FAILED_TO_MERGE_BUT_POSSIBLE_RESOLUTION, 0,
1833
+ path, NULL, NULL, NULL,
1834
_("Failed to merge submodule %s, but a possible merge "
1835
"resolution exists: %s"),
1836
path, sb.buf);
@@ -1707,7 +1840,8 @@ static int merge_submodule(struct merge_options *opt,
1840
for (i = 0; i < merges.nr; i++)
1841
format_commit(&sb, 4, &subrepo,
1842
(struct commit *)merges.objects[i].item);
1710
- path_msg(opt, path, 0,
1843
+ path_msg(opt, CONFLICT_SUBMODULE_FAILED_TO_MERGE_BUT_POSSIBLE_RESOLUTION, 0,
1844
+ path, NULL, NULL, NULL,
1845
_("Failed to merge submodule %s, but multiple "
1846
"possible merges exist:\n%s"), path, sb.buf);
1847
strbuf_release(&sb);
@@ -1833,7 +1967,8 @@ static int merge_3way(struct merge_options *opt,
1967
&src1, name1, &src2, name2,
1968
&opt->priv->attr_index, &ll_opts);
1969
if (merge_status == LL_MERGE_BINARY_CONFLICT)
1836
- path_msg(opt, path, 0,
1970
+ path_msg(opt, CONFLICT_BINARY, 0,
1971
+ path, NULL, NULL, NULL,
1972
"warning: Cannot merge binary files: %s (%s vs. %s)",
1973
path, name1, name2);
1974
@@ -1945,7 +2080,8 @@ static int handle_content_merge(struct merge_options *opt,
2080
if (ret)
2081
return -1;
2082
clean &= (merge_status == 0);
1948
- path_msg(opt, path, 1, _("Auto-merging %s"), path);
2083
+ path_msg(opt, INFO_AUTO_MERGING, 1, path, NULL, NULL, NULL,
2084
+ _("Auto-merging %s"), path);
2085
} else if (S_ISGITLINK(a->mode)) {
2086
int two_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));
2087
clean = merge_submodule(opt, pathnames[0],
@@ -2083,21 +2219,24 @@ static char *handle_path_level_conflicts(struct merge_options *opt,
2219
c_info->reported_already = 1;
2220
strbuf_add_separated_string_list(&collision_paths, ", ",
2221
&c_info->source_files);
2086
- path_msg(opt, new_path, 0,
2087
- _("CONFLICT (implicit dir rename): Existing file/dir "
2088
- "at %s in the way of implicit directory rename(s) "
2089
- "putting the following path(s) there: %s."),
2090
- new_path, collision_paths.buf);
2222
+ path_msg(opt, CONFLICT_DIR_RENAME_FILE_IN_WAY, 0,
2223
+ new_path, NULL, NULL, &c_info->source_files,
2224
+ _("CONFLICT (implicit dir rename): Existing "
2225
+ "file/dir at %s in the way of implicit "
2226
+ "directory rename(s) putting the following "
2227
+ "path(s) there: %s."),
2228
+ new_path, collision_paths.buf);
2229
clean = 0;
2230
} else if (c_info->source_files.nr > 1) {
2231
c_info->reported_already = 1;
2232
strbuf_add_separated_string_list(&collision_paths, ", ",
2233
&c_info->source_files);
2096
- path_msg(opt, new_path, 0,
2097
- _("CONFLICT (implicit dir rename): Cannot map more "
2098
- "than one path to %s; implicit directory renames "
2099
- "tried to put these paths there: %s"),
2100
- new_path, collision_paths.buf);
2234
+ path_msg(opt, CONFLICT_DIR_RENAME_COLLISION, 0,
2235
+ new_path, NULL, NULL, &c_info->source_files,
2236
+ _("CONFLICT (implicit dir rename): Cannot map "
2237
+ "more than one path to %s; implicit directory "
2238
+ "renames tried to put these paths there: %s"),
2239
+ new_path, collision_paths.buf);
2240
clean = 0;
2241
}
2242
@@ -2151,13 +2290,14 @@ static void get_provisional_directory_renames(struct merge_options *opt,
2290
continue;
2291
2292
if (bad_max == max) {
2154
- path_msg(opt, source_dir, 0,
2155
- _("CONFLICT (directory rename split): "
2156
- "Unclear where to rename %s to; it was "
2157
- "renamed to multiple other directories, with "
2158
- "no destination getting a majority of the "
2159
- "files."),
2160
- source_dir);
2293
+ path_msg(opt, CONFLICT_DIR_RENAME_SPLIT, 0,
2294
+ source_dir, NULL, NULL, NULL,
2295
+ _("CONFLICT (directory rename split): "
2296
+ "Unclear where to rename %s to; it was "
2297
+ "renamed to multiple other directories, "
2298
+ "with no destination getting a majority of "
2299
+ "the files."),
2300
+ source_dir);
2301
*clean = 0;
2302
} else {
2303
strmap_put(&renames->dir_renames[side],
@@ -2305,7 +2445,8 @@ static char *check_for_directory_rename(struct merge_options *opt,
2445
*/
2446
otherinfo = strmap_get_entry(dir_rename_exclusions, new_dir);
2447
if (otherinfo) {
2308
- path_msg(opt, rename_info->key, 1,
2448
+ path_msg(opt, INFO_DIR_RENAME_SKIPPED_DUE_TO_RERENAME, 1,
2449
+ rename_info->key, path, new_dir, NULL,
2450
_("WARNING: Avoiding applying %s -> %s rename "
2451
"to %s, because %s itself was renamed."),
2452
rename_info->key, new_dir, path, new_dir);
@@ -2445,14 +2586,16 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
2586
if (opt->detect_directory_renames == MERGE_DIRECTORY_RENAMES_TRUE) {
2587
/* Notify user of updated path */
2588
if (pair->status == 'A')
2448
- path_msg(opt, new_path, 1,
2589
+ path_msg(opt, INFO_DIR_RENAME_APPLIED, 1,
2590
+ new_path, old_path, NULL, NULL,
2591
_("Path updated: %s added in %s inside a "
2592
"directory that was renamed in %s; moving "
2593
"it to %s."),
2594
old_path, branch_with_new_path,
2595
branch_with_dir_rename, new_path);
2596
else
2455
- path_msg(opt, new_path, 1,
2597
+ path_msg(opt, INFO_DIR_RENAME_APPLIED, 1,
2598
+ new_path, old_path, NULL, NULL,
2599
_("Path updated: %s renamed to %s in %s, "
2600
"inside a directory that was renamed in %s; "
2601
"moving it to %s."),
@@ -2465,7 +2608,8 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
2608
*/
2609
ci->path_conflict = 1;
2610
if (pair->status == 'A')
2468
- path_msg(opt, new_path, 1,
2611
+ path_msg(opt, CONFLICT_DIR_RENAME_SUGGESTED, 1,
2612
+ new_path, old_path, NULL, NULL,
2613
_("CONFLICT (file location): %s added in %s "
2614
"inside a directory that was renamed in %s, "
2615
"suggesting it should perhaps be moved to "
@@ -2473,7 +2617,8 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
2617
old_path, branch_with_new_path,
2618
branch_with_dir_rename, new_path);
2619
else
2476
- path_msg(opt, new_path, 1,
2620
+ path_msg(opt, CONFLICT_DIR_RENAME_SUGGESTED, 1,
2621
+ new_path, old_path, NULL, NULL,
2622
_("CONFLICT (file location): %s renamed to %s "
2623
"in %s, inside a directory that was renamed "
2624
"in %s, suggesting it should perhaps be "
@@ -2629,7 +2774,8 @@ static int process_renames(struct merge_options *opt,
2774
* and remove the setting of base->path_conflict to 1.
2775
*/
2776
base->path_conflict = 1;
2632
- path_msg(opt, oldpath, 0,
2777
+ path_msg(opt, CONFLICT_RENAME_RENAME, 0,
2778
+ pathnames[0], pathnames[1], pathnames[2], NULL,
2779
_("CONFLICT (rename/rename): %s renamed to "
2780
"%s in %s and to %s in %s."),
2781
pathnames[0],
@@ -2724,7 +2870,8 @@ static int process_renames(struct merge_options *opt,
2870
memcpy(&newinfo->stages[target_index], &merged,
2871
sizeof(merged));
2872
if (!clean) {
2727
- path_msg(opt, newpath, 0,
2873
+ path_msg(opt, CONFLICT_RENAME_COLLIDES, 0,
2874
+ newpath, oldpath, NULL, NULL,
2875
_("CONFLICT (rename involved in "
2876
"collision): rename of %s -> %s has "
2877
"content conflicts AND collides "
@@ -2743,7 +2890,8 @@ static int process_renames(struct merge_options *opt,
2890
*/
2891
2892
newinfo->path_conflict = 1;
2746
- path_msg(opt, newpath, 0,
2893
+ path_msg(opt, CONFLICT_RENAME_DELETE, 0,
2894
+ newpath, oldpath, NULL, NULL,
2895
_("CONFLICT (rename/delete): %s renamed "
2896
"to %s in %s, but deleted in %s."),
2897
oldpath, newpath, rename_branch, delete_branch);
@@ -2767,7 +2915,8 @@ static int process_renames(struct merge_options *opt,
2915
} else if (source_deleted) {
2916
/* rename/delete */
2917
newinfo->path_conflict = 1;
2770
- path_msg(opt, newpath, 0,
2918
+ path_msg(opt, CONFLICT_RENAME_DELETE, 0,
2919
+ newpath, oldpath, NULL, NULL,
2920
_("CONFLICT (rename/delete): %s renamed"
2921
" to %s in %s, but deleted in %s."),
2922
oldpath, newpath,
@@ -3688,7 +3837,8 @@ static void process_entry(struct merge_options *opt,
3837
path = unique_path(opt, path, branch);
3838
strmap_put(&opt->priv->paths, path, new_ci);
3839
3691
- path_msg(opt, path, 0,
3840
+ path_msg(opt, CONFLICT_FILE_DIRECTORY, 0,
3841
+ path, old_path, NULL, NULL,
3842
_("CONFLICT (file/directory): directory in the way "
3843
"of %s from %s; moving it to %s instead."),
3844
old_path, branch, path);
@@ -3764,15 +3914,23 @@ static void process_entry(struct merge_options *opt,
3914
rename_b = 1;
3915
}
3916
3917
+ if (rename_a)
3918
+ a_path = unique_path(opt, path, opt->branch1);
3919
+ if (rename_b)
3920
+ b_path = unique_path(opt, path, opt->branch2);
3921
+
3922
if (rename_a && rename_b) {
3768
- path_msg(opt, path, 0,
3923
+ path_msg(opt, CONFLICT_DISTINCT_MODES, 0,
3924
+ path, a_path, b_path, NULL,
3925
_("CONFLICT (distinct types): %s had "
3926
"different types on each side; "
3927
"renamed both of them so each can "
3928
"be recorded somewhere."),
3929
path);
3930
} else {
3775
- path_msg(opt, path, 0,
3931
+ path_msg(opt, CONFLICT_DISTINCT_MODES, 0,
3932
+ path, rename_a ? a_path : b_path,
3933
+ NULL, NULL,
3934
_("CONFLICT (distinct types): %s had "
3935
"different types on each side; "
3936
"renamed one of them so each can be "
@@ -3809,14 +3967,10 @@ static void process_entry(struct merge_options *opt,
3967
3968
/* Insert entries into opt->priv_paths */
3969
assert(rename_a || rename_b);
3812
- if (rename_a) {
3813
- a_path = unique_path(opt, path, opt->branch1);
3970
+ if (rename_a)
3971
strmap_put(&opt->priv->paths, a_path, ci);
3815
- }
3972
3817
- if (rename_b)
3818
- b_path = unique_path(opt, path, opt->branch2);
3819
- else
3973
+ if (!rename_b)
3974
b_path = path;
3975
strmap_put(&opt->priv->paths, b_path, new_ci);
3976
@@ -3867,7 +4021,8 @@ static void process_entry(struct merge_options *opt,
4021
reason = _("add/add");
4022
if (S_ISGITLINK(merged_file.mode))
4023
reason = _("submodule");
3870
- path_msg(opt, path, 0,
4024
+ path_msg(opt, CONFLICT_CONTENTS, 0,
4025
+ path, NULL, NULL, NULL,
4026
_("CONFLICT (%s): Merge conflict in %s"),
4027
reason, path);
4028
}
@@ -3911,7 +4066,8 @@ static void process_entry(struct merge_options *opt,
4066
* since the contents were not modified.
4067
*/
4068
} else {
3914
- path_msg(opt, path, 0,
4069
+ path_msg(opt, CONFLICT_MODIFY_DELETE, 0,
4070
+ path, NULL, NULL, NULL,
4071
_("CONFLICT (modify/delete): %s deleted in %s "
4072
"and modified in %s. Version %s of %s left "
4073
"in tree."),
@@ -4207,7 +4363,8 @@ static int record_conflicted_index_entries(struct merge_options *opt)
4363
path,
4364
"cruft");
4365
4210
- path_msg(opt, path, 1,
4366
+ path_msg(opt, CONFLICT_PRESENT_DESPITE_SKIPPED, 1,
4367
+ path, NULL, NULL, NULL,
4368
_("Note: %s not up to date and in way of checking out conflicted version; old copy renamed to %s"),
4369
path, new_name);
4370
errs |= rename(path, new_name);