From 808e83f2667e4b442a8f58f0c7ef55feb6864f65 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 14 Sep 2023 05:39:48 -0400 Subject: [PATCH 1/5] merge-ort: drop custom err() function The merge-ort code has an err() function, but it's really just error() in disguise. It differs in two ways: 1. It takes a "struct merge_options" argument. But the function completely ignores it! We can simply remove it. 2. It formats the error string into a strbuf, prepending "error: ", and then feeds the result into error(). But this is wrong! The error() function already adds the prefix, so we end up with: error: error: Failed to execute internal merge So let's just drop this function entirely and call error() directly, as the functions are otherwise identical (note that they both always return -1). Presumably nobody noticed the bogus messages because they are quite hard to trigger (they are mostly internal errors reading and writing objects). However, one easy trigger is a custom merge driver which dies by signal; we have a test already here, but we were not checking the contents of stderr. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- merge-ort.c | 28 +++++----------------------- t/t6406-merge-attr.sh | 3 ++- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/merge-ort.c b/merge-ort.c index 8631c99700..027ecc7f78 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -721,23 +721,6 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti, renames->callback_data_nr = renames->callback_data_alloc = 0; } -__attribute__((format (printf, 2, 3))) -static int err(struct merge_options *opt, const char *err, ...) -{ - va_list params; - struct strbuf sb = STRBUF_INIT; - - strbuf_addstr(&sb, "error: "); - va_start(params, err); - strbuf_vaddf(&sb, err, params); - va_end(params); - - error("%s", sb.buf); - strbuf_release(&sb); - - return -1; -} - static void format_commit(struct strbuf *sb, int indent, struct repository *repo, @@ -2122,13 +2105,12 @@ static int handle_content_merge(struct merge_options *opt, &result_buf); if ((merge_status < 0) || !result_buf.ptr) - ret = err(opt, _("Failed to execute internal merge")); + ret = error(_("Failed to execute internal merge")); if (!ret && write_object_file(result_buf.ptr, result_buf.size, OBJ_BLOB, &result->oid)) - ret = err(opt, _("Unable to add %s to database"), - path); + ret = error(_("Unable to add %s to database"), path); free(result_buf.ptr); if (ret) @@ -3518,10 +3500,10 @@ static int read_oid_strbuf(struct merge_options *opt, unsigned long size; buf = repo_read_object_file(the_repository, oid, &type, &size); if (!buf) - return err(opt, _("cannot read object %s"), oid_to_hex(oid)); + return error(_("cannot read object %s"), oid_to_hex(oid)); if (type != OBJ_BLOB) { free(buf); - return err(opt, _("object %s is not a blob"), oid_to_hex(oid)); + return error(_("object %s is not a blob"), oid_to_hex(oid)); } strbuf_attach(dst, buf, size, size + 1); return 0; @@ -4973,7 +4955,7 @@ redo: * TRANSLATORS: The %s arguments are: 1) tree hash of a merge * base, and 2-3) the trees for the two trees we're merging. */ - err(opt, _("collecting merge info failed for trees %s, %s, %s"), + error(_("collecting merge info failed for trees %s, %s, %s"), oid_to_hex(&merge_base->object.oid), oid_to_hex(&side1->object.oid), oid_to_hex(&side2->object.oid)); diff --git a/t/t6406-merge-attr.sh b/t/t6406-merge-attr.sh index 9677180a5b..05ad13b23e 100755 --- a/t/t6406-merge-attr.sh +++ b/t/t6406-merge-attr.sh @@ -179,7 +179,8 @@ test_expect_success !WINDOWS 'custom merge driver that is killed with a signal' >./please-abort && echo "* merge=custom" >.gitattributes && - test_must_fail git merge main && + test_must_fail git merge main 2>err && + grep "^error: Failed to execute internal merge" err && git ls-files -u >output && git diff --name-only HEAD >>output && test_must_be_empty output From 1c9419ae9d262dab33bef22dea5c166d990b921e Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 14 Sep 2023 05:39:53 -0400 Subject: [PATCH 2/5] merge-ort: stop passing "opt" to read_oid_strbuf() This function doesn't look at its merge_options parameter. It used to pass it down to err(), but that function no longer exists (and didn't look at "opt" anyway). We can drop it here. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- merge-ort.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/merge-ort.c b/merge-ort.c index 027ecc7f78..31c663b297 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -3491,8 +3491,7 @@ static int sort_dirs_next_to_their_children(const char *one, const char *two) return c1 - c2; } -static int read_oid_strbuf(struct merge_options *opt, - const struct object_id *oid, +static int read_oid_strbuf(const struct object_id *oid, struct strbuf *dst) { void *buf; @@ -3527,8 +3526,8 @@ static int blob_unchanged(struct merge_options *opt, if (oideq(&base->oid, &side->oid)) return 1; - if (read_oid_strbuf(opt, &base->oid, &basebuf) || - read_oid_strbuf(opt, &side->oid, &sidebuf)) + if (read_oid_strbuf(&base->oid, &basebuf) || + read_oid_strbuf(&side->oid, &sidebuf)) goto error_return; /* * Note: binary | is used so that both renormalizations are From fce9ffb2253660346c826a969c2b49a485e70cbd Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 14 Sep 2023 05:39:58 -0400 Subject: [PATCH 3/5] merge-ort: drop unused parameters from detect_and_process_renames() This function takes three trees representing the merge base and both sides of the merge, but never looks at any of them. This is due to f78cf97617 (merge-ort: call diffcore_rename() directly, 2021-02-14). Prior to that commit, we passed pairs of trees to diff_tree_oid(). But after that commit, we collect a custom diff_queue for each pair in the merge_options struct, and just run diffcore_rename() on the result. So the function does not need to know about the original trees at all anymore. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- merge-ort.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/merge-ort.c b/merge-ort.c index 31c663b297..20eefd9b5e 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -3324,10 +3324,7 @@ static int collect_renames(struct merge_options *opt, return clean; } -static int detect_and_process_renames(struct merge_options *opt, - struct tree *merge_base, - struct tree *side1, - struct tree *side2) +static int detect_and_process_renames(struct merge_options *opt) { struct diff_queue_struct combined = { 0 }; struct rename_info *renames = &opt->priv->renames; @@ -4964,8 +4961,7 @@ redo: trace2_region_leave("merge", "collect_merge_info", opt->repo); trace2_region_enter("merge", "renames", opt->repo); - result->clean = detect_and_process_renames(opt, merge_base, - side1, side2); + result->clean = detect_and_process_renames(opt); trace2_region_leave("merge", "renames", opt->repo); if (opt->priv->renames.redo_after_renames == 2) { trace2_region_enter("merge", "reset_maps", opt->repo); From 6eb0c0eb7ac23da7d3bc437b7a5c31f628c25531 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 14 Sep 2023 05:40:04 -0400 Subject: [PATCH 4/5] merge-ort: drop unused "opt" parameter from merge_check_renames_reusable() The merge_options parameter has never been used since the function was introduced in 64aceb6d73 (merge-ort: add code to check for whether cached renames can be reused, 2021-05-20). In theory some merge options might impact our decisions here, but that has never been the case so far. Let's drop it to appease -Wunused-parameter; it would be easy to add back later if we need to (there is only one caller). Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- merge-ort.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/merge-ort.c b/merge-ort.c index 20eefd9b5e..3953c9f745 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -4880,8 +4880,7 @@ static void merge_start(struct merge_options *opt, struct merge_result *result) trace2_region_leave("merge", "allocate/init", opt->repo); } -static void merge_check_renames_reusable(struct merge_options *opt, - struct merge_result *result, +static void merge_check_renames_reusable(struct merge_result *result, struct tree *merge_base, struct tree *side1, struct tree *side2) @@ -5083,7 +5082,7 @@ void merge_incore_nonrecursive(struct merge_options *opt, trace2_region_enter("merge", "merge_start", opt->repo); assert(opt->ancestor != NULL); - merge_check_renames_reusable(opt, result, merge_base, side1, side2); + merge_check_renames_reusable(result, merge_base, side1, side2); merge_start(opt, result); /* * Record the trees used in this merge, so if there's a next merge in From 24c5a270d10a7857cc3f0e6f3b04933f69ee2c8c Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sat, 16 Sep 2023 18:11:46 -0400 Subject: [PATCH 5/5] merge-ort: lowercase a few error messages As noted in CodingGuidelines, error messages should not be capitalized. Fix up a few of these that were copied verbatim from merge-recursive to match our modern style. We'll likewise fix up the matching ones from merge-recursive. We care a bit less there, since the hope is that it will eventually go away. But besides being the right thing to do in the meantime, it is necessary for t6406 to pass both with and without GIT_TEST_MERGE_ALGORITHM set (one of our CI jobs sets it to "recursive", which will use the merge-recursive.c code). An alternative would be to use "grep -i" in the test to check the message, but it's nice for the test suite to be be more exact (we'd notice if the capitalization fix regressed). Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- merge-ort.c | 4 ++-- merge-recursive.c | 4 ++-- t/t6406-merge-attr.sh | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/merge-ort.c b/merge-ort.c index 3953c9f745..7857ce9fbd 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -2105,12 +2105,12 @@ static int handle_content_merge(struct merge_options *opt, &result_buf); if ((merge_status < 0) || !result_buf.ptr) - ret = error(_("Failed to execute internal merge")); + ret = error(_("failed to execute internal merge")); if (!ret && write_object_file(result_buf.ptr, result_buf.size, OBJ_BLOB, &result->oid)) - ret = error(_("Unable to add %s to database"), path); + ret = error(_("unable to add %s to database"), path); free(result_buf.ptr); if (ret) diff --git a/merge-recursive.c b/merge-recursive.c index 6a4081bb0f..0d7e57e2df 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -1383,12 +1383,12 @@ static int merge_mode_and_contents(struct merge_options *opt, extra_marker_size); if ((merge_status < 0) || !result_buf.ptr) - ret = err(opt, _("Failed to execute internal merge")); + ret = err(opt, _("failed to execute internal merge")); if (!ret && write_object_file(result_buf.ptr, result_buf.size, OBJ_BLOB, &result->blob.oid)) - ret = err(opt, _("Unable to add %s to database"), + ret = err(opt, _("unable to add %s to database"), a->path); free(result_buf.ptr); diff --git a/t/t6406-merge-attr.sh b/t/t6406-merge-attr.sh index 05ad13b23e..72f8c1722f 100755 --- a/t/t6406-merge-attr.sh +++ b/t/t6406-merge-attr.sh @@ -180,7 +180,7 @@ test_expect_success !WINDOWS 'custom merge driver that is killed with a signal' >./please-abort && echo "* merge=custom" >.gitattributes && test_must_fail git merge main 2>err && - grep "^error: Failed to execute internal merge" err && + grep "^error: failed to execute internal merge" err && git ls-files -u >output && git diff --name-only HEAD >>output && test_must_be_empty output