From: René Scharfe Date: Wed, 13 May 2026 15:49:11 +0000 (+0200) Subject: hex: add and use strbuf_add_oid_hex() X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=63621bcbba81a131794d510bcedfa08d9318219c;p=thirdparty%2Fgit.git hex: add and use strbuf_add_oid_hex() Add a function for adding the full hexadecimal hash value of an object ID to a strbuf. It's thread-safe and slightly more efficient than using strbuf_addstr() with oid_to_hex() because it doesn't have to determine the length of the string or copy it from the intermediate static buffer. Add and apply a semantic patch to use it throughout the code base. I get a tiny speedup for git log showing a single hash per commit: Benchmark 1: ./git_main log --format=%H Time (mean ± σ): 91.2 ms ± 0.7 ms [User: 51.9 ms, System: 38.6 ms] Range (min … max): 89.8 ms … 92.6 ms 31 runs Benchmark 2: ./git log --format=%H Time (mean ± σ): 90.5 ms ± 0.7 ms [User: 51.0 ms, System: 38.8 ms] Range (min … max): 89.2 ms … 92.3 ms 32 runs Summary ./git log --format=%H ran 1.01 ± 0.01 times faster than ./git_main log --format=%H Signed-off-by: René Scharfe Signed-off-by: Junio C Hamano --- diff --git a/bisect.c b/bisect.c index ef17a442e5..e67226a6dc 100644 --- a/bisect.c +++ b/bisect.c @@ -512,7 +512,7 @@ static char *join_oid_array_hex(struct oid_array *array, char delim) int i; for (i = 0; i < array->nr; i++) { - strbuf_addstr(&joined_hexs, oid_to_hex(array->oid + i)); + strbuf_add_oid_hex(&joined_hexs, array->oid + i); if (i + 1 < array->nr) strbuf_addch(&joined_hexs, delim); } diff --git a/builtin/bisect.c b/builtin/bisect.c index 4520e585d0..0f679e7af9 100644 --- a/builtin/bisect.c +++ b/builtin/bisect.c @@ -833,7 +833,7 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, int argc, if (!repo_get_oid(the_repository, head, &head_oid) && !starts_with(head, "refs/heads/")) { strbuf_reset(&start_head); - strbuf_addstr(&start_head, oid_to_hex(&head_oid)); + strbuf_add_oid_hex(&start_head, &head_oid); } else if (!repo_get_oid(the_repository, head, &head_oid) && skip_prefix(head, "refs/heads/", &head)) { strbuf_addstr(&start_head, head); diff --git a/builtin/cat-file.c b/builtin/cat-file.c index d9fbad5358..f015e5f415 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -320,7 +320,7 @@ static int expand_atom(struct strbuf *sb, const char *atom, int len, { if (is_atom("objectname", atom, len)) { if (!data->mark_query) - strbuf_addstr(sb, oid_to_hex(&data->oid)); + strbuf_add_oid_hex(sb, &data->oid); } else if (is_atom("objecttype", atom, len)) { if (data->mark_query) data->info.typep = &data->type; @@ -345,8 +345,7 @@ static int expand_atom(struct strbuf *sb, const char *atom, int len, if (data->mark_query) data->info.delta_base_oid = &data->delta_base_oid; else - strbuf_addstr(sb, - oid_to_hex(&data->delta_base_oid)); + strbuf_add_oid_hex(sb, &data->delta_base_oid); } else if (is_atom("objectmode", atom, len)) { if (!data->mark_query && !(S_IFINVALID == data->mode)) strbuf_addf(sb, "%06o", data->mode); diff --git a/builtin/replace.c b/builtin/replace.c index 4c62c5ab58..aed6b2c8de 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -127,7 +127,7 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn) } strbuf_setlen(&ref, base_len); - strbuf_addstr(&ref, oid_to_hex(&oid)); + strbuf_add_oid_hex(&ref, &oid); full_hex = ref.buf + base_len; if (refs_read_ref(get_main_ref_store(the_repository), ref.buf, &oid)) { diff --git a/convert.c b/convert.c index eae36c8a59..036506842c 100644 --- a/convert.c +++ b/convert.c @@ -1239,7 +1239,7 @@ static int ident_to_worktree(const char *src, size_t len, /* step 4: substitute */ strbuf_addstr(buf, "Id: "); - strbuf_addstr(buf, oid_to_hex(&oid)); + strbuf_add_oid_hex(buf, &oid); strbuf_addstr(buf, " $"); } strbuf_add(buf, src, len); diff --git a/fsck.c b/fsck.c index b72200c352..b4ffee6a04 100644 --- a/fsck.c +++ b/fsck.c @@ -344,7 +344,7 @@ const char *fsck_describe_object(struct fsck_options *options, buf = bufs + b; b = (b + 1) % ARRAY_SIZE(bufs); strbuf_reset(buf); - strbuf_addstr(buf, oid_to_hex(oid)); + strbuf_add_oid_hex(buf, oid); if (name) strbuf_addf(buf, " (%s)", name); diff --git a/hex.c b/hex.c index bc756722ca..f02832140d 100644 --- a/hex.c +++ b/hex.c @@ -3,6 +3,7 @@ #include "git-compat-util.h" #include "hash.h" #include "hex.h" +#include "strbuf.h" static int get_hash_hex_algop(const char *hex, unsigned char *hash, const struct git_hash_algo *algop) @@ -122,3 +123,12 @@ char *oid_to_hex(const struct object_id *oid) { return hash_to_hex_algop(oid->hash, &hash_algos[oid->algo]); } + +void strbuf_add_oid_hex(struct strbuf *sb, const struct object_id *oid) +{ + const struct git_hash_algo *algop = oid->algo ? + &hash_algos[oid->algo] : the_hash_algo; + strbuf_grow(sb, algop->hexsz); + hash_to_hex_algop_r(sb->buf + sb->len, oid->hash, algop); + strbuf_setlen(sb, sb->len + algop->hexsz); +} diff --git a/hex.h b/hex.h index 1e9a65d83a..f15c7e2220 100644 --- a/hex.h +++ b/hex.h @@ -33,6 +33,11 @@ char *oid_to_hex_r(char *out, const struct object_id *oid); char *hash_to_hex_algop(const unsigned char *hash, const struct git_hash_algo *); /* static buffer result! */ char *oid_to_hex(const struct object_id *oid); /* same static buffer */ +struct strbuf; + +/* Apply oid_to_hex_r() to a strbuf to append the hexadecimal hash. */ +void strbuf_add_oid_hex(struct strbuf *sb, const struct object_id *oid); + /* * Parse a 40-character hexadecimal object ID starting from hex, updating the * pointer specified by end when parsing stops. The resulting object ID is diff --git a/pretty.c b/pretty.c index 814803980b..2684223946 100644 --- a/pretty.c +++ b/pretty.c @@ -662,7 +662,7 @@ static void add_merge_info(const struct pretty_print_context *pp, if (pp->abbrev) strbuf_add_unique_abbrev(sb, oidp, pp->abbrev); else - strbuf_addstr(sb, oid_to_hex(oidp)); + strbuf_add_oid_hex(sb, oidp); parent = parent->next; } strbuf_addch(sb, '\n'); @@ -1567,7 +1567,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ switch (placeholder[0]) { case 'H': /* commit hash */ strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT)); - strbuf_addstr(sb, oid_to_hex(&commit->object.oid)); + strbuf_add_oid_hex(sb, &commit->object.oid); strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET)); return 1; case 'h': /* abbreviated commit hash */ @@ -1577,7 +1577,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET)); return 1; case 'T': /* tree hash */ - strbuf_addstr(sb, oid_to_hex(get_commit_tree_oid(commit))); + strbuf_add_oid_hex(sb, get_commit_tree_oid(commit)); return 1; case 't': /* abbreviated tree hash */ strbuf_add_unique_abbrev(sb, @@ -1588,7 +1588,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ for (p = commit->parents; p; p = p->next) { if (p != commit->parents) strbuf_addch(sb, ' '); - strbuf_addstr(sb, oid_to_hex(&p->item->object.oid)); + strbuf_add_oid_hex(sb, &p->item->object.oid); } return 1; case 'p': /* abbreviated parent hashes */ diff --git a/refs.c b/refs.c index bfcb9c7ac3..d5b968c28e 100644 --- a/refs.c +++ b/refs.c @@ -2498,7 +2498,7 @@ int refs_update_symref_extended(struct ref_store *refs, const char *ref, if (referent && refs_read_symbolic_ref(refs, ref, referent) == NOT_A_SYMREF) { struct object_id oid; if (!refs_read_ref(refs, ref, &oid)) { - strbuf_addstr(referent, oid_to_hex(&oid)); + strbuf_add_oid_hex(referent, &oid); ret = NOT_A_SYMREF; } } diff --git a/sequencer.c b/sequencer.c index b7d8dca47f..b4df04b672 100644 --- a/sequencer.c +++ b/sequencer.c @@ -2223,7 +2223,7 @@ static void refer_to_commit(struct repository *r, struct strbuf *msgbuf, repo_format_commit_message(r, commit, "%h (%s, %ad)", msgbuf, &ctx); } else { - strbuf_addstr(msgbuf, oid_to_hex(&commit->object.oid)); + strbuf_add_oid_hex(msgbuf, &commit->object.oid); } } @@ -2395,7 +2395,7 @@ static int do_pick_commit(struct repository *r, if (!has_conforming_footer(&ctx->message, NULL, 0)) strbuf_addch(&ctx->message, '\n'); strbuf_addstr(&ctx->message, cherry_picked_prefix); - strbuf_addstr(&ctx->message, oid_to_hex(&commit->object.oid)); + strbuf_add_oid_hex(&ctx->message, &commit->object.oid); strbuf_addstr(&ctx->message, ")\n"); } if (!is_fixup(command)) diff --git a/shallow.c b/shallow.c index a8ad92e303..b4b4e2e32a 100644 --- a/shallow.c +++ b/shallow.c @@ -395,7 +395,7 @@ static int write_shallow_commits_1(struct strbuf *out, int use_pack_protocol, if (!extra) return data.count; for (size_t i = 0; i < extra->nr; i++) { - strbuf_addstr(out, oid_to_hex(extra->oid + i)); + strbuf_add_oid_hex(out, extra->oid + i); strbuf_addch(out, '\n'); data.count++; } diff --git a/tools/coccinelle/strbuf.cocci b/tools/coccinelle/strbuf.cocci index f586128329..667903d1d4 100644 --- a/tools/coccinelle/strbuf.cocci +++ b/tools/coccinelle/strbuf.cocci @@ -78,3 +78,9 @@ struct strbuf SB; @@ - SB.buf ? SB.buf : "" + SB.buf + +@@ +expression SB, OID; +@@ +- strbuf_addstr(SB, oid_to_hex(OID)) ++ strbuf_add_oid_hex(SB, OID) diff --git a/transport-helper.c b/transport-helper.c index 4e5d1d914f..145a0cd7e6 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -1053,7 +1053,7 @@ static int push_refs_with_push(struct transport *transport, if (ref->peer_ref) strbuf_addstr(&buf, ref->peer_ref->name); else - strbuf_addstr(&buf, oid_to_hex(&ref->new_oid)); + strbuf_add_oid_hex(&buf, &ref->new_oid); } strbuf_addch(&buf, ':'); strbuf_addstr(&buf, ref->name);