hash: convert remaining direct function calls

The previous patch added a coccinelle rule to make sure callers always use git_hash_init() rather than direct function pointers from the algo struct. Let's do the same for the rest of the git_hash_*() wrappers. I split these out because they're a bit different: they implicitly use the algop pointer in the git_hash_ctx. So when we convert: -algo->update_fn(&ctx, buf, len); +git_hash_update(&ctx, buf, len); we drop the reference to algo entirely! But this is always going to be the right thing. If "algo" does not match what is in ctx.algop, then we'd already be invoking undefined behavior. So in addition to making it possible to add more logic to the git_hash_*() functions, we're avoiding the need to pass around the extra algo pointer and make sure that it matches what's in "ctx". The rest of the patch is the mechanical application of that coccinelle patch, plus a minor cleanup in test-synthesize.c to drop a now-unused function parameter (since we don't have to pass around the algo separately anymore). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Jul 7, 2026 at 23:52 UTC b87af5aa77c07f014e14c91ac5f942fdef132df9
3 files changed +72 -19
builtin/submodule--helper.c
+4 -4
@@ -551,10 +551,10 @@ static void create_default_gitdir_config(const char *submodule_name)
551 /* Case 2.4: If all the above failed, try a hash of the name as a last resort */
552 header_len = snprintf(header, sizeof(header), "blob %zu", strlen(submodule_name));
553 git_hash_init(&ctx, the_hash_algo);
554 - the_hash_algo->update_fn(&ctx, header, header_len);
555 - the_hash_algo->update_fn(&ctx, "\0", 1);
556 - the_hash_algo->update_fn(&ctx, submodule_name, strlen(submodule_name));
557 - the_hash_algo->final_fn(raw_name_hash, &ctx);
554 + git_hash_update(&ctx, header, header_len);
555 + git_hash_update(&ctx, "\0", 1);
556 + git_hash_update(&ctx, submodule_name, strlen(submodule_name));
557 + git_hash_final(raw_name_hash, &ctx);
558 hash_to_hex_algop_r(hex_name_hash, raw_name_hash, the_hash_algo);
559 strbuf_reset(&gitdir_path);
560 repo_git_path_append(the_repository, &gitdir_path, "modules/%s", hex_name_hash);
t/helper/test-synthesize.c
+14 -15
@@ -25,8 +25,7 @@ static const unsigned char zeros[BLOCK_SIZE];
25 * Updates the pack checksum context.
26 */
27 static void write_uncompressed_zlib(FILE *f, struct git_hash_ctx *pack_ctx,
28 - const void *data, size_t len,
29 - const struct git_hash_algo *algo)
28 + const void *data, size_t len)
29 {
30 unsigned char zlib_header[2] = { 0x78, 0x01 }; /* CMF, FLG */
31 unsigned char block_header[5];
@@ -37,7 +36,7 @@ static void write_uncompressed_zlib(FILE *f, struct git_hash_ctx *pack_ctx,
36
37 /* Write zlib header */
38 fwrite_or_die(f, zlib_header, sizeof(zlib_header));
40 - algo->update_fn(pack_ctx, zlib_header, 2);
39 + git_hash_update(pack_ctx, zlib_header, 2);
40
41 /* Write uncompressed blocks (max 64KB each) */
42 do {
@@ -52,11 +51,11 @@ static void write_uncompressed_zlib(FILE *f, struct git_hash_ctx *pack_ctx,
51 block_header[4] = block_header[2] ^ 0xff;
52
53 fwrite_or_die(f, block_header, sizeof(block_header));
55 - algo->update_fn(pack_ctx, block_header, 5);
54 + git_hash_update(pack_ctx, block_header, 5);
55
56 if (block_len) {
57 fwrite_or_die(f, block_data, block_len);
59 - algo->update_fn(pack_ctx, block_data, block_len);
58 + git_hash_update(pack_ctx, block_data, block_len);
59 adler = adler32(adler, block_data, block_len);
60 }
61
@@ -68,7 +67,7 @@ static void write_uncompressed_zlib(FILE *f, struct git_hash_ctx *pack_ctx,
67 /* Write adler32 checksum */
68 put_be32(adler_buf, adler);
69 fwrite_or_die(f, adler_buf, sizeof(adler_buf));
71 - algo->update_fn(pack_ctx, adler_buf, 4);
70 + git_hash_update(pack_ctx, adler_buf, 4);
71 }
72
73 /*
@@ -92,24 +91,24 @@ static void write_pack_object(FILE *f, struct git_hash_ctx *pack_ctx,
91 sizeof(pack_header),
92 type, len);
93 fwrite_or_die(f, pack_header, pack_header_len);
95 - algo->update_fn(pack_ctx, pack_header, pack_header_len);
94 + git_hash_update(pack_ctx, pack_header, pack_header_len);
95
96 /* Write the data as uncompressed zlib */
98 - write_uncompressed_zlib(f, pack_ctx, data, len, algo);
97 + write_uncompressed_zlib(f, pack_ctx, data, len);
98
99 git_hash_init(&ctx, algo);
100 object_header_len = format_object_header(object_header,
101 sizeof(object_header),
102 type, len);
104 - algo->update_fn(&ctx, object_header, object_header_len);
103 + git_hash_update(&ctx, object_header, object_header_len);
104 if (data)
106 - algo->update_fn(&ctx, data, len);
105 + git_hash_update(&ctx, data, len);
106 else {
107 for (size_t i = len / BLOCK_SIZE; i; i--)
109 - algo->update_fn(&ctx, zeros, BLOCK_SIZE);
110 - algo->update_fn(&ctx, zeros, len % BLOCK_SIZE);
108 + git_hash_update(&ctx, zeros, BLOCK_SIZE);
109 + git_hash_update(&ctx, zeros, len % BLOCK_SIZE);
110 }
112 - algo->final_oid_fn(oid, &ctx);
111 + git_hash_final_oid(oid, &ctx);
112 }
113
114 /*
@@ -434,7 +433,7 @@ static int generate_pack_with_large_object(const char *path, size_t blob_size,
433
434 /* Write pack header */
435 fwrite_or_die(f, &pack_header, sizeof(pack_header));
437 - algo->update_fn(&pack_ctx, &pack_header, sizeof(pack_header));
436 + git_hash_update(&pack_ctx, &pack_header, sizeof(pack_header));
437
438 /* 1. Write the large blob */
439 write_pack_object(f, &pack_ctx, OBJ_BLOB, NULL, blob_size, &blob_oid, algo);
@@ -472,7 +471,7 @@ static int generate_pack_with_large_object(const char *path, size_t blob_size,
471 write_pack_object(f, &pack_ctx, OBJ_COMMIT, buf.buf, buf.len, &final_commit_oid, algo);
472
473 /* Write pack trailer (checksum) */
475 - algo->final_fn(pack_hash, &pack_ctx);
474 + git_hash_final(pack_hash, &pack_ctx);
475 fwrite_or_die(f, pack_hash, algo->rawsz);
476 if (fclose(f))
477 die_errno(_("could not close '%s'"), path);
tools/coccinelle/hash.cocci
+54
@@ -7,3 +7,57 @@ struct git_hash_ctx *CTX;
7 - ALGO->init_fn(CTX);
8 + git_hash_init(CTX, ALGO);
9 ...>}
10 +
11 +@@
12 +identifier f != git_hash_clone;
13 +expression ALGO;
14 +struct git_hash_ctx *SRC;
15 +struct git_hash_ctx *DST;
16 +@@
17 + f(...) {<...
18 +- ALGO->clone_fn(DST, SRC);
19 ++ git_hash_clone(DST, SRC);
20 + ...>}
21 +
22 +@@
23 +identifier f != git_hash_update;
24 +expression ALGO;
25 +struct git_hash_ctx *CTX;
26 +expression list ARGS;
27 +@@
28 + f(...) {<...
29 +- ALGO->update_fn(CTX, ARGS);
30 ++ git_hash_update(CTX, ARGS);
31 + ...>}
32 +
33 +@@
34 +identifier f != git_hash_final;
35 +expression ALGO;
36 +struct git_hash_ctx *CTX;
37 +expression list ARGS;
38 +@@
39 + f(...) {<...
40 +- ALGO->final_fn(ARGS, CTX);
41 ++ git_hash_final(ARGS, CTX);
42 + ...>}
43 +
44 +@@
45 +identifier f != git_hash_final_oid;
46 +expression ALGO;
47 +struct git_hash_ctx *CTX;
48 +expression list ARGS;
49 +@@
50 + f(...) {<...
51 +- ALGO->final_oid_fn(ARGS, CTX);
52 ++ git_hash_final_oid(ARGS, CTX);
53 + ...>}
54 +
55 +@@
56 +identifier f != git_hash_discard;
57 +expression ALGO;
58 +struct git_hash_ctx *CTX;
59 +@@
60 + f(...) {<...
61 +- ALGO->discard_fn(CTX);
62 ++ git_hash_discard(CTX);
63 + ...>}