merge-ort: handle book-keeping around two- and three-way content merge

In addition to the content merge (which will go in a subsequent commit), we need to worry about conflict messages, placing results in higher order stages in case of a df_conflict, and making sure the results are placed in ci->merged.result so that they will show up in the working tree. Take care of all that external book-keeping, moving the simplistic just-take-HEAD code into the barebones handle_content_merge() function for now. Subsequent commits will flesh out handle_content_merge(). Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Jan 1, 2021 at 02:34 UTC 991bbdcab94d93c2a325c4ce74cff139f0f49d97
1 file changed +41 -11
merge-ort.c
+41 -11
@@ -640,7 +640,15 @@ static int handle_content_merge(struct merge_options *opt,
640 const int extra_marker_size,
641 struct version_info *result)
642 {
643 - die("Not yet implemented");
643 + int clean = 0;
644 + /*
645 + * TODO: Needs a two-way or three-way content merge, but we're
646 + * just being lazy and copying the version from HEAD and
647 + * leaving it as conflicted.
648 + */
649 + result->mode = a->mode;
650 + oidcpy(&result->oid, &a->oid);
651 + return clean;
652 }
653
654 /*** Function Grouping: functions related to detect_and_process_renames(), ***
@@ -1138,16 +1146,38 @@ static void process_entry(struct merge_options *opt,
1146 */
1147 die("Not yet implemented.");
1148 } else if (ci->filemask >= 6) {
1141 - /*
1142 - * TODO: Needs a two-way or three-way content merge, but we're
1143 - * just being lazy and copying the version from HEAD and
1144 - * leaving it as conflicted.
1145 - */
1146 - ci->merged.clean = 0;
1147 - ci->merged.result.mode = ci->stages[1].mode;
1148 - oidcpy(&ci->merged.result.oid, &ci->stages[1].oid);
1149 - /* When we fix above, we'll call handle_content_merge() */
1150 - (void)handle_content_merge;
1149 + /* Need a two-way or three-way content merge */
1150 + struct version_info merged_file;
1151 + unsigned clean_merge;
1152 + struct version_info *o = &ci->stages[0];
1153 + struct version_info *a = &ci->stages[1];
1154 + struct version_info *b = &ci->stages[2];
1155 +
1156 + clean_merge = handle_content_merge(opt, path, o, a, b,
1157 + ci->pathnames,
1158 + opt->priv->call_depth * 2,
1159 + &merged_file);
1160 + ci->merged.clean = clean_merge &&
1161 + !ci->df_conflict && !ci->path_conflict;
1162 + ci->merged.result.mode = merged_file.mode;
1163 + ci->merged.is_null = (merged_file.mode == 0);
1164 + oidcpy(&ci->merged.result.oid, &merged_file.oid);
1165 + if (clean_merge && ci->df_conflict) {
1166 + assert(df_file_index == 1 || df_file_index == 2);
1167 + ci->filemask = 1 << df_file_index;
1168 + ci->stages[df_file_index].mode = merged_file.mode;
1169 + oidcpy(&ci->stages[df_file_index].oid, &merged_file.oid);
1170 + }
1171 + if (!clean_merge) {
1172 + const char *reason = _("content");
1173 + if (ci->filemask == 6)
1174 + reason = _("add/add");
1175 + if (S_ISGITLINK(merged_file.mode))
1176 + reason = _("submodule");
1177 + path_msg(opt, path, 0,
1178 + _("CONFLICT (%s): Merge conflict in %s"),
1179 + reason, path);
1180 + }
1181 } else if (ci->filemask == 3 || ci->filemask == 5) {
1182 /* Modify/delete */
1183 const char *modify_branch, *delete_branch;