git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 1/2] merge_recursive_options: introduce the "gentle" flag

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Oct 8, 2015, 20:35 UTC
Message-ID
<fed6b32cff01f38196e3dd43025076a47f841a74.1444336120.git.johannes.schindelin@gmx.de>
In-Reply-To
<cover.1444336120.git.johannes.schindelin@gmx.de>

Traditionally, all of Git's operations were intended as single executables to be run once and exit, not as library functions with careful error code paths. Therefore, it was okay for those operations to simply die() with an error.

However, this assumption no longer holds true: builtin `am` calls merge_recursive_generic() as a regular library function whose return value indicates whether there was a problem.

Throughout Git's source code, that paradigm (to return an error instead of die()ing) is called "gentle".

Let's introduce this flag and heed it in as many places as is easily done.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 merge-recursive.c | 44 +++++++++++++++++++++++++++++++++++---------
 merge-recursive.h |  1 +
 2 files changed, 36 insertions(+), 9 deletions(-)
diff --git a/merge-recursive.c b/merge-recursive.c
index 44d85be..37528c9 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -266,8 +266,12 @@ struct tree *write_tree_from_memory(struct merge_options *o)
 		active_cache_tree = cache_tree();
 
 	if (!cache_tree_fully_valid(active_cache_tree) &&
-	    cache_tree_update(&the_index, 0) < 0)
-		die(_("error building trees"));
+	    cache_tree_update(&the_index, 0) < 0) {
+		if (!o->gentle)
+			die(_("error building trees"));
+		error(_("error building trees"));
+		return NULL;
+	}
 
 	result = lookup_tree(active_cache_tree->sha1);
 
@@ -712,6 +716,8 @@ static int make_room_for_path(struct merge_options *o, const char *path)
 			error(msg, path, _(": perhaps a D/F conflict?"));
 			return -1;
 		}
+		if (o->gentle)
+			return error(msg, path, "");
 		die(msg, path, "");
 	}
 
@@ -1340,8 +1346,11 @@ static int process_renames(struct merge_options *o,
 			const char *ren2_src = ren2->pair->one->path;
 			const char *ren2_dst = ren2->pair->two->path;
 			enum rename_type rename_type;
-			if (strcmp(ren1_src, ren2_src) != 0)
+			if (strcmp(ren1_src, ren2_src) != 0) {
+				if (o->gentle)
+					return error("ren1_src != ren2_src");
 				die("ren1_src != ren2_src");
+			}
 			ren2->dst_entry->processed = 1;
 			ren2->processed = 1;
 			if (strcmp(ren1_dst, ren2_dst) != 0) {
@@ -1374,8 +1383,11 @@ static int process_renames(struct merge_options *o,
 			char *ren2_dst;
 			ren2 = lookup->util;
 			ren2_dst = ren2->pair->two->path;
-			if (strcmp(ren1_dst, ren2_dst) != 0)
+			if (strcmp(ren1_dst, ren2_dst) != 0) {
+				if (o->gentle)
+					return error("ren1_dst != ren2_dst");
 				die("ren1_dst != ren2_dst");
+			}
 
 			clean_merge = 0;
 			ren2->processed = 1;
@@ -1818,6 +1830,11 @@ int merge_trees(struct merge_options *o,
 	code = git_merge_trees(o->call_depth, common, head, merge);
 
 	if (code != 0) {
+		if (o->gentle)
+			return error(_("merging of trees %s and %s failed"),
+			    sha1_to_hex(head->object.sha1),
+			    sha1_to_hex(merge->object.sha1));
+
 		if (show(o, 4) || o->call_depth)
 			die(_("merging of trees %s and %s failed"),
 			    sha1_to_hex(head->object.sha1),
@@ -1864,8 +1881,8 @@ int merge_trees(struct merge_options *o,
 	else
 		clean = 1;
 
-	if (o->call_depth)
-		*result = write_tree_from_memory(o);
+	if (o->call_depth && !(*result = write_tree_from_memory(o)))
+		return -1;
 
 	return clean;
 }
@@ -1940,14 +1957,18 @@ int merge_recursive(struct merge_options *o,
 		saved_b2 = o->branch2;
 		o->branch1 = "Temporary merge branch 1";
 		o->branch2 = "Temporary merge branch 2";
-		merge_recursive(o, merged_common_ancestors, iter->item,
-				NULL, &merged_common_ancestors);
+		if (merge_recursive(o, merged_common_ancestors, iter->item,
+				NULL, &merged_common_ancestors) < 0)
+			return -1;
 		o->branch1 = saved_b1;
 		o->branch2 = saved_b2;
 		o->call_depth--;
 
-		if (!merged_common_ancestors)
+		if (!merged_common_ancestors) {
+			if (o->gentle)
+				return error(_("merge returned no commit"));
 			die(_("merge returned no commit"));
+		}
 	}
 
 	discard_cache();
@@ -1957,6 +1978,8 @@ int merge_recursive(struct merge_options *o,
 	o->ancestor = "merged common ancestors";
 	clean = merge_trees(o, h1->tree, h2->tree, merged_common_ancestors->tree,
 			    &mrtree);
+	if (clean < 0)
+		return clean;
 
 	if (o->call_depth) {
 		*result = make_virtual_commit(mrtree, "merged tree");
@@ -2013,6 +2036,9 @@ int merge_recursive_generic(struct merge_options *o,
 	hold_locked_index(lock, 1);
 	clean = merge_recursive(o, head_commit, next_commit, ca,
 			result);
+	if (clean < 0)
+		return clean;
+
 	if (active_cache_changed &&
 	    write_locked_index(&the_index, lock, COMMIT_LOCK))
 		return error(_("Unable to write index."));
diff --git a/merge-recursive.h b/merge-recursive.h
index 9e090a3..06f9b7e 100644
--- a/merge-recursive.h
+++ b/merge-recursive.h
@@ -15,6 +15,7 @@ struct merge_options {
 	const char *subtree_shift;
 	unsigned buffer_output : 1;
 	unsigned renormalize : 1;
+	unsigned gentle : 1;
 	long xdl_opts;
 	int verbosity;
 	int diff_rename_limit;
-- 
2.6.1.windows.1
Previous: Johannes SchindelinNext: Johannes Schindelin
Message 2 of 22 in “Reinstate the helpful message when `git pull --rebase` fails”
  1. 0/2 Reinstate the helpful message when `git pull --rebase` failsJohannes Schindelin, Oct 8, 2015
  2. 1/2 merge_recursive_options: introduce the "gentle" flagJohannes Schindelin, Oct 8, 2015
  3. 2/2 pull --rebase: reinstate helpful message on abortJohannes Schindelin, Oct 8, 2015
  4. Junio C HamanoOct 9, 2015
  5. Johannes SchindelinOct 12, 2015
  6. Junio C HamanoOct 12, 2015
  7. Junio C HamanoOct 9, 2015
  8. Paul TanOct 9, 2015
  9. Johannes SchindelinOct 9, 2015
  10. Johannes SchindelinOct 9, 2015
  11. Junio C HamanoOct 9, 2015
  12. Torsten BögershausenOct 10, 2015
  13. Torsten BögershausenOct 10, 2015
  14. Johannes SchindelinOct 12, 2015
  15. Junio C HamanoOct 9, 2015
  16. Junio C HamanoOct 9, 2015
  17. Junio C HamanoOct 9, 2015
  18. Johannes SchindelinOct 12, 2015
  19. Junio C HamanoOct 9, 2015
  20. Johannes SchindelinOct 12, 2015
  21. Junio C HamanoOct 12, 2015
  22. Johannes SchindelinOct 13, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.