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>maint
							parent
							
								
									2715e8a931
								
							
						
					
					
						commit
						cb2607759e
					
				
							
								
								
									
										267
									
								
								merge-ort.c
								
								
								
								
							
							
						
						
									
										267
									
								
								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,16 +1757,18 @@ 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, | ||||
| 				_("Failed to merge submodule %s (not checked out)"), | ||||
| 				path); | ||||
| 		path_msg(opt, CONFLICT_SUBMODULE_NOT_INITIALIZED, 0, | ||||
| 			 path, NULL, NULL, NULL, | ||||
| 			 _("Failed to merge submodule %s (not checked out)"), | ||||
| 			 path); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	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,21 +2219,24 @@ 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."), | ||||
| 		       new_path, collision_paths.buf); | ||||
| 		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"), | ||||
| 		       new_path, collision_paths.buf); | ||||
| 		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,13 +2290,14 @@ static void get_provisional_directory_renames(struct merge_options *opt, | |||
| 			continue; | ||||
|  | ||||
| 		if (bad_max == max) { | ||||
| 			path_msg(opt, source_dir, 0, | ||||
| 			       _("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."), | ||||
| 			       source_dir); | ||||
| 			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."), | ||||
| 				 source_dir); | ||||
| 			*clean = 0; | ||||
| 		} else { | ||||
| 			strmap_put(&renames->dir_renames[side], | ||||
|  | @ -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); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Elijah Newren
						Elijah Newren