From 8d56136d038a611ee69cfd6531a5b86028ef147b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Thu, 27 Jan 2022 06:26:43 +0100 Subject: [PATCH 1/7] object-name tests: add tests for ambiguous object blind spots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend the tests for ambiguous objects to check how we handle objects where we return OBJ_BAD when trying to parse them. As noted in [1] we have a blindspot when it comes to this behavior. Since we need to add new test data here let's extend these tests to be tested under SHA-256, in d7a2fc82491 (t1512: skip test if not using SHA-1, 2018-05-13) all of the existing tests were skipped, as they rely on specific SHA-1 object IDs. For these tests it only matters that the first 4 characters of the OID prefix are the same for both SHA-1 and SHA-256. This uses strings that I mined, and have the same prefix when hashed with both. We "test_cmp" the full output to guard against any future regressions, and because a subsequent commit will tweak it. Showing a diff of how the output changes is helpful to explain those subsequent commits. The "sed" invocation in test_cmp_failed_rev_parse() doesn't need a "/g" because under both SHA-1 and SHA-256 we'll wildcard match any trailing part of the OID after our known starting prefix. We'd like to convert all of that to just "..." for the "test_cmp" which follows. 1. https://lore.kernel.org/git/YZwbphPpfGk78w2f@coredump.intra.peff.net/ Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- t/t1512-rev-parse-disambiguation.sh | 82 +++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 7891a6becf..010d9c1b8a 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -25,6 +25,88 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh +test_cmp_failed_rev_parse () { + dir=$1 + rev=$2 + + cat >expect && + test_must_fail git -C "$dir" rev-parse "$rev" 2>actual.raw && + sed "s/\($rev\)[0-9a-f]*/\1.../" actual && + test_cmp expect actual +} + +test_expect_success 'ambiguous blob output' ' + git init --bare blob.prefix && + ( + cd blob.prefix && + + # Both start with "dead..", under both SHA-1 and SHA-256 + echo brocdnra | git hash-object -w --stdin && + echo brigddsv | git hash-object -w --stdin && + + # Both start with "beef.." + echo 1agllotbh | git hash-object -w --stdin && + echo 1bbfctrkc | git hash-object -w --stdin + ) && + + test_must_fail git -C blob.prefix rev-parse dead && + test_cmp_failed_rev_parse blob.prefix beef <<-\EOF + error: short object ID beef... is ambiguous + hint: The candidates are: + hint: beef... blob + hint: beef... blob + fatal: ambiguous argument '\''beef...'\'': unknown revision or path not in the working tree. + Use '\''--'\'' to separate paths from revisions, like this: + '\''git [...] -- [...]'\'' + EOF +' + +test_expect_success 'ambiguous loose bad object parsed as OBJ_BAD' ' + git init --bare blob.bad && + ( + cd blob.bad && + + # Both have the prefix "bad0" + echo xyzfaowcoh | git hash-object -t bad -w --stdin --literally && + echo xyzhjpyvwl | git hash-object -t bad -w --stdin --literally + ) && + + test_cmp_failed_rev_parse blob.bad bad0 <<-\EOF + error: short object ID bad0... is ambiguous + hint: The candidates are: + fatal: invalid object type + EOF +' + +test_expect_success POSIXPERM 'ambigous zlib corrupt loose blob' ' + git init --bare blob.corrupt && + ( + cd blob.corrupt && + + # Both have the prefix "cafe" + echo bnkxmdwz | git hash-object -w --stdin && + oid=$(echo bmwsjxzi | git hash-object -w --stdin) && + + oidf=objects/$(test_oid_to_path "$oid") && + chmod 755 $oidf && + echo broken >$oidf + ) && + + test_cmp_failed_rev_parse blob.corrupt cafe <<-\EOF + error: short object ID cafe... is ambiguous + hint: The candidates are: + error: inflate: data stream error (incorrect header check) + error: unable to unpack cafe... header + error: inflate: data stream error (incorrect header check) + error: unable to unpack cafe... header + hint: cafe... unknown type + hint: cafe... blob + fatal: ambiguous argument '\''cafe...'\'': unknown revision or path not in the working tree. + Use '\''--'\'' to separate paths from revisions, like this: + '\''git [...] -- [...]'\'' + EOF +' + if ! test_have_prereq SHA1 then skip_all='not using SHA-1 for objects' From 6780e6804087a89bddfb0333171d005b309941a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Thu, 27 Jan 2022 06:26:44 +0100 Subject: [PATCH 2/7] object-name: explicitly handle OBJ_BAD in show_ambiguous_object() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Amend the "unknown type" handling in the code that displays the ambiguous object list to assert() that we're either going to get the "real" object types we can pass to type_name(), or a -1 (OBJ_BAD) return value from oid_object_info(). See [1] for the current output, and [1] for the commit that added the "unknown type" handling. We are never going to get an "unknown type" in the sense of custom types crafted with "hash-object --literally", since we're not using the OBJECT_INFO_ALLOW_UNKNOWN_TYPE flag. If we manage to otherwise unpack such an object without errors we'll die() in parse_loose_header_extended() called by sort_ambiguous() before we get to show_ambiguous_object(), as is asserted by the test added in the preceding commit. So saying "unknown type" here was always misleading, we really meant to say that we had a failure parsing the object at all, i.e. that we had repository corruption. If the problem is only that it's type is unknown we won't reach this code. So let's emit a generic "[bad object]" instead. As our tests added in the preceding commit show, we'll have emitted various "error" output already in those cases. We should do better in the truly "unknown type" cases, which we'd need to handle if we were passing down the OBJECT_INFO_ALLOW_UNKNOWN_TYPE flag. But let's leave that for some future improvement. In a subsequent commit I'll improve the output we do show, and not having to handle the "unknown type" (as in OBJECT_INFO_ALLOW_UNKNOWN_TYPE) simplifies that change. 1. 5cc044e0257 (get_short_oid: sort ambiguous objects by type, then SHA-1, 2018-05-10) 2. 1ffa26c461 (get_short_sha1: list ambiguous objects on error, 2016-09-26) Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-name.c | 14 ++++++++++++-- t/t1512-rev-parse-disambiguation.sh | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/object-name.c b/object-name.c index fdff4601b2..9750634ee7 100644 --- a/object-name.c +++ b/object-name.c @@ -361,6 +361,16 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) return 0; type = oid_object_info(ds->repo, oid, NULL); + + if (type < 0) { + strbuf_addstr(&desc, "[bad object]"); + goto out; + } + + assert(type == OBJ_TREE || type == OBJ_COMMIT || + type == OBJ_BLOB || type == OBJ_TAG); + strbuf_addstr(&desc, type_name(type)); + if (type == OBJ_COMMIT) { struct commit *commit = lookup_commit(ds->repo, oid); if (commit) { @@ -374,9 +384,9 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) strbuf_addf(&desc, " %s", tag->tag); } - advise(" %s %s%s", +out: + advise(" %s %s", repo_find_unique_abbrev(ds->repo, oid, DEFAULT_ABBREV), - type_name(type) ? type_name(type) : "unknown type", desc.buf); strbuf_release(&desc); diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 010d9c1b8a..0282ada133 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -99,7 +99,7 @@ test_expect_success POSIXPERM 'ambigous zlib corrupt loose blob' ' error: unable to unpack cafe... header error: inflate: data stream error (incorrect header check) error: unable to unpack cafe... header - hint: cafe... unknown type + hint: cafe... [bad object] hint: cafe... blob fatal: ambiguous argument '\''cafe...'\'': unknown revision or path not in the working tree. Use '\''--'\'' to separate paths from revisions, like this: From 667a560be7ae977e61d81ca4bcb95ded1cdacc9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Thu, 27 Jan 2022 06:26:45 +0100 Subject: [PATCH 3/7] object-name: explicitly handle bad tags in show_ambiguous_object() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up the handling of OBJ_BAD in the preceding commit and explicitly handle those cases where parse_tag() fails, or we don't end up with a non-NULL pointer in in tag->tag. If we run into such a tag we'd previously be silent about it. We really should also be handling these batter in parse_tag_buffer() by being more eager to emit an error(), instead of silently aborting with "return -1;". One example of such a tag is the one that's tested for in "t3800-mktag.sh", where the code takes the "size < the_hash_algo->hexsz + 24" branch. But in lieu of earlier missing "error" output let's show the user something to indicate why we're not showing a tag message in these cases, now instead of showing: hint: deadbeef tag We'll instead display: hint: deadbeef tag [tag could not be parsed] Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-name.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/object-name.c b/object-name.c index 9750634ee7..298b742bac 100644 --- a/object-name.c +++ b/object-name.c @@ -382,6 +382,8 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) struct tag *tag = lookup_tag(ds->repo, oid); if (!parse_tag(tag) && tag->tag) strbuf_addf(&desc, " %s", tag->tag); + else + strbuf_addstr(&desc, " [tag could not be parsed]"); } out: From ba5e8a0eb8011f7ffb246804e91c9ba0db3befe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Thu, 27 Jan 2022 06:26:46 +0100 Subject: [PATCH 4/7] object-name: make ambiguous object output translatable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the output of show_ambiguous_object() added in [1] and last tweaked in [2] and the preceding commit to be more friendly to translators. By being able to customize the "%s\n" format we're even ready for RTL languages, who'd presumably like to change that to "%s\n". In the case of the existing "tag [tag could not be parsed]" output we'll now instead emit "[bad tag, could not parse it]". This is consistent with the "[bad object]" output. Rephrasing the message like this is possible because we're not unconditionally adding the type_name() at the beginning. 1. 1ffa26c461 (get_short_sha1: list ambiguous objects on error, 2016-09-26) 2. 5cc044e0257 (get_short_oid: sort ambiguous objects by type, then SHA-1, 2018-05-10) Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Josh Steadmon Signed-off-by: Junio C Hamano --- object-name.c | 78 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/object-name.c b/object-name.c index 298b742bac..f31b50bc31 100644 --- a/object-name.c +++ b/object-name.c @@ -356,40 +356,98 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) const struct disambiguate_state *ds = data; struct strbuf desc = STRBUF_INIT; int type; + const char *hash; if (ds->fn && !ds->fn(ds->repo, oid, ds->cb_data)) return 0; + hash = repo_find_unique_abbrev(ds->repo, oid, DEFAULT_ABBREV); type = oid_object_info(ds->repo, oid, NULL); if (type < 0) { - strbuf_addstr(&desc, "[bad object]"); + /* + * TRANSLATORS: This is a line of ambiguous object + * output shown when we cannot look up or parse the + * object in question. E.g. "deadbeef [bad object]". + */ + strbuf_addf(&desc, _("%s [bad object]"), hash); goto out; } assert(type == OBJ_TREE || type == OBJ_COMMIT || type == OBJ_BLOB || type == OBJ_TAG); - strbuf_addstr(&desc, type_name(type)); if (type == OBJ_COMMIT) { + struct strbuf date = STRBUF_INIT; + struct strbuf msg = STRBUF_INIT; struct commit *commit = lookup_commit(ds->repo, oid); + if (commit) { struct pretty_print_context pp = {0}; pp.date_mode.type = DATE_SHORT; - format_commit_message(commit, " %ad - %s", &desc, &pp); + format_commit_message(commit, "%ad", &date, &pp); + format_commit_message(commit, "%s", &msg, &pp); } + + /* + * TRANSLATORS: This is a line of ambiguous commit + * object output. E.g.: + * + * "deadbeef commit 2021-01-01 - Some Commit Message" + */ + strbuf_addf(&desc, _("%s commit %s - %s"), + hash, date.buf, msg.buf); + + strbuf_release(&date); + strbuf_release(&msg); } else if (type == OBJ_TAG) { struct tag *tag = lookup_tag(ds->repo, oid); - if (!parse_tag(tag) && tag->tag) - strbuf_addf(&desc, " %s", tag->tag); - else - strbuf_addstr(&desc, " [tag could not be parsed]"); + + if (!parse_tag(tag) && tag->tag) { + /* + * TRANSLATORS: This is a line of ambiguous + * tag object output. E.g.: + * + * "deadbeef tag Some Tag Message" + * + * The second argument is the "tag" string + * from object.c. + */ + strbuf_addf(&desc, _("%s tag %s"), hash, tag->tag); + } else { + /* + * TRANSLATORS: This is a line of ambiguous + * tag object output where we couldn't parse + * the tag itself. E.g.: + * + * "deadbeef tag [bad tag, could not parse it]" + */ + strbuf_addf(&desc, _("%s [bad tag, could not parse it]"), + hash); + } + } else if (type == OBJ_TREE) { + /* + * TRANSLATORS: This is a line of ambiguous + * object output. E.g. "deadbeef tree". + */ + strbuf_addf(&desc, _("%s tree"), hash); + } else if (type == OBJ_BLOB) { + /* + * TRANSLATORS: This is a line of ambiguous + * object output. E.g. "deadbeef blob". + */ + strbuf_addf(&desc, _("%s blob"), hash); } + out: - advise(" %s %s", - repo_find_unique_abbrev(ds->repo, oid, DEFAULT_ABBREV), - desc.buf); + /* + * TRANSLATORS: This is line item of ambiguous object output + * from describe_ambiguous_object() above. For RTL languages + * you'll probably want to swap the "%s" and leading " " space + * around. + */ + advise(_(" %s"), desc.buf); strbuf_release(&desc); return 0; From 851b3d7671778b74e40bf155c49f6b045f5eb4df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Thu, 27 Jan 2022 06:26:47 +0100 Subject: [PATCH 5/7] object-name: show date for ambiguous tag objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the ambiguous tag object output nicer in the case of tag objects such as ebf3c04b262 (Git 2.32, 2021-06-06) by including the date in the "tagger" header. I.e.: $ git rev-parse b7e68 error: short object ID b7e68 is ambiguous hint: The candidates are: hint: b7e68c41d92 tag 2021-06-06 - v2.32.0 hint: b7e68ae18e0 commit 2019-12-23 - bisect: use the standard 'if (!var)' way to check for 0 hint: b7e68f6b413 tree hint: b7e68490b97 blob b7e68 [...] Before this we'd emit a "tag" line without a date, e.g.: hint: b7e68c41d92 tag v2.32.0 Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-name.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/object-name.c b/object-name.c index f31b50bc31..cbf459f566 100644 --- a/object-name.c +++ b/object-name.c @@ -408,19 +408,24 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) * TRANSLATORS: This is a line of ambiguous * tag object output. E.g.: * - * "deadbeef tag Some Tag Message" + * "deadbeef tag 2022-01-01 - Some Tag Message" * - * The second argument is the "tag" string + * The second argument is the YYYY-MM-DD found + * in the tag. + * + * The third argument is the "tag" string * from object.c. */ - strbuf_addf(&desc, _("%s tag %s"), hash, tag->tag); + strbuf_addf(&desc, _("%s tag %s - %s"), hash, + show_date(tag->date, 0, DATE_MODE(SHORT)), + tag->tag); } else { /* * TRANSLATORS: This is a line of ambiguous * tag object output where we couldn't parse * the tag itself. E.g.: * - * "deadbeef tag [bad tag, could not parse it]" + * "deadbeef [bad tag, could not parse it]" */ strbuf_addf(&desc, _("%s [bad tag, could not parse it]"), hash); From d2ef3cb7e29c35362125a61f1d96576c200076f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Thu, 27 Jan 2022 06:26:48 +0100 Subject: [PATCH 6/7] object-name: iterate ambiguous objects before showing header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Junio C Hamano --- object-name.c | 27 +++++++++++++++++++++++---- t/t1512-rev-parse-disambiguation.sh | 9 ++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/object-name.c b/object-name.c index cbf459f566..6154e1ec6f 100644 --- a/object-name.c +++ b/object-name.c @@ -351,9 +351,16 @@ static int init_object_disambiguation(struct repository *r, return 0; } +struct ambiguous_output { + const struct disambiguate_state *ds; + struct strbuf advice; +}; + static int show_ambiguous_object(const struct object_id *oid, void *data) { - const struct disambiguate_state *ds = data; + struct ambiguous_output *state = data; + const struct disambiguate_state *ds = state->ds; + struct strbuf *advice = &state->advice; struct strbuf desc = STRBUF_INIT; int type; const char *hash; @@ -452,7 +459,7 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) * you'll probably want to swap the "%s" and leading " " space * around. */ - advise(_(" %s"), desc.buf); + strbuf_addf(advice, _(" %s\n"), desc.buf); strbuf_release(&desc); return 0; @@ -551,6 +558,10 @@ static enum get_oid_result get_short_oid(struct repository *r, if (!quietly && (status == SHORT_NAME_AMBIGUOUS)) { struct oid_array collect = OID_ARRAY_INIT; + struct ambiguous_output out = { + .ds = &ds, + .advice = STRBUF_INIT, + }; error(_("short object ID %s is ambiguous"), ds.hex_pfx); @@ -563,13 +574,21 @@ static enum get_oid_result get_short_oid(struct repository *r, if (!ds.ambiguous) ds.fn = NULL; - advise(_("The candidates are:")); repo_for_each_abbrev(r, ds.hex_pfx, collect_ambiguous, &collect); sort_ambiguous_oid_array(r, &collect); - if (oid_array_for_each(&collect, show_ambiguous_object, &ds)) + if (oid_array_for_each(&collect, show_ambiguous_object, &out)) BUG("show_ambiguous_object shouldn't return non-zero"); + + /* + * TRANSLATORS: The argument is the list of ambiguous + * objects composed in show_ambiguous_object(). See + * its "TRANSLATORS" comments for details. + */ + advise(_("The candidates are:\n%s"), out.advice.buf); + oid_array_clear(&collect); + strbuf_release(&out.advice); } return status; diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 0282ada133..be687aebb2 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -73,7 +73,6 @@ test_expect_success 'ambiguous loose bad object parsed as OBJ_BAD' ' test_cmp_failed_rev_parse blob.bad bad0 <<-\EOF error: short object ID bad0... is ambiguous - hint: The candidates are: fatal: invalid object type EOF ' @@ -94,11 +93,11 @@ test_expect_success POSIXPERM 'ambigous zlib corrupt loose blob' ' test_cmp_failed_rev_parse blob.corrupt cafe <<-\EOF error: short object ID cafe... is ambiguous + error: inflate: data stream error (incorrect header check) + error: unable to unpack cafe... header + error: inflate: data stream error (incorrect header check) + error: unable to unpack cafe... header hint: The candidates are: - error: inflate: data stream error (incorrect header check) - error: unable to unpack cafe... header - error: inflate: data stream error (incorrect header check) - error: unable to unpack cafe... header hint: cafe... [bad object] hint: cafe... blob fatal: ambiguous argument '\''cafe...'\'': unknown revision or path not in the working tree. From 3a73c1dfafcc53831a252fc3aededeb59be476f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Thu, 27 Jan 2022 06:26:49 +0100 Subject: [PATCH 7/7] object-name: re-use "struct strbuf" in show_ambiguous_object() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce the allocations done by show_ambiguous_object() by moving the "desc" strbuf into the "struct ambiguous_output" introduced in the preceding commit. This doesn't matter for optimization purposes, but since we're accumulating a "struct strbuf advice" anyway let's follow that pattern and add a "struct strbuf sb", we can then strbuf_reset() it rather than calling strbuf_release() for each call to show_ambiguous_object(). Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-name.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/object-name.c b/object-name.c index 6154e1ec6f..61b58a2f29 100644 --- a/object-name.c +++ b/object-name.c @@ -354,6 +354,7 @@ static int init_object_disambiguation(struct repository *r, struct ambiguous_output { const struct disambiguate_state *ds; struct strbuf advice; + struct strbuf sb; }; static int show_ambiguous_object(const struct object_id *oid, void *data) @@ -361,7 +362,7 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) struct ambiguous_output *state = data; const struct disambiguate_state *ds = state->ds; struct strbuf *advice = &state->advice; - struct strbuf desc = STRBUF_INIT; + struct strbuf *sb = &state->sb; int type; const char *hash; @@ -377,7 +378,7 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) * output shown when we cannot look up or parse the * object in question. E.g. "deadbeef [bad object]". */ - strbuf_addf(&desc, _("%s [bad object]"), hash); + strbuf_addf(sb, _("%s [bad object]"), hash); goto out; } @@ -402,8 +403,8 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) * * "deadbeef commit 2021-01-01 - Some Commit Message" */ - strbuf_addf(&desc, _("%s commit %s - %s"), - hash, date.buf, msg.buf); + strbuf_addf(sb, _("%s commit %s - %s"), hash, date.buf, + msg.buf); strbuf_release(&date); strbuf_release(&msg); @@ -423,7 +424,7 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) * The third argument is the "tag" string * from object.c. */ - strbuf_addf(&desc, _("%s tag %s - %s"), hash, + strbuf_addf(sb, _("%s tag %s - %s"), hash, show_date(tag->date, 0, DATE_MODE(SHORT)), tag->tag); } else { @@ -434,7 +435,7 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) * * "deadbeef [bad tag, could not parse it]" */ - strbuf_addf(&desc, _("%s [bad tag, could not parse it]"), + strbuf_addf(sb, _("%s [bad tag, could not parse it]"), hash); } } else if (type == OBJ_TREE) { @@ -442,13 +443,13 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) * TRANSLATORS: This is a line of ambiguous * object output. E.g. "deadbeef tree". */ - strbuf_addf(&desc, _("%s tree"), hash); + strbuf_addf(sb, _("%s tree"), hash); } else if (type == OBJ_BLOB) { /* * TRANSLATORS: This is a line of ambiguous * object output. E.g. "deadbeef blob". */ - strbuf_addf(&desc, _("%s blob"), hash); + strbuf_addf(sb, _("%s blob"), hash); } @@ -459,9 +460,9 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) * you'll probably want to swap the "%s" and leading " " space * around. */ - strbuf_addf(advice, _(" %s\n"), desc.buf); + strbuf_addf(advice, _(" %s\n"), sb->buf); - strbuf_release(&desc); + strbuf_reset(sb); return 0; } @@ -560,6 +561,7 @@ static enum get_oid_result get_short_oid(struct repository *r, struct oid_array collect = OID_ARRAY_INIT; struct ambiguous_output out = { .ds = &ds, + .sb = STRBUF_INIT, .advice = STRBUF_INIT, }; @@ -589,6 +591,7 @@ static enum get_oid_result get_short_oid(struct repository *r, oid_array_clear(&collect); strbuf_release(&out.advice); + strbuf_release(&out.sb); } return status;