object-name: iterate ambiguous objects before showing header

Change the "The candidates are" header that's shown for ambiguous objects to be shown after we've iterated over all of the objects. If we get any errors while doing so we don't want to split up the the header and the list as a result. The two will now be printed together, as shown in the updated testcase. As we're accumulating the lines into as "struct strbuf" before emitting them we need to add a trailing newline to the call in show_ambiguous_object(). This and the change from "The candidates are:" to "The candidates are:\n%s" helps to give translators more context. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ævar Arnfjörð Bjarmason committed Jan 27, 2022 at 06:26 UTC d2ef3cb7e29c35362125a61f1d96576c200076f6
2 files changed +24 -6
object-name.c
+23 -4
@@ -351,9 +351,16 @@ static int init_object_disambiguation(struct repository *r,
351 return 0;
352 }
353
354 +struct ambiguous_output {
355 + const struct disambiguate_state *ds;
356 + struct strbuf advice;
357 +};
358 +
359 static int show_ambiguous_object(const struct object_id *oid, void *data)
360 {
356 - const struct disambiguate_state *ds = data;
361 + struct ambiguous_output *state = data;
362 + const struct disambiguate_state *ds = state->ds;
363 + struct strbuf *advice = &state->advice;
364 struct strbuf desc = STRBUF_INIT;
365 int type;
366 const char *hash;
@@ -452,7 +459,7 @@ out:
459 * you'll probably want to swap the "%s" and leading " " space
460 * around.
461 */
455 - advise(_(" %s"), desc.buf);
462 + strbuf_addf(advice, _(" %s\n"), desc.buf);
463
464 strbuf_release(&desc);
465 return 0;
@@ -551,6 +558,10 @@ static enum get_oid_result get_short_oid(struct repository *r,
558
559 if (!quietly && (status == SHORT_NAME_AMBIGUOUS)) {
560 struct oid_array collect = OID_ARRAY_INIT;
561 + struct ambiguous_output out = {
562 + .ds = &ds,
563 + .advice = STRBUF_INIT,
564 + };
565
566 error(_("short object ID %s is ambiguous"), ds.hex_pfx);
567
@@ -563,13 +574,21 @@ static enum get_oid_result get_short_oid(struct repository *r,
574 if (!ds.ambiguous)
575 ds.fn = NULL;
576
566 - advise(_("The candidates are:"));
577 repo_for_each_abbrev(r, ds.hex_pfx, collect_ambiguous, &collect);
578 sort_ambiguous_oid_array(r, &collect);
579
570 - if (oid_array_for_each(&collect, show_ambiguous_object, &ds))
580 + if (oid_array_for_each(&collect, show_ambiguous_object, &out))
581 BUG("show_ambiguous_object shouldn't return non-zero");
582 +
583 + /*
584 + * TRANSLATORS: The argument is the list of ambiguous
585 + * objects composed in show_ambiguous_object(). See
586 + * its "TRANSLATORS" comments for details.
587 + */
588 + advise(_("The candidates are:\n%s"), out.advice.buf);
589 +
590 oid_array_clear(&collect);
591 + strbuf_release(&out.advice);
592 }
593
594 return status;
t/t1512-rev-parse-disambiguation.sh
+1 -2
@@ -73,7 +73,6 @@ test_expect_success 'ambiguous loose bad object parsed as OBJ_BAD' '
73
74 test_cmp_failed_rev_parse blob.bad bad0 <<-\EOF
75 error: short object ID bad0... is ambiguous
76 - hint: The candidates are:
76 fatal: invalid object type
77 EOF
78 '
@@ -94,11 +93,11 @@ test_expect_success POSIXPERM 'ambigous zlib corrupt loose blob' '
93
94 test_cmp_failed_rev_parse blob.corrupt cafe <<-\EOF
95 error: short object ID cafe... is ambiguous
97 - hint: The candidates are:
96 error: inflate: data stream error (incorrect header check)
97 error: unable to unpack cafe... header
98 error: inflate: data stream error (incorrect header check)
99 error: unable to unpack cafe... header
100 + hint: The candidates are:
101 hint: cafe... [bad object]
102 hint: cafe... blob
103 fatal: ambiguous argument '\''cafe...'\'': unknown revision or path not in the working tree.