]> git.ipfire.org Git - thirdparty/git.git/commitdiff
hex: add and use strbuf_add_oid_hex()
authorRené Scharfe <l.s.r@web.de>
Wed, 13 May 2026 15:49:11 +0000 (17:49 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 14 May 2026 06:59:25 +0000 (15:59 +0900)
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 <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
14 files changed:
bisect.c
builtin/bisect.c
builtin/cat-file.c
builtin/replace.c
convert.c
fsck.c
hex.c
hex.h
pretty.c
refs.c
sequencer.c
shallow.c
tools/coccinelle/strbuf.cocci
transport-helper.c

index ef17a442e55d2c738249247e58ea4fb15a6c0b92..e67226a6dcbe69f104fe61cde97797b396c3674d 100644 (file)
--- 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);
        }
index 4520e585d0677f1dee3da8c8b4511fff67060e4c..0f679e7af926db0ac0aeeca2eab37f81714b9dea 100644 (file)
@@ -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);
index d9fbad535868bb90fba41a8c9e4e3c4381e4cade..f015e5f415bc3fc1c35f306b04a0ac8e2d752f15 100644 (file)
@@ -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);
index 4c62c5ab58bd0ac7b8d9fd47e9a92166bd1eed9c..aed6b2c8debf8640013158eae279b35f64205aaf 100644 (file)
@@ -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)) {
index eae36c8a5936f4bfef4bdd519fa385b841c495bf..036506842c3d41784a282a7ebde533ea3ad907f5 100644 (file)
--- 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 b72200c352d66363d72fc050a2853732dd4aea46..b4ffee6a04347481abad6f0097c2be1bd480f207 100644 (file)
--- 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 bc756722ca623beca587c511c75ebb3eece57121..f02832140d2d434d7eab3e857d6ef545a7cdaa09 100644 (file)
--- 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 1e9a65d83a4f6ba783449debc4cbe53e259ec471..f15c7e22201ceac652738742d0426166636546d7 100644 (file)
--- 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
index 814803980b8d1a239bad7a25d34e26a3219ae961..268422394648fe2d6cc878846771d95c16c3ae35 100644 (file)
--- 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 bfcb9c7ac3d38c6c13d0b83973147fbf60106e1e..d5b968c28ef6151f62f5247a6fc8f541aa1ff3d0 100644 (file)
--- 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;
                }
        }
index b7d8dca47f4a58a7b67340dabea99a0f3ace86d0..b4df04b67242062118960c57eff6d4ab646e8841 100644 (file)
@@ -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))
index a8ad92e303d24d705e3402612cb9dc832386c304..b4b4e2e32a76002197c565c628a9ec4ca2a28b04 100644 (file)
--- 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++;
        }
index f5861283297acda05e1045d0d5e6e25731a8f089..667903d1d48ad8b328c98a209703ac1eb9df3d8b 100644 (file)
@@ -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)
index 4e5d1d914fb12a6e8abb532985140683489773b8..145a0cd7e6143a38c1771df2b8a352a3036f9788 100644 (file)
@@ -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);