{"thread":{"id":"63046","subject":"[PATCH 00/12] Stop depending on `the_repository` in object-related subsystems","startedAt":"2025-03-03T08:47:37Z","lastAt":"2025-03-10T22:39:13Z","messageCount":73,"participants":["Patrick Steinhardt","Justin Tobler","Karthik Nayak","Junio C Hamano","Elijah Newren"],"isPatch":true,"patchVersion":1,"patchTotal":12},"messages":[{"id":"513377","messageId":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","threadId":"63046","inReplyTo":null,"subject":"[PATCH 00/12] Stop depending on `the_repository` in object-related subsystems","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-03T08:47:29Z","receivedAt":"2025-03-03T08:47:37Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis patch series is another step to remove our dependency on the global\n`the_repository` variable. The series focusses on subsystems related to\nobjects.\n\nThe intent here is to work towards libification of the whole subsystem\nso that we can start splitting out something like an object \"backend\".\nIt is thus part of a set of refactorings aimed at allowing pluggable\nobject databases eventually. I'm not discussing that bigger effort yet,\nmostly because it's still taking shape. So these patch series contains\nthings that make sense standalone, even if pluggable ODBs never get to\nbe a thing.\n\nNote that this patch series stop short of dropping `the_repository` in\n\"object-file.c\". This is a bigger undertaking, so I'm pushing that into\nthe next patch series.\n\nThe series is built on top of cb0ae672aea (A bit more post -rc0,\n2025-02-27) with ps/path-sans-the-repository at 028f618658e (path:\nadjust last remaining users of `the_repository`, 2025-02-07) merged into\nit.\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (12):\n      csum-file: stop depending on `the_repository`\n      object: stop depending on `the_repository`\n      pack-write: stop depending on `the_repository` and `the_hash_algo`\n      environment: move access to \"core.bigFileThreshold\" into repo settings\n      pack-check: stop depending on `the_repository`\n      pack-revindex: stop depending on `the_repository`\n      pack-bitmap-write: stop depending on `the_repository`\n      object-file-convert: stop depending on `the_repository`\n      delta-islands: stop depending on `the_repository`\n      object-file: split out logic regarding hash algorithms\n      hash: fix \"-Wsign-compare\" warnings\n      hash: stop depending on `the_repository` in `null_oid()`\n\n Makefile                                     |   1 +\n archive.c                                    |   4 +-\n blame.c                                      |   2 +-\n branch.c                                     |   2 +-\n builtin/checkout.c                           |   6 +-\n builtin/clone.c                              |   2 +-\n builtin/describe.c                           |   2 +-\n builtin/diff.c                               |   5 +-\n builtin/fast-export.c                        |  10 +-\n builtin/fast-import.c                        |   8 +-\n builtin/fsck.c                               |   6 +-\n builtin/grep.c                               |   4 +-\n builtin/index-pack.c                         |  16 +-\n builtin/log.c                                |   2 +-\n builtin/ls-files.c                           |   2 +-\n builtin/name-rev.c                           |   4 +-\n builtin/pack-objects.c                       |  17 +-\n builtin/prune.c                              |   2 +-\n builtin/rebase.c                             |   2 +-\n builtin/receive-pack.c                       |   2 +-\n builtin/submodule--helper.c                  |  36 ++--\n builtin/tag.c                                |   2 +-\n builtin/unpack-objects.c                     |   5 +-\n builtin/update-ref.c                         |   2 +-\n builtin/worktree.c                           |   2 +-\n bulk-checkin.c                               |   4 +-\n combine-diff.c                               |   2 +-\n commit-graph.c                               |   9 +-\n commit.c                                     |   2 +-\n config.c                                     |   5 -\n csum-file.c                                  |  28 +--\n csum-file.h                                  |  12 +-\n delta-islands.c                              |  14 +-\n delta-islands.h                              |   2 +-\n diff-lib.c                                   |  10 +-\n diff-no-index.c                              |  28 +--\n diff.c                                       |  14 +-\n diff.h                                       |   2 +-\n dir.c                                        |   2 +-\n environment.c                                |   1 -\n environment.h                                |   1 -\n grep.c                                       |   2 +-\n hash.c                                       | 277 +++++++++++++++++++++++++\n hash.h                                       |   4 +-\n log-tree.c                                   |   2 +-\n merge-ort.c                                  |  26 +--\n merge-recursive.c                            |  12 +-\n meson.build                                  |   1 +\n midx-write.c                                 |  12 +-\n midx.c                                       |   3 +-\n notes-merge.c                                |   2 +-\n notes.c                                      |   2 +-\n object-file-convert.c                        |  29 +--\n object-file-convert.h                        |   3 +-\n object-file.c                                | 292 +--------------------------\n object.c                                     |  21 +-\n object.h                                     |  10 +-\n pack-bitmap-write.c                          |  36 ++--\n pack-bitmap.c                                |  15 +-\n pack-bitmap.h                                |   1 +\n pack-check.c                                 |  12 +-\n pack-revindex.c                              |  35 ++--\n pack-write.c                                 |  55 +++--\n pack.h                                       |  11 +-\n parse-options-cb.c                           |   2 +-\n range-diff.c                                 |   2 +-\n reachable.c                                  |   6 +-\n read-cache.c                                 |   4 +-\n refs.c                                       |  12 +-\n refs/debug.c                                 |   2 +-\n refs/files-backend.c                         |   2 +-\n repo-settings.c                              |  20 ++\n repo-settings.h                              |   5 +\n reset.c                                      |   2 +-\n revision.c                                   |   3 +-\n sequencer.c                                  |  10 +-\n shallow.c                                    |  10 +-\n streaming.c                                  |   3 +-\n submodule-config.c                           |   2 +-\n submodule.c                                  |  28 +--\n t/helper/test-ref-store.c                    |   2 +-\n t/helper/test-submodule-nested-repo-config.c |   2 +-\n t/t1050-large.sh                             |   3 +-\n tree-diff.c                                  |   4 +-\n upload-pack.c                                |  14 +-\n wt-status.c                                  |   4 +-\n xdiff-interface.c                            |   2 +-\n 87 files changed, 676 insertions(+), 613 deletions(-)\n\n\n---\nbase-commit: e2cb568e11f4ceb427ba4205e6b8a4426d26be12\nchange-id: 20250210-b4-pks-objects-without-the-repository-6ba8398f7cc0\n\n"},{"id":"513378","messageId":"20250303-b4-pks-objects-without-the-repository-v1-1-c5dd43f2476e@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH 01/12] csum-file: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-03T08:47:30Z","receivedAt":"2025-03-03T08:47:38Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"csum-file.c\" where we use the global\n`the_repository` variable, either explicitly or implicitly by using\n`the_hash_algo`.\n\nRefactor the code to stop using `the_repository` by adapting functions\nto receive required data as parameters. Adapt callsites accordingly by\neither using `the_repository->hash_algo`, or by using a context-provided\nhash algorithm in case the subsystem already got rid of its dependency\non `the_repository`.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fast-import.c  |  2 +-\n builtin/index-pack.c   |  2 +-\n builtin/pack-objects.c |  3 ++-\n commit-graph.c         |  9 ++++++---\n csum-file.c            | 28 ++++++++++++++++------------\n csum-file.h            | 12 ++++++++----\n midx-write.c           |  6 ++++--\n midx.c                 |  3 ++-\n pack-bitmap-write.c    |  2 +-\n pack-bitmap.c          |  9 +++++----\n pack-check.c           |  2 +-\n pack-revindex.c        |  3 ++-\n pack-write.c           | 12 ++++++------\n read-cache.c           |  2 +-\n 14 files changed, 56 insertions(+), 39 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 397a6f46ad8..86e6e754816 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -770,7 +770,7 @@ static void start_packfile(void)\n \tp->pack_fd = pack_fd;\n \tp->do_not_close = 1;\n \tp->repo = the_repository;\n-\tpack_file = hashfd(pack_fd, p->pack_name);\n+\tpack_file = hashfd(the_repository->hash_algo, pack_fd, p->pack_name);\n \n \tpack_data = p;\n \tpack_size = write_pack_header(pack_file, 0);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 52cc97d52cb..3eb5af20950 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -1381,7 +1381,7 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha\n \t\tREALLOC_ARRAY(objects, nr_objects + nr_unresolved + 1);\n \t\tmemset(objects + nr_objects + 1, 0,\n \t\t       nr_unresolved * sizeof(*objects));\n-\t\tf = hashfd(output_fd, curr_pack);\n+\t\tf = hashfd(the_repository->hash_algo, output_fd, curr_pack);\n \t\tfix_unresolved_deltas(f);\n \t\tstrbuf_addf(&msg, Q_(\"completed with %d local object\",\n \t\t\t\t     \"completed with %d local objects\",\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 58a9b161262..8e282f2a980 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -1311,7 +1311,8 @@ static void write_pack_file(void)\n \t\tchar *pack_tmp_name = NULL;\n \n \t\tif (pack_to_stdout)\n-\t\t\tf = hashfd_throughput(1, \"<stdout>\", progress_state);\n+\t\t\tf = hashfd_throughput(the_repository->hash_algo, 1,\n+\t\t\t\t\t      \"<stdout>\", progress_state);\n \t\telse\n \t\t\tf = create_tmp_packfile(&pack_tmp_name);\n \ndiff --git a/commit-graph.c b/commit-graph.c\nindex 1021ccb983d..8286d5dda24 100644\n--- a/commit-graph.c\n+++ b/commit-graph.c\n@@ -2090,11 +2090,13 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)\n \t\t\treturn -1;\n \t\t}\n \n-\t\tf = hashfd(get_tempfile_fd(graph_layer), get_tempfile_path(graph_layer));\n+\t\tf = hashfd(the_repository->hash_algo,\n+\t\t\t   get_tempfile_fd(graph_layer), get_tempfile_path(graph_layer));\n \t} else {\n \t\thold_lock_file_for_update_mode(&lk, ctx->graph_name,\n \t\t\t\t\t       LOCK_DIE_ON_ERROR, 0444);\n-\t\tf = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk));\n+\t\tf = hashfd(the_repository->hash_algo,\n+\t\t\t   get_lock_file_fd(&lk), get_lock_file_path(&lk));\n \t}\n \n \tcf = init_chunkfile(f);\n@@ -2716,7 +2718,8 @@ static void graph_report(const char *fmt, ...)\n \n static int commit_graph_checksum_valid(struct commit_graph *g)\n {\n-\treturn hashfile_checksum_valid(g->data, g->data_len);\n+\treturn hashfile_checksum_valid(the_repository->hash_algo,\n+\t\t\t\t       g->data, g->data_len);\n }\n \n static int verify_one_commit_graph(struct repository *r,\ndiff --git a/csum-file.c b/csum-file.c\nindex b58c183a4f0..6e21e3cac8a 100644\n--- a/csum-file.c\n+++ b/csum-file.c\n@@ -8,8 +8,6 @@\n  * able to verify hasn't been messed with afterwards.\n  */\n \n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"csum-file.h\"\n #include \"git-zlib.h\"\n@@ -148,21 +146,23 @@ void hashwrite(struct hashfile *f, const void *buf, unsigned int count)\n \t}\n }\n \n-struct hashfile *hashfd_check(const char *name)\n+struct hashfile *hashfd_check(const struct git_hash_algo *algop,\n+\t\t\t      const char *name)\n {\n \tint sink, check;\n \tstruct hashfile *f;\n \n \tsink = xopen(\"/dev/null\", O_WRONLY);\n \tcheck = xopen(name, O_RDONLY);\n-\tf = hashfd(sink, name);\n+\tf = hashfd(algop, sink, name);\n \tf->check_fd = check;\n \tf->check_buffer = xmalloc(f->buffer_len);\n \n \treturn f;\n }\n \n-static struct hashfile *hashfd_internal(int fd, const char *name,\n+static struct hashfile *hashfd_internal(const struct git_hash_algo *algop,\n+\t\t\t\t\tint fd, const char *name,\n \t\t\t\t\tstruct progress *tp,\n \t\t\t\t\tsize_t buffer_len)\n {\n@@ -176,7 +176,7 @@ static struct hashfile *hashfd_internal(int fd, const char *name,\n \tf->do_crc = 0;\n \tf->skip_hash = 0;\n \n-\tf->algop = unsafe_hash_algo(the_hash_algo);\n+\tf->algop = unsafe_hash_algo(algop);\n \tf->algop->init_fn(&f->ctx);\n \n \tf->buffer_len = buffer_len;\n@@ -186,17 +186,19 @@ static struct hashfile *hashfd_internal(int fd, const char *name,\n \treturn f;\n }\n \n-struct hashfile *hashfd(int fd, const char *name)\n+struct hashfile *hashfd(const struct git_hash_algo *algop,\n+\t\t\tint fd, const char *name)\n {\n \t/*\n \t * Since we are not going to use a progress meter to\n \t * measure the rate of data passing through this hashfile,\n \t * use a larger buffer size to reduce fsync() calls.\n \t */\n-\treturn hashfd_internal(fd, name, NULL, 128 * 1024);\n+\treturn hashfd_internal(algop, fd, name, NULL, 128 * 1024);\n }\n \n-struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp)\n+struct hashfile *hashfd_throughput(const struct git_hash_algo *algop,\n+\t\t\t\t   int fd, const char *name, struct progress *tp)\n {\n \t/*\n \t * Since we are expecting to report progress of the\n@@ -204,7 +206,7 @@ struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp\n \t * size so the progress indicators arrive at a more\n \t * frequent rate.\n \t */\n-\treturn hashfd_internal(fd, name, tp, 8 * 1024);\n+\treturn hashfd_internal(algop, fd, name, tp, 8 * 1024);\n }\n \n void hashfile_checkpoint_init(struct hashfile *f,\n@@ -246,13 +248,15 @@ uint32_t crc32_end(struct hashfile *f)\n \treturn f->crc32;\n }\n \n-int hashfile_checksum_valid(const unsigned char *data, size_t total_len)\n+int hashfile_checksum_valid(const struct git_hash_algo *algop,\n+\t\t\t    const unsigned char *data, size_t total_len)\n {\n \tunsigned char got[GIT_MAX_RAWSZ];\n \tstruct git_hash_ctx ctx;\n-\tconst struct git_hash_algo *algop = unsafe_hash_algo(the_hash_algo);\n \tsize_t data_len = total_len - algop->rawsz;\n \n+\talgop = unsafe_hash_algo(algop);\n+\n \tif (total_len < algop->rawsz)\n \t\treturn 0; /* say \"too short\"? */\n \ndiff --git a/csum-file.h b/csum-file.h\nindex ffccbf09966..07ae11024af 100644\n--- a/csum-file.h\n+++ b/csum-file.h\n@@ -45,9 +45,12 @@ int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *);\n #define CSUM_FSYNC\t\t2\n #define CSUM_HASH_IN_STREAM\t4\n \n-struct hashfile *hashfd(int fd, const char *name);\n-struct hashfile *hashfd_check(const char *name);\n-struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp);\n+struct hashfile *hashfd(const struct git_hash_algo *algop,\n+\t\t\tint fd, const char *name);\n+struct hashfile *hashfd_check(const struct git_hash_algo *algop,\n+\t\t\t      const char *name);\n+struct hashfile *hashfd_throughput(const struct git_hash_algo *algop,\n+\t\t\t\t   int fd, const char *name, struct progress *tp);\n \n /*\n  * Free the hashfile without flushing its contents to disk. This only\n@@ -66,7 +69,8 @@ void crc32_begin(struct hashfile *);\n uint32_t crc32_end(struct hashfile *);\n \n /* Verify checksum validity while reading. Returns non-zero on success. */\n-int hashfile_checksum_valid(const unsigned char *data, size_t len);\n+int hashfile_checksum_valid(const struct git_hash_algo *algop,\n+\t\t\t    const unsigned char *data, size_t len);\n \n /*\n  * Returns the total number of bytes fed to the hashfile so far (including ones\ndiff --git a/midx-write.c b/midx-write.c\nindex 48d6558253e..26d9d8bb148 100644\n--- a/midx-write.c\n+++ b/midx-write.c\n@@ -1342,10 +1342,12 @@ static int write_midx_internal(struct repository *r, const char *object_dir,\n \t\t\treturn -1;\n \t\t}\n \n-\t\tf = hashfd(get_tempfile_fd(incr), get_tempfile_path(incr));\n+\t\tf = hashfd(r->hash_algo, get_tempfile_fd(incr),\n+\t\t\t   get_tempfile_path(incr));\n \t} else {\n \t\thold_lock_file_for_update(&lk, midx_name.buf, LOCK_DIE_ON_ERROR);\n-\t\tf = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk));\n+\t\tf = hashfd(r->hash_algo, get_lock_file_fd(&lk),\n+\t\t\t   get_lock_file_path(&lk));\n \t}\n \n \tcf = init_chunkfile(f);\ndiff --git a/midx.c b/midx.c\nindex d91088efb87..807fdf72f7b 100644\n--- a/midx.c\n+++ b/midx.c\n@@ -747,7 +747,8 @@ int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, i\n \n int midx_checksum_valid(struct multi_pack_index *m)\n {\n-\treturn hashfile_checksum_valid(m->data, m->data_len);\n+\treturn hashfile_checksum_valid(m->repo->hash_algo,\n+\t\t\t\t       m->data, m->data_len);\n }\n \n struct clear_midx_data {\ndiff --git a/pack-bitmap-write.c b/pack-bitmap-write.c\nindex 34e86d49947..50e5c491ccb 100644\n--- a/pack-bitmap-write.c\n+++ b/pack-bitmap-write.c\n@@ -1030,7 +1030,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,\n \tif (writer->pseudo_merges_nr)\n \t\toptions |= BITMAP_OPT_PSEUDO_MERGES;\n \n-\tf = hashfd(fd, tmp_file.buf);\n+\tf = hashfd(the_repository->hash_algo, fd, tmp_file.buf);\n \n \tmemcpy(header.magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE));\n \theader.version = htons(default_version);\ndiff --git a/pack-bitmap.c b/pack-bitmap.c\nindex 6406953d322..f0e2c000252 100644\n--- a/pack-bitmap.c\n+++ b/pack-bitmap.c\n@@ -3024,7 +3024,8 @@ int bitmap_is_preferred_refname(struct repository *r, const char *refname)\n \treturn 0;\n }\n \n-static int verify_bitmap_file(const char *name)\n+static int verify_bitmap_file(const struct git_hash_algo *algop,\n+\t\t\t      const char *name)\n {\n \tstruct stat st;\n \tunsigned char *data;\n@@ -3040,7 +3041,7 @@ static int verify_bitmap_file(const char *name)\n \n \tdata = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);\n \tclose(fd);\n-\tif (!hashfile_checksum_valid(data, st.st_size))\n+\tif (!hashfile_checksum_valid(algop, data, st.st_size))\n \t\tres = error(_(\"bitmap file '%s' has invalid checksum\"),\n \t\t\t    name);\n \n@@ -3055,14 +3056,14 @@ int verify_bitmap_files(struct repository *r)\n \tfor (struct multi_pack_index *m = get_multi_pack_index(r);\n \t     m; m = m->next) {\n \t\tchar *midx_bitmap_name = midx_bitmap_filename(m);\n-\t\tres |= verify_bitmap_file(midx_bitmap_name);\n+\t\tres |= verify_bitmap_file(r->hash_algo, midx_bitmap_name);\n \t\tfree(midx_bitmap_name);\n \t}\n \n \tfor (struct packed_git *p = get_all_packs(r);\n \t     p; p = p->next) {\n \t\tchar *pack_bitmap_name = pack_bitmap_filename(p);\n-\t\tres |= verify_bitmap_file(pack_bitmap_name);\n+\t\tres |= verify_bitmap_file(r->hash_algo, pack_bitmap_name);\n \t\tfree(pack_bitmap_name);\n \t}\n \ndiff --git a/pack-check.c b/pack-check.c\nindex d0aeb5ec412..6bcadc1e679 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -180,7 +180,7 @@ int verify_pack_index(struct packed_git *p)\n \t\treturn error(\"packfile %s index not opened\", p->pack_name);\n \n \t/* Verify SHA1 sum of the index file */\n-\tif (!hashfile_checksum_valid(p->index_data, p->index_size))\n+\tif (!hashfile_checksum_valid(the_repository->hash_algo, p->index_data, p->index_size))\n \t\terr = error(\"Packfile index for %s hash mismatch\",\n \t\t\t    p->pack_name);\n \treturn err;\ndiff --git a/pack-revindex.c b/pack-revindex.c\nindex d3832478d99..78139e3d7f5 100644\n--- a/pack-revindex.c\n+++ b/pack-revindex.c\n@@ -322,7 +322,8 @@ int verify_pack_revindex(struct packed_git *p)\n \tif (!p->revindex_map || !p->revindex_data)\n \t\treturn res;\n \n-\tif (!hashfile_checksum_valid((const unsigned char *)p->revindex_map, p->revindex_size)) {\n+\tif (!hashfile_checksum_valid(the_repository->hash_algo,\n+\t\t\t\t     (const unsigned char *)p->revindex_map, p->revindex_size)) {\n \t\terror(_(\"invalid checksum\"));\n \t\tres = -1;\n \t}\ndiff --git a/pack-write.c b/pack-write.c\nindex 823e40b42f2..5eb89f44cf4 100644\n--- a/pack-write.c\n+++ b/pack-write.c\n@@ -82,7 +82,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \n \tif (opts->flags & WRITE_IDX_VERIFY) {\n \t\tassert(index_name);\n-\t\tf = hashfd_check(index_name);\n+\t\tf = hashfd_check(the_repository->hash_algo, index_name);\n \t} else {\n \t\tif (!index_name) {\n \t\t\tstruct strbuf tmp_file = STRBUF_INIT;\n@@ -92,7 +92,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\t\tunlink(index_name);\n \t\t\tfd = xopen(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t}\n-\t\tf = hashfd(fd, index_name);\n+\t\tf = hashfd(the_repository->hash_algo, fd, index_name);\n \t}\n \n \t/* if last object's offset is >= 2^31 we should use index V2 */\n@@ -268,7 +268,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\tfd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t\tpath = xstrdup(rev_name);\n \t\t}\n-\t\tf = hashfd(fd, path);\n+\t\tf = hashfd(the_repository->hash_algo, fd, path);\n \t} else if (flags & WRITE_REV_VERIFY) {\n \t\tstruct stat statbuf;\n \t\tif (stat(rev_name, &statbuf)) {\n@@ -278,7 +278,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\t} else\n \t\t\t\tdie_errno(_(\"could not stat: %s\"), rev_name);\n \t\t}\n-\t\tf = hashfd_check(rev_name);\n+\t\tf = hashfd_check(the_repository->hash_algo, rev_name);\n \t\tpath = xstrdup(rev_name);\n \t} else {\n \t\treturn NULL;\n@@ -346,7 +346,7 @@ static char *write_mtimes_file(const struct git_hash_algo *hash_algo,\n \n \tfd = odb_mkstemp(&tmp_file, \"pack/tmp_mtimes_XXXXXX\");\n \tmtimes_name = strbuf_detach(&tmp_file, NULL);\n-\tf = hashfd(fd, mtimes_name);\n+\tf = hashfd(the_repository->hash_algo, fd, mtimes_name);\n \n \twrite_mtimes_header(hash_algo, f);\n \twrite_mtimes_objects(f, to_pack, objects, nr_objects);\n@@ -534,7 +534,7 @@ struct hashfile *create_tmp_packfile(char **pack_tmp_name)\n \n \tfd = odb_mkstemp(&tmpname, \"pack/tmp_pack_XXXXXX\");\n \t*pack_tmp_name = strbuf_detach(&tmpname, NULL);\n-\treturn hashfd(fd, *pack_tmp_name);\n+\treturn hashfd(the_repository->hash_algo, fd, *pack_tmp_name);\n }\n \n static void rename_tmp_packfile(struct strbuf *name_prefix, const char *source,\ndiff --git a/read-cache.c b/read-cache.c\nindex e678c13e8f1..a012cb22368 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -2848,7 +2848,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,\n \tstruct strbuf sb = STRBUF_INIT;\n \tint nr, nr_threads, ret;\n \n-\tf = hashfd(tempfile->fd, tempfile->filename.buf);\n+\tf = hashfd(the_repository->hash_algo, tempfile->fd, tempfile->filename.buf);\n \n \tprepare_repo_settings(r);\n \tf->skip_hash = r->settings.index_skip_hash;\n\n-- \n2.49.0.rc0.375.gae4b89d849.dirty\n\n"},{"id":"513379","messageId":"20250303-b4-pks-objects-without-the-repository-v1-3-c5dd43f2476e@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH 03/12] pack-write: stop depending on `the_repository` and `the_hash_algo`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-03T08:47:32Z","receivedAt":"2025-03-03T08:47:39Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are a couple of functions in \"pack-write.c\" that implicitly depend\non `the_repository` or `the_hash_algo`. Remove this dependency by\ninjecting the repository via a parameter and adapt callers accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fast-import.c  |  2 +-\n builtin/index-pack.c   |  4 ++--\n builtin/pack-objects.c |  4 ++--\n bulk-checkin.c         |  4 ++--\n midx-write.c           |  2 +-\n pack-write.c           | 55 +++++++++++++++++++++++++-------------------------\n pack.h                 | 11 +++++-----\n 7 files changed, 41 insertions(+), 41 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 86e6e754816..e1758aa9514 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -798,7 +798,7 @@ static const char *create_index(void)\n \tif (c != last)\n \t\tdie(\"internal consistency error creating the index\");\n \n-\ttmpfile = write_idx_file(the_hash_algo, NULL, idx, object_count,\n+\ttmpfile = write_idx_file(the_repository, NULL, idx, object_count,\n \t\t\t\t &pack_idx_opts, pack_data->hash);\n \tfree(idx);\n \treturn tmpfile;\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex b8bb0ac01de..e4f2aa01ed5 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -2088,10 +2088,10 @@ int cmd_index_pack(int argc,\n \tALLOC_ARRAY(idx_objects, nr_objects);\n \tfor (i = 0; i < nr_objects; i++)\n \t\tidx_objects[i] = &objects[i].idx;\n-\tcurr_index = write_idx_file(the_hash_algo, index_name, idx_objects,\n+\tcurr_index = write_idx_file(the_repository, index_name, idx_objects,\n \t\t\t\t    nr_objects, &opts, pack_hash);\n \tif (rev_index)\n-\t\tcurr_rev_index = write_rev_file(the_hash_algo, rev_index_name,\n+\t\tcurr_rev_index = write_rev_file(the_repository, rev_index_name,\n \t\t\t\t\t\tidx_objects, nr_objects,\n \t\t\t\t\t\tpack_hash, opts.flags);\n \tfree(idx_objects);\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex c3adbc94504..e05dfc4021e 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -1314,7 +1314,7 @@ static void write_pack_file(void)\n \t\t\tf = hashfd_throughput(the_repository->hash_algo, 1,\n \t\t\t\t\t      \"<stdout>\", progress_state);\n \t\telse\n-\t\t\tf = create_tmp_packfile(&pack_tmp_name);\n+\t\t\tf = create_tmp_packfile(the_repository, &pack_tmp_name);\n \n \t\toffset = write_pack_header(f, nr_remaining);\n \n@@ -1407,7 +1407,7 @@ static void write_pack_file(void)\n \t\t\tif (cruft)\n \t\t\t\tpack_idx_opts.flags |= WRITE_MTIMES;\n \n-\t\t\tstage_tmp_packfiles(the_hash_algo, &tmpname,\n+\t\t\tstage_tmp_packfiles(the_repository, &tmpname,\n \t\t\t\t\t    pack_tmp_name, written_list,\n \t\t\t\t\t    nr_written, &to_pack,\n \t\t\t\t\t    &pack_idx_opts, hash,\ndiff --git a/bulk-checkin.c b/bulk-checkin.c\nindex 20f2da67b93..23ac00ea0a6 100644\n--- a/bulk-checkin.c\n+++ b/bulk-checkin.c\n@@ -44,7 +44,7 @@ static void finish_tmp_packfile(struct strbuf *basename,\n {\n \tchar *idx_tmp_name = NULL;\n \n-\tstage_tmp_packfiles(the_hash_algo, basename, pack_tmp_name,\n+\tstage_tmp_packfiles(the_repository, basename, pack_tmp_name,\n \t\t\t    written_list, nr_written, NULL, pack_idx_opts, hash,\n \t\t\t    &idx_tmp_name);\n \trename_tmp_packfile_idx(basename, &idx_tmp_name);\n@@ -244,7 +244,7 @@ static void prepare_to_stream(struct bulk_checkin_packfile *state,\n \tif (!(flags & HASH_WRITE_OBJECT) || state->f)\n \t\treturn;\n \n-\tstate->f = create_tmp_packfile(&state->pack_tmp_name);\n+\tstate->f = create_tmp_packfile(the_repository, &state->pack_tmp_name);\n \treset_pack_idx_option(&state->pack_idx_opts);\n \n \t/* Pretend we are going to write only one object */\ndiff --git a/midx-write.c b/midx-write.c\nindex ac80a8298ed..a628ac24dcb 100644\n--- a/midx-write.c\n+++ b/midx-write.c\n@@ -658,7 +658,7 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash,\n \tstrbuf_addf(&buf, \"%s-%s.rev\", midx_name, hash_to_hex_algop(midx_hash,\n \t\t\t\t\t\t\t\t    ctx->repo->hash_algo));\n \n-\ttmp_file = write_rev_file_order(ctx->repo->hash_algo, NULL, ctx->pack_order,\n+\ttmp_file = write_rev_file_order(ctx->repo, NULL, ctx->pack_order,\n \t\t\t\t\tctx->entries_nr, midx_hash, WRITE_REV);\n \n \tif (finalize_object_file(tmp_file, buf.buf))\ndiff --git a/pack-write.c b/pack-write.c\nindex 5eb89f44cf4..6b06315f80a 100644\n--- a/pack-write.c\n+++ b/pack-write.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"gettext.h\"\n@@ -56,7 +54,7 @@ static int need_large_offset(off_t offset, const struct pack_idx_option *opts)\n  * The *sha1 contains the pack content SHA1 hash.\n  * The objects array passed in will be sorted by SHA1 on exit.\n  */\n-const char *write_idx_file(const struct git_hash_algo *hash_algo,\n+const char *write_idx_file(struct repository *repo,\n \t\t\t   const char *index_name, struct pack_idx_entry **objects,\n \t\t\t   int nr_objects, const struct pack_idx_option *opts,\n \t\t\t   const unsigned char *sha1)\n@@ -82,7 +80,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \n \tif (opts->flags & WRITE_IDX_VERIFY) {\n \t\tassert(index_name);\n-\t\tf = hashfd_check(the_repository->hash_algo, index_name);\n+\t\tf = hashfd_check(repo->hash_algo, index_name);\n \t} else {\n \t\tif (!index_name) {\n \t\t\tstruct strbuf tmp_file = STRBUF_INIT;\n@@ -92,7 +90,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\t\tunlink(index_name);\n \t\t\tfd = xopen(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t}\n-\t\tf = hashfd(the_repository->hash_algo, fd, index_name);\n+\t\tf = hashfd(repo->hash_algo, fd, index_name);\n \t}\n \n \t/* if last object's offset is >= 2^31 we should use index V2 */\n@@ -131,7 +129,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\tstruct pack_idx_entry *obj = *list++;\n \t\tif (index_version < 2)\n \t\t\thashwrite_be32(f, obj->offset);\n-\t\thashwrite(f, obj->oid.hash, hash_algo->rawsz);\n+\t\thashwrite(f, obj->oid.hash, repo->hash_algo->rawsz);\n \t\tif ((opts->flags & WRITE_IDX_STRICT) &&\n \t\t    (i && oideq(&list[-2]->oid, &obj->oid)))\n \t\t\tdie(\"The same object %s appears twice in the pack\",\n@@ -173,7 +171,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\t}\n \t}\n \n-\thashwrite(f, sha1, hash_algo->rawsz);\n+\thashwrite(f, sha1, repo->hash_algo->rawsz);\n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n \t\t\t  CSUM_HASH_IN_STREAM | CSUM_CLOSE |\n \t\t\t  ((opts->flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC));\n@@ -217,7 +215,7 @@ static void write_rev_trailer(const struct git_hash_algo *hash_algo,\n \thashwrite(f, hash, hash_algo->rawsz);\n }\n \n-char *write_rev_file(const struct git_hash_algo *hash_algo,\n+char *write_rev_file(struct repository *repo,\n \t\t     const char *rev_name,\n \t\t     struct pack_idx_entry **objects,\n \t\t     uint32_t nr_objects,\n@@ -236,7 +234,7 @@ char *write_rev_file(const struct git_hash_algo *hash_algo,\n \t\tpack_order[i] = i;\n \tQSORT_S(pack_order, nr_objects, pack_order_cmp, objects);\n \n-\tret = write_rev_file_order(hash_algo, rev_name, pack_order, nr_objects,\n+\tret = write_rev_file_order(repo, rev_name, pack_order, nr_objects,\n \t\t\t\t   hash, flags);\n \n \tfree(pack_order);\n@@ -244,7 +242,7 @@ char *write_rev_file(const struct git_hash_algo *hash_algo,\n \treturn ret;\n }\n \n-char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n+char *write_rev_file_order(struct repository *repo,\n \t\t\t   const char *rev_name,\n \t\t\t   uint32_t *pack_order,\n \t\t\t   uint32_t nr_objects,\n@@ -268,7 +266,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\tfd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t\tpath = xstrdup(rev_name);\n \t\t}\n-\t\tf = hashfd(the_repository->hash_algo, fd, path);\n+\t\tf = hashfd(repo->hash_algo, fd, path);\n \t} else if (flags & WRITE_REV_VERIFY) {\n \t\tstruct stat statbuf;\n \t\tif (stat(rev_name, &statbuf)) {\n@@ -278,18 +276,18 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\t} else\n \t\t\t\tdie_errno(_(\"could not stat: %s\"), rev_name);\n \t\t}\n-\t\tf = hashfd_check(the_repository->hash_algo, rev_name);\n+\t\tf = hashfd_check(repo->hash_algo, rev_name);\n \t\tpath = xstrdup(rev_name);\n \t} else {\n \t\treturn NULL;\n \t}\n \n-\twrite_rev_header(hash_algo, f);\n+\twrite_rev_header(repo->hash_algo, f);\n \n \twrite_rev_index_positions(f, pack_order, nr_objects);\n-\twrite_rev_trailer(hash_algo, f, hash);\n+\twrite_rev_trailer(repo->hash_algo, f, hash);\n \n-\tif (adjust_shared_perm(the_repository, path) < 0)\n+\tif (adjust_shared_perm(repo, path) < 0)\n \t\tdie(_(\"failed to make %s readable\"), path);\n \n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n@@ -330,7 +328,7 @@ static void write_mtimes_trailer(const struct git_hash_algo *hash_algo,\n \thashwrite(f, hash, hash_algo->rawsz);\n }\n \n-static char *write_mtimes_file(const struct git_hash_algo *hash_algo,\n+static char *write_mtimes_file(struct repository *repo,\n \t\t\t       struct packing_data *to_pack,\n \t\t\t       struct pack_idx_entry **objects,\n \t\t\t       uint32_t nr_objects,\n@@ -346,13 +344,13 @@ static char *write_mtimes_file(const struct git_hash_algo *hash_algo,\n \n \tfd = odb_mkstemp(&tmp_file, \"pack/tmp_mtimes_XXXXXX\");\n \tmtimes_name = strbuf_detach(&tmp_file, NULL);\n-\tf = hashfd(the_repository->hash_algo, fd, mtimes_name);\n+\tf = hashfd(repo->hash_algo, fd, mtimes_name);\n \n-\twrite_mtimes_header(hash_algo, f);\n+\twrite_mtimes_header(repo->hash_algo, f);\n \twrite_mtimes_objects(f, to_pack, objects, nr_objects);\n-\twrite_mtimes_trailer(hash_algo, f, hash);\n+\twrite_mtimes_trailer(repo->hash_algo, f, hash);\n \n-\tif (adjust_shared_perm(the_repository, mtimes_name) < 0)\n+\tif (adjust_shared_perm(repo, mtimes_name) < 0)\n \t\tdie(_(\"failed to make %s readable\"), mtimes_name);\n \n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n@@ -527,14 +525,15 @@ int encode_in_pack_object_header(unsigned char *hdr, int hdr_len,\n \treturn n;\n }\n \n-struct hashfile *create_tmp_packfile(char **pack_tmp_name)\n+struct hashfile *create_tmp_packfile(struct repository *repo,\n+\t\t\t\t     char **pack_tmp_name)\n {\n \tstruct strbuf tmpname = STRBUF_INIT;\n \tint fd;\n \n \tfd = odb_mkstemp(&tmpname, \"pack/tmp_pack_XXXXXX\");\n \t*pack_tmp_name = strbuf_detach(&tmpname, NULL);\n-\treturn hashfd(the_repository->hash_algo, fd, *pack_tmp_name);\n+\treturn hashfd(repo->hash_algo, fd, *pack_tmp_name);\n }\n \n static void rename_tmp_packfile(struct strbuf *name_prefix, const char *source,\n@@ -555,7 +554,7 @@ void rename_tmp_packfile_idx(struct strbuf *name_buffer,\n \trename_tmp_packfile(name_buffer, *idx_tmp_name, \"idx\");\n }\n \n-void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,\n+void stage_tmp_packfiles(struct repository *repo,\n \t\t\t struct strbuf *name_buffer,\n \t\t\t const char *pack_tmp_name,\n \t\t\t struct pack_idx_entry **written_list,\n@@ -568,19 +567,19 @@ void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,\n \tchar *rev_tmp_name = NULL;\n \tchar *mtimes_tmp_name = NULL;\n \n-\tif (adjust_shared_perm(the_repository, pack_tmp_name))\n+\tif (adjust_shared_perm(repo, pack_tmp_name))\n \t\tdie_errno(\"unable to make temporary pack file readable\");\n \n-\t*idx_tmp_name = (char *)write_idx_file(hash_algo, NULL, written_list,\n+\t*idx_tmp_name = (char *)write_idx_file(repo, NULL, written_list,\n \t\t\t\t\t       nr_written, pack_idx_opts, hash);\n-\tif (adjust_shared_perm(the_repository, *idx_tmp_name))\n+\tif (adjust_shared_perm(repo, *idx_tmp_name))\n \t\tdie_errno(\"unable to make temporary index file readable\");\n \n-\trev_tmp_name = write_rev_file(hash_algo, NULL, written_list, nr_written,\n+\trev_tmp_name = write_rev_file(repo, NULL, written_list, nr_written,\n \t\t\t\t      hash, pack_idx_opts->flags);\n \n \tif (pack_idx_opts->flags & WRITE_MTIMES) {\n-\t\tmtimes_tmp_name = write_mtimes_file(hash_algo, to_pack,\n+\t\tmtimes_tmp_name = write_mtimes_file(repo, to_pack,\n \t\t\t\t\t\t    written_list, nr_written,\n \t\t\t\t\t\t    hash);\n \t}\ndiff --git a/pack.h b/pack.h\nindex 9f1194ac13d..5d4393eaffe 100644\n--- a/pack.h\n+++ b/pack.h\n@@ -87,7 +87,7 @@ struct progress;\n /* Note, the data argument could be NULL if object type is blob */\n typedef int (*verify_fn)(const struct object_id *, enum object_type, unsigned long, void*, int*);\n \n-const char *write_idx_file(const struct git_hash_algo *hash_algo,\n+const char *write_idx_file(struct repository *repo,\n \t\t\t   const char *index_name,\n \t\t\t   struct pack_idx_entry **objects,\n \t\t\t   int nr_objects,\n@@ -106,13 +106,13 @@ struct ref;\n \n void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought);\n \n-char *write_rev_file(const struct git_hash_algo *hash_algo,\n+char *write_rev_file(struct repository *repo,\n \t\t     const char *rev_name,\n \t\t     struct pack_idx_entry **objects,\n \t\t     uint32_t nr_objects,\n \t\t     const unsigned char *hash,\n \t\t     unsigned flags);\n-char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n+char *write_rev_file_order(struct repository *repo,\n \t\t\t   const char *rev_name,\n \t\t\t   uint32_t *pack_order,\n \t\t\t   uint32_t nr_objects,\n@@ -134,8 +134,9 @@ int read_pack_header(int fd, struct pack_header *);\n \n struct packing_data;\n \n-struct hashfile *create_tmp_packfile(char **pack_tmp_name);\n-void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,\n+struct hashfile *create_tmp_packfile(struct repository *repo,\n+\t\t\t\t     char **pack_tmp_name);\n+void stage_tmp_packfiles(struct repository *repo,\n \t\t\t struct strbuf *name_buffer,\n \t\t\t const char *pack_tmp_name,\n \t\t\t struct pack_idx_entry **written_list,\n\n-- \n2.49.0.rc0.375.gae4b89d849.dirty\n\n"},{"id":"513383","messageId":"20250303-b4-pks-objects-without-the-repository-v1-2-c5dd43f2476e@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH 02/12] object: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-03T08:47:31Z","receivedAt":"2025-03-03T08:47:39Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are a couple of functions exposed by \"object.c\" that implicitly\ndepend on `the_repository`. Remove this dependency by injecting the\nrepository via a parameter. Adapt callers accordingly by simply using\n`the_repository`, except in cases where the subsystem is already free of\nthe repository. In that case, we instead pass the repository provided by\nthe caller's context.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fsck.c         |  4 ++--\n builtin/grep.c         |  2 +-\n builtin/index-pack.c   |  4 ++--\n builtin/log.c          |  2 +-\n builtin/name-rev.c     |  4 ++--\n builtin/pack-objects.c |  2 +-\n builtin/prune.c        |  2 +-\n midx-write.c           |  4 ++--\n object.c               | 21 +++++++++++----------\n object.h               | 10 ++++++----\n pack-bitmap.c          |  6 +++---\n reachable.c            |  6 +++---\n revision.c             |  3 ++-\n shallow.c              | 10 +++++-----\n upload-pack.c          | 12 ++++++------\n 15 files changed, 48 insertions(+), 44 deletions(-)\n\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex eea1d43647f..a441eda7ff9 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -399,12 +399,12 @@ static void check_connectivity(void)\n \t}\n \n \t/* Look up all the requirements, warn about missing objects.. */\n-\tmax = get_max_object_index();\n+\tmax = repo_get_max_object_index(the_repository);\n \tif (verbose)\n \t\tfprintf_ln(stderr, _(\"Checking connectivity (%d objects)\"), max);\n \n \tfor (i = 0; i < max; i++) {\n-\t\tstruct object *obj = get_indexed_object(i);\n+\t\tstruct object *obj = repo_get_indexed_object(the_repository, i);\n \n \t\tif (obj)\n \t\t\tcheck_object(obj);\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex d1427290f77..cbbf6f26439 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -1144,7 +1144,7 @@ int cmd_grep(int argc,\n \t\t\tbreak;\n \t\t}\n \n-\t\tobject = parse_object_or_die(&oid, arg);\n+\t\tobject = parse_object_or_die(the_repository, &oid, arg);\n \t\tif (!seen_dashdash)\n \t\t\tverify_non_filename(prefix, arg);\n \t\tadd_object_array_with_path(object, arg, &list, oc.mode, oc.path);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 3eb5af20950..b8bb0ac01de 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -279,14 +279,14 @@ static unsigned check_objects(void)\n {\n \tunsigned i, max, foreign_nr = 0;\n \n-\tmax = get_max_object_index();\n+\tmax = repo_get_max_object_index(the_repository);\n \n \tif (verbose)\n \t\tprogress = start_delayed_progress(the_repository,\n \t\t\t\t\t\t  _(\"Checking objects\"), max);\n \n \tfor (i = 0; i < max; i++) {\n-\t\tforeign_nr += check_object(get_indexed_object(i));\n+\t\tforeign_nr += check_object(repo_get_indexed_object(the_repository, i));\n \t\tdisplay_progress(progress, i + 1);\n \t}\n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 04a6ef97bc1..0d4c579dad7 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -2468,7 +2468,7 @@ int cmd_format_patch(int argc,\n \tbase = get_base_commit(&cfg, list, nr);\n \tif (base) {\n \t\treset_revision_walk();\n-\t\tclear_object_flags(UNINTERESTING);\n+\t\tclear_object_flags(the_repository, UNINTERESTING);\n \t\tprepare_bases(&bases, base, list, nr);\n \t}\n \ndiff --git a/builtin/name-rev.c b/builtin/name-rev.c\nindex beac166b5cb..645de1cf819 100644\n--- a/builtin/name-rev.c\n+++ b/builtin/name-rev.c\n@@ -667,9 +667,9 @@ int cmd_name_rev(int argc,\n \t} else if (all) {\n \t\tint i, max;\n \n-\t\tmax = get_max_object_index();\n+\t\tmax = repo_get_max_object_index(the_repository);\n \t\tfor (i = 0; i < max; i++) {\n-\t\t\tstruct object *obj = get_indexed_object(i);\n+\t\t\tstruct object *obj = repo_get_indexed_object(the_repository, i);\n \t\t\tif (!obj || obj->type != OBJ_COMMIT)\n \t\t\t\tcontinue;\n \t\t\tshow_name(obj, NULL,\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 8e282f2a980..c3adbc94504 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -4161,7 +4161,7 @@ static int mark_bitmap_preferred_tip(const char *refname,\n \tif (!peel_iterated_oid(the_repository, oid, &peeled))\n \t\toid = &peeled;\n \n-\tobject = parse_object_or_die(oid, refname);\n+\tobject = parse_object_or_die(the_repository, oid, refname);\n \tif (object->type == OBJ_COMMIT)\n \t\tobject->flags |= NEEDS_BITMAP;\n \ndiff --git a/builtin/prune.c b/builtin/prune.c\nindex 1c357fffd8c..8f52da8bd66 100644\n--- a/builtin/prune.c\n+++ b/builtin/prune.c\n@@ -185,7 +185,7 @@ int cmd_prune(int argc,\n \t\tconst char *name = *argv++;\n \n \t\tif (!repo_get_oid(the_repository, name, &oid)) {\n-\t\t\tstruct object *object = parse_object_or_die(&oid,\n+\t\t\tstruct object *object = parse_object_or_die(the_repository, &oid,\n \t\t\t\t\t\t\t\t    name);\n \t\t\tadd_pending_object(&revs, object, \"\");\n \t\t}\ndiff --git a/midx-write.c b/midx-write.c\nindex 26d9d8bb148..ac80a8298ed 100644\n--- a/midx-write.c\n+++ b/midx-write.c\n@@ -708,7 +708,7 @@ static int add_ref_to_pending(const char *refname, const char *referent UNUSED,\n \tif (!peel_iterated_oid(revs->repo, oid, &peeled))\n \t\toid = &peeled;\n \n-\tobject = parse_object_or_die(oid, refname);\n+\tobject = parse_object_or_die(revs->repo, oid, refname);\n \tif (object->type != OBJ_COMMIT)\n \t\treturn 0;\n \n@@ -768,7 +768,7 @@ static int read_refs_snapshot(const char *refs_snapshot,\n \t\tif (*end)\n \t\t\tdie(_(\"malformed line: %s\"), buf.buf);\n \n-\t\tobject = parse_object_or_die(&oid, NULL);\n+\t\tobject = parse_object_or_die(revs->repo, &oid, NULL);\n \t\tif (preferred)\n \t\t\tobject->flags |= NEEDS_BITMAP;\n \ndiff --git a/object.c b/object.c\nindex 100bf9b8d12..d0a6b371b36 100644\n--- a/object.c\n+++ b/object.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -18,14 +17,15 @@\n #include \"commit-graph.h\"\n #include \"loose.h\"\n \n-unsigned int get_max_object_index(void)\n+unsigned int repo_get_max_object_index(const struct repository *repo)\n {\n-\treturn the_repository->parsed_objects->obj_hash_size;\n+\treturn repo->parsed_objects->obj_hash_size;\n }\n \n-struct object *get_indexed_object(unsigned int idx)\n+struct object *repo_get_indexed_object(const struct repository *repo,\n+\t\t\t\t       unsigned int idx)\n {\n-\treturn the_repository->parsed_objects->obj_hash[idx];\n+\treturn repo->parsed_objects->obj_hash[idx];\n }\n \n static const char *object_type_strings[] = {\n@@ -283,10 +283,11 @@ struct object *parse_object_buffer(struct repository *r, const struct object_id\n \treturn obj;\n }\n \n-struct object *parse_object_or_die(const struct object_id *oid,\n+struct object *parse_object_or_die(struct repository *repo,\n+\t\t\t\t   const struct object_id *oid,\n \t\t\t\t   const char *name)\n {\n-\tstruct object *o = parse_object(the_repository, oid);\n+\tstruct object *o = parse_object(repo, oid);\n \tif (o)\n \t\treturn o;\n \n@@ -524,12 +525,12 @@ void object_array_remove_duplicates(struct object_array *array)\n \t}\n }\n \n-void clear_object_flags(unsigned flags)\n+void clear_object_flags(struct repository *repo, unsigned flags)\n {\n \tint i;\n \n-\tfor (i=0; i < the_repository->parsed_objects->obj_hash_size; i++) {\n-\t\tstruct object *obj = the_repository->parsed_objects->obj_hash[i];\n+\tfor (i=0; i < repo->parsed_objects->obj_hash_size; i++) {\n+\t\tstruct object *obj = repo->parsed_objects->obj_hash[i];\n \t\tif (obj)\n \t\t\tobj->flags &= ~flags;\n \t}\ndiff --git a/object.h b/object.h\nindex 17f32f1103e..0a5293e9911 100644\n--- a/object.h\n+++ b/object.h\n@@ -169,12 +169,13 @@ int type_from_string_gently(const char *str, ssize_t, int gentle);\n /*\n  * Return the current number of buckets in the object hashmap.\n  */\n-unsigned int get_max_object_index(void);\n+unsigned int repo_get_max_object_index(const struct repository *repo);\n \n /*\n  * Return the object from the specified bucket in the object hashmap.\n  */\n-struct object *get_indexed_object(unsigned int);\n+struct object *repo_get_indexed_object(const struct repository *repo,\n+\t\t\t\t       unsigned int);\n \n /*\n  * This can be used to see if we have heard of the object before, but\n@@ -231,7 +232,8 @@ struct object *parse_object_with_flags(struct repository *r,\n  * \"name\" parameter is not NULL, it is included in the error message\n  * (otherwise, the hex object ID is given).\n  */\n-struct object *parse_object_or_die(const struct object_id *oid, const char *name);\n+struct object *parse_object_or_die(struct repository *repo, const struct object_id *oid,\n+\t\t\t\t   const char *name);\n \n /* Given the result of read_sha1_file(), returns the object after\n  * parsing it.  eaten_p indicates if the object has a borrowed copy\n@@ -336,7 +338,7 @@ void object_array_remove_duplicates(struct object_array *array);\n  */\n void object_array_clear(struct object_array *array);\n \n-void clear_object_flags(unsigned flags);\n+void clear_object_flags(struct repository *repo, unsigned flags);\n \n /*\n  * Clear the specified object flags from all in-core commit objects from\ndiff --git a/pack-bitmap.c b/pack-bitmap.c\nindex f0e2c000252..7fd78c634ef 100644\n--- a/pack-bitmap.c\n+++ b/pack-bitmap.c\n@@ -1301,7 +1301,7 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,\n \trevs->tag_objects = tmp_tags;\n \n \treset_revision_walk();\n-\tclear_object_flags(UNINTERESTING);\n+\tclear_object_flags(repo, UNINTERESTING);\n \n \t/*\n \t * Then add the boundary commit(s) as fill-in traversal tips.\n@@ -1935,7 +1935,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,\n \t\tstruct object *object = revs->pending.objects[i].item;\n \n \t\tif (object->type == OBJ_NONE)\n-\t\t\tparse_object_or_die(&object->oid, NULL);\n+\t\t\tparse_object_or_die(revs->repo, &object->oid, NULL);\n \n \t\twhile (object->type == OBJ_TAG) {\n \t\t\tstruct tag *tag = (struct tag *) object;\n@@ -1945,7 +1945,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,\n \t\t\telse\n \t\t\t\tobject_list_insert(object, &wants);\n \n-\t\t\tobject = parse_object_or_die(get_tagged_oid(tag), NULL);\n+\t\t\tobject = parse_object_or_die(revs->repo, get_tagged_oid(tag), NULL);\n \t\t\tobject->flags |= (tag->object.flags & UNINTERESTING);\n \t\t}\n \ndiff --git a/reachable.c b/reachable.c\nindex 9ee04c89ec6..1b26b9b1d76 100644\n--- a/reachable.c\n+++ b/reachable.c\n@@ -45,7 +45,7 @@ static void add_one_file(const char *path, struct rev_info *revs)\n \t}\n \tstrbuf_trim(&buf);\n \tif (!get_oid_hex(buf.buf, &oid)) {\n-\t\tobject = parse_object_or_die(&oid, buf.buf);\n+\t\tobject = parse_object_or_die(the_repository, &oid, buf.buf);\n \t\tadd_pending_object(revs, object, \"\");\n \t}\n \tstrbuf_release(&buf);\n@@ -94,7 +94,7 @@ static int add_one_ref(const char *path, const char *referent UNUSED, const stru\n \t\treturn 0;\n \t}\n \n-\tobject = parse_object_or_die(oid, path);\n+\tobject = parse_object_or_die(the_repository, oid, path);\n \tadd_pending_object(revs, object, \"\");\n \n \treturn 0;\n@@ -218,7 +218,7 @@ static void add_recent_object(const struct object_id *oid,\n \tswitch (type) {\n \tcase OBJ_TAG:\n \tcase OBJ_COMMIT:\n-\t\tobj = parse_object_or_die(oid, NULL);\n+\t\tobj = parse_object_or_die(the_repository, oid, NULL);\n \t\tbreak;\n \tcase OBJ_TREE:\n \t\tobj = (struct object *)lookup_tree(the_repository, oid);\ndiff --git a/revision.c b/revision.c\nindex c4390f0938c..b536c4a29ad 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -3612,7 +3612,8 @@ static void set_children(struct rev_info *revs)\n \n void reset_revision_walk(void)\n {\n-\tclear_object_flags(SEEN | ADDED | SHOWN | TOPO_WALK_EXPLORED | TOPO_WALK_INDEGREE);\n+\tclear_object_flags(the_repository,\n+\t\t\t   SEEN | ADDED | SHOWN | TOPO_WALK_EXPLORED | TOPO_WALK_INDEGREE);\n }\n \n static int mark_uninteresting(const struct object_id *oid,\ndiff --git a/shallow.c b/shallow.c\nindex 4bd9342c9a7..4b11b9062af 100644\n--- a/shallow.c\n+++ b/shallow.c\n@@ -226,7 +226,7 @@ struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av,\n \t * SHALLOW (excluded) and NOT_SHALLOW (included) should not be\n \t * set at this point. But better be safe than sorry.\n \t */\n-\tclear_object_flags(both_flags);\n+\tclear_object_flags(the_repository, both_flags);\n \n \tis_repository_shallow(the_repository); /* make sure shallows are read */\n \n@@ -613,9 +613,9 @@ static void paint_down(struct paint_info *info, const struct object_id *oid,\n \t\t}\n \t}\n \n-\tnr = get_max_object_index();\n+\tnr = repo_get_max_object_index(the_repository);\n \tfor (i = 0; i < nr; i++) {\n-\t\tstruct object *o = get_indexed_object(i);\n+\t\tstruct object *o = repo_get_indexed_object(the_repository, i);\n \t\tif (o && o->type == OBJ_COMMIT)\n \t\t\to->flags &= ~SEEN;\n \t}\n@@ -675,9 +675,9 @@ void assign_shallow_commits_to_refs(struct shallow_info *info,\n \t * Prepare the commit graph to track what refs can reach what\n \t * (new) shallow commits.\n \t */\n-\tnr = get_max_object_index();\n+\tnr = repo_get_max_object_index(the_repository);\n \tfor (i = 0; i < nr; i++) {\n-\t\tstruct object *o = get_indexed_object(i);\n+\t\tstruct object *o = repo_get_indexed_object(the_repository, i);\n \t\tif (!o || o->type != OBJ_COMMIT)\n \t\t\tcontinue;\n \ndiff --git a/upload-pack.c b/upload-pack.c\nindex 728b2477fcc..2b37d1e28f1 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -662,8 +662,8 @@ static int do_reachable_revlist(struct child_process *cmd,\n \n \tcmd_in = xfdopen(cmd->in, \"w\");\n \n-\tfor (i = get_max_object_index(); 0 < i; ) {\n-\t\to = get_indexed_object(--i);\n+\tfor (i = repo_get_max_object_index(the_repository); 0 < i; ) {\n+\t\to = repo_get_indexed_object(the_repository, --i);\n \t\tif (!o)\n \t\t\tcontinue;\n \t\tif (reachable && o->type == OBJ_COMMIT)\n@@ -731,8 +731,8 @@ static int get_reachable_list(struct upload_pack_data *data,\n \t\t\to->flags &= ~TMP_MARK;\n \t\t}\n \t}\n-\tfor (i = get_max_object_index(); 0 < i; i--) {\n-\t\to = get_indexed_object(i - 1);\n+\tfor (i = repo_get_max_object_index(the_repository); 0 < i; i--) {\n+\t\to = repo_get_indexed_object(the_repository, i - 1);\n \t\tif (o && o->type == OBJ_COMMIT &&\n \t\t    (o->flags & TMP_MARK)) {\n \t\t\tadd_object_array(o, NULL, reachable);\n@@ -1554,7 +1554,7 @@ static int parse_want_ref(struct packet_writer *writer, const char *line,\n \t\t}\n \n \t\tif (!o)\n-\t\t\to = parse_object_or_die(&oid, refname_nons);\n+\t\t\to = parse_object_or_die(the_repository, &oid, refname_nons);\n \n \t\tif (!(o->flags & WANTED)) {\n \t\t\to->flags |= WANTED;\n@@ -1790,7 +1790,7 @@ int upload_pack_v2(struct repository *r, struct packet_reader *request)\n \tenum fetch_state state = FETCH_PROCESS_ARGS;\n \tstruct upload_pack_data data;\n \n-\tclear_object_flags(ALL_FLAGS);\n+\tclear_object_flags(the_repository, ALL_FLAGS);\n \n \tupload_pack_data_init(&data);\n \tdata.use_sideband = LARGE_PACKET_MAX;\n\n-- \n2.49.0.rc0.375.gae4b89d849.dirty\n\n"},{"id":"513380","messageId":"20250303-b4-pks-objects-without-the-repository-v1-5-c5dd43f2476e@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH 05/12] pack-check: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-03T08:47:34Z","receivedAt":"2025-03-03T08:47:40Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"pack-check.c\" where we use the global\n`the_repository` variable, either explicitly or implicitly by using\n`the_hash_algo`. In all of those cases we already have a repository\navailable in the calling context though.\n\nRefactor the code to instead use the caller-provided repository and\nremove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n pack-check.c | 11 +++++------\n 1 file changed, 5 insertions(+), 6 deletions(-)\n\ndiff --git a/pack-check.c b/pack-check.c\nindex 017dc740f7b..95dcbbe9852 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -44,7 +43,7 @@ int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,\n \t} while (len);\n \n \tindex_crc = p->index_data;\n-\tindex_crc += 2 + 256 + (size_t)p->num_objects * (the_hash_algo->rawsz/4) + nr;\n+\tindex_crc += 2 + 256 + (size_t)p->num_objects * (p->repo->hash_algo->rawsz/4) + nr;\n \n \treturn data_crc != ntohl(*index_crc);\n }\n@@ -81,11 +80,11 @@ static int verify_packfile(struct repository *r,\n \t} while (offset < pack_sig_ofs);\n \tgit_hash_final(hash, &ctx);\n \tpack_sig = use_pack(p, w_curs, pack_sig_ofs, NULL);\n-\tif (!hasheq(hash, pack_sig, the_repository->hash_algo))\n+\tif (!hasheq(hash, pack_sig, r->hash_algo))\n \t\terr = error(\"%s pack checksum mismatch\",\n \t\t\t    p->pack_name);\n \tif (!hasheq(index_base + index_size - r->hash_algo->hexsz, pack_sig,\n-\t\t    the_repository->hash_algo))\n+\t\t    r->hash_algo))\n \t\terr = error(\"%s pack checksum does not match its index\",\n \t\t\t    p->pack_name);\n \tunuse_pack(w_curs);\n@@ -132,7 +131,7 @@ static int verify_packfile(struct repository *r,\n \t\tunuse_pack(w_curs);\n \n \t\tif (type == OBJ_BLOB &&\n-\t\t    repo_settings_get_big_file_threshold(the_repository) <= size) {\n+\t\t    repo_settings_get_big_file_threshold(r) <= size) {\n \t\t\t/*\n \t\t\t * Let stream_object_signature() check it with\n \t\t\t * the streaming interface; no point slurping\n@@ -181,7 +180,7 @@ int verify_pack_index(struct packed_git *p)\n \t\treturn error(\"packfile %s index not opened\", p->pack_name);\n \n \t/* Verify SHA1 sum of the index file */\n-\tif (!hashfile_checksum_valid(the_repository->hash_algo, p->index_data, p->index_size))\n+\tif (!hashfile_checksum_valid(p->repo->hash_algo, p->index_data, p->index_size))\n \t\terr = error(\"Packfile index for %s hash mismatch\",\n \t\t\t    p->pack_name);\n \treturn err;\n\n-- \n2.49.0.rc0.375.gae4b89d849.dirty\n\n"},{"id":"513381","messageId":"20250303-b4-pks-objects-without-the-repository-v1-4-c5dd43f2476e@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH 04/12] environment: move access to \"core.bigFileThreshold\" into repo settings","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-03T08:47:33Z","receivedAt":"2025-03-03T08:47:40Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The \"core.bigFileThreshold\" setting is stored in a global variable and\npopulated via `git_default_core_config()`. This may cause issues in\nthe case where one is handling multiple different repositories in a\nsingle process with different values for that config key, as we may or\nmay not see the correct value in that case. Furthermore, global state\nblocks our path towards libification.\n\nRefactor the code so that we instead store the value in `struct\nrepo_settings`, where the value is computed as-needed and cached.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n archive.c                |  2 +-\n builtin/fast-import.c    |  4 ++--\n builtin/index-pack.c     |  6 ++++--\n builtin/pack-objects.c   |  6 ++++--\n builtin/unpack-objects.c |  3 ++-\n config.c                 |  5 -----\n diff.c                   |  6 ++++--\n environment.c            |  1 -\n environment.h            |  1 -\n object-file.c            |  6 ++++--\n pack-check.c             |  3 ++-\n repo-settings.c          | 20 ++++++++++++++++++++\n repo-settings.h          |  5 +++++\n streaming.c              |  3 ++-\n t/t1050-large.sh         |  3 ++-\n 15 files changed, 52 insertions(+), 22 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex 8be4e7ac8db..f4331aeb49e 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -216,7 +216,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,\n \t/* Stream it? */\n \tif (S_ISREG(mode) && !args->convert &&\n \t    oid_object_info(args->repo, oid, &size) == OBJ_BLOB &&\n-\t    size > big_file_threshold)\n+\t    size > repo_settings_get_big_file_threshold(the_repository))\n \t\treturn write_entry(args, oid, path.buf, path.len, mode, NULL, size);\n \n \tbuffer = object_file_to_archive(args, path.buf, oid, mode, &type, &size);\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex e1758aa9514..ce52f78579d 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -2021,7 +2021,7 @@ static void parse_and_store_blob(\n \tstatic struct strbuf buf = STRBUF_INIT;\n \tuintmax_t len;\n \n-\tif (parse_data(&buf, big_file_threshold, &len))\n+\tif (parse_data(&buf, repo_settings_get_big_file_threshold(the_repository), &len))\n \t\tstore_object(OBJ_BLOB, &buf, last, oidout, mark);\n \telse {\n \t\tif (last) {\n@@ -3402,7 +3402,7 @@ static int parse_one_option(const char *option)\n \t\tunsigned long v;\n \t\tif (!git_parse_ulong(option, &v))\n \t\t\treturn 0;\n-\t\tbig_file_threshold = v;\n+\t\trepo_settings_set_big_file_threshold(the_repository, v);\n \t} else if (skip_prefix(option, \"depth=\", &option)) {\n \t\toption_depth(option);\n \t} else if (skip_prefix(option, \"active-branches=\", &option)) {\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex e4f2aa01ed5..4235215a1fd 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -485,7 +485,8 @@ static void *unpack_entry_data(off_t offset, unsigned long size,\n \t\tgit_hash_update(&c, hdr, hdrlen);\n \t} else\n \t\toid = NULL;\n-\tif (type == OBJ_BLOB && size > big_file_threshold)\n+\tif (type == OBJ_BLOB &&\n+\t    size > repo_settings_get_big_file_threshold(the_repository))\n \t\tbuf = fixed_buf;\n \telse\n \t\tbuf = xmallocz(size);\n@@ -799,7 +800,8 @@ static int check_collison(struct object_entry *entry)\n \tenum object_type type;\n \tunsigned long size;\n \n-\tif (entry->size <= big_file_threshold || entry->type != OBJ_BLOB)\n+\tif (entry->size <= repo_settings_get_big_file_threshold(the_repository) ||\n+\t    entry->type != OBJ_BLOB)\n \t\treturn -1;\n \n \tmemset(&data, 0, sizeof(data));\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex e05dfc4021e..eefc6c78096 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -499,7 +499,8 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent\n \n \tif (!usable_delta) {\n \t\tif (oe_type(entry) == OBJ_BLOB &&\n-\t\t    oe_size_greater_than(&to_pack, entry, big_file_threshold) &&\n+\t\t    oe_size_greater_than(&to_pack, entry,\n+\t\t\t\t\t repo_settings_get_big_file_threshold(the_repository)) &&\n \t\t    (st = open_istream(the_repository, &entry->idx.oid, &type,\n \t\t\t\t       &size, NULL)) != NULL)\n \t\t\tbuf = NULL;\n@@ -2454,7 +2455,8 @@ static void get_object_details(void)\n \t\tstruct object_entry *entry = sorted_by_offset[i];\n \t\tcheck_object(entry, i);\n \t\tif (entry->type_valid &&\n-\t\t    oe_size_greater_than(&to_pack, entry, big_file_threshold))\n+\t\t    oe_size_greater_than(&to_pack, entry,\n+\t\t\t\t\t repo_settings_get_big_file_threshold(the_repository)))\n \t\t\tentry->no_try_delta = 1;\n \t\tdisplay_progress(progress_state, i + 1);\n \t}\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex 8383bcf4049..e20c120913e 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -553,7 +553,8 @@ static void unpack_one(unsigned nr)\n \n \tswitch (type) {\n \tcase OBJ_BLOB:\n-\t\tif (!dry_run && size > big_file_threshold) {\n+\t\tif (!dry_run &&\n+\t\t    size > repo_settings_get_big_file_threshold(the_repository)) {\n \t\t\tstream_blob(size, nr);\n \t\t\treturn;\n \t\t}\ndiff --git a/config.c b/config.c\nindex dfd03b9421c..dc95608f749 100644\n--- a/config.c\n+++ b/config.c\n@@ -1490,11 +1490,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.bigfilethreshold\")) {\n-\t\tbig_file_threshold = git_config_ulong(var, value, ctx->kvi);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.autocrlf\")) {\n \t\tif (value && !strcasecmp(value, \"input\")) {\n \t\t\tauto_crlf = AUTO_CRLF_INPUT;\ndiff --git a/diff.c b/diff.c\nindex c89c15d98e0..4f802b4251c 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -4193,7 +4193,8 @@ int diff_populate_filespec(struct repository *r,\n \t\t * is probably fine.\n \t\t */\n \t\tif (check_binary &&\n-\t\t    s->size > big_file_threshold && s->is_binary == -1) {\n+\t\t    s->size > repo_settings_get_big_file_threshold(the_repository) &&\n+\t\t    s->is_binary == -1) {\n \t\t\ts->is_binary = 1;\n \t\t\treturn 0;\n \t\t}\n@@ -4243,7 +4244,8 @@ int diff_populate_filespec(struct repository *r,\n \t\tif (size_only || check_binary) {\n \t\t\tif (size_only)\n \t\t\t\treturn 0;\n-\t\t\tif (s->size > big_file_threshold && s->is_binary == -1) {\n+\t\t\tif (s->size > repo_settings_get_big_file_threshold(the_repository) &&\n+\t\t\t    s->is_binary == -1) {\n \t\t\t\ts->is_binary = 1;\n \t\t\t\treturn 0;\n \t\t\t}\ndiff --git a/environment.c b/environment.c\nindex 9e4c7781be0..3c32367c28c 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -49,7 +49,6 @@ int fsync_object_files = -1;\n int use_fsync = -1;\n enum fsync_method fsync_method = FSYNC_METHOD_DEFAULT;\n enum fsync_component fsync_components = FSYNC_COMPONENTS_DEFAULT;\n-unsigned long big_file_threshold = 512 * 1024 * 1024;\n char *editor_program;\n char *askpass_program;\n char *excludes_file;\ndiff --git a/environment.h b/environment.h\nindex 45e690f203f..91d854dcb08 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -154,7 +154,6 @@ extern int zlib_compression_level;\n extern int pack_compression_level;\n extern size_t packed_git_window_size;\n extern size_t packed_git_limit;\n-extern unsigned long big_file_threshold;\n extern unsigned long pack_size_limit_cfg;\n extern int max_allowed_tree_depth;\n \ndiff --git a/object-file.c b/object-file.c\nindex 726e41a0475..b3e0276b2a4 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2803,7 +2803,8 @@ int index_fd(struct index_state *istate, struct object_id *oid,\n \t\tret = index_stream_convert_blob(istate, oid, fd, path, flags);\n \telse if (!S_ISREG(st->st_mode))\n \t\tret = index_pipe(istate, oid, fd, type, path, flags);\n-\telse if (st->st_size <= big_file_threshold || type != OBJ_BLOB ||\n+\telse if (st->st_size <= repo_settings_get_big_file_threshold(the_repository) ||\n+\t\t type != OBJ_BLOB ||\n \t\t (path && would_convert_to_git(istate, path)))\n \t\tret = index_core(istate, oid, fd, xsize_t(st->st_size),\n \t\t\t\t type, path, flags);\n@@ -3137,7 +3138,8 @@ int read_loose_object(const char *path,\n \t\tgoto out;\n \t}\n \n-\tif (*oi->typep == OBJ_BLOB && *size > big_file_threshold) {\n+\tif (*oi->typep == OBJ_BLOB &&\n+\t    *size > repo_settings_get_big_file_threshold(the_repository)) {\n \t\tif (check_stream_oid(&stream, hdr, *size, path, expected_oid) < 0)\n \t\t\tgoto out;\n \t} else {\ndiff --git a/pack-check.c b/pack-check.c\nindex 6bcadc1e679..017dc740f7b 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -131,7 +131,8 @@ static int verify_packfile(struct repository *r,\n \t\ttype = unpack_object_header(p, w_curs, &curpos, &size);\n \t\tunuse_pack(w_curs);\n \n-\t\tif (type == OBJ_BLOB && big_file_threshold <= size) {\n+\t\tif (type == OBJ_BLOB &&\n+\t\t    repo_settings_get_big_file_threshold(the_repository) <= size) {\n \t\t\t/*\n \t\t\t * Let stream_object_signature() check it with\n \t\t\t * the streaming interface; no point slurping\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 67e9cfd2e63..4129f8fb2b4 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -20,6 +20,13 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest,\n \t\t*dest = def;\n }\n \n+static void repo_cfg_ulong(struct repository *r, const char *key, unsigned long *dest,\n+\t\t\t   unsigned long def)\n+{\n+\tif (repo_config_get_ulong(r, key, dest))\n+\t\t*dest = def;\n+}\n+\n void prepare_repo_settings(struct repository *r)\n {\n \tint experimental;\n@@ -151,6 +158,19 @@ void repo_settings_clear(struct repository *r)\n \tr->settings = empty;\n }\n \n+unsigned long repo_settings_get_big_file_threshold(struct repository *repo)\n+{\n+\tif (!repo->settings.big_file_threshold)\n+\t\trepo_cfg_ulong(repo, \"core.bigfilethreshold\",\n+\t\t\t       &repo->settings.big_file_threshold, 512 * 1024 * 1024);\n+\treturn repo->settings.big_file_threshold;\n+}\n+\n+void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value)\n+{\n+\trepo->settings.big_file_threshold = value;\n+}\n+\n enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo)\n {\n \tconst char *value;\ndiff --git a/repo-settings.h b/repo-settings.h\nindex ddc11967e01..2bf24b25973 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -64,6 +64,7 @@ struct repo_settings {\n \tsize_t delta_base_cache_limit;\n \tsize_t packed_git_window_size;\n \tsize_t packed_git_limit;\n+\tunsigned long big_file_threshold;\n \n \tchar *hooks_path;\n };\n@@ -88,6 +89,10 @@ int repo_settings_get_warn_ambiguous_refs(struct repository *repo);\n /* Read the value for \"core.hooksPath\". */\n const char *repo_settings_get_hooks_path(struct repository *repo);\n \n+/* Read and set the value for \"core.bigFileThreshold\". */\n+unsigned long repo_settings_get_big_file_threshold(struct repository *repo);\n+void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value);\n+\n /* Read, set or reset the value for \"core.sharedRepository\". */\n int repo_settings_get_shared_repository(struct repository *repo);\n void repo_settings_set_shared_repository(struct repository *repo, int value);\ndiff --git a/streaming.c b/streaming.c\nindex 38839511afc..018b794d252 100644\n--- a/streaming.c\n+++ b/streaming.c\n@@ -431,7 +431,8 @@ static int istream_source(struct git_istream *st,\n \t\tst->open = open_istream_loose;\n \t\treturn 0;\n \tcase OI_PACKED:\n-\t\tif (!oi.u.packed.is_delta && big_file_threshold < size) {\n+\t\tif (!oi.u.packed.is_delta &&\n+\t\t    repo_settings_get_big_file_threshold(the_repository) < size) {\n \t\t\tst->u.in_pack.pack = oi.u.packed.pack;\n \t\t\tst->u.in_pack.pos = oi.u.packed.offset;\n \t\t\tst->open = open_istream_pack_non_delta;\ndiff --git a/t/t1050-large.sh b/t/t1050-large.sh\nindex c71932b0242..5be273611ad 100755\n--- a/t/t1050-large.sh\n+++ b/t/t1050-large.sh\n@@ -6,7 +6,8 @@ test_description='adding and checking out large blobs'\n . ./test-lib.sh\n \n test_expect_success 'core.bigFileThreshold must be non-negative' '\n-\ttest_must_fail git -c core.bigFileThreshold=-1 rev-parse >out 2>err &&\n+\t: >input &&\n+\ttest_must_fail git -c core.bigFileThreshold=-1 hash-object input >out 2>err &&\n \tgrep \"bad numeric config value\" err &&\n \ttest_must_be_empty out\n '\n\n-- \n2.49.0.rc0.375.gae4b89d849.dirty\n\n"},{"id":"513382","messageId":"20250303-b4-pks-objects-without-the-repository-v1-6-c5dd43f2476e@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH 06/12] pack-revindex: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-03T08:47:35Z","receivedAt":"2025-03-03T08:47:41Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"pack-revindex.c\" where we use the global\n`the_repository` variable, either explicitly or implicitly by using\n`the_hash_algo`. In all of those cases we already have a repository\navailable in the calling context though.\n\nRefactor the code to instead use the caller-provided repository and\nremove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n pack-revindex.c | 34 ++++++++++++++++++++--------------\n 1 file changed, 20 insertions(+), 14 deletions(-)\n\ndiff --git a/pack-revindex.c b/pack-revindex.c\nindex 78139e3d7f5..038e0c96b1c 100644\n--- a/pack-revindex.c\n+++ b/pack-revindex.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"gettext.h\"\n #include \"pack-revindex.h\"\n@@ -9,6 +7,7 @@\n #include \"strbuf.h\"\n #include \"trace2.h\"\n #include \"parse.h\"\n+#include \"repository.h\"\n #include \"midx.h\"\n #include \"csum-file.h\"\n \n@@ -137,7 +136,7 @@ static void create_pack_revindex(struct packed_git *p)\n \tconst unsigned num_ent = p->num_objects;\n \tunsigned i;\n \tconst char *index = p->index_data;\n-\tconst unsigned hashsz = the_hash_algo->rawsz;\n+\tconst unsigned hashsz = p->repo->hash_algo->rawsz;\n \n \tALLOC_ARRAY(p->revindex, num_ent + 1);\n \tindex += 4 * 256;\n@@ -193,7 +192,11 @@ static char *pack_revindex_filename(struct packed_git *p)\n }\n \n #define RIDX_HEADER_SIZE (12)\n-#define RIDX_MIN_SIZE (RIDX_HEADER_SIZE + (2 * the_hash_algo->rawsz))\n+\n+static size_t ridx_min_size(const struct git_hash_algo *algo)\n+{\n+\treturn RIDX_HEADER_SIZE + (2 * algo->rawsz);\n+}\n \n struct revindex_header {\n \tuint32_t signature;\n@@ -201,7 +204,8 @@ struct revindex_header {\n \tuint32_t hash_id;\n };\n \n-static int load_revindex_from_disk(char *revindex_name,\n+static int load_revindex_from_disk(const struct git_hash_algo *algo,\n+\t\t\t\t   char *revindex_name,\n \t\t\t\t   uint32_t num_objects,\n \t\t\t\t   const uint32_t **data_p, size_t *len_p)\n {\n@@ -228,12 +232,12 @@ static int load_revindex_from_disk(char *revindex_name,\n \n \trevindex_size = xsize_t(st.st_size);\n \n-\tif (revindex_size < RIDX_MIN_SIZE) {\n+\tif (revindex_size < ridx_min_size(algo)) {\n \t\tret = error(_(\"reverse-index file %s is too small\"), revindex_name);\n \t\tgoto cleanup;\n \t}\n \n-\tif (revindex_size - RIDX_MIN_SIZE != st_mult(sizeof(uint32_t), num_objects)) {\n+\tif (revindex_size - ridx_min_size(algo) != st_mult(sizeof(uint32_t), num_objects)) {\n \t\tret = error(_(\"reverse-index file %s is corrupt\"), revindex_name);\n \t\tgoto cleanup;\n \t}\n@@ -279,7 +283,8 @@ int load_pack_revindex_from_disk(struct packed_git *p)\n \n \trevindex_name = pack_revindex_filename(p);\n \n-\tret = load_revindex_from_disk(revindex_name,\n+\tret = load_revindex_from_disk(p->repo->hash_algo,\n+\t\t\t\t      revindex_name,\n \t\t\t\t      p->num_objects,\n \t\t\t\t      &p->revindex_map,\n \t\t\t\t      &p->revindex_size);\n@@ -322,7 +327,7 @@ int verify_pack_revindex(struct packed_git *p)\n \tif (!p->revindex_map || !p->revindex_data)\n \t\treturn res;\n \n-\tif (!hashfile_checksum_valid(the_repository->hash_algo,\n+\tif (!hashfile_checksum_valid(p->repo->hash_algo,\n \t\t\t\t     (const unsigned char *)p->revindex_map, p->revindex_size)) {\n \t\terror(_(\"invalid checksum\"));\n \t\tres = -1;\n@@ -375,19 +380,20 @@ int load_midx_revindex(struct multi_pack_index *m)\n \t\t * not want to accidentally call munmap() in the middle of the\n \t\t * MIDX.\n \t\t */\n-\t\ttrace2_data_string(\"load_midx_revindex\", the_repository,\n+\t\ttrace2_data_string(\"load_midx_revindex\", m->repo,\n \t\t\t\t   \"source\", \"midx\");\n \t\tm->revindex_data = (const uint32_t *)m->chunk_revindex;\n \t\treturn 0;\n \t}\n \n-\ttrace2_data_string(\"load_midx_revindex\", the_repository,\n+\ttrace2_data_string(\"load_midx_revindex\", m->repo,\n \t\t\t   \"source\", \"rev\");\n \n \tget_midx_filename_ext(m->repo->hash_algo, &revindex_name, m->object_dir,\n \t\t\t      get_midx_checksum(m), MIDX_EXT_REV);\n \n-\tret = load_revindex_from_disk(revindex_name.buf,\n+\tret = load_revindex_from_disk(m->repo->hash_algo,\n+\t\t\t\t      revindex_name.buf,\n \t\t\t\t      m->num_objects,\n \t\t\t\t      &m->revindex_map,\n \t\t\t\t      &m->revindex_len);\n@@ -419,7 +425,7 @@ int offset_to_pack_pos(struct packed_git *p, off_t ofs, uint32_t *pos)\n {\n \tunsigned lo, hi;\n \n-\tif (load_pack_revindex(the_repository, p) < 0)\n+\tif (load_pack_revindex(p->repo, p) < 0)\n \t\treturn -1;\n \n \tlo = 0;\n@@ -465,7 +471,7 @@ off_t pack_pos_to_offset(struct packed_git *p, uint32_t pos)\n \tif (p->revindex)\n \t\treturn p->revindex[pos].offset;\n \telse if (pos == p->num_objects)\n-\t\treturn p->pack_size - the_hash_algo->rawsz;\n+\t\treturn p->pack_size - p->repo->hash_algo->rawsz;\n \telse\n \t\treturn nth_packed_object_offset(p, pack_pos_to_index(p, pos));\n }\n\n-- \n2.49.0.rc0.375.gae4b89d849.dirty\n\n"},{"id":"513384","messageId":"20250303-b4-pks-objects-without-the-repository-v1-7-c5dd43f2476e@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH 07/12] pack-bitmap-write: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-03T08:47:36Z","receivedAt":"2025-03-03T08:47:42Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"pack-bitmap-write.c\" where we use the\nglobal `the_repository` variable, either explicitly or implicitly by\nusing `the_hash_algo`.\n\nRefactor the code so that the `struct bitmap_writer` stores the\nrepository it is getting initialized with. Like this, we can adapt\ncallsites that use `the_repository` to instead use the repository\nprovided by the writer.\n\nRemove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n pack-bitmap-write.c | 36 ++++++++++++++++++------------------\n pack-bitmap.h       |  1 +\n 2 files changed, 19 insertions(+), 18 deletions(-)\n\ndiff --git a/pack-bitmap-write.c b/pack-bitmap-write.c\nindex 50e5c491ccb..6a97b52b36d 100644\n--- a/pack-bitmap-write.c\n+++ b/pack-bitmap-write.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -48,6 +47,7 @@ void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r,\n \tmemset(writer, 0, sizeof(struct bitmap_writer));\n \tif (writer->bitmaps)\n \t\tBUG(\"bitmap writer already initialized\");\n+\twriter->repo = r;\n \twriter->bitmaps = kh_init_oid_map();\n \twriter->pseudo_merge_commits = kh_init_oid_map();\n \twriter->to_pack = pdata;\n@@ -415,9 +415,9 @@ static void bitmap_builder_init(struct bitmap_builder *bb,\n \t\tbb->commits[bb->commits_nr++] = r->item;\n \t}\n \n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"num_selected_commits\", writer->selected_nr);\n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"num_maximal_commits\", num_maximal);\n \n \trelease_revisions(&revs);\n@@ -460,7 +460,7 @@ static int fill_bitmap_tree(struct bitmap_writer *writer,\n \t\tswitch (object_type(entry.mode)) {\n \t\tcase OBJ_TREE:\n \t\t\tif (fill_bitmap_tree(writer, bitmap,\n-\t\t\t\t\t     lookup_tree(the_repository, &entry.oid)) < 0)\n+\t\t\t\t\t     lookup_tree(writer->repo, &entry.oid)) < 0)\n \t\t\t\treturn -1;\n \t\t\tbreak;\n \t\tcase OBJ_BLOB:\n@@ -536,7 +536,7 @@ static int fill_bitmap_commit(struct bitmap_writer *writer,\n \t\t\t\treturn -1;\n \t\t\tbitmap_set(ent->bitmap, pos);\n \t\t\tprio_queue_put(tree_queue,\n-\t\t\t\t       repo_get_commit_tree(the_repository, c));\n+\t\t\t\t       repo_get_commit_tree(writer->repo, c));\n \t\t}\n \n \t\tfor (p = c->parents; p; p = p->next) {\n@@ -590,11 +590,11 @@ int bitmap_writer_build(struct bitmap_writer *writer)\n \tint closed = 1; /* until proven otherwise */\n \n \tif (writer->show_progress)\n-\t\twriter->progress = start_progress(the_repository,\n+\t\twriter->progress = start_progress(writer->repo,\n \t\t\t\t\t\t  \"Building bitmaps\",\n \t\t\t\t\t\t  writer->selected_nr);\n \ttrace2_region_enter(\"pack-bitmap-write\", \"building_bitmaps_total\",\n-\t\t\t    the_repository);\n+\t\t\t    writer->repo);\n \n \told_bitmap = prepare_bitmap_git(writer->to_pack->repo);\n \tif (old_bitmap)\n@@ -645,10 +645,10 @@ int bitmap_writer_build(struct bitmap_writer *writer)\n \tfree(mapping);\n \n \ttrace2_region_leave(\"pack-bitmap-write\", \"building_bitmaps_total\",\n-\t\t\t    the_repository);\n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\t\t\t    writer->repo);\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"building_bitmaps_reused\", reused_bitmaps_nr);\n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"building_bitmaps_pseudo_merge_reused\",\n \t\t\t   reused_pseudo_merge_bitmaps_nr);\n \n@@ -711,7 +711,7 @@ void bitmap_writer_select_commits(struct bitmap_writer *writer,\n \t}\n \n \tif (writer->show_progress)\n-\t\twriter->progress = start_progress(the_repository,\n+\t\twriter->progress = start_progress(writer->repo,\n \t\t\t\t\t\t  \"Selecting bitmap commits\", 0);\n \n \tfor (;;) {\n@@ -960,7 +960,7 @@ static void write_lookup_table(struct bitmap_writer *writer, struct hashfile *f,\n \tfor (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++)\n \t\ttable_inv[table[i]] = i;\n \n-\ttrace2_region_enter(\"pack-bitmap-write\", \"writing_lookup_table\", the_repository);\n+\ttrace2_region_enter(\"pack-bitmap-write\", \"writing_lookup_table\", writer->repo);\n \tfor (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) {\n \t\tstruct bitmapped_commit *selected = &writer->selected[table[i]];\n \t\tuint32_t xor_offset = selected->xor_offset;\n@@ -987,7 +987,7 @@ static void write_lookup_table(struct bitmap_writer *writer, struct hashfile *f,\n \t\thashwrite_be64(f, (uint64_t)offsets[table[i]]);\n \t\thashwrite_be32(f, xor_row);\n \t}\n-\ttrace2_region_leave(\"pack-bitmap-write\", \"writing_lookup_table\", the_repository);\n+\ttrace2_region_leave(\"pack-bitmap-write\", \"writing_lookup_table\", writer->repo);\n \n \tfree(table);\n \tfree(table_inv);\n@@ -1008,7 +1008,7 @@ static void write_hash_cache(struct hashfile *f,\n void bitmap_writer_set_checksum(struct bitmap_writer *writer,\n \t\t\t\tconst unsigned char *sha1)\n {\n-\thashcpy(writer->pack_checksum, sha1, the_repository->hash_algo);\n+\thashcpy(writer->pack_checksum, sha1, writer->repo->hash_algo);\n }\n \n void bitmap_writer_finish(struct bitmap_writer *writer,\n@@ -1030,15 +1030,15 @@ void bitmap_writer_finish(struct bitmap_writer *writer,\n \tif (writer->pseudo_merges_nr)\n \t\toptions |= BITMAP_OPT_PSEUDO_MERGES;\n \n-\tf = hashfd(the_repository->hash_algo, fd, tmp_file.buf);\n+\tf = hashfd(writer->repo->hash_algo, fd, tmp_file.buf);\n \n \tmemcpy(header.magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE));\n \theader.version = htons(default_version);\n \theader.options = htons(flags | options);\n \theader.entry_count = htonl(bitmap_writer_nr_selected_commits(writer));\n-\thashcpy(header.checksum, writer->pack_checksum, the_repository->hash_algo);\n+\thashcpy(header.checksum, writer->pack_checksum, writer->repo->hash_algo);\n \n-\thashwrite(f, &header, sizeof(header) - GIT_MAX_RAWSZ + the_hash_algo->rawsz);\n+\thashwrite(f, &header, sizeof(header) - GIT_MAX_RAWSZ + writer->repo->hash_algo->rawsz);\n \tdump_bitmap(f, writer->commits);\n \tdump_bitmap(f, writer->trees);\n \tdump_bitmap(f, writer->blobs);\n@@ -1072,7 +1072,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,\n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n \t\t\t  CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE);\n \n-\tif (adjust_shared_perm(the_repository, tmp_file.buf))\n+\tif (adjust_shared_perm(writer->repo, tmp_file.buf))\n \t\tdie_errno(\"unable to make temporary bitmap file readable\");\n \n \tif (rename(tmp_file.buf, filename))\ndiff --git a/pack-bitmap.h b/pack-bitmap.h\nindex d7f4b8b8e95..53cd42772f3 100644\n--- a/pack-bitmap.h\n+++ b/pack-bitmap.h\n@@ -104,6 +104,7 @@ int bitmap_has_oid_in_uninteresting(struct bitmap_index *, const struct object_i\n off_t get_disk_usage_from_bitmap(struct bitmap_index *, struct rev_info *);\n \n struct bitmap_writer {\n+\tstruct repository *repo;\n \tstruct ewah_bitmap *commits;\n \tstruct ewah_bitmap *trees;\n \tstruct ewah_bitmap *blobs;\n\n-- \n2.49.0.rc0.375.gae4b89d849.dirty\n\n"},{"id":"513385","messageId":"20250303-b4-pks-objects-without-the-repository-v1-8-c5dd43f2476e@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH 08/12] object-file-convert: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-03T08:47:37Z","receivedAt":"2025-03-03T08:47:43Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"object-file-convert.c\" where we use the\nglobal `the_repository` variable, either explicitly or implicitly by\nusing `the_hash_algo`. All of these callsites are transitively called\nfrom `convert_object_file()`, which indeed has no repo as input.\n\nRefactor the function so that it receives a repository as parameter and\npass it through to all internal functions to get rid of the dependency.\nRemove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/tag.c         |  2 +-\n commit.c              |  2 +-\n object-file-convert.c | 29 ++++++++++++++++-------------\n object-file-convert.h |  3 ++-\n object-file.c         |  7 ++++---\n 5 files changed, 24 insertions(+), 19 deletions(-)\n\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex d3e0943b734..7c173535cb3 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -172,7 +172,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,\n \tif (compat) {\n \t\tconst struct git_hash_algo *algo = the_repository->hash_algo;\n \n-\t\tif (convert_object_file(&compat_buf, algo, compat,\n+\t\tif (convert_object_file(the_repository ,&compat_buf, algo, compat,\n \t\t\t\t\tbuffer->buf, buffer->len, OBJ_TAG, 1))\n \t\t\tgoto out;\n \t\tif (sign_buffer(&compat_buf, &compat_sig, keyid))\ndiff --git a/commit.c b/commit.c\nindex 6efdb03997d..48aeefaad31 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1380,7 +1380,7 @@ static int convert_commit_extra_headers(const struct commit_extra_header *orig,\n \t\tstruct commit_extra_header *new;\n \t\tCALLOC_ARRAY(new, 1);\n \t\tif (!strcmp(orig->key, \"mergetag\")) {\n-\t\t\tif (convert_object_file(&out, algo, compat,\n+\t\t\tif (convert_object_file(the_repository, &out, algo, compat,\n \t\t\t\t\t\torig->value, orig->len,\n \t\t\t\t\t\tOBJ_TAG, 1)) {\n \t\t\t\tfree(new);\ndiff --git a/object-file-convert.c b/object-file-convert.c\nindex eba71955cf7..7ab875afe6c 100644\n--- a/object-file-convert.c\n+++ b/object-file-convert.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -63,7 +62,8 @@ static int decode_tree_entry_raw(struct object_id *oid, const char **path,\n \treturn 0;\n }\n \n-static int convert_tree_object(struct strbuf *out,\n+static int convert_tree_object(struct repository *repo,\n+\t\t\t       struct strbuf *out,\n \t\t\t       const struct git_hash_algo *from,\n \t\t\t       const struct git_hash_algo *to,\n \t\t\t       const char *buffer, size_t size)\n@@ -78,7 +78,7 @@ static int convert_tree_object(struct strbuf *out,\n \t\tif (decode_tree_entry_raw(&entry_oid, &path, &pathlen, from, p,\n \t\t\t\t\t  end - p))\n \t\t\treturn error(_(\"failed to decode tree entry\"));\n-\t\tif (repo_oid_to_algop(the_repository, &entry_oid, to, &mapped_oid))\n+\t\tif (repo_oid_to_algop(repo, &entry_oid, to, &mapped_oid))\n \t\t\treturn error(_(\"failed to map tree entry for %s\"), oid_to_hex(&entry_oid));\n \t\tstrbuf_add(out, p, path - p);\n \t\tstrbuf_add(out, path, pathlen);\n@@ -88,7 +88,8 @@ static int convert_tree_object(struct strbuf *out,\n \treturn 0;\n }\n \n-static int convert_tag_object(struct strbuf *out,\n+static int convert_tag_object(struct repository *repo,\n+\t\t\t      struct strbuf *out,\n \t\t\t      const struct git_hash_algo *from,\n \t\t\t      const struct git_hash_algo *to,\n \t\t\t      const char *buffer, size_t size)\n@@ -105,7 +106,7 @@ static int convert_tag_object(struct strbuf *out,\n \t\treturn error(\"bogus tag object\");\n \tif (parse_oid_hex_algop(buffer + 7, &oid, &p, from) < 0)\n \t\treturn error(\"bad tag object ID\");\n-\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n+\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n \t\treturn error(\"unable to map tree %s in tag object\",\n \t\t\t     oid_to_hex(&oid));\n \tsize -= ((p + 1) - buffer);\n@@ -139,7 +140,8 @@ static int convert_tag_object(struct strbuf *out,\n \treturn 0;\n }\n \n-static int convert_commit_object(struct strbuf *out,\n+static int convert_commit_object(struct repository *repo,\n+\t\t\t\t struct strbuf *out,\n \t\t\t\t const struct git_hash_algo *from,\n \t\t\t\t const struct git_hash_algo *to,\n \t\t\t\t const char *buffer, size_t size)\n@@ -165,7 +167,7 @@ static int convert_commit_object(struct strbuf *out,\n \t\t\t    (p != eol))\n \t\t\t\treturn error(_(\"bad %s in commit\"), \"tree\");\n \n-\t\t\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n+\t\t\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n \t\t\t\treturn error(_(\"unable to map %s %s in commit object\"),\n \t\t\t\t\t     \"tree\", oid_to_hex(&oid));\n \t\t\tstrbuf_addf(out, \"tree %s\\n\", oid_to_hex(&mapped_oid));\n@@ -177,7 +179,7 @@ static int convert_commit_object(struct strbuf *out,\n \t\t\t    (p != eol))\n \t\t\t\treturn error(_(\"bad %s in commit\"), \"parent\");\n \n-\t\t\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n+\t\t\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n \t\t\t\treturn error(_(\"unable to map %s %s in commit object\"),\n \t\t\t\t\t     \"parent\", oid_to_hex(&oid));\n \n@@ -202,7 +204,7 @@ static int convert_commit_object(struct strbuf *out,\n \t\t\t}\n \n \t\t\t/* Compute the new tag object */\n-\t\t\tif (convert_tag_object(&new_tag, from, to, tag.buf, tag.len)) {\n+\t\t\tif (convert_tag_object(repo, &new_tag, from, to, tag.buf, tag.len)) {\n \t\t\t\tstrbuf_release(&tag);\n \t\t\t\tstrbuf_release(&new_tag);\n \t\t\t\treturn -1;\n@@ -241,7 +243,8 @@ static int convert_commit_object(struct strbuf *out,\n \treturn 0;\n }\n \n-int convert_object_file(struct strbuf *outbuf,\n+int convert_object_file(struct repository *repo,\n+\t\t\tstruct strbuf *outbuf,\n \t\t\tconst struct git_hash_algo *from,\n \t\t\tconst struct git_hash_algo *to,\n \t\t\tconst void *buf, size_t len,\n@@ -256,13 +259,13 @@ int convert_object_file(struct strbuf *outbuf,\n \n \tswitch (type) {\n \tcase OBJ_COMMIT:\n-\t\tret = convert_commit_object(outbuf, from, to, buf, len);\n+\t\tret = convert_commit_object(repo, outbuf, from, to, buf, len);\n \t\tbreak;\n \tcase OBJ_TREE:\n-\t\tret = convert_tree_object(outbuf, from, to, buf, len);\n+\t\tret = convert_tree_object(repo, outbuf, from, to, buf, len);\n \t\tbreak;\n \tcase OBJ_TAG:\n-\t\tret = convert_tag_object(outbuf, from, to, buf, len);\n+\t\tret = convert_tag_object(repo, outbuf, from, to, buf, len);\n \t\tbreak;\n \tdefault:\n \t\t/* Not implemented yet, so fail. */\ndiff --git a/object-file-convert.h b/object-file-convert.h\nindex a4f802aa8ee..9b3cc5e533d 100644\n--- a/object-file-convert.h\n+++ b/object-file-convert.h\n@@ -14,7 +14,8 @@ int repo_oid_to_algop(struct repository *repo, const struct object_id *src,\n  * Convert an object file from one hash algorithm to another algorithm.\n  * Return -1 on failure, 0 on success.\n  */\n-int convert_object_file(struct strbuf *outbuf,\n+int convert_object_file(struct repository *repo,\n+\t\t\tstruct strbuf *outbuf,\n \t\t\tconst struct git_hash_algo *from,\n \t\t\tconst struct git_hash_algo *to,\n \t\t\tconst void *buf, size_t len,\ndiff --git a/object-file.c b/object-file.c\nindex b3e0276b2a4..b0e237a2acc 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1793,7 +1793,7 @@ static int oid_object_info_convert(struct repository *r,\n \t\tif (type == -1)\n \t\t\treturn -1;\n \t\tif (type != OBJ_BLOB) {\n-\t\t\tret = convert_object_file(&outbuf,\n+\t\t\tret = convert_object_file(the_repository, &outbuf,\n \t\t\t\t\t\t  the_hash_algo, input_algo,\n \t\t\t\t\t\t  content, size, type, !do_die);\n \t\t\tfree(content);\n@@ -2510,7 +2510,7 @@ int write_object_file_flags(const void *buf, unsigned long len,\n \t\t\thash_object_file(compat, buf, len, type, &compat_oid);\n \t\telse {\n \t\t\tstruct strbuf converted = STRBUF_INIT;\n-\t\t\tconvert_object_file(&converted, algo, compat,\n+\t\t\tconvert_object_file(the_repository, &converted, algo, compat,\n \t\t\t\t\t    buf, len, type, 0);\n \t\t\thash_object_file(compat, converted.buf, converted.len,\n \t\t\t\t\t type, &compat_oid);\n@@ -2550,7 +2550,8 @@ int write_object_file_literally(const void *buf, unsigned long len,\n \t\t\t\t\t &compat_oid);\n \t\telse if (compat_type != -1) {\n \t\t\tstruct strbuf converted = STRBUF_INIT;\n-\t\t\tconvert_object_file(&converted, algo, compat,\n+\t\t\tconvert_object_file(the_repository,\n+\t\t\t\t\t    &converted, algo, compat,\n \t\t\t\t\t    buf, len, compat_type, 0);\n \t\t\thash_object_file(compat, converted.buf, converted.len,\n \t\t\t\t\t compat_type, &compat_oid);\n\n-- \n2.49.0.rc0.375.gae4b89d849.dirty\n\n"},{"id":"513386","messageId":"20250303-b4-pks-objects-without-the-repository-v1-9-c5dd43f2476e@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH 09/12] delta-islands: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-03T08:47:38Z","receivedAt":"2025-03-03T08:47:44Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"delta-islands.c\" where we use the\nglobal `the_repository` variable, either explicitly or implicitly by\nusing `the_hash_algo`.\n\nRefactor the code to stop using `the_repository`. In most cases this is\ntrivial because we already had a repository availabe in the calling\ncontext, with the only exception being `propagate_island_marks()`. Adapt\nit so that the repository gets passed in via a parameter.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/pack-objects.c |  2 +-\n delta-islands.c        | 14 ++++++--------\n delta-islands.h        |  2 +-\n 3 files changed, 8 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex eefc6c78096..fba5db74656 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -3847,7 +3847,7 @@ static void show_commit(struct commit *commit, void *data UNUSED)\n \t\tindex_commit_for_bitmap(commit);\n \n \tif (use_delta_islands)\n-\t\tpropagate_island_marks(commit);\n+\t\tpropagate_island_marks(the_repository, commit);\n }\n \n static void show_object(struct object *obj, const char *name,\ndiff --git a/delta-islands.c b/delta-islands.c\nindex 3aec43fada3..36c94799d69 100644\n--- a/delta-islands.c\n+++ b/delta-islands.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -267,8 +266,7 @@ void resolve_tree_islands(struct repository *r,\n \tQSORT(todo, nr, tree_depth_compare);\n \n \tif (progress)\n-\t\tprogress_state = start_progress(the_repository,\n-\t\t\t\t\t\t_(\"Propagating island marks\"), nr);\n+\t\tprogress_state = start_progress(r, _(\"Propagating island marks\"), nr);\n \n \tfor (i = 0; i < nr; i++) {\n \t\tstruct object_entry *ent = todo[i].entry;\n@@ -490,9 +488,9 @@ void load_delta_islands(struct repository *r, int progress)\n \n \tisland_marks = kh_init_oid_map();\n \n-\tgit_config(island_config_callback, &ild);\n+\trepo_config(r, island_config_callback, &ild);\n \tild.remote_islands = kh_init_str();\n-\trefs_for_each_ref(get_main_ref_store(the_repository),\n+\trefs_for_each_ref(get_main_ref_store(r),\n \t\t\t  find_island_for_ref, &ild);\n \tfree_config_regexes(&ild);\n \tdeduplicate_islands(ild.remote_islands, r);\n@@ -502,7 +500,7 @@ void load_delta_islands(struct repository *r, int progress)\n \t\tfprintf(stderr, _(\"Marked %d islands, done.\\n\"), island_counter);\n }\n \n-void propagate_island_marks(struct commit *commit)\n+void propagate_island_marks(struct repository *r, struct commit *commit)\n {\n \tkhiter_t pos = kh_get_oid_map(island_marks, commit->object.oid);\n \n@@ -510,8 +508,8 @@ void propagate_island_marks(struct commit *commit)\n \t\tstruct commit_list *p;\n \t\tstruct island_bitmap *root_marks = kh_value(island_marks, pos);\n \n-\t\trepo_parse_commit(the_repository, commit);\n-\t\tset_island_marks(&repo_get_commit_tree(the_repository, commit)->object,\n+\t\trepo_parse_commit(r, commit);\n+\t\tset_island_marks(&repo_get_commit_tree(r, commit)->object,\n \t\t\t\t root_marks);\n \t\tfor (p = commit->parents; p; p = p->next)\n \t\t\tset_island_marks(&p->item->object, root_marks);\ndiff --git a/delta-islands.h b/delta-islands.h\nindex 8d1591ae28b..6107660306b 100644\n--- a/delta-islands.h\n+++ b/delta-islands.h\n@@ -12,7 +12,7 @@ void resolve_tree_islands(struct repository *r,\n \t\t\t  int progress,\n \t\t\t  struct packing_data *to_pack);\n void load_delta_islands(struct repository *r, int progress);\n-void propagate_island_marks(struct commit *commit);\n+void propagate_island_marks(struct repository *r, struct commit *commit);\n int compute_pack_layers(struct packing_data *to_pack);\n void free_island_marks(void);\n \n\n-- \n2.49.0.rc0.375.gae4b89d849.dirty\n\n"},{"id":"513388","messageId":"20250303-b4-pks-objects-without-the-repository-v1-10-c5dd43f2476e@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH 10/12] object-file: split out logic regarding hash algorithms","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-03T08:47:39Z","receivedAt":"2025-03-03T08:47:45Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"While we have a \"hash.h\" header, the actual implementation of the\nsubsystem is hosted by \"object-file.c\". This makes it harder than\nnecessary to find the actual implementation of the hash subsystem and\nintermingles the different concerns with one another.\n\nSplit out the implementation of hash algorithms into a new, separate\n\"hash.c\" file.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile      |   1 +\n hash.c        | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n meson.build   |   1 +\n object-file.c | 277 --------------------------------------------------------\n 4 files changed, 285 insertions(+), 277 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 6d45093089d..6dfe88322dd 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1041,6 +1041,7 @@ LIB_OBJS += gpg-interface.o\n LIB_OBJS += graph.o\n LIB_OBJS += grep.o\n LIB_OBJS += hash-lookup.o\n+LIB_OBJS += hash.o\n LIB_OBJS += hashmap.o\n LIB_OBJS += help.o\n LIB_OBJS += hex.o\ndiff --git a/hash.c b/hash.c\nnew file mode 100644\nindex 00000000000..dd5ac9d0eb2\n--- /dev/null\n+++ b/hash.c\n@@ -0,0 +1,283 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+#define DISABLE_SIGN_COMPARE_WARNINGS\n+\n+#include \"git-compat-util.h\"\n+#include \"hash.h\"\n+#include \"hex.h\"\n+\n+static const struct object_id empty_tree_oid = {\n+\t.hash = {\n+\t\t0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,\n+\t\t0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04\n+\t},\n+\t.algo = GIT_HASH_SHA1,\n+};\n+static const struct object_id empty_blob_oid = {\n+\t.hash = {\n+\t\t0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,\n+\t\t0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91\n+\t},\n+\t.algo = GIT_HASH_SHA1,\n+};\n+static const struct object_id null_oid_sha1 = {\n+\t.hash = {0},\n+\t.algo = GIT_HASH_SHA1,\n+};\n+static const struct object_id empty_tree_oid_sha256 = {\n+\t.hash = {\n+\t\t0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1,\n+\t\t0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5,\n+\t\t0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc,\n+\t\t0x53, 0x21\n+\t},\n+\t.algo = GIT_HASH_SHA256,\n+};\n+static const struct object_id empty_blob_oid_sha256 = {\n+\t.hash = {\n+\t\t0x47, 0x3a, 0x0f, 0x4c, 0x3b, 0xe8, 0xa9, 0x36, 0x81, 0xa2,\n+\t\t0x67, 0xe3, 0xb1, 0xe9, 0xa7, 0xdc, 0xda, 0x11, 0x85, 0x43,\n+\t\t0x6f, 0xe1, 0x41, 0xf7, 0x74, 0x91, 0x20, 0xa3, 0x03, 0x72,\n+\t\t0x18, 0x13\n+\t},\n+\t.algo = GIT_HASH_SHA256,\n+};\n+static const struct object_id null_oid_sha256 = {\n+\t.hash = {0},\n+\t.algo = GIT_HASH_SHA256,\n+};\n+\n+static void git_hash_sha1_init(struct git_hash_ctx *ctx)\n+{\n+\tctx->algop = &hash_algos[GIT_HASH_SHA1];\n+\tgit_SHA1_Init(&ctx->state.sha1);\n+}\n+\n+static void git_hash_sha1_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n+{\n+\tdst->algop = src->algop;\n+\tgit_SHA1_Clone(&dst->state.sha1, &src->state.sha1);\n+}\n+\n+static void git_hash_sha1_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n+{\n+\tgit_SHA1_Update(&ctx->state.sha1, data, len);\n+}\n+\n+static void git_hash_sha1_final(unsigned char *hash, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final(hash, &ctx->state.sha1);\n+}\n+\n+static void git_hash_sha1_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final(oid->hash, &ctx->state.sha1);\n+\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n+\toid->algo = GIT_HASH_SHA1;\n+}\n+\n+static void git_hash_sha1_init_unsafe(struct git_hash_ctx *ctx)\n+{\n+\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA1]);\n+\tgit_SHA1_Init_unsafe(&ctx->state.sha1_unsafe);\n+}\n+\n+static void git_hash_sha1_clone_unsafe(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n+{\n+\tdst->algop = src->algop;\n+\tgit_SHA1_Clone_unsafe(&dst->state.sha1_unsafe, &src->state.sha1_unsafe);\n+}\n+\n+static void git_hash_sha1_update_unsafe(struct git_hash_ctx *ctx, const void *data,\n+\t\t\t\t      size_t len)\n+{\n+\tgit_SHA1_Update_unsafe(&ctx->state.sha1_unsafe, data, len);\n+}\n+\n+static void git_hash_sha1_final_unsafe(unsigned char *hash, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final_unsafe(hash, &ctx->state.sha1_unsafe);\n+}\n+\n+static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final_unsafe(oid->hash, &ctx->state.sha1_unsafe);\n+\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n+\toid->algo = GIT_HASH_SHA1;\n+}\n+\n+static void git_hash_sha256_init(struct git_hash_ctx *ctx)\n+{\n+\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA256]);\n+\tgit_SHA256_Init(&ctx->state.sha256);\n+}\n+\n+static void git_hash_sha256_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n+{\n+\tdst->algop = src->algop;\n+\tgit_SHA256_Clone(&dst->state.sha256, &src->state.sha256);\n+}\n+\n+static void git_hash_sha256_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n+{\n+\tgit_SHA256_Update(&ctx->state.sha256, data, len);\n+}\n+\n+static void git_hash_sha256_final(unsigned char *hash, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA256_Final(hash, &ctx->state.sha256);\n+}\n+\n+static void git_hash_sha256_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA256_Final(oid->hash, &ctx->state.sha256);\n+\t/*\n+\t * This currently does nothing, so the compiler should optimize it out,\n+\t * but keep it in case we extend the hash size again.\n+\t */\n+\tmemset(oid->hash + GIT_SHA256_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA256_RAWSZ);\n+\toid->algo = GIT_HASH_SHA256;\n+}\n+\n+static void git_hash_unknown_init(struct git_hash_ctx *ctx UNUSED)\n+{\n+\tBUG(\"trying to init unknown hash\");\n+}\n+\n+static void git_hash_unknown_clone(struct git_hash_ctx *dst UNUSED,\n+\t\t\t\t   const struct git_hash_ctx *src UNUSED)\n+{\n+\tBUG(\"trying to clone unknown hash\");\n+}\n+\n+static void git_hash_unknown_update(struct git_hash_ctx *ctx UNUSED,\n+\t\t\t\t    const void *data UNUSED,\n+\t\t\t\t    size_t len UNUSED)\n+{\n+\tBUG(\"trying to update unknown hash\");\n+}\n+\n+static void git_hash_unknown_final(unsigned char *hash UNUSED,\n+\t\t\t\t   struct git_hash_ctx *ctx UNUSED)\n+{\n+\tBUG(\"trying to finalize unknown hash\");\n+}\n+\n+static void git_hash_unknown_final_oid(struct object_id *oid UNUSED,\n+\t\t\t\t       struct git_hash_ctx *ctx UNUSED)\n+{\n+\tBUG(\"trying to finalize unknown hash\");\n+}\n+\n+static const struct git_hash_algo sha1_unsafe_algo = {\n+\t.name = \"sha1\",\n+\t.format_id = GIT_SHA1_FORMAT_ID,\n+\t.rawsz = GIT_SHA1_RAWSZ,\n+\t.hexsz = GIT_SHA1_HEXSZ,\n+\t.blksz = GIT_SHA1_BLKSZ,\n+\t.init_fn = git_hash_sha1_init_unsafe,\n+\t.clone_fn = git_hash_sha1_clone_unsafe,\n+\t.update_fn = git_hash_sha1_update_unsafe,\n+\t.final_fn = git_hash_sha1_final_unsafe,\n+\t.final_oid_fn = git_hash_sha1_final_oid_unsafe,\n+\t.empty_tree = &empty_tree_oid,\n+\t.empty_blob = &empty_blob_oid,\n+\t.null_oid = &null_oid_sha1,\n+};\n+\n+const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n+\t{\n+\t\t.name = NULL,\n+\t\t.format_id = 0x00000000,\n+\t\t.rawsz = 0,\n+\t\t.hexsz = 0,\n+\t\t.blksz = 0,\n+\t\t.init_fn = git_hash_unknown_init,\n+\t\t.clone_fn = git_hash_unknown_clone,\n+\t\t.update_fn = git_hash_unknown_update,\n+\t\t.final_fn = git_hash_unknown_final,\n+\t\t.final_oid_fn = git_hash_unknown_final_oid,\n+\t\t.empty_tree = NULL,\n+\t\t.empty_blob = NULL,\n+\t\t.null_oid = NULL,\n+\t},\n+\t{\n+\t\t.name = \"sha1\",\n+\t\t.format_id = GIT_SHA1_FORMAT_ID,\n+\t\t.rawsz = GIT_SHA1_RAWSZ,\n+\t\t.hexsz = GIT_SHA1_HEXSZ,\n+\t\t.blksz = GIT_SHA1_BLKSZ,\n+\t\t.init_fn = git_hash_sha1_init,\n+\t\t.clone_fn = git_hash_sha1_clone,\n+\t\t.update_fn = git_hash_sha1_update,\n+\t\t.final_fn = git_hash_sha1_final,\n+\t\t.final_oid_fn = git_hash_sha1_final_oid,\n+\t\t.unsafe = &sha1_unsafe_algo,\n+\t\t.empty_tree = &empty_tree_oid,\n+\t\t.empty_blob = &empty_blob_oid,\n+\t\t.null_oid = &null_oid_sha1,\n+\t},\n+\t{\n+\t\t.name = \"sha256\",\n+\t\t.format_id = GIT_SHA256_FORMAT_ID,\n+\t\t.rawsz = GIT_SHA256_RAWSZ,\n+\t\t.hexsz = GIT_SHA256_HEXSZ,\n+\t\t.blksz = GIT_SHA256_BLKSZ,\n+\t\t.init_fn = git_hash_sha256_init,\n+\t\t.clone_fn = git_hash_sha256_clone,\n+\t\t.update_fn = git_hash_sha256_update,\n+\t\t.final_fn = git_hash_sha256_final,\n+\t\t.final_oid_fn = git_hash_sha256_final_oid,\n+\t\t.empty_tree = &empty_tree_oid_sha256,\n+\t\t.empty_blob = &empty_blob_oid_sha256,\n+\t\t.null_oid = &null_oid_sha256,\n+\t}\n+};\n+\n+const struct object_id *null_oid(void)\n+{\n+\treturn the_hash_algo->null_oid;\n+}\n+\n+const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\n+{\n+\tstatic char buf[GIT_MAX_HEXSZ + 1];\n+\treturn oid_to_hex_r(buf, algop->empty_tree);\n+}\n+\n+int hash_algo_by_name(const char *name)\n+{\n+\tint i;\n+\tif (!name)\n+\t\treturn GIT_HASH_UNKNOWN;\n+\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\t\tif (!strcmp(name, hash_algos[i].name))\n+\t\t\treturn i;\n+\treturn GIT_HASH_UNKNOWN;\n+}\n+\n+int hash_algo_by_id(uint32_t format_id)\n+{\n+\tint i;\n+\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\t\tif (format_id == hash_algos[i].format_id)\n+\t\t\treturn i;\n+\treturn GIT_HASH_UNKNOWN;\n+}\n+\n+int hash_algo_by_length(int len)\n+{\n+\tint i;\n+\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\t\tif (len == hash_algos[i].rawsz)\n+\t\t\treturn i;\n+\treturn GIT_HASH_UNKNOWN;\n+}\n+\n+const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop)\n+{\n+\t/* If we have a faster \"unsafe\" implementation, use that. */\n+\tif (algop->unsafe)\n+\t\treturn algop->unsafe;\n+\t/* Otherwise use the default one. */\n+\treturn algop;\n+}\ndiff --git a/meson.build b/meson.build\nindex 021a182135f..38568344953 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -311,6 +311,7 @@ libgit_sources = [\n   'graph.c',\n   'grep.c',\n   'hash-lookup.c',\n+  'hash.c',\n   'hashmap.c',\n   'help.c',\n   'hex.c',\ndiff --git a/object-file.c b/object-file.c\nindex b0e237a2acc..de603e2ca8c 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -45,283 +45,6 @@\n /* The maximum size for an object header. */\n #define MAX_HEADER_LEN 32\n \n-static const struct object_id empty_tree_oid = {\n-\t.hash = {\n-\t\t0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,\n-\t\t0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04\n-\t},\n-\t.algo = GIT_HASH_SHA1,\n-};\n-static const struct object_id empty_blob_oid = {\n-\t.hash = {\n-\t\t0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,\n-\t\t0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91\n-\t},\n-\t.algo = GIT_HASH_SHA1,\n-};\n-static const struct object_id null_oid_sha1 = {\n-\t.hash = {0},\n-\t.algo = GIT_HASH_SHA1,\n-};\n-static const struct object_id empty_tree_oid_sha256 = {\n-\t.hash = {\n-\t\t0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1,\n-\t\t0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5,\n-\t\t0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc,\n-\t\t0x53, 0x21\n-\t},\n-\t.algo = GIT_HASH_SHA256,\n-};\n-static const struct object_id empty_blob_oid_sha256 = {\n-\t.hash = {\n-\t\t0x47, 0x3a, 0x0f, 0x4c, 0x3b, 0xe8, 0xa9, 0x36, 0x81, 0xa2,\n-\t\t0x67, 0xe3, 0xb1, 0xe9, 0xa7, 0xdc, 0xda, 0x11, 0x85, 0x43,\n-\t\t0x6f, 0xe1, 0x41, 0xf7, 0x74, 0x91, 0x20, 0xa3, 0x03, 0x72,\n-\t\t0x18, 0x13\n-\t},\n-\t.algo = GIT_HASH_SHA256,\n-};\n-static const struct object_id null_oid_sha256 = {\n-\t.hash = {0},\n-\t.algo = GIT_HASH_SHA256,\n-};\n-\n-static void git_hash_sha1_init(struct git_hash_ctx *ctx)\n-{\n-\tctx->algop = &hash_algos[GIT_HASH_SHA1];\n-\tgit_SHA1_Init(&ctx->state.sha1);\n-}\n-\n-static void git_hash_sha1_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n-{\n-\tdst->algop = src->algop;\n-\tgit_SHA1_Clone(&dst->state.sha1, &src->state.sha1);\n-}\n-\n-static void git_hash_sha1_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n-{\n-\tgit_SHA1_Update(&ctx->state.sha1, data, len);\n-}\n-\n-static void git_hash_sha1_final(unsigned char *hash, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final(hash, &ctx->state.sha1);\n-}\n-\n-static void git_hash_sha1_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final(oid->hash, &ctx->state.sha1);\n-\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n-\toid->algo = GIT_HASH_SHA1;\n-}\n-\n-static void git_hash_sha1_init_unsafe(struct git_hash_ctx *ctx)\n-{\n-\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA1]);\n-\tgit_SHA1_Init_unsafe(&ctx->state.sha1_unsafe);\n-}\n-\n-static void git_hash_sha1_clone_unsafe(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n-{\n-\tdst->algop = src->algop;\n-\tgit_SHA1_Clone_unsafe(&dst->state.sha1_unsafe, &src->state.sha1_unsafe);\n-}\n-\n-static void git_hash_sha1_update_unsafe(struct git_hash_ctx *ctx, const void *data,\n-\t\t\t\t      size_t len)\n-{\n-\tgit_SHA1_Update_unsafe(&ctx->state.sha1_unsafe, data, len);\n-}\n-\n-static void git_hash_sha1_final_unsafe(unsigned char *hash, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final_unsafe(hash, &ctx->state.sha1_unsafe);\n-}\n-\n-static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final_unsafe(oid->hash, &ctx->state.sha1_unsafe);\n-\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n-\toid->algo = GIT_HASH_SHA1;\n-}\n-\n-static void git_hash_sha256_init(struct git_hash_ctx *ctx)\n-{\n-\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA256]);\n-\tgit_SHA256_Init(&ctx->state.sha256);\n-}\n-\n-static void git_hash_sha256_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n-{\n-\tdst->algop = src->algop;\n-\tgit_SHA256_Clone(&dst->state.sha256, &src->state.sha256);\n-}\n-\n-static void git_hash_sha256_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n-{\n-\tgit_SHA256_Update(&ctx->state.sha256, data, len);\n-}\n-\n-static void git_hash_sha256_final(unsigned char *hash, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA256_Final(hash, &ctx->state.sha256);\n-}\n-\n-static void git_hash_sha256_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA256_Final(oid->hash, &ctx->state.sha256);\n-\t/*\n-\t * This currently does nothing, so the compiler should optimize it out,\n-\t * but keep it in case we extend the hash size again.\n-\t */\n-\tmemset(oid->hash + GIT_SHA256_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA256_RAWSZ);\n-\toid->algo = GIT_HASH_SHA256;\n-}\n-\n-static void git_hash_unknown_init(struct git_hash_ctx *ctx UNUSED)\n-{\n-\tBUG(\"trying to init unknown hash\");\n-}\n-\n-static void git_hash_unknown_clone(struct git_hash_ctx *dst UNUSED,\n-\t\t\t\t   const struct git_hash_ctx *src UNUSED)\n-{\n-\tBUG(\"trying to clone unknown hash\");\n-}\n-\n-static void git_hash_unknown_update(struct git_hash_ctx *ctx UNUSED,\n-\t\t\t\t    const void *data UNUSED,\n-\t\t\t\t    size_t len UNUSED)\n-{\n-\tBUG(\"trying to update unknown hash\");\n-}\n-\n-static void git_hash_unknown_final(unsigned char *hash UNUSED,\n-\t\t\t\t   struct git_hash_ctx *ctx UNUSED)\n-{\n-\tBUG(\"trying to finalize unknown hash\");\n-}\n-\n-static void git_hash_unknown_final_oid(struct object_id *oid UNUSED,\n-\t\t\t\t       struct git_hash_ctx *ctx UNUSED)\n-{\n-\tBUG(\"trying to finalize unknown hash\");\n-}\n-\n-static const struct git_hash_algo sha1_unsafe_algo = {\n-\t.name = \"sha1\",\n-\t.format_id = GIT_SHA1_FORMAT_ID,\n-\t.rawsz = GIT_SHA1_RAWSZ,\n-\t.hexsz = GIT_SHA1_HEXSZ,\n-\t.blksz = GIT_SHA1_BLKSZ,\n-\t.init_fn = git_hash_sha1_init_unsafe,\n-\t.clone_fn = git_hash_sha1_clone_unsafe,\n-\t.update_fn = git_hash_sha1_update_unsafe,\n-\t.final_fn = git_hash_sha1_final_unsafe,\n-\t.final_oid_fn = git_hash_sha1_final_oid_unsafe,\n-\t.empty_tree = &empty_tree_oid,\n-\t.empty_blob = &empty_blob_oid,\n-\t.null_oid = &null_oid_sha1,\n-};\n-\n-const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n-\t{\n-\t\t.name = NULL,\n-\t\t.format_id = 0x00000000,\n-\t\t.rawsz = 0,\n-\t\t.hexsz = 0,\n-\t\t.blksz = 0,\n-\t\t.init_fn = git_hash_unknown_init,\n-\t\t.clone_fn = git_hash_unknown_clone,\n-\t\t.update_fn = git_hash_unknown_update,\n-\t\t.final_fn = git_hash_unknown_final,\n-\t\t.final_oid_fn = git_hash_unknown_final_oid,\n-\t\t.empty_tree = NULL,\n-\t\t.empty_blob = NULL,\n-\t\t.null_oid = NULL,\n-\t},\n-\t{\n-\t\t.name = \"sha1\",\n-\t\t.format_id = GIT_SHA1_FORMAT_ID,\n-\t\t.rawsz = GIT_SHA1_RAWSZ,\n-\t\t.hexsz = GIT_SHA1_HEXSZ,\n-\t\t.blksz = GIT_SHA1_BLKSZ,\n-\t\t.init_fn = git_hash_sha1_init,\n-\t\t.clone_fn = git_hash_sha1_clone,\n-\t\t.update_fn = git_hash_sha1_update,\n-\t\t.final_fn = git_hash_sha1_final,\n-\t\t.final_oid_fn = git_hash_sha1_final_oid,\n-\t\t.unsafe = &sha1_unsafe_algo,\n-\t\t.empty_tree = &empty_tree_oid,\n-\t\t.empty_blob = &empty_blob_oid,\n-\t\t.null_oid = &null_oid_sha1,\n-\t},\n-\t{\n-\t\t.name = \"sha256\",\n-\t\t.format_id = GIT_SHA256_FORMAT_ID,\n-\t\t.rawsz = GIT_SHA256_RAWSZ,\n-\t\t.hexsz = GIT_SHA256_HEXSZ,\n-\t\t.blksz = GIT_SHA256_BLKSZ,\n-\t\t.init_fn = git_hash_sha256_init,\n-\t\t.clone_fn = git_hash_sha256_clone,\n-\t\t.update_fn = git_hash_sha256_update,\n-\t\t.final_fn = git_hash_sha256_final,\n-\t\t.final_oid_fn = git_hash_sha256_final_oid,\n-\t\t.empty_tree = &empty_tree_oid_sha256,\n-\t\t.empty_blob = &empty_blob_oid_sha256,\n-\t\t.null_oid = &null_oid_sha256,\n-\t}\n-};\n-\n-const struct object_id *null_oid(void)\n-{\n-\treturn the_hash_algo->null_oid;\n-}\n-\n-const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\n-{\n-\tstatic char buf[GIT_MAX_HEXSZ + 1];\n-\treturn oid_to_hex_r(buf, algop->empty_tree);\n-}\n-\n-int hash_algo_by_name(const char *name)\n-{\n-\tint i;\n-\tif (!name)\n-\t\treturn GIT_HASH_UNKNOWN;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n-\t\tif (!strcmp(name, hash_algos[i].name))\n-\t\t\treturn i;\n-\treturn GIT_HASH_UNKNOWN;\n-}\n-\n-int hash_algo_by_id(uint32_t format_id)\n-{\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n-\t\tif (format_id == hash_algos[i].format_id)\n-\t\t\treturn i;\n-\treturn GIT_HASH_UNKNOWN;\n-}\n-\n-int hash_algo_by_length(int len)\n-{\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n-\t\tif (len == hash_algos[i].rawsz)\n-\t\t\treturn i;\n-\treturn GIT_HASH_UNKNOWN;\n-}\n-\n-const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop)\n-{\n-\t/* If we have a faster \"unsafe\" implementation, use that. */\n-\tif (algop->unsafe)\n-\t\treturn algop->unsafe;\n-\t/* Otherwise use the default one. */\n-\treturn algop;\n-}\n-\n /*\n  * This is meant to hold a *small* number of objects that you would\n  * want repo_read_object_file() to be able to return, but yet you do not want\n\n-- \n2.49.0.rc0.375.gae4b89d849.dirty\n\n"},{"id":"513387","messageId":"20250303-b4-pks-objects-without-the-repository-v1-11-c5dd43f2476e@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH 11/12] hash: fix \"-Wsign-compare\" warnings","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-03T08:47:40Z","receivedAt":"2025-03-03T08:47:46Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are a couple of trivial \"-Wsign-compare\" warnings in \"hash.c\". Fix\nthem.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n hash.c | 12 ++++--------\n hash.h |  2 +-\n 2 files changed, 5 insertions(+), 9 deletions(-)\n\ndiff --git a/hash.c b/hash.c\nindex dd5ac9d0eb2..4d9f98f72c2 100644\n--- a/hash.c\n+++ b/hash.c\n@@ -1,5 +1,4 @@\n #define USE_THE_REPOSITORY_VARIABLE\n-#define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n #include \"hash.h\"\n@@ -246,10 +245,9 @@ const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\n \n int hash_algo_by_name(const char *name)\n {\n-\tint i;\n \tif (!name)\n \t\treturn GIT_HASH_UNKNOWN;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\tfor (size_t i = 1; i < GIT_HASH_NALGOS; i++)\n \t\tif (!strcmp(name, hash_algos[i].name))\n \t\t\treturn i;\n \treturn GIT_HASH_UNKNOWN;\n@@ -257,17 +255,15 @@ int hash_algo_by_name(const char *name)\n \n int hash_algo_by_id(uint32_t format_id)\n {\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\tfor (size_t i = 1; i < GIT_HASH_NALGOS; i++)\n \t\tif (format_id == hash_algos[i].format_id)\n \t\t\treturn i;\n \treturn GIT_HASH_UNKNOWN;\n }\n \n-int hash_algo_by_length(int len)\n+int hash_algo_by_length(size_t len)\n {\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\tfor (size_t i = 1; i < GIT_HASH_NALGOS; i++)\n \t\tif (len == hash_algos[i].rawsz)\n \t\t\treturn i;\n \treturn GIT_HASH_UNKNOWN;\ndiff --git a/hash.h b/hash.h\nindex 4367acfec50..55d67ed83f3 100644\n--- a/hash.h\n+++ b/hash.h\n@@ -325,7 +325,7 @@ int hash_algo_by_name(const char *name);\n /* Identical, except based on the format ID. */\n int hash_algo_by_id(uint32_t format_id);\n /* Identical, except based on the length. */\n-int hash_algo_by_length(int len);\n+int hash_algo_by_length(size_t len);\n /* Identical, except for a pointer to struct git_hash_algo. */\n static inline int hash_algo_by_ptr(const struct git_hash_algo *p)\n {\n\n-- \n2.49.0.rc0.375.gae4b89d849.dirty\n\n"},{"id":"513389","messageId":"20250303-b4-pks-objects-without-the-repository-v1-12-c5dd43f2476e@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH 12/12] hash: stop depending on `the_repository` in `null_oid()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-03T08:47:41Z","receivedAt":"2025-03-03T08:47:47Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `null_oid()` function returns the object ID that only consists of\nzeroes. Naturally, this ID also depends on the hash algorithm used, as\nthe number of zeroes is different between SHA1 and SHA256. Consequently,\nthe function returns the hash-algorithm-specific null object ID.\n\nThis is currently done by depending on `the_hash_algo`, which implicitly\nmakes us depend on `the_repository`. Refactor the function to instead\npass in the hash algorithm for which we want to retrieve the null object\nID. Adapt callsites accordingly by passing in `the_repository`, thus\nbubbling up the dependency on that global variable by one layer.\n\nThere are a couple of trivial exceptions for subsystems that already got\nrid of `the_repository`. These subsystems instead use the repository\nthat is available via the calling context:\n\n  - \"builtin/grep.c\"\n  - \"grep.c\"\n  - \"refs/debug.c\"\n\nThere is also a single non-trivial exception with \"diff-no-index.c\".\nHere we know that we may not have a repository initialized at all, so we\ncannot rely on `the_repository`. Instead, we adapt `diff_no_index()` to\nget a `struct git_hash_algo` as parameter. The only caller is located in\n\"builtin/diff.c\", where we know to call `repo_set_hash_algo()` in case\nwe're running outside of a Git repository. Consequently, it is fine to\ncontinue passing `the_repository->hash_algo` even in this case.\n\nThis means that we could in theory just not bother about this edge case\nat all and just use `the_repository` in \"diff-no-index.c\". But doing so\nwould feel misdesigned.\n\nRemove the `USE_THE_REPOSITORY_VARIABLE` preprocessor define in\n\"hash.c\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n archive.c                                    |  2 +-\n blame.c                                      |  2 +-\n branch.c                                     |  2 +-\n builtin/checkout.c                           |  6 ++---\n builtin/clone.c                              |  2 +-\n builtin/describe.c                           |  2 +-\n builtin/diff.c                               |  5 ++--\n builtin/fast-export.c                        | 10 ++++----\n builtin/fsck.c                               |  2 +-\n builtin/grep.c                               |  2 +-\n builtin/ls-files.c                           |  2 +-\n builtin/rebase.c                             |  2 +-\n builtin/receive-pack.c                       |  2 +-\n builtin/submodule--helper.c                  | 36 ++++++++++++++--------------\n builtin/unpack-objects.c                     |  2 +-\n builtin/update-ref.c                         |  2 +-\n builtin/worktree.c                           |  2 +-\n combine-diff.c                               |  2 +-\n diff-lib.c                                   | 10 ++++----\n diff-no-index.c                              | 28 +++++++++++-----------\n diff.c                                       |  8 +++----\n diff.h                                       |  2 +-\n dir.c                                        |  2 +-\n grep.c                                       |  2 +-\n hash.c                                       |  6 ++---\n hash.h                                       |  2 +-\n log-tree.c                                   |  2 +-\n merge-ort.c                                  | 26 ++++++++++----------\n merge-recursive.c                            | 12 +++++-----\n notes-merge.c                                |  2 +-\n notes.c                                      |  2 +-\n object-file.c                                |  2 +-\n parse-options-cb.c                           |  2 +-\n range-diff.c                                 |  2 +-\n read-cache.c                                 |  2 +-\n refs.c                                       | 12 +++++-----\n refs/debug.c                                 |  2 +-\n refs/files-backend.c                         |  2 +-\n reset.c                                      |  2 +-\n sequencer.c                                  | 10 ++++----\n submodule-config.c                           |  2 +-\n submodule.c                                  | 28 +++++++++++-----------\n t/helper/test-ref-store.c                    |  2 +-\n t/helper/test-submodule-nested-repo-config.c |  2 +-\n tree-diff.c                                  |  4 ++--\n upload-pack.c                                |  2 +-\n wt-status.c                                  |  4 ++--\n xdiff-interface.c                            |  2 +-\n 48 files changed, 135 insertions(+), 136 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex f4331aeb49e..c95e3981524 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -312,7 +312,7 @@ int write_archive_entries(struct archiver_args *args,\n \tstruct object_id fake_oid;\n \tint i;\n \n-\toidcpy(&fake_oid, null_oid());\n+\toidcpy(&fake_oid, null_oid(the_hash_algo));\n \n \tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n \t\tsize_t len = args->baselen;\ndiff --git a/blame.c b/blame.c\nindex a15ddf93335..703dab43e78 100644\n--- a/blame.c\n+++ b/blame.c\n@@ -255,7 +255,7 @@ static struct commit *fake_working_tree_commit(struct repository *r,\n \t\tswitch (st.st_mode & S_IFMT) {\n \t\tcase S_IFREG:\n \t\t\tif (opt->flags.allow_textconv &&\n-\t\t\t    textconv_object(r, read_from, mode, null_oid(), 0, &buf_ptr, &buf_len))\n+\t\t\t    textconv_object(r, read_from, mode, null_oid(the_hash_algo), 0, &buf_ptr, &buf_len))\n \t\t\t\tstrbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1);\n \t\t\telse if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)\n \t\t\t\tdie_errno(\"cannot open or read '%s'\", read_from);\ndiff --git a/branch.c b/branch.c\nindex 91297d55ac9..6d01d7d6bdb 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -633,7 +633,7 @@ void create_branch(struct repository *r,\n \t\t\t\t\t\t  0, &err);\n \tif (!transaction ||\n \t\tref_transaction_update(transaction, ref.buf,\n-\t\t\t\t\t&oid, forcing ? NULL : null_oid(),\n+\t\t\t\t\t&oid, forcing ? NULL : null_oid(the_hash_algo),\n \t\t\t\t\tNULL, NULL, flags, msg, &err) ||\n \t\tref_transaction_commit(transaction, &err))\n \t\tdie(\"%s\", err.buf);\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 01ea9ff8b28..2e7486cf658 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -130,8 +130,8 @@ static int post_checkout_hook(struct commit *old_commit, struct commit *new_comm\n \t\t\t      int changed)\n {\n \treturn run_hooks_l(the_repository, \"post-checkout\",\n-\t\t\t   oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()),\n-\t\t\t   oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()),\n+\t\t\t   oid_to_hex(old_commit ? &old_commit->object.oid : null_oid(the_hash_algo)),\n+\t\t\t   oid_to_hex(new_commit ? &new_commit->object.oid : null_oid(the_hash_algo)),\n \t\t\t   changed ? \"1\" : \"0\", NULL);\n \t/* \"new_commit\" can be NULL when checking out from the index before\n \t   a commit exists. */\n@@ -710,7 +710,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,\n \topts.src_index = the_repository->index;\n \topts.dst_index = the_repository->index;\n \tinit_checkout_metadata(&opts.meta, info->refname,\n-\t\t\t       info->commit ? &info->commit->object.oid : null_oid(),\n+\t\t\t       info->commit ? &info->commit->object.oid : null_oid(the_hash_algo),\n \t\t\t       NULL);\n \tif (parse_tree(tree) < 0)\n \t\treturn 128;\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex f14229abf45..36aba65e06c 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -690,7 +690,7 @@ static int checkout(int submodule_progress, int filter_submodules,\n \tif (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))\n \t\tdie(_(\"unable to write new index file\"));\n \n-\terr |= run_hooks_l(the_repository, \"post-checkout\", oid_to_hex(null_oid()),\n+\terr |= run_hooks_l(the_repository, \"post-checkout\", oid_to_hex(null_oid(the_hash_algo)),\n \t\t\t   oid_to_hex(&oid), \"1\", NULL);\n \n \tif (!err && (option_recurse_submodules.nr > 0)) {\ndiff --git a/builtin/describe.c b/builtin/describe.c\nindex e2e73f3d757..23df333fd04 100644\n--- a/builtin/describe.c\n+++ b/builtin/describe.c\n@@ -518,7 +518,7 @@ static void describe_blob(struct object_id oid, struct strbuf *dst)\n {\n \tstruct rev_info revs;\n \tstruct strvec args = STRVEC_INIT;\n-\tstruct process_commit_data pcd = { *null_oid(), oid, dst, &revs};\n+\tstruct process_commit_data pcd = { *null_oid(the_hash_algo), oid, dst, &revs};\n \n \tstrvec_pushl(&args, \"internal: The first arg is not parsed\",\n \t\t     \"--objects\", \"--in-commit-order\", \"--reverse\", \"HEAD\",\ndiff --git a/builtin/diff.c b/builtin/diff.c\nindex a4fffee42c6..fa963808c31 100644\n--- a/builtin/diff.c\n+++ b/builtin/diff.c\n@@ -104,7 +104,7 @@ static void builtin_diff_b_f(struct rev_info *revs,\n \n \tstuff_change(&revs->diffopt,\n \t\t     blob[0]->mode, canon_mode(st.st_mode),\n-\t\t     &blob[0]->item->oid, null_oid(),\n+\t\t     &blob[0]->item->oid, null_oid(the_hash_algo),\n \t\t     1, 0,\n \t\t     blob[0]->path ? blob[0]->path : path,\n \t\t     path);\n@@ -498,7 +498,8 @@ int cmd_diff(int argc,\n \n \t/* If this is a no-index diff, just run it and exit there. */\n \tif (no_index)\n-\t\texit(diff_no_index(&rev, no_index == DIFF_NO_INDEX_IMPLICIT,\n+\t\texit(diff_no_index(&rev, the_repository->hash_algo,\n+\t\t\t\t   no_index == DIFF_NO_INDEX_IMPLICIT,\n \t\t\t\t   argc, argv));\n \n \ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex a5c82eef1de..7a5c2925cd2 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -869,7 +869,7 @@ static void handle_tag(const char *name, struct tag *tag)\n \t\t\t\tp = rewrite_commit((struct commit *)tagged);\n \t\t\t\tif (!p) {\n \t\t\t\t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\t\t       name, oid_to_hex(null_oid()));\n+\t\t\t\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t\t\t\t\tfree(buf);\n \t\t\t\t\treturn;\n \t\t\t\t}\n@@ -883,7 +883,7 @@ static void handle_tag(const char *name, struct tag *tag)\n \n \tif (tagged->type == OBJ_TAG) {\n \t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t       name, oid_to_hex(null_oid()));\n+\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t}\n \tskip_prefix(name, \"refs/tags/\", &name);\n \tprintf(\"tag %s\\n\", name);\n@@ -1023,7 +1023,7 @@ static void handle_tags_and_duplicates(struct string_list *extras)\n \t\t\t\t * it.\n \t\t\t\t */\n \t\t\t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\t       name, oid_to_hex(null_oid()));\n+\t\t\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t\t\t\tcontinue;\n \t\t\t}\n \n@@ -1042,7 +1042,7 @@ static void handle_tags_and_duplicates(struct string_list *extras)\n \t\t\t\tif (!reference_excluded_commits) {\n \t\t\t\t\t/* delete the ref */\n \t\t\t\t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\t\t       name, oid_to_hex(null_oid()));\n+\t\t\t\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t\t\t\t\tcontinue;\n \t\t\t\t}\n \t\t\t\t/* set ref to commit using oid, not mark */\n@@ -1153,7 +1153,7 @@ static void handle_deletes(void)\n \t\t\tcontinue;\n \n \t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\trefspec->dst, oid_to_hex(null_oid()));\n+\t\t\t\trefspec->dst, oid_to_hex(null_oid(the_hash_algo)));\n \t}\n }\n \ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex a441eda7ff9..5da3a2078d0 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -625,7 +625,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)\n \tvoid *contents = NULL;\n \tint eaten;\n \tstruct object_info oi = OBJECT_INFO_INIT;\n-\tstruct object_id real_oid = *null_oid();\n+\tstruct object_id real_oid = *null_oid(the_hash_algo);\n \tint err = 0;\n \n \tstrbuf_reset(&cb_data->obj_type);\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex cbbf6f26439..283d64cab80 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -453,7 +453,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t\treturn 0;\n \n \tsubrepo = xmalloc(sizeof(*subrepo));\n-\tif (repo_submodule_init(subrepo, superproject, path, null_oid())) {\n+\tif (repo_submodule_init(subrepo, superproject, path, null_oid(opt->repo->hash_algo))) {\n \t\tfree(subrepo);\n \t\treturn 0;\n \t}\ndiff --git a/builtin/ls-files.c b/builtin/ls-files.c\nindex a4431429b7d..2d2e90bc23a 100644\n--- a/builtin/ls-files.c\n+++ b/builtin/ls-files.c\n@@ -234,7 +234,7 @@ static void show_submodule(struct repository *superproject,\n {\n \tstruct repository subrepo;\n \n-\tif (repo_submodule_init(&subrepo, superproject, path, null_oid()))\n+\tif (repo_submodule_init(&subrepo, superproject, path, null_oid(the_hash_algo)))\n \t\treturn;\n \n \tif (repo_read_index(&subrepo) < 0)\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex d4715ed35d7..1cd802dd92a 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -925,7 +925,7 @@ static void fill_branch_base(struct rebase_options *options,\n \t\t\t\t options->orig_head, &merge_bases) < 0)\n \t\texit(128);\n \tif (!merge_bases || merge_bases->next)\n-\t\toidcpy(branch_base, null_oid());\n+\t\toidcpy(branch_base, null_oid(the_hash_algo));\n \telse\n \t\toidcpy(branch_base, &merge_bases->item->object.oid);\n \ndiff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\nindex 7b28fc9df6e..b3e2a9d0c60 100644\n--- a/builtin/receive-pack.c\n+++ b/builtin/receive-pack.c\n@@ -363,7 +363,7 @@ static void write_head_info(void)\n \tstrvec_clear(&excludes_vector);\n \n \tif (!sent_capabilities)\n-\t\tshow_ref(\"capabilities^{}\", null_oid());\n+\t\tshow_ref(\"capabilities^{}\", null_oid(the_hash_algo));\n \n \tadvertise_shallow_grafts(1);\n \ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex c1a8029714b..570226ea166 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -78,7 +78,7 @@ static int get_default_remote_submodule(const char *module_path, char **default_\n \tint ret;\n \n \tif (repo_submodule_init(&subrepo, the_repository, module_path,\n-\t\t\t\tnull_oid()) < 0)\n+\t\t\t\tnull_oid(the_hash_algo)) < 0)\n \t\treturn die_message(_(\"could not get a repository handle for submodule '%s'\"),\n \t\t\t\t   module_path);\n \tret = repo_get_default_remote(&subrepo, default_remote);\n@@ -308,7 +308,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,\n \tdisplaypath = get_submodule_displaypath(path, info->prefix,\n \t\t\t\t\t\tinfo->super_prefix);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n@@ -468,7 +468,7 @@ static void init_submodule(const char *path, const char *prefix,\n \n \tdisplaypath = get_submodule_displaypath(path, prefix, super_prefix);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n@@ -645,14 +645,14 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,\n \tif (validate_submodule_path(path) < 0)\n \t\texit(128);\n \n-\tif (!submodule_from_path(the_repository, null_oid(), path))\n+\tif (!submodule_from_path(the_repository, null_oid(the_hash_algo), path))\n \t\tdie(_(\"no submodule mapping found in .gitmodules for path '%s'\"),\n \t\t      path);\n \n \tdisplaypath = get_submodule_displaypath(path, prefix, super_prefix);\n \n \tif ((CE_STAGEMASK & ce_flags) >> CE_STAGESHIFT) {\n-\t\tprint_status(flags, 'U', path, null_oid(), displaypath);\n+\t\tprint_status(flags, 'U', path, null_oid(the_hash_algo), displaypath);\n \t\tgoto cleanup;\n \t}\n \n@@ -912,7 +912,7 @@ static void generate_submodule_summary(struct summary_cb *info,\n \tstruct strbuf errmsg = STRBUF_INIT;\n \tint total_commits = -1;\n \n-\tif (!info->cached && oideq(&p->oid_dst, null_oid())) {\n+\tif (!info->cached && oideq(&p->oid_dst, null_oid(the_hash_algo))) {\n \t\tif (S_ISGITLINK(p->mod_dst)) {\n \t\t\tstruct ref_store *refs = repo_get_submodule_ref_store(the_repository,\n \t\t\t\t\t\t\t\t\t      p->sm_path);\n@@ -1051,7 +1051,7 @@ static void prepare_submodule_summary(struct summary_cb *info,\n \n \t\tif (info->for_status && p->status != 'A' &&\n \t\t    (sub = submodule_from_path(the_repository,\n-\t\t\t\t\t       null_oid(), p->sm_path))) {\n+\t\t\t\t\t       null_oid(the_hash_algo), p->sm_path))) {\n \t\t\tchar *config_key = NULL;\n \t\t\tconst char *value;\n \t\t\tint ignore_all = 0;\n@@ -1259,7 +1259,7 @@ static void sync_submodule(const char *path, const char *prefix,\n \tif (validate_submodule_path(path) < 0)\n \t\texit(128);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (sub && sub->url) {\n \t\tif (starts_with_dot_dot_slash(sub->url) ||\n@@ -1404,7 +1404,7 @@ static void deinit_submodule(const char *path, const char *prefix,\n \tif (validate_submodule_path(path) < 0)\n \t\texit(128);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub || !sub->name)\n \t\tgoto cleanup;\n@@ -1929,7 +1929,7 @@ static int determine_submodule_update_strategy(struct repository *r,\n \t\t\t\t\t       enum submodule_update_type update,\n \t\t\t\t\t       struct submodule_update_strategy *out)\n {\n-\tconst struct submodule *sub = submodule_from_path(r, null_oid(), path);\n+\tconst struct submodule *sub = submodule_from_path(r, null_oid(the_hash_algo), path);\n \tchar *key;\n \tconst char *val;\n \tint ret;\n@@ -2089,7 +2089,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\tgoto cleanup;\n \t}\n \n-\tsub = submodule_from_path(the_repository, null_oid(), ce->name);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), ce->name);\n \n \tif (!sub) {\n \t\tnext_submodule_warn_missing(suc, out, displaypath);\n@@ -2485,7 +2485,7 @@ static int remote_submodule_branch(const char *path, const char **branch)\n \tchar *key;\n \t*branch = NULL;\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \tif (!sub)\n \t\treturn die_message(_(\"could not initialize submodule at path '%s'\"),\n \t\t\t\t   path);\n@@ -2531,7 +2531,7 @@ static int ensure_core_worktree(const char *path)\n \tconst char *cw;\n \tstruct repository subrepo;\n \n-\tif (repo_submodule_init(&subrepo, the_repository, path, null_oid()))\n+\tif (repo_submodule_init(&subrepo, the_repository, path, null_oid(the_hash_algo)))\n \t\treturn die_message(_(\"could not get a repository handle for submodule '%s'\"),\n \t\t\t\t   path);\n \n@@ -2644,7 +2644,7 @@ static int update_submodule(struct update_data *update_data)\n \t\treturn ret;\n \n \tif (update_data->just_cloned)\n-\t\toidcpy(&update_data->suboid, null_oid());\n+\t\toidcpy(&update_data->suboid, null_oid(the_hash_algo));\n \telse if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path,\n \t\t\t\t\t  \"HEAD\", &update_data->suboid))\n \t\treturn die_message(_(\"Unable to find current revision in submodule path '%s'\"),\n@@ -2697,8 +2697,8 @@ static int update_submodule(struct update_data *update_data)\n \t\tstruct update_data next = *update_data;\n \n \t\tnext.prefix = NULL;\n-\t\toidcpy(&next.oid, null_oid());\n-\t\toidcpy(&next.suboid, null_oid());\n+\t\toidcpy(&next.oid, null_oid(the_hash_algo));\n+\t\toidcpy(&next.suboid, null_oid(the_hash_algo));\n \n \t\tcp.dir = update_data->sm_path;\n \t\tcp.git_cmd = 1;\n@@ -3057,7 +3057,7 @@ static int module_set_url(int argc, const char **argv, const char *prefix,\n \tif (argc != 2 || !(path = argv[0]) || !(newurl = argv[1]))\n \t\tusage_with_options(usage, options);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"no submodule mapping found in .gitmodules for path '%s'\"),\n@@ -3113,7 +3113,7 @@ static int module_set_branch(int argc, const char **argv, const char *prefix,\n \tif (argc != 1 || !(path = argv[0]))\n \t\tusage_with_options(usage, options);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"no submodule mapping found in .gitmodules for path '%s'\"),\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex e20c120913e..73d431a0dde 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -505,7 +505,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,\n \t\t\t * has not been resolved yet.\n \t\t\t */\n \t\t\toidclr(&obj_list[nr].oid, the_repository->hash_algo);\n-\t\t\tadd_delta_to_list(nr, null_oid(), base_offset,\n+\t\t\tadd_delta_to_list(nr, null_oid(the_hash_algo), base_offset,\n \t\t\t\t\t  delta_data, delta_size);\n \t\t\treturn;\n \t\t}\ndiff --git a/builtin/update-ref.c b/builtin/update-ref.c\nindex 4d35bdc4b4b..3796b9844d1 100644\n--- a/builtin/update-ref.c\n+++ b/builtin/update-ref.c\n@@ -500,7 +500,7 @@ static void parse_cmd_symref_verify(struct ref_transaction *transaction,\n \t */\n \told_target = parse_next_refname(&next);\n \tif (!old_target)\n-\t\toidcpy(&old_oid, null_oid());\n+\t\toidcpy(&old_oid, null_oid(the_hash_algo));\n \n \tif (*next != line_termination)\n \t\tdie(\"symref-verify %s: extra input: %s\", refname, next);\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 48448a83550..87ccd47794c 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -578,7 +578,7 @@ static int add_worktree(const char *path, const char *refname,\n \n \t\tstrvec_pushl(&opt.env, \"GIT_DIR\", \"GIT_WORK_TREE\", NULL);\n \t\tstrvec_pushl(&opt.args,\n-\t\t\t     oid_to_hex(null_oid()),\n+\t\t\t     oid_to_hex(null_oid(the_hash_algo)),\n \t\t\t     oid_to_hex(&commit->object.oid),\n \t\t\t     \"1\",\n \t\t\t     NULL);\ndiff --git a/combine-diff.c b/combine-diff.c\nindex 9527f3160d8..553bf59fed6 100644\n--- a/combine-diff.c\n+++ b/combine-diff.c\n@@ -1066,7 +1066,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,\n \t\t\t\t\t\t   &result_size, NULL, NULL);\n \t\t} else if (textconv) {\n \t\t\tstruct diff_filespec *df = alloc_filespec(elem->path);\n-\t\t\tfill_filespec(df, null_oid(), 0, st.st_mode);\n+\t\t\tfill_filespec(df, null_oid(the_hash_algo), 0, st.st_mode);\n \t\t\tresult_size = fill_textconv(opt->repo, textconv, df, &result);\n \t\t\tfree_filespec(df);\n \t\t} else if (0 <= (fd = open(elem->path, O_RDONLY))) {\ndiff --git a/diff-lib.c b/diff-lib.c\nindex 353b473ed52..244468dd1a2 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -172,7 +172,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t\t * these from (stage - 2).\n \t\t\t */\n \t\t\tdpath = combine_diff_path_new(ce->name, ce_namelen(ce),\n-\t\t\t\t\t\t      wt_mode, null_oid(), 2);\n+\t\t\t\t\t\t      wt_mode, null_oid(the_hash_algo), 2);\n \n \t\t\twhile (i < entries) {\n \t\t\t\tstruct cache_entry *nce = istate->cache[i];\n@@ -257,7 +257,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t\t\t   ce_intent_to_add(ce)) {\n \t\t\t\tnewmode = ce_mode_from_stat(ce, st.st_mode);\n \t\t\t\tdiff_addremove(&revs->diffopt, '+', newmode,\n-\t\t\t\t\t       null_oid(), 0, ce->name, 0);\n+\t\t\t\t\t       null_oid(the_hash_algo), 0, ce->name, 0);\n \t\t\t\tcontinue;\n \t\t\t}\n \n@@ -274,7 +274,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t}\n \t\toldmode = ce->ce_mode;\n \t\told_oid = &ce->oid;\n-\t\tnew_oid = changed ? null_oid() : &ce->oid;\n+\t\tnew_oid = changed ? null_oid(the_hash_algo) : &ce->oid;\n \t\tdiff_change(&revs->diffopt, oldmode, newmode,\n \t\t\t    old_oid, new_oid,\n \t\t\t    !is_null_oid(old_oid),\n@@ -330,7 +330,7 @@ static int get_stat_data(const struct cache_entry *ce,\n \t\t\t\t\t\t    0, dirty_submodule);\n \t\tif (changed) {\n \t\t\tmode = ce_mode_from_stat(ce, st.st_mode);\n-\t\t\toid = null_oid();\n+\t\t\toid = null_oid(the_hash_algo);\n \t\t}\n \t}\n \n@@ -402,7 +402,7 @@ static int show_modified(struct rev_info *revs,\n \n \t\tp = combine_diff_path_new(new_entry->name,\n \t\t\t\t\t  ce_namelen(new_entry),\n-\t\t\t\t\t  mode, null_oid(), 2);\n+\t\t\t\t\t  mode, null_oid(the_hash_algo), 2);\n \t\tp->parent[0].status = DIFF_STATUS_MODIFIED;\n \t\tp->parent[0].mode = new_entry->ce_mode;\n \t\toidcpy(&p->parent[0].oid, &new_entry->oid);\ndiff --git a/diff-no-index.c b/diff-no-index.c\nindex 6f277892d3a..9739b2b268b 100644\n--- a/diff-no-index.c\n+++ b/diff-no-index.c\n@@ -113,7 +113,8 @@ static void populate_from_stdin(struct diff_filespec *s)\n \tpopulate_common(s, &buf);\n }\n \n-static struct diff_filespec *noindex_filespec(const char *name, int mode,\n+static struct diff_filespec *noindex_filespec(const struct git_hash_algo *algop,\n+\t\t\t\t\t      const char *name, int mode,\n \t\t\t\t\t      enum special special)\n {\n \tstruct diff_filespec *s;\n@@ -121,7 +122,7 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode,\n \tif (!name)\n \t\tname = \"/dev/null\";\n \ts = alloc_filespec(name);\n-\tfill_filespec(s, null_oid(), 0, mode);\n+\tfill_filespec(s, null_oid(algop), 0, mode);\n \tif (special == SPECIAL_STDIN)\n \t\tpopulate_from_stdin(s);\n \telse if (special == SPECIAL_PIPE)\n@@ -129,7 +130,7 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode,\n \treturn s;\n }\n \n-static int queue_diff(struct diff_options *o,\n+static int queue_diff(struct diff_options *o, const struct git_hash_algo *algop,\n \t\t      const char *name1, const char *name2, int recursing)\n {\n \tint mode1 = 0, mode2 = 0;\n@@ -145,14 +146,14 @@ static int queue_diff(struct diff_options *o,\n \n \t\tif (S_ISDIR(mode1)) {\n \t\t\t/* 2 is file that is created */\n-\t\t\td1 = noindex_filespec(NULL, 0, SPECIAL_NONE);\n-\t\t\td2 = noindex_filespec(name2, mode2, special2);\n+\t\t\td1 = noindex_filespec(algop, NULL, 0, SPECIAL_NONE);\n+\t\t\td2 = noindex_filespec(algop, name2, mode2, special2);\n \t\t\tname2 = NULL;\n \t\t\tmode2 = 0;\n \t\t} else {\n \t\t\t/* 1 is file that is deleted */\n-\t\t\td1 = noindex_filespec(name1, mode1, special1);\n-\t\t\td2 = noindex_filespec(NULL, 0, SPECIAL_NONE);\n+\t\t\td1 = noindex_filespec(algop, name1, mode1, special1);\n+\t\t\td2 = noindex_filespec(algop, NULL, 0, SPECIAL_NONE);\n \t\t\tname1 = NULL;\n \t\t\tmode1 = 0;\n \t\t}\n@@ -217,7 +218,7 @@ static int queue_diff(struct diff_options *o,\n \t\t\t\tn2 = buffer2.buf;\n \t\t\t}\n \n-\t\t\tret = queue_diff(o, n1, n2, 1);\n+\t\t\tret = queue_diff(o, algop, n1, n2, 1);\n \t\t}\n \t\tstring_list_clear(&p1, 0);\n \t\tstring_list_clear(&p2, 0);\n@@ -234,8 +235,8 @@ static int queue_diff(struct diff_options *o,\n \t\t\tSWAP(special1, special2);\n \t\t}\n \n-\t\td1 = noindex_filespec(name1, mode1, special1);\n-\t\td2 = noindex_filespec(name2, mode2, special2);\n+\t\td1 = noindex_filespec(algop, name1, mode1, special1);\n+\t\td2 = noindex_filespec(algop, name2, mode2, special2);\n \t\tdiff_queue(&diff_queued_diff, d1, d2);\n \t\treturn 0;\n \t}\n@@ -297,9 +298,8 @@ static const char * const diff_no_index_usage[] = {\n \tNULL\n };\n \n-int diff_no_index(struct rev_info *revs,\n-\t\t  int implicit_no_index,\n-\t\t  int argc, const char **argv)\n+int diff_no_index(struct rev_info *revs, const struct git_hash_algo *algop,\n+\t\t  int implicit_no_index, int argc, const char **argv)\n {\n \tint i, no_index;\n \tint ret = 1;\n@@ -354,7 +354,7 @@ int diff_no_index(struct rev_info *revs,\n \tsetup_diff_pager(&revs->diffopt);\n \trevs->diffopt.flags.exit_with_status = 1;\n \n-\tif (queue_diff(&revs->diffopt, paths[0], paths[1], 0))\n+\tif (queue_diff(&revs->diffopt, algop, paths[0], paths[1], 0))\n \t\tgoto out;\n \tdiff_set_mnemonic_prefix(&revs->diffopt, \"1/\", \"2/\");\n \tdiffcore_std(&revs->diffopt);\ndiff --git a/diff.c b/diff.c\nindex 4f802b4251c..4ce5933a442 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -4346,7 +4346,7 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r,\n \t\t\t\tdie_errno(\"readlink(%s)\", one->path);\n \t\t\tprep_temp_blob(r->index, one->path, temp, sb.buf, sb.len,\n \t\t\t\t       (one->oid_valid ?\n-\t\t\t\t\t&one->oid : null_oid()),\n+\t\t\t\t\t&one->oid : null_oid(the_hash_algo)),\n \t\t\t\t       (one->oid_valid ?\n \t\t\t\t\tone->mode : S_IFLNK));\n \t\t\tstrbuf_release(&sb);\n@@ -4355,7 +4355,7 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r,\n \t\t\t/* we can borrow from the file in the work tree */\n \t\t\ttemp->name = one->path;\n \t\t\tif (!one->oid_valid)\n-\t\t\t\toid_to_hex_r(temp->hex, null_oid());\n+\t\t\t\toid_to_hex_r(temp->hex, null_oid(the_hash_algo));\n \t\t\telse\n \t\t\t\toid_to_hex_r(temp->hex, &one->oid);\n \t\t\t/* Even though we may sometimes borrow the\n@@ -6649,8 +6649,8 @@ static void create_filepairs_for_header_only_notifications(struct diff_options *\n \n \t\t\tone = alloc_filespec(e->key);\n \t\t\ttwo = alloc_filespec(e->key);\n-\t\t\tfill_filespec(one, null_oid(), 0, 0);\n-\t\t\tfill_filespec(two, null_oid(), 0, 0);\n+\t\t\tfill_filespec(one, null_oid(the_hash_algo), 0, 0);\n+\t\t\tfill_filespec(two, null_oid(the_hash_algo), 0, 0);\n \t\t\tp = diff_queue(q, one, two);\n \t\t\tp->status = DIFF_STATUS_MODIFIED;\n \t\t}\ndiff --git a/diff.h b/diff.h\nindex 0a566f5531a..0822111c62a 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -656,7 +656,7 @@ void flush_one_hunk(struct object_id *result, struct git_hash_ctx *ctx);\n \n int diff_result_code(struct rev_info *);\n \n-int diff_no_index(struct rev_info *,\n+int diff_no_index(struct rev_info *, const struct git_hash_algo *algop,\n \t\t  int implicit_no_index, int, const char **);\n \n int index_differs_from(struct repository *r, const char *def,\ndiff --git a/dir.c b/dir.c\nindex cbd82be6c91..28b0e03feb4 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -4035,7 +4035,7 @@ static void connect_wt_gitdir_in_nested(const char *sub_worktree,\n \t\t\t */\n \t\t\ti++;\n \n-\t\tsub = submodule_from_path(&subrepo, null_oid(), ce->name);\n+\t\tsub = submodule_from_path(&subrepo, null_oid(the_hash_algo), ce->name);\n \t\tif (!sub || !is_submodule_active(&subrepo, ce->name))\n \t\t\t/* .gitmodules broken or inactive sub */\n \t\t\tcontinue;\ndiff --git a/grep.c b/grep.c\nindex 4e155ee9e66..9284b5741f5 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -1517,7 +1517,7 @@ static int fill_textconv_grep(struct repository *r,\n \t\tfill_filespec(df, gs->identifier, 1, 0100644);\n \t\tbreak;\n \tcase GREP_SOURCE_FILE:\n-\t\tfill_filespec(df, null_oid(), 0, 0100644);\n+\t\tfill_filespec(df, null_oid(r->hash_algo), 0, 0100644);\n \t\tbreak;\n \tdefault:\n \t\tBUG(\"attempt to textconv something without a path?\");\ndiff --git a/hash.c b/hash.c\nindex 4d9f98f72c2..4a04ecb50e8 100644\n--- a/hash.c\n+++ b/hash.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"hash.h\"\n #include \"hex.h\"\n@@ -232,9 +230,9 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n \t}\n };\n \n-const struct object_id *null_oid(void)\n+const struct object_id *null_oid(const struct git_hash_algo *algop)\n {\n-\treturn the_hash_algo->null_oid;\n+\treturn algop->null_oid;\n }\n \n const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\ndiff --git a/hash.h b/hash.h\nindex 55d67ed83f3..a9ef76fc8e7 100644\n--- a/hash.h\n+++ b/hash.h\n@@ -340,7 +340,7 @@ static inline int hash_algo_by_ptr(const struct git_hash_algo *p)\n \n const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop);\n \n-const struct object_id *null_oid(void);\n+const struct object_id *null_oid(const struct git_hash_algo *algop);\n \n static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)\n {\ndiff --git a/log-tree.c b/log-tree.c\nindex 8b184d67763..5dd1b63076f 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -499,7 +499,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,\n {\n \tstruct strbuf headers = STRBUF_INIT;\n \tconst char *name = oid_to_hex(opt->zero_commit ?\n-\t\t\t\t      null_oid() : &commit->object.oid);\n+\t\t\t\t      null_oid(the_hash_algo) : &commit->object.oid);\n \n \t*need_8bit_cte_p = 0; /* unknown */\n \ndiff --git a/merge-ort.c b/merge-ort.c\nindex 46e78c3ffa6..eb3a834652a 100644\n--- a/merge-ort.c\n+++ b/merge-ort.c\n@@ -1817,7 +1817,7 @@ static int merge_submodule(struct merge_options *opt,\n \t\tBUG(\"submodule deleted on one side; this should be handled outside of merge_submodule()\");\n \n \tif ((sub_not_initialized = repo_submodule_init(&subrepo,\n-\t\topt->repo, path, null_oid()))) {\n+\t\topt->repo, path, null_oid(the_hash_algo)))) {\n \t\tpath_msg(opt, CONFLICT_SUBMODULE_NOT_INITIALIZED, 0,\n \t\t\t path, NULL, NULL, NULL,\n \t\t\t _(\"Failed to merge submodule %s (not checked out)\"),\n@@ -2199,7 +2199,7 @@ static int handle_content_merge(struct merge_options *opt,\n \t\ttwo_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));\n \n \t\tmerge_status = merge_3way(opt, path,\n-\t\t\t\t\t  two_way ? null_oid() : &o->oid,\n+\t\t\t\t\t  two_way ? null_oid(the_hash_algo) : &o->oid,\n \t\t\t\t\t  &a->oid, &b->oid,\n \t\t\t\t\t  pathnames, extra_marker_size,\n \t\t\t\t\t  &result_buf);\n@@ -2231,7 +2231,7 @@ static int handle_content_merge(struct merge_options *opt,\n \t} else if (S_ISGITLINK(a->mode)) {\n \t\tint two_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));\n \t\tclean = merge_submodule(opt, pathnames[0],\n-\t\t\t\t\ttwo_way ? null_oid() : &o->oid,\n+\t\t\t\t\ttwo_way ? null_oid(the_hash_algo) : &o->oid,\n \t\t\t\t\t&a->oid, &b->oid, &result->oid);\n \t\tif (clean < 0)\n \t\t\treturn -1;\n@@ -2739,7 +2739,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt,\n \t\tassert(!new_ci->match_mask);\n \t\tnew_ci->dirmask = 0;\n \t\tnew_ci->stages[1].mode = 0;\n-\t\toidcpy(&new_ci->stages[1].oid, null_oid());\n+\t\toidcpy(&new_ci->stages[1].oid, null_oid(the_hash_algo));\n \n \t\t/*\n \t\t * Now that we have the file information in new_ci, make sure\n@@ -2752,7 +2752,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt,\n \t\t\t\tcontinue;\n \t\t\t/* zero out any entries related to files */\n \t\t\tci->stages[i].mode = 0;\n-\t\t\toidcpy(&ci->stages[i].oid, null_oid());\n+\t\t\toidcpy(&ci->stages[i].oid, null_oid(the_hash_algo));\n \t\t}\n \n \t\t/* Now we want to focus on new_ci, so reassign ci to it. */\n@@ -3122,7 +3122,7 @@ static int process_renames(struct merge_options *opt,\n \t\t\tif (type_changed) {\n \t\t\t\t/* rename vs. typechange */\n \t\t\t\t/* Mark the original as resolved by removal */\n-\t\t\t\tmemcpy(&oldinfo->stages[0].oid, null_oid(),\n+\t\t\t\tmemcpy(&oldinfo->stages[0].oid, null_oid(the_hash_algo),\n \t\t\t\t       sizeof(oldinfo->stages[0].oid));\n \t\t\t\toldinfo->stages[0].mode = 0;\n \t\t\t\toldinfo->filemask &= 0x06;\n@@ -3994,7 +3994,7 @@ static int process_entry(struct merge_options *opt,\n \t\t\tif (ci->filemask & (1 << i))\n \t\t\t\tcontinue;\n \t\t\tci->stages[i].mode = 0;\n-\t\t\toidcpy(&ci->stages[i].oid, null_oid());\n+\t\t\toidcpy(&ci->stages[i].oid, null_oid(the_hash_algo));\n \t\t}\n \t} else if (ci->df_conflict && ci->merged.result.mode != 0) {\n \t\t/*\n@@ -4041,7 +4041,7 @@ static int process_entry(struct merge_options *opt,\n \t\t\t\tcontinue;\n \t\t\t/* zero out any entries related to directories */\n \t\t\tnew_ci->stages[i].mode = 0;\n-\t\t\toidcpy(&new_ci->stages[i].oid, null_oid());\n+\t\t\toidcpy(&new_ci->stages[i].oid, null_oid(the_hash_algo));\n \t\t}\n \n \t\t/*\n@@ -4163,11 +4163,11 @@ static int process_entry(struct merge_options *opt,\n \t\t\tnew_ci->merged.result.mode = ci->stages[2].mode;\n \t\t\toidcpy(&new_ci->merged.result.oid, &ci->stages[2].oid);\n \t\t\tnew_ci->stages[1].mode = 0;\n-\t\t\toidcpy(&new_ci->stages[1].oid, null_oid());\n+\t\t\toidcpy(&new_ci->stages[1].oid, null_oid(the_hash_algo));\n \t\t\tnew_ci->filemask = 5;\n \t\t\tif ((S_IFMT & b_mode) != (S_IFMT & o_mode)) {\n \t\t\t\tnew_ci->stages[0].mode = 0;\n-\t\t\t\toidcpy(&new_ci->stages[0].oid, null_oid());\n+\t\t\t\toidcpy(&new_ci->stages[0].oid, null_oid(the_hash_algo));\n \t\t\t\tnew_ci->filemask = 4;\n \t\t\t}\n \n@@ -4175,11 +4175,11 @@ static int process_entry(struct merge_options *opt,\n \t\t\tci->merged.result.mode = ci->stages[1].mode;\n \t\t\toidcpy(&ci->merged.result.oid, &ci->stages[1].oid);\n \t\t\tci->stages[2].mode = 0;\n-\t\t\toidcpy(&ci->stages[2].oid, null_oid());\n+\t\t\toidcpy(&ci->stages[2].oid, null_oid(the_hash_algo));\n \t\t\tci->filemask = 3;\n \t\t\tif ((S_IFMT & a_mode) != (S_IFMT & o_mode)) {\n \t\t\t\tci->stages[0].mode = 0;\n-\t\t\t\toidcpy(&ci->stages[0].oid, null_oid());\n+\t\t\t\toidcpy(&ci->stages[0].oid, null_oid(the_hash_algo));\n \t\t\t\tci->filemask = 2;\n \t\t\t}\n \n@@ -4304,7 +4304,7 @@ static int process_entry(struct merge_options *opt,\n \t\t/* Deleted on both sides */\n \t\tci->merged.is_null = 1;\n \t\tci->merged.result.mode = 0;\n-\t\toidcpy(&ci->merged.result.oid, null_oid());\n+\t\toidcpy(&ci->merged.result.oid, null_oid(the_hash_algo));\n \t\tassert(!ci->df_conflict);\n \t\tci->merged.clean = !ci->path_conflict;\n \t}\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 5dfaf32b2c1..d88e61b07a9 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -502,7 +502,7 @@ static int get_tree_entry_if_blob(struct repository *r,\n \n \tret = get_tree_entry(r, tree, path, &dfs->oid, &dfs->mode);\n \tif (S_ISDIR(dfs->mode)) {\n-\t\toidcpy(&dfs->oid, null_oid());\n+\t\toidcpy(&dfs->oid, null_oid(the_hash_algo));\n \t\tdfs->mode = 0;\n \t}\n \treturn ret;\n@@ -1238,7 +1238,7 @@ static int merge_submodule(struct merge_options *opt,\n \tif (is_null_oid(b))\n \t\treturn 0;\n \n-\tif (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) {\n+\tif (repo_submodule_init(&subrepo, opt->repo, path, null_oid(the_hash_algo))) {\n \t\toutput(opt, 1, _(\"Failed to merge submodule %s (not checked out)\"), path);\n \t\treturn 0;\n \t}\n@@ -1698,7 +1698,7 @@ static int handle_file_collision(struct merge_options *opt,\n \n \t/* Store things in diff_filespecs for functions that need it */\n \tnull.path = (char *)collide_path;\n-\toidcpy(&null.oid, null_oid());\n+\toidcpy(&null.oid, null_oid(the_hash_algo));\n \tnull.mode = 0;\n \n \tif (merge_mode_and_contents(opt, &null, a, b, collide_path,\n@@ -2898,14 +2898,14 @@ static int process_renames(struct merge_options *opt,\n \t\t\tdst_other.mode = ren1->dst_entry->stages[other_stage].mode;\n \t\t\ttry_merge = 0;\n \n-\t\t\tif (oideq(&src_other.oid, null_oid()) &&\n+\t\t\tif (oideq(&src_other.oid, null_oid(the_hash_algo)) &&\n \t\t\t    ren1->dir_rename_original_type == 'A') {\n \t\t\t\tsetup_rename_conflict_info(RENAME_VIA_DIR,\n \t\t\t\t\t\t\t   opt, ren1, NULL);\n \t\t\t} else if (renamed_to_self) {\n \t\t\t\tsetup_rename_conflict_info(RENAME_NORMAL,\n \t\t\t\t\t\t\t   opt, ren1, NULL);\n-\t\t\t} else if (oideq(&src_other.oid, null_oid())) {\n+\t\t\t} else if (oideq(&src_other.oid, null_oid(the_hash_algo))) {\n \t\t\t\tsetup_rename_conflict_info(RENAME_DELETE,\n \t\t\t\t\t\t\t   opt, ren1, NULL);\n \t\t\t} else if ((dst_other.mode == ren1->pair->two->mode) &&\n@@ -2924,7 +2924,7 @@ static int process_renames(struct merge_options *opt,\n \t\t\t\t\t\t      1, /* update_cache */\n \t\t\t\t\t\t      0  /* update_wd    */))\n \t\t\t\t\tclean_merge = -1;\n-\t\t\t} else if (!oideq(&dst_other.oid, null_oid())) {\n+\t\t\t} else if (!oideq(&dst_other.oid, null_oid(the_hash_algo))) {\n \t\t\t\t/*\n \t\t\t\t * Probably not a clean merge, but it's\n \t\t\t\t * premature to set clean_merge to 0 here,\ndiff --git a/notes-merge.c b/notes-merge.c\nindex 67a472020de..5008faef450 100644\n--- a/notes-merge.c\n+++ b/notes-merge.c\n@@ -617,7 +617,7 @@ int notes_merge(struct notes_merge_options *o,\n \tif (repo_get_merge_bases(the_repository, local, remote, &bases) < 0)\n \t\texit(128);\n \tif (!bases) {\n-\t\tbase_oid = null_oid();\n+\t\tbase_oid = null_oid(the_hash_algo);\n \t\tbase_tree_oid = the_hash_algo->empty_tree;\n \t\tif (o->verbosity >= 4)\n \t\t\tprintf(\"No merge base found; doing history-less merge\\n\");\ndiff --git a/notes.c b/notes.c\nindex f5344230505..ce5a1006a83 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -1353,7 +1353,7 @@ int copy_note(struct notes_tree *t,\n \tif (note)\n \t\treturn add_note(t, to_obj, note, combine_notes);\n \telse if (existing_note)\n-\t\treturn add_note(t, to_obj, null_oid(), combine_notes);\n+\t\treturn add_note(t, to_obj, null_oid(the_hash_algo), combine_notes);\n \n \treturn 0;\n }\ndiff --git a/object-file.c b/object-file.c\nindex de603e2ca8c..772c311f188 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2405,7 +2405,7 @@ static int index_mem(struct index_state *istate,\n \n \t\topts.strict = 1;\n \t\topts.error_func = hash_format_check_report;\n-\t\tif (fsck_buffer(null_oid(), type, buf, size, &opts))\n+\t\tif (fsck_buffer(null_oid(the_hash_algo), type, buf, size, &opts))\n \t\t\tdie(_(\"refusing to create malformed object\"));\n \t\tfsck_finish(&opts);\n \t}\ndiff --git a/parse-options-cb.c b/parse-options-cb.c\nindex 166d35e0ebd..50c8afe4121 100644\n--- a/parse-options-cb.c\n+++ b/parse-options-cb.c\n@@ -145,7 +145,7 @@ int parse_opt_object_id(const struct option *opt, const char *arg, int unset)\n \tstruct object_id *target = opt->value;\n \n \tif (unset) {\n-\t\toidcpy(target, null_oid());\n+\t\toidcpy(target, null_oid(the_hash_algo));\n \t\treturn 0;\n \t}\n \tif (!arg)\ndiff --git a/range-diff.c b/range-diff.c\nindex 9501c358a84..8a2dcbee322 100644\n--- a/range-diff.c\n+++ b/range-diff.c\n@@ -467,7 +467,7 @@ static struct diff_filespec *get_filespec(const char *name, const char *p)\n {\n \tstruct diff_filespec *spec = alloc_filespec(name);\n \n-\tfill_filespec(spec, null_oid(), 0, 0100644);\n+\tfill_filespec(spec, null_oid(the_hash_algo), 0, 0100644);\n \tspec->data = (char *)p;\n \tspec->size = strlen(p);\n \tspec->should_munmap = 0;\ndiff --git a/read-cache.c b/read-cache.c\nindex a012cb22368..2f9e21c897d 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1735,7 +1735,7 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)\n \tend = (unsigned char *)hdr + size;\n \tstart = end - the_hash_algo->rawsz;\n \toidread(&oid, start, the_repository->hash_algo);\n-\tif (oideq(&oid, null_oid()))\n+\tif (oideq(&oid, null_oid(the_hash_algo)))\n \t\treturn 0;\n \n \tthe_hash_algo->init_fn(&c);\ndiff --git a/refs.c b/refs.c\nindex 118465271d7..215294115b4 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1377,7 +1377,7 @@ int ref_transaction_create(struct ref_transaction *transaction,\n \t\treturn 1;\n \t}\n \treturn ref_transaction_update(transaction, refname, new_oid,\n-\t\t\t\t      null_oid(), new_target, NULL, flags,\n+\t\t\t\t      null_oid(the_hash_algo), new_target, NULL, flags,\n \t\t\t\t      msg, err);\n }\n \n@@ -1396,7 +1396,7 @@ int ref_transaction_delete(struct ref_transaction *transaction,\n \tif (old_target && !(flags & REF_NO_DEREF))\n \t\tBUG(\"delete cannot operate on symrefs with deref mode\");\n \treturn ref_transaction_update(transaction, refname,\n-\t\t\t\t      null_oid(), old_oid,\n+\t\t\t\t      null_oid(the_hash_algo), old_oid,\n \t\t\t\t      NULL, old_target, flags,\n \t\t\t\t      msg, err);\n }\n@@ -2160,7 +2160,7 @@ struct ref_store *repo_get_submodule_ref_store(struct repository *repo,\n \tsubrepo = xmalloc(sizeof(*subrepo));\n \n \tif (repo_submodule_init(subrepo, repo, submodule,\n-\t\t\t\tnull_oid())) {\n+\t\t\t\tnull_oid(the_hash_algo))) {\n \t\tfree(subrepo);\n \t\tgoto done;\n \t}\n@@ -2345,14 +2345,14 @@ static int run_transaction_hook(struct ref_transaction *transaction,\n \t\tstrbuf_reset(&buf);\n \n \t\tif (!(update->flags & REF_HAVE_OLD))\n-\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid()));\n+\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid(the_hash_algo)));\n \t\telse if (update->old_target)\n \t\t\tstrbuf_addf(&buf, \"ref:%s \", update->old_target);\n \t\telse\n \t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(&update->old_oid));\n \n \t\tif (!(update->flags & REF_HAVE_NEW))\n-\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid()));\n+\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid(the_hash_algo)));\n \t\telse if (update->new_target)\n \t\t\tstrbuf_addf(&buf, \"ref:%s \", update->new_target);\n \t\telse\n@@ -2794,7 +2794,7 @@ static int migrate_one_ref(const char *refname, const char *referent UNUSED, con\n \t\tif (ret < 0)\n \t\t\tgoto done;\n \n-\t\tret = ref_transaction_update(data->transaction, refname, NULL, null_oid(),\n+\t\tret = ref_transaction_update(data->transaction, refname, NULL, null_oid(the_hash_algo),\n \t\t\t\t\t     symref_target.buf, NULL,\n \t\t\t\t\t     REF_SKIP_CREATE_REFLOG | REF_NO_DEREF, NULL, data->errbuf);\n \t\tif (ret < 0)\ndiff --git a/refs/debug.c b/refs/debug.c\nindex fbc4df08b43..7c61b775e4e 100644\n--- a/refs/debug.c\n+++ b/refs/debug.c\n@@ -217,7 +217,7 @@ static int debug_read_raw_ref(struct ref_store *ref_store, const char *refname,\n \tstruct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;\n \tint res = 0;\n \n-\toidcpy(oid, null_oid());\n+\toidcpy(oid, null_oid(ref_store->repo->hash_algo));\n \tres = drefs->refs->be->read_raw_ref(drefs->refs, refname, oid, referent,\n \t\t\t\t\t    type, failure_errno);\n \ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 6c6e67dc1c4..ba31cfdb93f 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1270,7 +1270,7 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r)\n \tref_transaction_add_update(\n \t\t\ttransaction, r->name,\n \t\t\tREF_NO_DEREF | REF_HAVE_NEW | REF_HAVE_OLD | REF_IS_PRUNING,\n-\t\t\tnull_oid(), &r->oid, NULL, NULL, NULL, NULL);\n+\t\t\tnull_oid(the_hash_algo), &r->oid, NULL, NULL, NULL, NULL);\n \tif (ref_transaction_commit(transaction, &err))\n \t\tgoto cleanup;\n \ndiff --git a/reset.c b/reset.c\nindex b22b1be792d..bb590271811 100644\n--- a/reset.c\n+++ b/reset.c\n@@ -80,7 +80,7 @@ static int update_refs(const struct reset_head_opts *opts,\n \t}\n \tif (!ret && run_hook)\n \t\trun_hooks_l(the_repository, \"post-checkout\",\n-\t\t\t    oid_to_hex(head ? head : null_oid()),\n+\t\t\t    oid_to_hex(head ? head : null_oid(the_hash_algo)),\n \t\t\t    oid_to_hex(oid), \"1\", NULL);\n \tstrbuf_release(&msg);\n \treturn ret;\ndiff --git a/sequencer.c b/sequencer.c\nindex ad0ab75c8d4..c112d2e1c43 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -265,8 +265,8 @@ static struct update_ref_record *init_update_ref_record(const char *ref)\n \n \tCALLOC_ARRAY(rec, 1);\n \n-\toidcpy(&rec->before, null_oid());\n-\toidcpy(&rec->after, null_oid());\n+\toidcpy(&rec->before, null_oid(the_hash_algo));\n+\toidcpy(&rec->after, null_oid(the_hash_algo));\n \n \t/* This may fail, but that's fine, we will keep the null OID. */\n \trefs_read_ref(get_main_ref_store(the_repository), ref, &rec->before);\n@@ -667,7 +667,7 @@ static int fast_forward_to(struct repository *r,\n \tif (!transaction ||\n \t    ref_transaction_update(transaction, \"HEAD\",\n \t\t\t\t   to, unborn && !is_rebase_i(opts) ?\n-\t\t\t\t   null_oid() : from, NULL, NULL,\n+\t\t\t\t   null_oid(the_hash_algo) : from, NULL, NULL,\n \t\t\t\t   0, sb.buf, &err) ||\n \t    ref_transaction_commit(transaction, &err)) {\n \t\tref_transaction_free(transaction);\n@@ -1301,7 +1301,7 @@ int update_head_with_reflog(const struct commit *old_head,\n \t\t\t\t\t\t  0, err);\n \tif (!transaction ||\n \t    ref_transaction_update(transaction, \"HEAD\", new_head,\n-\t\t\t\t   old_head ? &old_head->object.oid : null_oid(),\n+\t\t\t\t   old_head ? &old_head->object.oid : null_oid(the_hash_algo),\n \t\t\t\t   NULL, NULL, 0, sb.buf, err) ||\n \t    ref_transaction_commit(transaction, err)) {\n \t\tret = -1;\n@@ -4683,7 +4683,7 @@ static void create_autostash_internal(struct repository *r,\n \t\t\twrite_file(path, \"%s\", oid_to_hex(&oid));\n \t\t} else {\n \t\t\trefs_update_ref(get_main_ref_store(r), \"\", refname,\n-\t\t\t\t\t&oid, null_oid(), 0, UPDATE_REFS_DIE_ON_ERR);\n+\t\t\t\t\t&oid, null_oid(the_hash_algo), 0, UPDATE_REFS_DIE_ON_ERR);\n \t\t}\n \n \t\tprintf(_(\"Created autostash: %s\\n\"), buf.buf);\ndiff --git a/submodule-config.c b/submodule-config.c\nindex a25059ed7f8..d82b404b73e 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -831,7 +831,7 @@ static int gitmodules_cb(const char *var, const char *value,\n \n \tparameter.cache = repo->submodule_cache;\n \tparameter.treeish_name = NULL;\n-\tparameter.gitmodules_oid = null_oid();\n+\tparameter.gitmodules_oid = null_oid(the_hash_algo);\n \tparameter.overwrite = 1;\n \n \treturn parse_config(var, value, ctx, &parameter);\ndiff --git a/submodule.c b/submodule.c\nindex 0530e8cf24e..0821507ecaa 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -124,7 +124,7 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)\n \tif (is_gitmodules_unmerged(the_repository->index))\n \t\tdie(_(\"Cannot change unmerged .gitmodules, resolve merge conflicts first\"));\n \n-\tsubmodule = submodule_from_path(the_repository, null_oid(), oldpath);\n+\tsubmodule = submodule_from_path(the_repository, null_oid(the_hash_algo), oldpath);\n \tif (!submodule || !submodule->name) {\n \t\twarning(_(\"Could not find section in .gitmodules where path=%s\"), oldpath);\n \t\treturn -1;\n@@ -153,7 +153,7 @@ int remove_path_from_gitmodules(const char *path)\n \tif (is_gitmodules_unmerged(the_repository->index))\n \t\tdie(_(\"Cannot change unmerged .gitmodules, resolve merge conflicts first\"));\n \n-\tsubmodule = submodule_from_path(the_repository, null_oid(), path);\n+\tsubmodule = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \tif (!submodule || !submodule->name) {\n \t\twarning(_(\"Could not find section in .gitmodules where path=%s\"), path);\n \t\treturn -1;\n@@ -204,7 +204,7 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,\n \t\t\t\t\t     const char *path)\n {\n \tconst struct submodule *submodule = submodule_from_path(the_repository,\n-\t\t\t\t\t\t\t\tnull_oid(),\n+\t\t\t\t\t\t\t\tnull_oid(the_hash_algo),\n \t\t\t\t\t\t\t\tpath);\n \tif (submodule) {\n \t\tconst char *ignore;\n@@ -312,7 +312,7 @@ int is_tree_submodule_active(struct repository *repo,\n \n int is_submodule_active(struct repository *repo, const char *path)\n {\n-\treturn is_tree_submodule_active(repo, null_oid(), path);\n+\treturn is_tree_submodule_active(repo, null_oid(the_hash_algo), path);\n }\n \n int is_submodule_populated_gently(const char *path, int *return_error_code)\n@@ -778,7 +778,7 @@ const struct submodule *submodule_from_ce(const struct cache_entry *ce)\n \tif (!should_update_submodules())\n \t\treturn NULL;\n \n-\treturn submodule_from_path(the_repository, null_oid(), ce->name);\n+\treturn submodule_from_path(the_repository, null_oid(the_hash_algo), ce->name);\n }\n \n \n@@ -1062,7 +1062,7 @@ static int submodule_needs_pushing(struct repository *r,\n \t\t\t\t   const char *path,\n \t\t\t\t   struct oid_array *commits)\n {\n-\tif (!submodule_has_commits(r, path, null_oid(), commits))\n+\tif (!submodule_has_commits(r, path, null_oid(the_hash_algo), commits))\n \t\t/*\n \t\t * NOTE: We do consider it safe to return \"no\" here. The\n \t\t * correct answer would be \"We do not know\" instead of\n@@ -1126,7 +1126,7 @@ int find_unpushed_submodules(struct repository *r,\n \t\tconst struct submodule *submodule;\n \t\tconst char *path = NULL;\n \n-\t\tsubmodule = submodule_from_name(r, null_oid(), name->string);\n+\t\tsubmodule = submodule_from_name(r, null_oid(the_hash_algo), name->string);\n \t\tif (submodule)\n \t\t\tpath = submodule->path;\n \t\telse\n@@ -1351,7 +1351,7 @@ static void calculate_changed_submodule_paths(struct repository *r,\n \t\tconst struct submodule *submodule;\n \t\tconst char *path = NULL;\n \n-\t\tsubmodule = submodule_from_name(r, null_oid(), name->string);\n+\t\tsubmodule = submodule_from_name(r, null_oid(the_hash_algo), name->string);\n \t\tif (submodule)\n \t\t\tpath = submodule->path;\n \t\telse\n@@ -1360,7 +1360,7 @@ static void calculate_changed_submodule_paths(struct repository *r,\n \t\tif (!path)\n \t\t\tcontinue;\n \n-\t\tif (submodule_has_commits(r, path, null_oid(), &cs_data->new_commits)) {\n+\t\tif (submodule_has_commits(r, path, null_oid(the_hash_algo), &cs_data->new_commits)) {\n \t\t\tchanged_submodule_data_clear(cs_data);\n \t\t\t*name->string = '\\0';\n \t\t}\n@@ -1602,7 +1602,7 @@ get_fetch_task_from_index(struct submodule_parallel_fetch *spf,\n \t\tif (!S_ISGITLINK(ce->ce_mode))\n \t\t\tcontinue;\n \n-\t\ttask = fetch_task_create(spf, ce->name, null_oid());\n+\t\ttask = fetch_task_create(spf, ce->name, null_oid(the_hash_algo));\n \t\tif (!task)\n \t\t\tcontinue;\n \n@@ -2166,7 +2166,7 @@ int submodule_move_head(const char *path, const char *super_prefix,\n \tif (old_head && !is_submodule_populated_gently(path, error_code_ptr))\n \t\treturn 0;\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tBUG(\"could not get submodule information for '%s'\", path);\n@@ -2376,7 +2376,7 @@ static void relocate_single_git_dir_into_superproject(const char *path,\n \n \treal_old_git_dir = real_pathdup(old_git_dir, 1);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \tif (!sub)\n \t\tdie(_(\"could not lookup name for submodule '%s'\"), path);\n \n@@ -2462,7 +2462,7 @@ void absorb_git_dir_into_superproject(const char *path,\n \t\t* superproject did not rewrite the git file links yet,\n \t\t* fix it now.\n \t\t*/\n-\t\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\t\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \t\tif (!sub)\n \t\t\tdie(_(\"could not lookup name for submodule '%s'\"), path);\n \t\tsubmodule_name_to_gitdir(&sub_gitdir, the_repository, sub->name);\n@@ -2594,7 +2594,7 @@ int submodule_to_gitdir(struct repository *repo,\n \t\tstrbuf_addstr(buf, git_dir);\n \t}\n \tif (!is_git_directory(buf->buf)) {\n-\t\tsub = submodule_from_path(repo, null_oid(), submodule);\n+\t\tsub = submodule_from_path(repo, null_oid(the_hash_algo), submodule);\n \t\tif (!sub) {\n \t\t\tret = -1;\n \t\t\tgoto cleanup;\ndiff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c\nindex e00fce592b1..2ff67c067ac 100644\n--- a/t/helper/test-ref-store.c\n+++ b/t/helper/test-ref-store.c\n@@ -179,7 +179,7 @@ static int cmd_for_each_ref__exclude(struct ref_store *refs, const char **argv)\n \n static int cmd_resolve_ref(struct ref_store *refs, const char **argv)\n {\n-\tstruct object_id oid = *null_oid();\n+\tstruct object_id oid = *null_oid(the_hash_algo);\n \tconst char *refname = notnull(*argv++, \"refname\");\n \tint resolve_flags = arg_flags(*argv++, \"resolve-flags\", empty_flags);\n \tint flags;\ndiff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c\nindex 6dce9571531..2710341cd5d 100644\n--- a/t/helper/test-submodule-nested-repo-config.c\n+++ b/t/helper/test-submodule-nested-repo-config.c\n@@ -21,7 +21,7 @@ int cmd__submodule_nested_repo_config(int argc, const char **argv)\n \n \tsetup_git_directory();\n \n-\tif (repo_submodule_init(&subrepo, the_repository, argv[1], null_oid())) {\n+\tif (repo_submodule_init(&subrepo, the_repository, argv[1], null_oid(the_hash_algo))) {\n \t\tdie_usage(argv, \"Submodule not found.\");\n \t}\n \ndiff --git a/tree-diff.c b/tree-diff.c\nindex 60c558c2b56..e00fc2f450d 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -181,7 +181,7 @@ static void emit_path(struct combine_diff_path ***tail,\n \n \t\tstrbuf_add(base, path, pathlen);\n \t\tp = combine_diff_path_new(base->buf, base->len, mode,\n-\t\t\t\t\t  oid ? oid : null_oid(),\n+\t\t\t\t\t  oid ? oid : null_oid(the_hash_algo),\n \t\t\t\t\t  nparent);\n \t\tstrbuf_setlen(base, old_baselen);\n \n@@ -206,7 +206,7 @@ static void emit_path(struct combine_diff_path ***tail,\n \t\t\t\tmode_i = tp[i].entry.mode;\n \t\t\t}\n \t\t\telse {\n-\t\t\t\toid_i = null_oid();\n+\t\t\t\toid_i = null_oid(the_hash_algo);\n \t\t\t\tmode_i = 0;\n \t\t\t}\n \ndiff --git a/upload-pack.c b/upload-pack.c\nindex 2b37d1e28f1..19b82f3b3d3 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -1446,7 +1446,7 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,\n \t\tfor_each_namespaced_ref_1(send_ref, &data);\n \t\tif (!data.sent_capabilities) {\n \t\t\tconst char *refname = \"capabilities^{}\";\n-\t\t\twrite_v0_ref(&data, refname, refname, null_oid());\n+\t\t\twrite_v0_ref(&data, refname, refname, null_oid(the_hash_algo));\n \t\t}\n \t\t/*\n \t\t * fflush stdout before calling advertise_shallow_grafts because send_ref\ndiff --git a/wt-status.c b/wt-status.c\nindex 1da5732f57b..454601afa15 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1824,10 +1824,10 @@ void wt_status_get_state(struct repository *r,\n \tif (!sequencer_get_last_command(r, &action)) {\n \t\tif (action == REPLAY_PICK && !state->cherry_pick_in_progress) {\n \t\t\tstate->cherry_pick_in_progress = 1;\n-\t\t\toidcpy(&state->cherry_pick_head_oid, null_oid());\n+\t\t\toidcpy(&state->cherry_pick_head_oid, null_oid(the_hash_algo));\n \t\t} else if (action == REPLAY_REVERT && !state->revert_in_progress) {\n \t\t\tstate->revert_in_progress = 1;\n-\t\t\toidcpy(&state->revert_head_oid, null_oid());\n+\t\t\toidcpy(&state->revert_head_oid, null_oid(the_hash_algo));\n \t\t}\n \t}\n \tif (get_detached_from)\ndiff --git a/xdiff-interface.c b/xdiff-interface.c\nindex 3bd61f26e90..77712811ff1 100644\n--- a/xdiff-interface.c\n+++ b/xdiff-interface.c\n@@ -181,7 +181,7 @@ void read_mmblob(mmfile_t *ptr, const struct object_id *oid)\n \tunsigned long size;\n \tenum object_type type;\n \n-\tif (oideq(oid, null_oid())) {\n+\tif (oideq(oid, null_oid(the_hash_algo))) {\n \t\tptr->ptr = xstrdup(\"\");\n \t\tptr->size = 0;\n \t\treturn;\n\n-- \n2.49.0.rc0.375.gae4b89d849.dirty\n\n"},{"id":"513564","messageId":"hqhlqyonijhjovsop3s3bqv2hjkfp2pde6h4r4jzlcrcreygvf@k53cld26eqs3","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-3-c5dd43f2476e@pks.im","subject":"Re: [PATCH 03/12] pack-write: stop depending on `the_repository` and `the_hash_algo`","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2025-03-04T18:46:44Z","receivedAt":"2025-03-04T18:50:06Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 25/03/03 09:47AM, Patrick Steinhardt wrote:\n> There are a couple of functions in \"pack-write.c\" that implicitly depend\n> on `the_repository` or `the_hash_algo`. Remove this dependency by\n> injecting the repository via a parameter and adapt callers accordingly.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n[snip]\n> diff --git a/pack.h b/pack.h\n> index 9f1194ac13d..5d4393eaffe 100644\n> --- a/pack.h\n> +++ b/pack.h\n> @@ -87,7 +87,7 @@ struct progress;\n>  /* Note, the data argument could be NULL if object type is blob */\n>  typedef int (*verify_fn)(const struct object_id *, enum object_type, unsigned long, void*, int*);\n>  \n> -const char *write_idx_file(const struct git_hash_algo *hash_algo,\n> +const char *write_idx_file(struct repository *repo,\n>  \t\t\t   const char *index_name,\n>  \t\t\t   struct pack_idx_entry **objects,\n>  \t\t\t   int nr_objects,\n> @@ -106,13 +106,13 @@ struct ref;\n>  \n>  void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought);\n>  \n> -char *write_rev_file(const struct git_hash_algo *hash_algo,\n> +char *write_rev_file(struct repository *repo,\n>  \t\t     const char *rev_name,\n>  \t\t     struct pack_idx_entry **objects,\n>  \t\t     uint32_t nr_objects,\n>  \t\t     const unsigned char *hash,\n>  \t\t     unsigned flags);\n> -char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n> +char *write_rev_file_order(struct repository *repo,\n\nThese couple of functions were already injecting git_hash_algo, but\nstill depended on the_repostiory. By instead injecting repository\ndirectly, we get both.\n\nMakes sense.\n\n>  \t\t\t   const char *rev_name,\n>  \t\t\t   uint32_t *pack_order,\n>  \t\t\t   uint32_t nr_objects,\n> @@ -134,8 +134,9 @@ int read_pack_header(int fd, struct pack_header *);\n>  \n>  struct packing_data;\n>  \n> -struct hashfile *create_tmp_packfile(char **pack_tmp_name);\n> -void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,\n> +struct hashfile *create_tmp_packfile(struct repository *repo,\n> +\t\t\t\t     char **pack_tmp_name);\n> +void stage_tmp_packfiles(struct repository *repo,\n>  \t\t\t struct strbuf *name_buffer,\n>  \t\t\t const char *pack_tmp_name,\n>  \t\t\t struct pack_idx_entry **written_list,\n> \n> -- \n> 2.49.0.rc0.375.gae4b89d849.dirty\n> \n> \n"},{"id":"513566","messageId":"rjhdutonrott3a3gpmq6t7qc7qtc4covk7gnp7kqvt3nh2676d@l3wkgwyotv2t","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-4-c5dd43f2476e@pks.im","subject":"Re: [PATCH 04/12] environment: move access to \"core.bigFileThreshold\" into repo settings","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2025-03-04T19:32:53Z","receivedAt":"2025-03-04T19:36:15Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 25/03/03 09:47AM, Patrick Steinhardt wrote:\n> The \"core.bigFileThreshold\" setting is stored in a global variable and\n> populated via `git_default_core_config()`. This may cause issues in\n> the case where one is handling multiple different repositories in a\n> single process with different values for that config key, as we may or\n> may not see the correct value in that case. Furthermore, global state\n> blocks our path towards libification.\n> \n> Refactor the code so that we instead store the value in `struct\n> repo_settings`, where the value is computed as-needed and cached.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n[snip]\n> diff --git a/repo-settings.c b/repo-settings.c\n> index 67e9cfd2e63..4129f8fb2b4 100644\n> --- a/repo-settings.c\n> +++ b/repo-settings.c\n> @@ -20,6 +20,13 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest,\n>  \t\t*dest = def;\n>  }\n>  \n> +static void repo_cfg_ulong(struct repository *r, const char *key, unsigned long *dest,\n> +\t\t\t   unsigned long def)\n> +{\n> +\tif (repo_config_get_ulong(r, key, dest))\n> +\t\t*dest = def;\n> +}\n> +\n>  void prepare_repo_settings(struct repository *r)\n>  {\n>  \tint experimental;\n> @@ -151,6 +158,19 @@ void repo_settings_clear(struct repository *r)\n>  \tr->settings = empty;\n>  }\n>  \n> +unsigned long repo_settings_get_big_file_threshold(struct repository *repo)\n> +{\n> +\tif (!repo->settings.big_file_threshold)\n> +\t\trepo_cfg_ulong(repo, \"core.bigfilethreshold\",\n> +\t\t\t       &repo->settings.big_file_threshold, 512 * 1024 * 1024);\n> +\treturn repo->settings.big_file_threshold;\n> +}\n\nOk, if big_file_threshold is not already set, the config is read\nchecking for a value. If there is no explictly configured value, we\nfallback to the default.\n\nThis matches the existing behavior.\n\n> +\n> +void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value)\n> +{\n> +\trepo->settings.big_file_threshold = value;\n> +}\n> +\n>  enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo)\n>  {\n>  \tconst char *value;\n> diff --git a/repo-settings.h b/repo-settings.h\n> index ddc11967e01..2bf24b25973 100644\n> --- a/repo-settings.h\n> +++ b/repo-settings.h\n> @@ -64,6 +64,7 @@ struct repo_settings {\n>  \tsize_t delta_base_cache_limit;\n>  \tsize_t packed_git_window_size;\n>  \tsize_t packed_git_limit;\n> +\tunsigned long big_file_threshold;\n>  \n>  \tchar *hooks_path;\n>  };\n> @@ -88,6 +89,10 @@ int repo_settings_get_warn_ambiguous_refs(struct repository *repo);\n>  /* Read the value for \"core.hooksPath\". */\n>  const char *repo_settings_get_hooks_path(struct repository *repo);\n>  \n> +/* Read and set the value for \"core.bigFileThreshold\". */\n> +unsigned long repo_settings_get_big_file_threshold(struct repository *repo);\n> +void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value);\n> +\n>  /* Read, set or reset the value for \"core.sharedRepository\". */\n>  int repo_settings_get_shared_repository(struct repository *repo);\n>  void repo_settings_set_shared_repository(struct repository *repo, int value);\n> diff --git a/streaming.c b/streaming.c\n> index 38839511afc..018b794d252 100644\n> --- a/streaming.c\n> +++ b/streaming.c\n> @@ -431,7 +431,8 @@ static int istream_source(struct git_istream *st,\n>  \t\tst->open = open_istream_loose;\n>  \t\treturn 0;\n>  \tcase OI_PACKED:\n> -\t\tif (!oi.u.packed.is_delta && big_file_threshold < size) {\n> +\t\tif (!oi.u.packed.is_delta &&\n> +\t\t    repo_settings_get_big_file_threshold(the_repository) < size) {\n>  \t\t\tst->u.in_pack.pack = oi.u.packed.pack;\n>  \t\t\tst->u.in_pack.pos = oi.u.packed.offset;\n>  \t\t\tst->open = open_istream_pack_non_delta;\n> diff --git a/t/t1050-large.sh b/t/t1050-large.sh\n> index c71932b0242..5be273611ad 100755\n> --- a/t/t1050-large.sh\n> +++ b/t/t1050-large.sh\n> @@ -6,7 +6,8 @@ test_description='adding and checking out large blobs'\n>  . ./test-lib.sh\n>  \n>  test_expect_success 'core.bigFileThreshold must be non-negative' '\n> -\ttest_must_fail git -c core.bigFileThreshold=-1 rev-parse >out 2>err &&\n> +\t: >input &&\n> +\ttest_must_fail git -c core.bigFileThreshold=-1 hash-object input >out 2>err &&\n>  \tgrep \"bad numeric config value\" err &&\n>  \ttest_must_be_empty out\n>  '\n\nI assume the test is updated because core.bigFileThreshold is now only\ncomputed as-needed. Is that correct?\n\nIt may be worth mentioning in the commit message.\n\n-Justin\n"},{"id":"513568","messageId":"walfo6kpxvjdenutznkb56yzlqgjetayquszinhjte2krq5dh6@3qkm2zk4gbwe","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-8-c5dd43f2476e@pks.im","subject":"Re: [PATCH 08/12] object-file-convert: stop depending on `the_repository`","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2025-03-04T19:45:31Z","receivedAt":"2025-03-04T19:48:54Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 25/03/03 09:47AM, Patrick Steinhardt wrote:\n> There are multiple sites in \"object-file-convert.c\" where we use the\n> global `the_repository` variable, either explicitly or implicitly by\n> using `the_hash_algo`. All of these callsites are transitively called\n> from `convert_object_file()`, which indeed has no repo as input.\n> \n> Refactor the function so that it receives a repository as parameter and\n\ns/parameter/a &/\n\n> pass it through to all internal functions to get rid of the dependency.\n> Remove the `USE_THE_REPOSITORY_VARIABLE` define.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  builtin/tag.c         |  2 +-\n>  commit.c              |  2 +-\n>  object-file-convert.c | 29 ++++++++++++++++-------------\n>  object-file-convert.h |  3 ++-\n>  object-file.c         |  7 ++++---\n>  5 files changed, 24 insertions(+), 19 deletions(-)\n> \n> diff --git a/builtin/tag.c b/builtin/tag.c\n> index d3e0943b734..7c173535cb3 100644\n> --- a/builtin/tag.c\n> +++ b/builtin/tag.c\n> @@ -172,7 +172,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,\n>  \tif (compat) {\n>  \t\tconst struct git_hash_algo *algo = the_repository->hash_algo;\n>  \n> -\t\tif (convert_object_file(&compat_buf, algo, compat,\n> +\t\tif (convert_object_file(the_repository ,&compat_buf, algo, compat,\n>  \t\t\t\t\tbuffer->buf, buffer->len, OBJ_TAG, 1))\n>  \t\t\tgoto out;\n>  \t\tif (sign_buffer(&compat_buf, &compat_sig, keyid))\n> diff --git a/commit.c b/commit.c\n> index 6efdb03997d..48aeefaad31 100644\n> --- a/commit.c\n> +++ b/commit.c\n> @@ -1380,7 +1380,7 @@ static int convert_commit_extra_headers(const struct commit_extra_header *orig,\n>  \t\tstruct commit_extra_header *new;\n>  \t\tCALLOC_ARRAY(new, 1);\n>  \t\tif (!strcmp(orig->key, \"mergetag\")) {\n> -\t\t\tif (convert_object_file(&out, algo, compat,\n> +\t\t\tif (convert_object_file(the_repository, &out, algo, compat,\n>  \t\t\t\t\t\torig->value, orig->len,\n>  \t\t\t\t\t\tOBJ_TAG, 1)) {\n>  \t\t\t\tfree(new);\n> diff --git a/object-file-convert.c b/object-file-convert.c\n> index eba71955cf7..7ab875afe6c 100644\n> --- a/object-file-convert.c\n> +++ b/object-file-convert.c\n> @@ -1,4 +1,3 @@\n> -#define USE_THE_REPOSITORY_VARIABLE\n\nLooking good :)\n\n>  #define DISABLE_SIGN_COMPARE_WARNINGS\n>  \n>  #include \"git-compat-util.h\"\n> @@ -63,7 +62,8 @@ static int decode_tree_entry_raw(struct object_id *oid, const char **path,\n>  \treturn 0;\n>  }\n>  \n> -static int convert_tree_object(struct strbuf *out,\n> +static int convert_tree_object(struct repository *repo,\n> +\t\t\t       struct strbuf *out,\n>  \t\t\t       const struct git_hash_algo *from,\n>  \t\t\t       const struct git_hash_algo *to,\n>  \t\t\t       const char *buffer, size_t size)\n> @@ -78,7 +78,7 @@ static int convert_tree_object(struct strbuf *out,\n>  \t\tif (decode_tree_entry_raw(&entry_oid, &path, &pathlen, from, p,\n>  \t\t\t\t\t  end - p))\n>  \t\t\treturn error(_(\"failed to decode tree entry\"));\n> -\t\tif (repo_oid_to_algop(the_repository, &entry_oid, to, &mapped_oid))\n> +\t\tif (repo_oid_to_algop(repo, &entry_oid, to, &mapped_oid))\n>  \t\t\treturn error(_(\"failed to map tree entry for %s\"), oid_to_hex(&entry_oid));\n>  \t\tstrbuf_add(out, p, path - p);\n>  \t\tstrbuf_add(out, path, pathlen);\n> @@ -88,7 +88,8 @@ static int convert_tree_object(struct strbuf *out,\n>  \treturn 0;\n>  }\n>  \n> -static int convert_tag_object(struct strbuf *out,\n> +static int convert_tag_object(struct repository *repo,\n> +\t\t\t      struct strbuf *out,\n>  \t\t\t      const struct git_hash_algo *from,\n>  \t\t\t      const struct git_hash_algo *to,\n>  \t\t\t      const char *buffer, size_t size)\n> @@ -105,7 +106,7 @@ static int convert_tag_object(struct strbuf *out,\n>  \t\treturn error(\"bogus tag object\");\n>  \tif (parse_oid_hex_algop(buffer + 7, &oid, &p, from) < 0)\n>  \t\treturn error(\"bad tag object ID\");\n> -\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n> +\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n>  \t\treturn error(\"unable to map tree %s in tag object\",\n>  \t\t\t     oid_to_hex(&oid));\n>  \tsize -= ((p + 1) - buffer);\n> @@ -139,7 +140,8 @@ static int convert_tag_object(struct strbuf *out,\n>  \treturn 0;\n>  }\n>  \n> -static int convert_commit_object(struct strbuf *out,\n> +static int convert_commit_object(struct repository *repo,\n> +\t\t\t\t struct strbuf *out,\n>  \t\t\t\t const struct git_hash_algo *from,\n>  \t\t\t\t const struct git_hash_algo *to,\n>  \t\t\t\t const char *buffer, size_t size)\n> @@ -165,7 +167,7 @@ static int convert_commit_object(struct strbuf *out,\n>  \t\t\t    (p != eol))\n>  \t\t\t\treturn error(_(\"bad %s in commit\"), \"tree\");\n>  \n> -\t\t\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n> +\t\t\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n>  \t\t\t\treturn error(_(\"unable to map %s %s in commit object\"),\n>  \t\t\t\t\t     \"tree\", oid_to_hex(&oid));\n>  \t\t\tstrbuf_addf(out, \"tree %s\\n\", oid_to_hex(&mapped_oid));\n> @@ -177,7 +179,7 @@ static int convert_commit_object(struct strbuf *out,\n>  \t\t\t    (p != eol))\n>  \t\t\t\treturn error(_(\"bad %s in commit\"), \"parent\");\n>  \n> -\t\t\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n> +\t\t\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n>  \t\t\t\treturn error(_(\"unable to map %s %s in commit object\"),\n>  \t\t\t\t\t     \"parent\", oid_to_hex(&oid));\n>  \n> @@ -202,7 +204,7 @@ static int convert_commit_object(struct strbuf *out,\n>  \t\t\t}\n>  \n>  \t\t\t/* Compute the new tag object */\n> -\t\t\tif (convert_tag_object(&new_tag, from, to, tag.buf, tag.len)) {\n> +\t\t\tif (convert_tag_object(repo, &new_tag, from, to, tag.buf, tag.len)) {\n>  \t\t\t\tstrbuf_release(&tag);\n>  \t\t\t\tstrbuf_release(&new_tag);\n>  \t\t\t\treturn -1;\n> @@ -241,7 +243,8 @@ static int convert_commit_object(struct strbuf *out,\n>  \treturn 0;\n>  }\n>  \n> -int convert_object_file(struct strbuf *outbuf,\n> +int convert_object_file(struct repository *repo,\n> +\t\t\tstruct strbuf *outbuf,\n>  \t\t\tconst struct git_hash_algo *from,\n>  \t\t\tconst struct git_hash_algo *to,\n>  \t\t\tconst void *buf, size_t len,\n> @@ -256,13 +259,13 @@ int convert_object_file(struct strbuf *outbuf,\n>  \n>  \tswitch (type) {\n>  \tcase OBJ_COMMIT:\n> -\t\tret = convert_commit_object(outbuf, from, to, buf, len);\n> +\t\tret = convert_commit_object(repo, outbuf, from, to, buf, len);\n>  \t\tbreak;\n>  \tcase OBJ_TREE:\n> -\t\tret = convert_tree_object(outbuf, from, to, buf, len);\n> +\t\tret = convert_tree_object(repo, outbuf, from, to, buf, len);\n>  \t\tbreak;\n>  \tcase OBJ_TAG:\n> -\t\tret = convert_tag_object(outbuf, from, to, buf, len);\n> +\t\tret = convert_tag_object(repo, outbuf, from, to, buf, len);\n>  \t\tbreak;\n>  \tdefault:\n>  \t\t/* Not implemented yet, so fail. */\n> diff --git a/object-file-convert.h b/object-file-convert.h\n> index a4f802aa8ee..9b3cc5e533d 100644\n> --- a/object-file-convert.h\n> +++ b/object-file-convert.h\n> @@ -14,7 +14,8 @@ int repo_oid_to_algop(struct repository *repo, const struct object_id *src,\n>   * Convert an object file from one hash algorithm to another algorithm.\n>   * Return -1 on failure, 0 on success.\n>   */\n> -int convert_object_file(struct strbuf *outbuf,\n> +int convert_object_file(struct repository *repo,\n> +\t\t\tstruct strbuf *outbuf,\n>  \t\t\tconst struct git_hash_algo *from,\n>  \t\t\tconst struct git_hash_algo *to,\n>  \t\t\tconst void *buf, size_t len,\n> diff --git a/object-file.c b/object-file.c\n> index b3e0276b2a4..b0e237a2acc 100644\n> --- a/object-file.c\n> +++ b/object-file.c\n> @@ -1793,7 +1793,7 @@ static int oid_object_info_convert(struct repository *r,\n>  \t\tif (type == -1)\n>  \t\t\treturn -1;\n>  \t\tif (type != OBJ_BLOB) {\n> -\t\t\tret = convert_object_file(&outbuf,\n> +\t\t\tret = convert_object_file(the_repository, &outbuf,\n>  \t\t\t\t\t\t  the_hash_algo, input_algo,\n>  \t\t\t\t\t\t  content, size, type, !do_die);\n>  \t\t\tfree(content);\n> @@ -2510,7 +2510,7 @@ int write_object_file_flags(const void *buf, unsigned long len,\n>  \t\t\thash_object_file(compat, buf, len, type, &compat_oid);\n>  \t\telse {\n>  \t\t\tstruct strbuf converted = STRBUF_INIT;\n> -\t\t\tconvert_object_file(&converted, algo, compat,\n> +\t\t\tconvert_object_file(the_repository, &converted, algo, compat,\n>  \t\t\t\t\t    buf, len, type, 0);\n>  \t\t\thash_object_file(compat, converted.buf, converted.len,\n>  \t\t\t\t\t type, &compat_oid);\n> @@ -2550,7 +2550,8 @@ int write_object_file_literally(const void *buf, unsigned long len,\n>  \t\t\t\t\t &compat_oid);\n>  \t\telse if (compat_type != -1) {\n>  \t\t\tstruct strbuf converted = STRBUF_INIT;\n> -\t\t\tconvert_object_file(&converted, algo, compat,\n> +\t\t\tconvert_object_file(the_repository,\n> +\t\t\t\t\t    &converted, algo, compat,\n>  \t\t\t\t\t    buf, len, compat_type, 0);\n>  \t\t\thash_object_file(compat, converted.buf, converted.len,\n>  \t\t\t\t\t compat_type, &compat_oid);\n> \n> -- \n> 2.49.0.rc0.375.gae4b89d849.dirty\n> \n> \n"},{"id":"513569","messageId":"ubagfibqx7xfcj4okemp3q2w3bfwpqat6piunvs7yl3lqpq6xg@ytzo7ogwir2l","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-9-c5dd43f2476e@pks.im","subject":"Re: [PATCH 09/12] delta-islands: stop depending on `the_repository`","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2025-03-04T19:48:14Z","receivedAt":"2025-03-04T19:51:36Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 25/03/03 09:47AM, Patrick Steinhardt wrote:\n> There are multiple sites in \"delta-islands.c\" where we use the\n> global `the_repository` variable, either explicitly or implicitly by\n> using `the_hash_algo`.\n> \n> Refactor the code to stop using `the_repository`. In most cases this is\n> trivial because we already had a repository availabe in the calling\n\ns/availabe/available/\n\n> context, with the only exception being `propagate_island_marks()`. Adapt\n> it so that the repository gets passed in via a parameter.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n"},{"id":"513570","messageId":"yl7t44tp5zhygppxrusdpiehjydncv3b6bmxhp2hgzk6xjwvbr@cjpzvpwo4vxk","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-12-c5dd43f2476e@pks.im","subject":"Re: [PATCH 12/12] hash: stop depending on `the_repository` in `null_oid()`","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2025-03-04T20:16:48Z","receivedAt":"2025-03-04T20:20:11Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 25/03/03 09:47AM, Patrick Steinhardt wrote:\n> The `null_oid()` function returns the object ID that only consists of\n> zeroes. Naturally, this ID also depends on the hash algorithm used, as\n> the number of zeroes is different between SHA1 and SHA256. Consequently,\n> the function returns the hash-algorithm-specific null object ID.\n> \n> This is currently done by depending on `the_hash_algo`, which implicitly\n> makes us depend on `the_repository`. Refactor the function to instead\n> pass in the hash algorithm for which we want to retrieve the null object\n> ID. Adapt callsites accordingly by passing in `the_repository`, thus\n> bubbling up the dependency on that global variable by one layer.\n> \n> There are a couple of trivial exceptions for subsystems that already got\n> rid of `the_repository`. These subsystems instead use the repository\n> that is available via the calling context:\n> \n>   - \"builtin/grep.c\"\n>   - \"grep.c\"\n>   - \"refs/debug.c\"\n> \n> There is also a single non-trivial exception with \"diff-no-index.c\".\n> Here we know that we may not have a repository initialized at all, so we\n> cannot rely on `the_repository`. Instead, we adapt `diff_no_index()` to\n> get a `struct git_hash_algo` as parameter. The only caller is located in\n> \"builtin/diff.c\", where we know to call `repo_set_hash_algo()` in case\n> we're running outside of a Git repository. Consequently, it is fine to\n> continue passing `the_repository->hash_algo` even in this case.\n> \n> This means that we could in theory just not bother about this edge case\n> at all and just use `the_repository` in \"diff-no-index.c\". But doing so\n> would feel misdesigned.\n> \n> Remove the `USE_THE_REPOSITORY_VARIABLE` preprocessor define in\n> \"hash.c\".\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n[snip]\n> -int diff_no_index(struct rev_info *revs,\n> -\t\t  int implicit_no_index,\n> -\t\t  int argc, const char **argv)\n> +int diff_no_index(struct rev_info *revs, const struct git_hash_algo *algop,\n> +\t\t  int implicit_no_index, int argc, const char **argv)\n\nAs mentioned in the commit message, diff_no_index() may not have a\nrepository initialized, so the git_hash_algo should be explicitly\npassed.\n\nMakes sense.\n\n>  {\n>  \tint i, no_index;\n>  \tint ret = 1;\n> @@ -354,7 +354,7 @@ int diff_no_index(struct rev_info *revs,\n>  \tsetup_diff_pager(&revs->diffopt);\n>  \trevs->diffopt.flags.exit_with_status = 1;\n>  \n> -\tif (queue_diff(&revs->diffopt, paths[0], paths[1], 0))\n> +\tif (queue_diff(&revs->diffopt, algop, paths[0], paths[1], 0))\n>  \t\tgoto out;\n>  \tdiff_set_mnemonic_prefix(&revs->diffopt, \"1/\", \"2/\");\n>  \tdiffcore_std(&revs->diffopt);\n[snip]\n\nThe other changes in this patch largely consist of just updating\nnull_oid() and its call sites to recieve the git_hash_algo explicitly.\n\nLooks good to me.\n\n-Justin\n"},{"id":"513644","messageId":"CAOLa=ZREou-t8m6-HqUXpgB1SygNzP1JXSUV09NzpaoKgEUdwQ@mail.gmail.com","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-1-c5dd43f2476e@pks.im","subject":"Re: [PATCH 01/12] csum-file: stop depending on `the_repository`","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-03-06T10:37:01Z","receivedAt":"2025-03-06T10:37:04Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> There are multiple sites in \"csum-file.c\" where we use the global\n> `the_repository` variable, either explicitly or implicitly by using\n> `the_hash_algo`.\n>\n> Refactor the code to stop using `the_repository` by adapting functions\n> to receive required data as parameters. Adapt callsites accordingly by\n> either using `the_repository->hash_algo`, or by using a context-provided\n> hash algorithm in case the subsystem already got rid of its dependency\n> on `the_repository`.\n>\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  builtin/fast-import.c  |  2 +-\n>  builtin/index-pack.c   |  2 +-\n>  builtin/pack-objects.c |  3 ++-\n>  commit-graph.c         |  9 ++++++---\n>  csum-file.c            | 28 ++++++++++++++++------------\n>  csum-file.h            | 12 ++++++++----\n>  midx-write.c           |  6 ++++--\n>  midx.c                 |  3 ++-\n>  pack-bitmap-write.c    |  2 +-\n>  pack-bitmap.c          |  9 +++++----\n>  pack-check.c           |  2 +-\n>  pack-revindex.c        |  3 ++-\n>  pack-write.c           | 12 ++++++------\n>  read-cache.c           |  2 +-\n>  14 files changed, 56 insertions(+), 39 deletions(-)\n>\n> diff --git a/builtin/fast-import.c b/builtin/fast-import.c\n> index 397a6f46ad8..86e6e754816 100644\n> --- a/builtin/fast-import.c\n> +++ b/builtin/fast-import.c\n> @@ -770,7 +770,7 @@ static void start_packfile(void)\n>  \tp->pack_fd = pack_fd;\n>  \tp->do_not_close = 1;\n>  \tp->repo = the_repository;\n> -\tpack_file = hashfd(pack_fd, p->pack_name);\n> +\tpack_file = hashfd(the_repository->hash_algo, pack_fd, p->pack_name);\n>\n\nI recall that `p->repo` should be an option here, but it makes to use\n`the_repository` directly here and not worry about it, this should apply\nto the other changes below too.\n\n[snip]\n\nThe rest of the changes look good.\n\n> diff --git a/pack-bitmap.c b/pack-bitmap.c\n> index 6406953d322..f0e2c000252 100644\n> --- a/pack-bitmap.c\n> +++ b/pack-bitmap.c\n> @@ -3024,7 +3024,8 @@ int bitmap_is_preferred_refname(struct repository *r, const char *refname)\n>  \treturn 0;\n>  }\n>\n> -static int verify_bitmap_file(const char *name)\n> +static int verify_bitmap_file(const struct git_hash_algo *algop,\n> +\t\t\t      const char *name)\n>  {\n>  \tstruct stat st;\n>  \tunsigned char *data;\n> @@ -3040,7 +3041,7 @@ static int verify_bitmap_file(const char *name)\n>\n>  \tdata = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);\n>  \tclose(fd);\n> -\tif (!hashfile_checksum_valid(data, st.st_size))\n> +\tif (!hashfile_checksum_valid(algop, data, st.st_size))\n>  \t\tres = error(_(\"bitmap file '%s' has invalid checksum\"),\n>  \t\t\t    name);\n>\n\nHere, we're modifying an internal function since it needs to pass the\nalgo to `hashfile_checksum_valid`. Makes sense.\n\n> @@ -3055,14 +3056,14 @@ int verify_bitmap_files(struct repository *r)\n>  \tfor (struct multi_pack_index *m = get_multi_pack_index(r);\n>  \t     m; m = m->next) {\n>  \t\tchar *midx_bitmap_name = midx_bitmap_filename(m);\n> -\t\tres |= verify_bitmap_file(midx_bitmap_name);\n> +\t\tres |= verify_bitmap_file(r->hash_algo, midx_bitmap_name);\n>  \t\tfree(midx_bitmap_name);\n>  \t}\n>\n>  \tfor (struct packed_git *p = get_all_packs(r);\n>  \t     p; p = p->next) {\n>  \t\tchar *pack_bitmap_name = pack_bitmap_filename(p);\n> -\t\tres |= verify_bitmap_file(pack_bitmap_name);\n> +\t\tres |= verify_bitmap_file(r->hash_algo, pack_bitmap_name);\n>  \t\tfree(pack_bitmap_name);\n>  \t}\n\n[snip]\n"},{"id":"513647","messageId":"CAOLa=ZQOoif7zFY30dF+SewKZw1Y8wTOq=npMpUzsJxtr_0mww@mail.gmail.com","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-2-c5dd43f2476e@pks.im","subject":"Re: [PATCH 02/12] object: stop depending on `the_repository`","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-03-06T11:07:20Z","receivedAt":"2025-03-06T11:07:22Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> There are a couple of functions exposed by \"object.c\" that implicitly\n> depend on `the_repository`. Remove this dependency by injecting the\n> repository via a parameter. Adapt callers accordingly by simply using\n> `the_repository`, except in cases where the subsystem is already free of\n> the repository. In that case, we instead pass the repository provided by\n> the caller's context.\n>\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  builtin/fsck.c         |  4 ++--\n>  builtin/grep.c         |  2 +-\n>  builtin/index-pack.c   |  4 ++--\n>  builtin/log.c          |  2 +-\n>  builtin/name-rev.c     |  4 ++--\n>  builtin/pack-objects.c |  2 +-\n>  builtin/prune.c        |  2 +-\n>  midx-write.c           |  4 ++--\n>  object.c               | 21 +++++++++++----------\n>  object.h               | 10 ++++++----\n>  pack-bitmap.c          |  6 +++---\n>  reachable.c            |  6 +++---\n>  revision.c             |  3 ++-\n>  shallow.c              | 10 +++++-----\n>  upload-pack.c          | 12 ++++++------\n>  15 files changed, 48 insertions(+), 44 deletions(-)\n>\n> diff --git a/builtin/fsck.c b/builtin/fsck.c\n> index eea1d43647f..a441eda7ff9 100644\n> --- a/builtin/fsck.c\n> +++ b/builtin/fsck.c\n> @@ -399,12 +399,12 @@ static void check_connectivity(void)\n>  \t}\n>\n>  \t/* Look up all the requirements, warn about missing objects.. */\n> -\tmax = get_max_object_index();\n> +\tmax = repo_get_max_object_index(the_repository);\n\nNit: I understand the rename here, but would be nice to callout the same\nin the commit message.\n\n[snip]\n\n> diff --git a/object.h b/object.h\n> index 17f32f1103e..0a5293e9911 100644\n> --- a/object.h\n> +++ b/object.h\n> @@ -169,12 +169,13 @@ int type_from_string_gently(const char *str, ssize_t, int gentle);\n>  /*\n>   * Return the current number of buckets in the object hashmap.\n>   */\n> -unsigned int get_max_object_index(void);\n> +unsigned int repo_get_max_object_index(const struct repository *repo);\n>\n>  /*\n>   * Return the object from the specified bucket in the object hashmap.\n>   */\n> -struct object *get_indexed_object(unsigned int);\n> +struct object *repo_get_indexed_object(const struct repository *repo,\n> +\t\t\t\t       unsigned int);\n>\n>  /*\n>   * This can be used to see if we have heard of the object before, but\n> @@ -231,7 +232,8 @@ struct object *parse_object_with_flags(struct repository *r,\n>   * \"name\" parameter is not NULL, it is included in the error message\n>   * (otherwise, the hex object ID is given).\n>   */\n> -struct object *parse_object_or_die(const struct object_id *oid, const char *name);\n> +struct object *parse_object_or_die(struct repository *repo, const struct object_id *oid,\n> +\t\t\t\t   const char *name);\n>\n>  /* Given the result of read_sha1_file(), returns the object after\n>   * parsing it.  eaten_p indicates if the object has a borrowed copy\n> @@ -336,7 +338,7 @@ void object_array_remove_duplicates(struct object_array *array);\n>   */\n>  void object_array_clear(struct object_array *array);\n>\n> -void clear_object_flags(unsigned flags);\n> +void clear_object_flags(struct repository *repo, unsigned flags);\n>\n\nCould you explain the reasoning behind only renaming the first two\nfunctions with 'repo_'?\n\n>  /*\n>   * Clear the specified object flags from all in-core commit objects from\n\n[snip]\n"},{"id":"513648","messageId":"CAOLa=ZTMKF2qvKtVibqAw3d0TnyKrKVD87ntu6p0aKGWYzL7LA@mail.gmail.com","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-5-c5dd43f2476e@pks.im","subject":"Re: [PATCH 05/12] pack-check: stop depending on `the_repository`","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-03-06T11:14:24Z","receivedAt":"2025-03-06T11:14:26Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> There are multiple sites in \"pack-check.c\" where we use the global\n> `the_repository` variable, either explicitly or implicitly by using\n> `the_hash_algo`. In all of those cases we already have a repository\n> available in the calling context though.\n>\n> Refactor the code to instead use the caller-provided repository and\n> remove the `USE_THE_REPOSITORY_VARIABLE` define.\n>\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  pack-check.c | 11 +++++------\n>  1 file changed, 5 insertions(+), 6 deletions(-)\n>\n\nThis was a simple and easy win. Nice.\n\n[snip]\n"},{"id":"513649","messageId":"CAOLa=ZR8x_7xPKTVf+9kxsCLFb2BN+GwqLkAOeXZfZyNk9cF+w@mail.gmail.com","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"Re: [PATCH 00/12] Stop depending on `the_repository` in object-related subsystems","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-03-06T11:20:19Z","receivedAt":"2025-03-06T11:20:20Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> Hi,\n>\n> this patch series is another step to remove our dependency on the global\n> `the_repository` variable. The series focusses on subsystems related to\n> objects.\n>\n> The intent here is to work towards libification of the whole subsystem\n> so that we can start splitting out something like an object \"backend\".\n> It is thus part of a set of refactorings aimed at allowing pluggable\n> object databases eventually. I'm not discussing that bigger effort yet,\n> mostly because it's still taking shape. So these patch series contains\n> things that make sense standalone, even if pluggable ODBs never get to\n> be a thing.\n>\n> Note that this patch series stop short of dropping `the_repository` in\n> \"object-file.c\". This is a bigger undertaking, so I'm pushing that into\n> the next patch series.\n>\n> The series is built on top of cb0ae672aea (A bit more post -rc0,\n> 2025-02-27) with ps/path-sans-the-repository at 028f618658e (path:\n> adjust last remaining users of `the_repository`, 2025-02-07) merged into\n> it.\n>\n> Thanks!\n>\n\nHad a look at the series, I only had a small nit or two. Looking great\nalready!\n\nThanks\n\n> Patrick\n>\n> ---\n> Patrick Steinhardt (12):\n>       csum-file: stop depending on `the_repository`\n>       object: stop depending on `the_repository`\n>       pack-write: stop depending on `the_repository` and `the_hash_algo`\n>       environment: move access to \"core.bigFileThreshold\" into repo settings\n>       pack-check: stop depending on `the_repository`\n>       pack-revindex: stop depending on `the_repository`\n>       pack-bitmap-write: stop depending on `the_repository`\n>       object-file-convert: stop depending on `the_repository`\n>       delta-islands: stop depending on `the_repository`\n>       object-file: split out logic regarding hash algorithms\n>       hash: fix \"-Wsign-compare\" warnings\n>       hash: stop depending on `the_repository` in `null_oid()`\n>\n>  Makefile                                     |   1 +\n>  archive.c                                    |   4 +-\n>  blame.c                                      |   2 +-\n>  branch.c                                     |   2 +-\n>  builtin/checkout.c                           |   6 +-\n>  builtin/clone.c                              |   2 +-\n>  builtin/describe.c                           |   2 +-\n>  builtin/diff.c                               |   5 +-\n>  builtin/fast-export.c                        |  10 +-\n>  builtin/fast-import.c                        |   8 +-\n>  builtin/fsck.c                               |   6 +-\n>  builtin/grep.c                               |   4 +-\n>  builtin/index-pack.c                         |  16 +-\n>  builtin/log.c                                |   2 +-\n>  builtin/ls-files.c                           |   2 +-\n>  builtin/name-rev.c                           |   4 +-\n>  builtin/pack-objects.c                       |  17 +-\n>  builtin/prune.c                              |   2 +-\n>  builtin/rebase.c                             |   2 +-\n>  builtin/receive-pack.c                       |   2 +-\n>  builtin/submodule--helper.c                  |  36 ++--\n>  builtin/tag.c                                |   2 +-\n>  builtin/unpack-objects.c                     |   5 +-\n>  builtin/update-ref.c                         |   2 +-\n>  builtin/worktree.c                           |   2 +-\n>  bulk-checkin.c                               |   4 +-\n>  combine-diff.c                               |   2 +-\n>  commit-graph.c                               |   9 +-\n>  commit.c                                     |   2 +-\n>  config.c                                     |   5 -\n>  csum-file.c                                  |  28 +--\n>  csum-file.h                                  |  12 +-\n>  delta-islands.c                              |  14 +-\n>  delta-islands.h                              |   2 +-\n>  diff-lib.c                                   |  10 +-\n>  diff-no-index.c                              |  28 +--\n>  diff.c                                       |  14 +-\n>  diff.h                                       |   2 +-\n>  dir.c                                        |   2 +-\n>  environment.c                                |   1 -\n>  environment.h                                |   1 -\n>  grep.c                                       |   2 +-\n>  hash.c                                       | 277 +++++++++++++++++++++++++\n>  hash.h                                       |   4 +-\n>  log-tree.c                                   |   2 +-\n>  merge-ort.c                                  |  26 +--\n>  merge-recursive.c                            |  12 +-\n>  meson.build                                  |   1 +\n>  midx-write.c                                 |  12 +-\n>  midx.c                                       |   3 +-\n>  notes-merge.c                                |   2 +-\n>  notes.c                                      |   2 +-\n>  object-file-convert.c                        |  29 +--\n>  object-file-convert.h                        |   3 +-\n>  object-file.c                                | 292 +--------------------------\n>  object.c                                     |  21 +-\n>  object.h                                     |  10 +-\n>  pack-bitmap-write.c                          |  36 ++--\n>  pack-bitmap.c                                |  15 +-\n>  pack-bitmap.h                                |   1 +\n>  pack-check.c                                 |  12 +-\n>  pack-revindex.c                              |  35 ++--\n>  pack-write.c                                 |  55 +++--\n>  pack.h                                       |  11 +-\n>  parse-options-cb.c                           |   2 +-\n>  range-diff.c                                 |   2 +-\n>  reachable.c                                  |   6 +-\n>  read-cache.c                                 |   4 +-\n>  refs.c                                       |  12 +-\n>  refs/debug.c                                 |   2 +-\n>  refs/files-backend.c                         |   2 +-\n>  repo-settings.c                              |  20 ++\n>  repo-settings.h                              |   5 +\n>  reset.c                                      |   2 +-\n>  revision.c                                   |   3 +-\n>  sequencer.c                                  |  10 +-\n>  shallow.c                                    |  10 +-\n>  streaming.c                                  |   3 +-\n>  submodule-config.c                           |   2 +-\n>  submodule.c                                  |  28 +--\n>  t/helper/test-ref-store.c                    |   2 +-\n>  t/helper/test-submodule-nested-repo-config.c |   2 +-\n>  t/t1050-large.sh                             |   3 +-\n>  tree-diff.c                                  |   4 +-\n>  upload-pack.c                                |  14 +-\n>  wt-status.c                                  |   4 +-\n>  xdiff-interface.c                            |   2 +-\n>  87 files changed, 676 insertions(+), 613 deletions(-)\n>\n>\n> ---\n> base-commit: e2cb568e11f4ceb427ba4205e6b8a4426d26be12\n> change-id: 20250210-b4-pks-objects-without-the-repository-6ba8398f7cc0\n"},{"id":"513673","messageId":"Z8m3QJPX-A_Bj3TX@pks.im","threadId":"63046","inReplyTo":"rjhdutonrott3a3gpmq6t7qc7qtc4covk7gnp7kqvt3nh2676d@l3wkgwyotv2t","subject":"Re: [PATCH 04/12] environment: move access to \"core.bigFileThreshold\" into repo settings","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T14:54:56Z","receivedAt":"2025-03-06T14:55:03Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, Mar 04, 2025 at 01:32:53PM -0600, Justin Tobler wrote:\n> On 25/03/03 09:47AM, Patrick Steinhardt wrote:\n> > diff --git a/t/t1050-large.sh b/t/t1050-large.sh\n> > index c71932b0242..5be273611ad 100755\n> > --- a/t/t1050-large.sh\n> > +++ b/t/t1050-large.sh\n> > @@ -6,7 +6,8 @@ test_description='adding and checking out large blobs'\n> >  . ./test-lib.sh\n> >  \n> >  test_expect_success 'core.bigFileThreshold must be non-negative' '\n> > -\ttest_must_fail git -c core.bigFileThreshold=-1 rev-parse >out 2>err &&\n> > +\t: >input &&\n> > +\ttest_must_fail git -c core.bigFileThreshold=-1 hash-object input >out 2>err &&\n> >  \tgrep \"bad numeric config value\" err &&\n> >  \ttest_must_be_empty out\n> >  '\n> \n> I assume the test is updated because core.bigFileThreshold is now only\n> computed as-needed. Is that correct?\n\nExactly. git-rev-parse(1) doesn't use the variable at all, so it won't\nhit the code anymore.\n\n> It may be worth mentioning in the commit message.\n\nWill do.\n\nPatrick\n"},{"id":"513674","messageId":"Z8m3R0KvU2crX35c@pks.im","threadId":"63046","inReplyTo":"CAOLa=ZQOoif7zFY30dF+SewKZw1Y8wTOq=npMpUzsJxtr_0mww@mail.gmail.com","subject":"Re: [PATCH 02/12] object: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T14:55:03Z","receivedAt":"2025-03-06T14:55:06Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Mar 06, 2025 at 03:07:20AM -0800, Karthik Nayak wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> > diff --git a/object.h b/object.h\n> > index 17f32f1103e..0a5293e9911 100644\n> > --- a/object.h\n> > +++ b/object.h\n> > @@ -336,7 +338,7 @@ void object_array_remove_duplicates(struct object_array *array);\n> >   */\n> >  void object_array_clear(struct object_array *array);\n> >\n> > -void clear_object_flags(unsigned flags);\n> > +void clear_object_flags(struct repository *repo, unsigned flags);\n> >\n> \n> Could you explain the reasoning behind only renaming the first two\n> functions with 'repo_'?\n\nHm, good callout, and I can't really explain it because it's rather\narbitrary. I'll drop the rename.\n\nPatrick\n"},{"id":"513692","messageId":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH v2 00/12] Stop depending on `the_repository` in object-related subsystems","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T15:10:24Z","receivedAt":"2025-03-06T15:10:32Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis patch series is another step to remove our dependency on the global\n`the_repository` variable. The series focusses on subsystems related to\nobjects.\n\nThe intent here is to work towards libification of the whole subsystem\nso that we can start splitting out something like an object \"backend\".\nIt is thus part of a set of refactorings aimed at allowing pluggable\nobject databases eventually. I'm not discussing that bigger effort yet,\nmostly because it's still taking shape. So these patch series contains\nthings that make sense standalone, even if pluggable ODBs never get to\nbe a thing.\n\nNote that this patch series stop short of dropping `the_repository` in\n\"object-file.c\". This is a bigger undertaking, so I'm pushing that into\nthe next patch series.\n\nThe series is built on top of cb0ae672aea (A bit more post -rc0,\n2025-02-27) with ps/path-sans-the-repository at 028f618658e (path:\nadjust last remaining users of `the_repository`, 2025-02-07) merged into\nit.\n\nChanges in v2:\n  - Point out why t1050 had to be adapted.\n  - Drop the rename of `get_max_object_index()` and\n    `get_indexed_object()`.\n  - Fix a couple of commit message typos.\n  - Link to v1: https://lore.kernel.org/r/20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (12):\n      csum-file: stop depending on `the_repository`\n      object: stop depending on `the_repository`\n      pack-write: stop depending on `the_repository` and `the_hash_algo`\n      environment: move access to \"core.bigFileThreshold\" into repo settings\n      pack-check: stop depending on `the_repository`\n      pack-revindex: stop depending on `the_repository`\n      pack-bitmap-write: stop depending on `the_repository`\n      object-file-convert: stop depending on `the_repository`\n      delta-islands: stop depending on `the_repository`\n      object-file: split out logic regarding hash algorithms\n      hash: fix \"-Wsign-compare\" warnings\n      hash: stop depending on `the_repository` in `null_oid()`\n\n Makefile                                     |   1 +\n archive.c                                    |   4 +-\n blame.c                                      |   2 +-\n branch.c                                     |   2 +-\n builtin/checkout.c                           |   6 +-\n builtin/clone.c                              |   2 +-\n builtin/describe.c                           |   2 +-\n builtin/diff.c                               |   5 +-\n builtin/fast-export.c                        |  10 +-\n builtin/fast-import.c                        |   8 +-\n builtin/fsck.c                               |   6 +-\n builtin/grep.c                               |   4 +-\n builtin/index-pack.c                         |  16 +-\n builtin/log.c                                |   2 +-\n builtin/ls-files.c                           |   2 +-\n builtin/name-rev.c                           |   4 +-\n builtin/pack-objects.c                       |  17 +-\n builtin/prune.c                              |   2 +-\n builtin/rebase.c                             |   2 +-\n builtin/receive-pack.c                       |   2 +-\n builtin/submodule--helper.c                  |  36 ++--\n builtin/tag.c                                |   2 +-\n builtin/unpack-objects.c                     |   5 +-\n builtin/update-ref.c                         |   2 +-\n builtin/worktree.c                           |   2 +-\n bulk-checkin.c                               |   4 +-\n combine-diff.c                               |   2 +-\n commit-graph.c                               |   9 +-\n commit.c                                     |   2 +-\n config.c                                     |   5 -\n csum-file.c                                  |  28 +--\n csum-file.h                                  |  12 +-\n delta-islands.c                              |  14 +-\n delta-islands.h                              |   2 +-\n diff-lib.c                                   |  10 +-\n diff-no-index.c                              |  28 +--\n diff.c                                       |  14 +-\n diff.h                                       |   2 +-\n dir.c                                        |   2 +-\n environment.c                                |   1 -\n environment.h                                |   1 -\n grep.c                                       |   2 +-\n hash.c                                       | 277 +++++++++++++++++++++++++\n hash.h                                       |   4 +-\n log-tree.c                                   |   2 +-\n merge-ort.c                                  |  26 +--\n merge-recursive.c                            |  12 +-\n meson.build                                  |   1 +\n midx-write.c                                 |  12 +-\n midx.c                                       |   3 +-\n notes-merge.c                                |   2 +-\n notes.c                                      |   2 +-\n object-file-convert.c                        |  29 +--\n object-file-convert.h                        |   3 +-\n object-file.c                                | 292 +--------------------------\n object.c                                     |  21 +-\n object.h                                     |  10 +-\n pack-bitmap-write.c                          |  36 ++--\n pack-bitmap.c                                |  15 +-\n pack-bitmap.h                                |   1 +\n pack-check.c                                 |  12 +-\n pack-revindex.c                              |  35 ++--\n pack-write.c                                 |  55 +++--\n pack.h                                       |  11 +-\n parse-options-cb.c                           |   2 +-\n range-diff.c                                 |   2 +-\n reachable.c                                  |   6 +-\n read-cache.c                                 |   4 +-\n refs.c                                       |  12 +-\n refs/debug.c                                 |   2 +-\n refs/files-backend.c                         |   2 +-\n repo-settings.c                              |  20 ++\n repo-settings.h                              |   5 +\n reset.c                                      |   2 +-\n revision.c                                   |   3 +-\n sequencer.c                                  |  10 +-\n shallow.c                                    |  10 +-\n streaming.c                                  |   3 +-\n submodule-config.c                           |   2 +-\n submodule.c                                  |  28 +--\n t/helper/test-ref-store.c                    |   2 +-\n t/helper/test-submodule-nested-repo-config.c |   2 +-\n t/t1050-large.sh                             |   3 +-\n tree-diff.c                                  |   4 +-\n upload-pack.c                                |  14 +-\n wt-status.c                                  |   4 +-\n xdiff-interface.c                            |   2 +-\n 87 files changed, 676 insertions(+), 613 deletions(-)\n\nRange-diff versus v1:\n\n 1:  48ad4678dd2 =  1:  3fefb9537f1 csum-file: stop depending on `the_repository`\n 2:  91843ef439a !  2:  11cf55dfa1d object: stop depending on `the_repository`\n    @@ builtin/fsck.c: static void check_connectivity(void)\n      \n      \t/* Look up all the requirements, warn about missing objects.. */\n     -\tmax = get_max_object_index();\n    -+\tmax = repo_get_max_object_index(the_repository);\n    ++\tmax = get_max_object_index(the_repository);\n      \tif (verbose)\n      \t\tfprintf_ln(stderr, _(\"Checking connectivity (%d objects)\"), max);\n      \n      \tfor (i = 0; i < max; i++) {\n     -\t\tstruct object *obj = get_indexed_object(i);\n    -+\t\tstruct object *obj = repo_get_indexed_object(the_repository, i);\n    ++\t\tstruct object *obj = get_indexed_object(the_repository, i);\n      \n      \t\tif (obj)\n      \t\t\tcheck_object(obj);\n    @@ builtin/index-pack.c: static unsigned check_objects(void)\n      \tunsigned i, max, foreign_nr = 0;\n      \n     -\tmax = get_max_object_index();\n    -+\tmax = repo_get_max_object_index(the_repository);\n    ++\tmax = get_max_object_index(the_repository);\n      \n      \tif (verbose)\n      \t\tprogress = start_delayed_progress(the_repository,\n    @@ builtin/index-pack.c: static unsigned check_objects(void)\n      \n      \tfor (i = 0; i < max; i++) {\n     -\t\tforeign_nr += check_object(get_indexed_object(i));\n    -+\t\tforeign_nr += check_object(repo_get_indexed_object(the_repository, i));\n    ++\t\tforeign_nr += check_object(get_indexed_object(the_repository, i));\n      \t\tdisplay_progress(progress, i + 1);\n      \t}\n      \n    @@ builtin/name-rev.c: int cmd_name_rev(int argc,\n      \t\tint i, max;\n      \n     -\t\tmax = get_max_object_index();\n    -+\t\tmax = repo_get_max_object_index(the_repository);\n    ++\t\tmax = get_max_object_index(the_repository);\n      \t\tfor (i = 0; i < max; i++) {\n     -\t\t\tstruct object *obj = get_indexed_object(i);\n    -+\t\t\tstruct object *obj = repo_get_indexed_object(the_repository, i);\n    ++\t\t\tstruct object *obj = get_indexed_object(the_repository, i);\n      \t\t\tif (!obj || obj->type != OBJ_COMMIT)\n      \t\t\t\tcontinue;\n      \t\t\tshow_name(obj, NULL,\n    @@ object.c\n      #include \"loose.h\"\n      \n     -unsigned int get_max_object_index(void)\n    -+unsigned int repo_get_max_object_index(const struct repository *repo)\n    ++unsigned int get_max_object_index(const struct repository *repo)\n      {\n     -\treturn the_repository->parsed_objects->obj_hash_size;\n     +\treturn repo->parsed_objects->obj_hash_size;\n      }\n      \n     -struct object *get_indexed_object(unsigned int idx)\n    -+struct object *repo_get_indexed_object(const struct repository *repo,\n    ++struct object *get_indexed_object(const struct repository *repo,\n     +\t\t\t\t       unsigned int idx)\n      {\n     -\treturn the_repository->parsed_objects->obj_hash[idx];\n    @@ object.h: int type_from_string_gently(const char *str, ssize_t, int gentle);\n       * Return the current number of buckets in the object hashmap.\n       */\n     -unsigned int get_max_object_index(void);\n    -+unsigned int repo_get_max_object_index(const struct repository *repo);\n    ++unsigned int get_max_object_index(const struct repository *repo);\n      \n      /*\n       * Return the object from the specified bucket in the object hashmap.\n       */\n     -struct object *get_indexed_object(unsigned int);\n    -+struct object *repo_get_indexed_object(const struct repository *repo,\n    ++struct object *get_indexed_object(const struct repository *repo,\n     +\t\t\t\t       unsigned int);\n      \n      /*\n    @@ shallow.c: static void paint_down(struct paint_info *info, const struct object_i\n      \t}\n      \n     -\tnr = get_max_object_index();\n    -+\tnr = repo_get_max_object_index(the_repository);\n    ++\tnr = get_max_object_index(the_repository);\n      \tfor (i = 0; i < nr; i++) {\n     -\t\tstruct object *o = get_indexed_object(i);\n    -+\t\tstruct object *o = repo_get_indexed_object(the_repository, i);\n    ++\t\tstruct object *o = get_indexed_object(the_repository, i);\n      \t\tif (o && o->type == OBJ_COMMIT)\n      \t\t\to->flags &= ~SEEN;\n      \t}\n    @@ shallow.c: void assign_shallow_commits_to_refs(struct shallow_info *info,\n      \t * (new) shallow commits.\n      \t */\n     -\tnr = get_max_object_index();\n    -+\tnr = repo_get_max_object_index(the_repository);\n    ++\tnr = get_max_object_index(the_repository);\n      \tfor (i = 0; i < nr; i++) {\n     -\t\tstruct object *o = get_indexed_object(i);\n    -+\t\tstruct object *o = repo_get_indexed_object(the_repository, i);\n    ++\t\tstruct object *o = get_indexed_object(the_repository, i);\n      \t\tif (!o || o->type != OBJ_COMMIT)\n      \t\t\tcontinue;\n      \n    @@ upload-pack.c: static int do_reachable_revlist(struct child_process *cmd,\n      \n     -\tfor (i = get_max_object_index(); 0 < i; ) {\n     -\t\to = get_indexed_object(--i);\n    -+\tfor (i = repo_get_max_object_index(the_repository); 0 < i; ) {\n    -+\t\to = repo_get_indexed_object(the_repository, --i);\n    ++\tfor (i = get_max_object_index(the_repository); 0 < i; ) {\n    ++\t\to = get_indexed_object(the_repository, --i);\n      \t\tif (!o)\n      \t\t\tcontinue;\n      \t\tif (reachable && o->type == OBJ_COMMIT)\n    @@ upload-pack.c: static int get_reachable_list(struct upload_pack_data *data,\n      \t}\n     -\tfor (i = get_max_object_index(); 0 < i; i--) {\n     -\t\to = get_indexed_object(i - 1);\n    -+\tfor (i = repo_get_max_object_index(the_repository); 0 < i; i--) {\n    -+\t\to = repo_get_indexed_object(the_repository, i - 1);\n    ++\tfor (i = get_max_object_index(the_repository); 0 < i; i--) {\n    ++\t\to = get_indexed_object(the_repository, i - 1);\n      \t\tif (o && o->type == OBJ_COMMIT &&\n      \t\t    (o->flags & TMP_MARK)) {\n      \t\t\tadd_object_array(o, NULL, reachable);\n 3:  d88c3aa6fc5 =  3:  5f2dcc39b7d pack-write: stop depending on `the_repository` and `the_hash_algo`\n 4:  be7bd50c73c !  4:  21677355fed environment: move access to \"core.bigFileThreshold\" into repo settings\n    @@ Commit message\n         Refactor the code so that we instead store the value in `struct\n         repo_settings`, where the value is computed as-needed and cached.\n     \n    +    Note that this change requires us to adapt one test in t1050 that\n    +    verifies that we die when parsing an invalid \"core.bigFileThreshold\"\n    +    value. The exercised Git command doesn't use the value at all, and thus\n    +    it won't hit the new code path that parses the value. This is addressed\n    +    by using git-hash-object(1) instead, which does read the value.\n    +\n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n      ## archive.c ##\n 5:  349fd4a74f4 =  5:  def4ca73269 pack-check: stop depending on `the_repository`\n 6:  dcc76a793a3 =  6:  cb8c7246af0 pack-revindex: stop depending on `the_repository`\n 7:  5964138dad8 =  7:  d97ea8590af pack-bitmap-write: stop depending on `the_repository`\n 8:  a35396c8981 !  8:  244d21ba448 object-file-convert: stop depending on `the_repository`\n    @@ Commit message\n         using `the_hash_algo`. All of these callsites are transitively called\n         from `convert_object_file()`, which indeed has no repo as input.\n     \n    -    Refactor the function so that it receives a repository as parameter and\n    -    pass it through to all internal functions to get rid of the dependency.\n    -    Remove the `USE_THE_REPOSITORY_VARIABLE` define.\n    +    Refactor the function so that it receives a repository as a parameter\n    +    and pass it through to all internal functions to get rid of the\n    +    dependency. Remove the `USE_THE_REPOSITORY_VARIABLE` define.\n     \n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n 9:  fdb9aebb23d !  9:  7f44a1ee7d6 delta-islands: stop depending on `the_repository`\n    @@ Commit message\n         using `the_hash_algo`.\n     \n         Refactor the code to stop using `the_repository`. In most cases this is\n    -    trivial because we already had a repository availabe in the calling\n    +    trivial because we already had a repository available in the calling\n         context, with the only exception being `propagate_island_marks()`. Adapt\n         it so that the repository gets passed in via a parameter.\n     \n10:  0db58f487f9 = 10:  df2a72c7a16 object-file: split out logic regarding hash algorithms\n11:  0ce33b057d3 = 11:  b5cdfff5719 hash: fix \"-Wsign-compare\" warnings\n12:  e5644afa940 = 12:  36d09bc2707 hash: stop depending on `the_repository` in `null_oid()`\n\n---\nbase-commit: e2cb568e11f4ceb427ba4205e6b8a4426d26be12\nchange-id: 20250210-b4-pks-objects-without-the-repository-6ba8398f7cc0\n\n"},{"id":"513693","messageId":"20250306-b4-pks-objects-without-the-repository-v2-1-f3465327be69@pks.im","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","subject":"[PATCH v2 01/12] csum-file: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T15:10:25Z","receivedAt":"2025-03-06T15:10:33Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"csum-file.c\" where we use the global\n`the_repository` variable, either explicitly or implicitly by using\n`the_hash_algo`.\n\nRefactor the code to stop using `the_repository` by adapting functions\nto receive required data as parameters. Adapt callsites accordingly by\neither using `the_repository->hash_algo`, or by using a context-provided\nhash algorithm in case the subsystem already got rid of its dependency\non `the_repository`.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fast-import.c  |  2 +-\n builtin/index-pack.c   |  2 +-\n builtin/pack-objects.c |  3 ++-\n commit-graph.c         |  9 ++++++---\n csum-file.c            | 28 ++++++++++++++++------------\n csum-file.h            | 12 ++++++++----\n midx-write.c           |  6 ++++--\n midx.c                 |  3 ++-\n pack-bitmap-write.c    |  2 +-\n pack-bitmap.c          |  9 +++++----\n pack-check.c           |  2 +-\n pack-revindex.c        |  3 ++-\n pack-write.c           | 12 ++++++------\n read-cache.c           |  2 +-\n 14 files changed, 56 insertions(+), 39 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 397a6f46ad8..86e6e754816 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -770,7 +770,7 @@ static void start_packfile(void)\n \tp->pack_fd = pack_fd;\n \tp->do_not_close = 1;\n \tp->repo = the_repository;\n-\tpack_file = hashfd(pack_fd, p->pack_name);\n+\tpack_file = hashfd(the_repository->hash_algo, pack_fd, p->pack_name);\n \n \tpack_data = p;\n \tpack_size = write_pack_header(pack_file, 0);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 52cc97d52cb..3eb5af20950 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -1381,7 +1381,7 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha\n \t\tREALLOC_ARRAY(objects, nr_objects + nr_unresolved + 1);\n \t\tmemset(objects + nr_objects + 1, 0,\n \t\t       nr_unresolved * sizeof(*objects));\n-\t\tf = hashfd(output_fd, curr_pack);\n+\t\tf = hashfd(the_repository->hash_algo, output_fd, curr_pack);\n \t\tfix_unresolved_deltas(f);\n \t\tstrbuf_addf(&msg, Q_(\"completed with %d local object\",\n \t\t\t\t     \"completed with %d local objects\",\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 58a9b161262..8e282f2a980 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -1311,7 +1311,8 @@ static void write_pack_file(void)\n \t\tchar *pack_tmp_name = NULL;\n \n \t\tif (pack_to_stdout)\n-\t\t\tf = hashfd_throughput(1, \"<stdout>\", progress_state);\n+\t\t\tf = hashfd_throughput(the_repository->hash_algo, 1,\n+\t\t\t\t\t      \"<stdout>\", progress_state);\n \t\telse\n \t\t\tf = create_tmp_packfile(&pack_tmp_name);\n \ndiff --git a/commit-graph.c b/commit-graph.c\nindex 1021ccb983d..8286d5dda24 100644\n--- a/commit-graph.c\n+++ b/commit-graph.c\n@@ -2090,11 +2090,13 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)\n \t\t\treturn -1;\n \t\t}\n \n-\t\tf = hashfd(get_tempfile_fd(graph_layer), get_tempfile_path(graph_layer));\n+\t\tf = hashfd(the_repository->hash_algo,\n+\t\t\t   get_tempfile_fd(graph_layer), get_tempfile_path(graph_layer));\n \t} else {\n \t\thold_lock_file_for_update_mode(&lk, ctx->graph_name,\n \t\t\t\t\t       LOCK_DIE_ON_ERROR, 0444);\n-\t\tf = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk));\n+\t\tf = hashfd(the_repository->hash_algo,\n+\t\t\t   get_lock_file_fd(&lk), get_lock_file_path(&lk));\n \t}\n \n \tcf = init_chunkfile(f);\n@@ -2716,7 +2718,8 @@ static void graph_report(const char *fmt, ...)\n \n static int commit_graph_checksum_valid(struct commit_graph *g)\n {\n-\treturn hashfile_checksum_valid(g->data, g->data_len);\n+\treturn hashfile_checksum_valid(the_repository->hash_algo,\n+\t\t\t\t       g->data, g->data_len);\n }\n \n static int verify_one_commit_graph(struct repository *r,\ndiff --git a/csum-file.c b/csum-file.c\nindex b58c183a4f0..6e21e3cac8a 100644\n--- a/csum-file.c\n+++ b/csum-file.c\n@@ -8,8 +8,6 @@\n  * able to verify hasn't been messed with afterwards.\n  */\n \n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"csum-file.h\"\n #include \"git-zlib.h\"\n@@ -148,21 +146,23 @@ void hashwrite(struct hashfile *f, const void *buf, unsigned int count)\n \t}\n }\n \n-struct hashfile *hashfd_check(const char *name)\n+struct hashfile *hashfd_check(const struct git_hash_algo *algop,\n+\t\t\t      const char *name)\n {\n \tint sink, check;\n \tstruct hashfile *f;\n \n \tsink = xopen(\"/dev/null\", O_WRONLY);\n \tcheck = xopen(name, O_RDONLY);\n-\tf = hashfd(sink, name);\n+\tf = hashfd(algop, sink, name);\n \tf->check_fd = check;\n \tf->check_buffer = xmalloc(f->buffer_len);\n \n \treturn f;\n }\n \n-static struct hashfile *hashfd_internal(int fd, const char *name,\n+static struct hashfile *hashfd_internal(const struct git_hash_algo *algop,\n+\t\t\t\t\tint fd, const char *name,\n \t\t\t\t\tstruct progress *tp,\n \t\t\t\t\tsize_t buffer_len)\n {\n@@ -176,7 +176,7 @@ static struct hashfile *hashfd_internal(int fd, const char *name,\n \tf->do_crc = 0;\n \tf->skip_hash = 0;\n \n-\tf->algop = unsafe_hash_algo(the_hash_algo);\n+\tf->algop = unsafe_hash_algo(algop);\n \tf->algop->init_fn(&f->ctx);\n \n \tf->buffer_len = buffer_len;\n@@ -186,17 +186,19 @@ static struct hashfile *hashfd_internal(int fd, const char *name,\n \treturn f;\n }\n \n-struct hashfile *hashfd(int fd, const char *name)\n+struct hashfile *hashfd(const struct git_hash_algo *algop,\n+\t\t\tint fd, const char *name)\n {\n \t/*\n \t * Since we are not going to use a progress meter to\n \t * measure the rate of data passing through this hashfile,\n \t * use a larger buffer size to reduce fsync() calls.\n \t */\n-\treturn hashfd_internal(fd, name, NULL, 128 * 1024);\n+\treturn hashfd_internal(algop, fd, name, NULL, 128 * 1024);\n }\n \n-struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp)\n+struct hashfile *hashfd_throughput(const struct git_hash_algo *algop,\n+\t\t\t\t   int fd, const char *name, struct progress *tp)\n {\n \t/*\n \t * Since we are expecting to report progress of the\n@@ -204,7 +206,7 @@ struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp\n \t * size so the progress indicators arrive at a more\n \t * frequent rate.\n \t */\n-\treturn hashfd_internal(fd, name, tp, 8 * 1024);\n+\treturn hashfd_internal(algop, fd, name, tp, 8 * 1024);\n }\n \n void hashfile_checkpoint_init(struct hashfile *f,\n@@ -246,13 +248,15 @@ uint32_t crc32_end(struct hashfile *f)\n \treturn f->crc32;\n }\n \n-int hashfile_checksum_valid(const unsigned char *data, size_t total_len)\n+int hashfile_checksum_valid(const struct git_hash_algo *algop,\n+\t\t\t    const unsigned char *data, size_t total_len)\n {\n \tunsigned char got[GIT_MAX_RAWSZ];\n \tstruct git_hash_ctx ctx;\n-\tconst struct git_hash_algo *algop = unsafe_hash_algo(the_hash_algo);\n \tsize_t data_len = total_len - algop->rawsz;\n \n+\talgop = unsafe_hash_algo(algop);\n+\n \tif (total_len < algop->rawsz)\n \t\treturn 0; /* say \"too short\"? */\n \ndiff --git a/csum-file.h b/csum-file.h\nindex ffccbf09966..07ae11024af 100644\n--- a/csum-file.h\n+++ b/csum-file.h\n@@ -45,9 +45,12 @@ int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *);\n #define CSUM_FSYNC\t\t2\n #define CSUM_HASH_IN_STREAM\t4\n \n-struct hashfile *hashfd(int fd, const char *name);\n-struct hashfile *hashfd_check(const char *name);\n-struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp);\n+struct hashfile *hashfd(const struct git_hash_algo *algop,\n+\t\t\tint fd, const char *name);\n+struct hashfile *hashfd_check(const struct git_hash_algo *algop,\n+\t\t\t      const char *name);\n+struct hashfile *hashfd_throughput(const struct git_hash_algo *algop,\n+\t\t\t\t   int fd, const char *name, struct progress *tp);\n \n /*\n  * Free the hashfile without flushing its contents to disk. This only\n@@ -66,7 +69,8 @@ void crc32_begin(struct hashfile *);\n uint32_t crc32_end(struct hashfile *);\n \n /* Verify checksum validity while reading. Returns non-zero on success. */\n-int hashfile_checksum_valid(const unsigned char *data, size_t len);\n+int hashfile_checksum_valid(const struct git_hash_algo *algop,\n+\t\t\t    const unsigned char *data, size_t len);\n \n /*\n  * Returns the total number of bytes fed to the hashfile so far (including ones\ndiff --git a/midx-write.c b/midx-write.c\nindex 48d6558253e..26d9d8bb148 100644\n--- a/midx-write.c\n+++ b/midx-write.c\n@@ -1342,10 +1342,12 @@ static int write_midx_internal(struct repository *r, const char *object_dir,\n \t\t\treturn -1;\n \t\t}\n \n-\t\tf = hashfd(get_tempfile_fd(incr), get_tempfile_path(incr));\n+\t\tf = hashfd(r->hash_algo, get_tempfile_fd(incr),\n+\t\t\t   get_tempfile_path(incr));\n \t} else {\n \t\thold_lock_file_for_update(&lk, midx_name.buf, LOCK_DIE_ON_ERROR);\n-\t\tf = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk));\n+\t\tf = hashfd(r->hash_algo, get_lock_file_fd(&lk),\n+\t\t\t   get_lock_file_path(&lk));\n \t}\n \n \tcf = init_chunkfile(f);\ndiff --git a/midx.c b/midx.c\nindex d91088efb87..807fdf72f7b 100644\n--- a/midx.c\n+++ b/midx.c\n@@ -747,7 +747,8 @@ int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, i\n \n int midx_checksum_valid(struct multi_pack_index *m)\n {\n-\treturn hashfile_checksum_valid(m->data, m->data_len);\n+\treturn hashfile_checksum_valid(m->repo->hash_algo,\n+\t\t\t\t       m->data, m->data_len);\n }\n \n struct clear_midx_data {\ndiff --git a/pack-bitmap-write.c b/pack-bitmap-write.c\nindex 34e86d49947..50e5c491ccb 100644\n--- a/pack-bitmap-write.c\n+++ b/pack-bitmap-write.c\n@@ -1030,7 +1030,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,\n \tif (writer->pseudo_merges_nr)\n \t\toptions |= BITMAP_OPT_PSEUDO_MERGES;\n \n-\tf = hashfd(fd, tmp_file.buf);\n+\tf = hashfd(the_repository->hash_algo, fd, tmp_file.buf);\n \n \tmemcpy(header.magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE));\n \theader.version = htons(default_version);\ndiff --git a/pack-bitmap.c b/pack-bitmap.c\nindex 6406953d322..f0e2c000252 100644\n--- a/pack-bitmap.c\n+++ b/pack-bitmap.c\n@@ -3024,7 +3024,8 @@ int bitmap_is_preferred_refname(struct repository *r, const char *refname)\n \treturn 0;\n }\n \n-static int verify_bitmap_file(const char *name)\n+static int verify_bitmap_file(const struct git_hash_algo *algop,\n+\t\t\t      const char *name)\n {\n \tstruct stat st;\n \tunsigned char *data;\n@@ -3040,7 +3041,7 @@ static int verify_bitmap_file(const char *name)\n \n \tdata = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);\n \tclose(fd);\n-\tif (!hashfile_checksum_valid(data, st.st_size))\n+\tif (!hashfile_checksum_valid(algop, data, st.st_size))\n \t\tres = error(_(\"bitmap file '%s' has invalid checksum\"),\n \t\t\t    name);\n \n@@ -3055,14 +3056,14 @@ int verify_bitmap_files(struct repository *r)\n \tfor (struct multi_pack_index *m = get_multi_pack_index(r);\n \t     m; m = m->next) {\n \t\tchar *midx_bitmap_name = midx_bitmap_filename(m);\n-\t\tres |= verify_bitmap_file(midx_bitmap_name);\n+\t\tres |= verify_bitmap_file(r->hash_algo, midx_bitmap_name);\n \t\tfree(midx_bitmap_name);\n \t}\n \n \tfor (struct packed_git *p = get_all_packs(r);\n \t     p; p = p->next) {\n \t\tchar *pack_bitmap_name = pack_bitmap_filename(p);\n-\t\tres |= verify_bitmap_file(pack_bitmap_name);\n+\t\tres |= verify_bitmap_file(r->hash_algo, pack_bitmap_name);\n \t\tfree(pack_bitmap_name);\n \t}\n \ndiff --git a/pack-check.c b/pack-check.c\nindex d0aeb5ec412..6bcadc1e679 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -180,7 +180,7 @@ int verify_pack_index(struct packed_git *p)\n \t\treturn error(\"packfile %s index not opened\", p->pack_name);\n \n \t/* Verify SHA1 sum of the index file */\n-\tif (!hashfile_checksum_valid(p->index_data, p->index_size))\n+\tif (!hashfile_checksum_valid(the_repository->hash_algo, p->index_data, p->index_size))\n \t\terr = error(\"Packfile index for %s hash mismatch\",\n \t\t\t    p->pack_name);\n \treturn err;\ndiff --git a/pack-revindex.c b/pack-revindex.c\nindex d3832478d99..78139e3d7f5 100644\n--- a/pack-revindex.c\n+++ b/pack-revindex.c\n@@ -322,7 +322,8 @@ int verify_pack_revindex(struct packed_git *p)\n \tif (!p->revindex_map || !p->revindex_data)\n \t\treturn res;\n \n-\tif (!hashfile_checksum_valid((const unsigned char *)p->revindex_map, p->revindex_size)) {\n+\tif (!hashfile_checksum_valid(the_repository->hash_algo,\n+\t\t\t\t     (const unsigned char *)p->revindex_map, p->revindex_size)) {\n \t\terror(_(\"invalid checksum\"));\n \t\tres = -1;\n \t}\ndiff --git a/pack-write.c b/pack-write.c\nindex 823e40b42f2..5eb89f44cf4 100644\n--- a/pack-write.c\n+++ b/pack-write.c\n@@ -82,7 +82,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \n \tif (opts->flags & WRITE_IDX_VERIFY) {\n \t\tassert(index_name);\n-\t\tf = hashfd_check(index_name);\n+\t\tf = hashfd_check(the_repository->hash_algo, index_name);\n \t} else {\n \t\tif (!index_name) {\n \t\t\tstruct strbuf tmp_file = STRBUF_INIT;\n@@ -92,7 +92,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\t\tunlink(index_name);\n \t\t\tfd = xopen(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t}\n-\t\tf = hashfd(fd, index_name);\n+\t\tf = hashfd(the_repository->hash_algo, fd, index_name);\n \t}\n \n \t/* if last object's offset is >= 2^31 we should use index V2 */\n@@ -268,7 +268,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\tfd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t\tpath = xstrdup(rev_name);\n \t\t}\n-\t\tf = hashfd(fd, path);\n+\t\tf = hashfd(the_repository->hash_algo, fd, path);\n \t} else if (flags & WRITE_REV_VERIFY) {\n \t\tstruct stat statbuf;\n \t\tif (stat(rev_name, &statbuf)) {\n@@ -278,7 +278,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\t} else\n \t\t\t\tdie_errno(_(\"could not stat: %s\"), rev_name);\n \t\t}\n-\t\tf = hashfd_check(rev_name);\n+\t\tf = hashfd_check(the_repository->hash_algo, rev_name);\n \t\tpath = xstrdup(rev_name);\n \t} else {\n \t\treturn NULL;\n@@ -346,7 +346,7 @@ static char *write_mtimes_file(const struct git_hash_algo *hash_algo,\n \n \tfd = odb_mkstemp(&tmp_file, \"pack/tmp_mtimes_XXXXXX\");\n \tmtimes_name = strbuf_detach(&tmp_file, NULL);\n-\tf = hashfd(fd, mtimes_name);\n+\tf = hashfd(the_repository->hash_algo, fd, mtimes_name);\n \n \twrite_mtimes_header(hash_algo, f);\n \twrite_mtimes_objects(f, to_pack, objects, nr_objects);\n@@ -534,7 +534,7 @@ struct hashfile *create_tmp_packfile(char **pack_tmp_name)\n \n \tfd = odb_mkstemp(&tmpname, \"pack/tmp_pack_XXXXXX\");\n \t*pack_tmp_name = strbuf_detach(&tmpname, NULL);\n-\treturn hashfd(fd, *pack_tmp_name);\n+\treturn hashfd(the_repository->hash_algo, fd, *pack_tmp_name);\n }\n \n static void rename_tmp_packfile(struct strbuf *name_prefix, const char *source,\ndiff --git a/read-cache.c b/read-cache.c\nindex e678c13e8f1..a012cb22368 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -2848,7 +2848,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,\n \tstruct strbuf sb = STRBUF_INIT;\n \tint nr, nr_threads, ret;\n \n-\tf = hashfd(tempfile->fd, tempfile->filename.buf);\n+\tf = hashfd(the_repository->hash_algo, tempfile->fd, tempfile->filename.buf);\n \n \tprepare_repo_settings(r);\n \tf->skip_hash = r->settings.index_skip_hash;\n\n-- \n2.49.0.rc0.416.g627208d89d.dirty\n\n"},{"id":"513694","messageId":"20250306-b4-pks-objects-without-the-repository-v2-2-f3465327be69@pks.im","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","subject":"[PATCH v2 02/12] object: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T15:10:26Z","receivedAt":"2025-03-06T15:10:34Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are a couple of functions exposed by \"object.c\" that implicitly\ndepend on `the_repository`. Remove this dependency by injecting the\nrepository via a parameter. Adapt callers accordingly by simply using\n`the_repository`, except in cases where the subsystem is already free of\nthe repository. In that case, we instead pass the repository provided by\nthe caller's context.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fsck.c         |  4 ++--\n builtin/grep.c         |  2 +-\n builtin/index-pack.c   |  4 ++--\n builtin/log.c          |  2 +-\n builtin/name-rev.c     |  4 ++--\n builtin/pack-objects.c |  2 +-\n builtin/prune.c        |  2 +-\n midx-write.c           |  4 ++--\n object.c               | 21 +++++++++++----------\n object.h               | 10 ++++++----\n pack-bitmap.c          |  6 +++---\n reachable.c            |  6 +++---\n revision.c             |  3 ++-\n shallow.c              | 10 +++++-----\n upload-pack.c          | 12 ++++++------\n 15 files changed, 48 insertions(+), 44 deletions(-)\n\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex eea1d43647f..62c7494bbda 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -399,12 +399,12 @@ static void check_connectivity(void)\n \t}\n \n \t/* Look up all the requirements, warn about missing objects.. */\n-\tmax = get_max_object_index();\n+\tmax = get_max_object_index(the_repository);\n \tif (verbose)\n \t\tfprintf_ln(stderr, _(\"Checking connectivity (%d objects)\"), max);\n \n \tfor (i = 0; i < max; i++) {\n-\t\tstruct object *obj = get_indexed_object(i);\n+\t\tstruct object *obj = get_indexed_object(the_repository, i);\n \n \t\tif (obj)\n \t\t\tcheck_object(obj);\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex d1427290f77..cbbf6f26439 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -1144,7 +1144,7 @@ int cmd_grep(int argc,\n \t\t\tbreak;\n \t\t}\n \n-\t\tobject = parse_object_or_die(&oid, arg);\n+\t\tobject = parse_object_or_die(the_repository, &oid, arg);\n \t\tif (!seen_dashdash)\n \t\t\tverify_non_filename(prefix, arg);\n \t\tadd_object_array_with_path(object, arg, &list, oc.mode, oc.path);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 3eb5af20950..1268032d769 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -279,14 +279,14 @@ static unsigned check_objects(void)\n {\n \tunsigned i, max, foreign_nr = 0;\n \n-\tmax = get_max_object_index();\n+\tmax = get_max_object_index(the_repository);\n \n \tif (verbose)\n \t\tprogress = start_delayed_progress(the_repository,\n \t\t\t\t\t\t  _(\"Checking objects\"), max);\n \n \tfor (i = 0; i < max; i++) {\n-\t\tforeign_nr += check_object(get_indexed_object(i));\n+\t\tforeign_nr += check_object(get_indexed_object(the_repository, i));\n \t\tdisplay_progress(progress, i + 1);\n \t}\n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 04a6ef97bc1..0d4c579dad7 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -2468,7 +2468,7 @@ int cmd_format_patch(int argc,\n \tbase = get_base_commit(&cfg, list, nr);\n \tif (base) {\n \t\treset_revision_walk();\n-\t\tclear_object_flags(UNINTERESTING);\n+\t\tclear_object_flags(the_repository, UNINTERESTING);\n \t\tprepare_bases(&bases, base, list, nr);\n \t}\n \ndiff --git a/builtin/name-rev.c b/builtin/name-rev.c\nindex beac166b5cb..2fe82c839ba 100644\n--- a/builtin/name-rev.c\n+++ b/builtin/name-rev.c\n@@ -667,9 +667,9 @@ int cmd_name_rev(int argc,\n \t} else if (all) {\n \t\tint i, max;\n \n-\t\tmax = get_max_object_index();\n+\t\tmax = get_max_object_index(the_repository);\n \t\tfor (i = 0; i < max; i++) {\n-\t\t\tstruct object *obj = get_indexed_object(i);\n+\t\t\tstruct object *obj = get_indexed_object(the_repository, i);\n \t\t\tif (!obj || obj->type != OBJ_COMMIT)\n \t\t\t\tcontinue;\n \t\t\tshow_name(obj, NULL,\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 8e282f2a980..c3adbc94504 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -4161,7 +4161,7 @@ static int mark_bitmap_preferred_tip(const char *refname,\n \tif (!peel_iterated_oid(the_repository, oid, &peeled))\n \t\toid = &peeled;\n \n-\tobject = parse_object_or_die(oid, refname);\n+\tobject = parse_object_or_die(the_repository, oid, refname);\n \tif (object->type == OBJ_COMMIT)\n \t\tobject->flags |= NEEDS_BITMAP;\n \ndiff --git a/builtin/prune.c b/builtin/prune.c\nindex 1c357fffd8c..8f52da8bd66 100644\n--- a/builtin/prune.c\n+++ b/builtin/prune.c\n@@ -185,7 +185,7 @@ int cmd_prune(int argc,\n \t\tconst char *name = *argv++;\n \n \t\tif (!repo_get_oid(the_repository, name, &oid)) {\n-\t\t\tstruct object *object = parse_object_or_die(&oid,\n+\t\t\tstruct object *object = parse_object_or_die(the_repository, &oid,\n \t\t\t\t\t\t\t\t    name);\n \t\t\tadd_pending_object(&revs, object, \"\");\n \t\t}\ndiff --git a/midx-write.c b/midx-write.c\nindex 26d9d8bb148..ac80a8298ed 100644\n--- a/midx-write.c\n+++ b/midx-write.c\n@@ -708,7 +708,7 @@ static int add_ref_to_pending(const char *refname, const char *referent UNUSED,\n \tif (!peel_iterated_oid(revs->repo, oid, &peeled))\n \t\toid = &peeled;\n \n-\tobject = parse_object_or_die(oid, refname);\n+\tobject = parse_object_or_die(revs->repo, oid, refname);\n \tif (object->type != OBJ_COMMIT)\n \t\treturn 0;\n \n@@ -768,7 +768,7 @@ static int read_refs_snapshot(const char *refs_snapshot,\n \t\tif (*end)\n \t\t\tdie(_(\"malformed line: %s\"), buf.buf);\n \n-\t\tobject = parse_object_or_die(&oid, NULL);\n+\t\tobject = parse_object_or_die(revs->repo, &oid, NULL);\n \t\tif (preferred)\n \t\t\tobject->flags |= NEEDS_BITMAP;\n \ndiff --git a/object.c b/object.c\nindex 100bf9b8d12..154525a4972 100644\n--- a/object.c\n+++ b/object.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -18,14 +17,15 @@\n #include \"commit-graph.h\"\n #include \"loose.h\"\n \n-unsigned int get_max_object_index(void)\n+unsigned int get_max_object_index(const struct repository *repo)\n {\n-\treturn the_repository->parsed_objects->obj_hash_size;\n+\treturn repo->parsed_objects->obj_hash_size;\n }\n \n-struct object *get_indexed_object(unsigned int idx)\n+struct object *get_indexed_object(const struct repository *repo,\n+\t\t\t\t       unsigned int idx)\n {\n-\treturn the_repository->parsed_objects->obj_hash[idx];\n+\treturn repo->parsed_objects->obj_hash[idx];\n }\n \n static const char *object_type_strings[] = {\n@@ -283,10 +283,11 @@ struct object *parse_object_buffer(struct repository *r, const struct object_id\n \treturn obj;\n }\n \n-struct object *parse_object_or_die(const struct object_id *oid,\n+struct object *parse_object_or_die(struct repository *repo,\n+\t\t\t\t   const struct object_id *oid,\n \t\t\t\t   const char *name)\n {\n-\tstruct object *o = parse_object(the_repository, oid);\n+\tstruct object *o = parse_object(repo, oid);\n \tif (o)\n \t\treturn o;\n \n@@ -524,12 +525,12 @@ void object_array_remove_duplicates(struct object_array *array)\n \t}\n }\n \n-void clear_object_flags(unsigned flags)\n+void clear_object_flags(struct repository *repo, unsigned flags)\n {\n \tint i;\n \n-\tfor (i=0; i < the_repository->parsed_objects->obj_hash_size; i++) {\n-\t\tstruct object *obj = the_repository->parsed_objects->obj_hash[i];\n+\tfor (i=0; i < repo->parsed_objects->obj_hash_size; i++) {\n+\t\tstruct object *obj = repo->parsed_objects->obj_hash[i];\n \t\tif (obj)\n \t\t\tobj->flags &= ~flags;\n \t}\ndiff --git a/object.h b/object.h\nindex 17f32f1103e..a3040939799 100644\n--- a/object.h\n+++ b/object.h\n@@ -169,12 +169,13 @@ int type_from_string_gently(const char *str, ssize_t, int gentle);\n /*\n  * Return the current number of buckets in the object hashmap.\n  */\n-unsigned int get_max_object_index(void);\n+unsigned int get_max_object_index(const struct repository *repo);\n \n /*\n  * Return the object from the specified bucket in the object hashmap.\n  */\n-struct object *get_indexed_object(unsigned int);\n+struct object *get_indexed_object(const struct repository *repo,\n+\t\t\t\t       unsigned int);\n \n /*\n  * This can be used to see if we have heard of the object before, but\n@@ -231,7 +232,8 @@ struct object *parse_object_with_flags(struct repository *r,\n  * \"name\" parameter is not NULL, it is included in the error message\n  * (otherwise, the hex object ID is given).\n  */\n-struct object *parse_object_or_die(const struct object_id *oid, const char *name);\n+struct object *parse_object_or_die(struct repository *repo, const struct object_id *oid,\n+\t\t\t\t   const char *name);\n \n /* Given the result of read_sha1_file(), returns the object after\n  * parsing it.  eaten_p indicates if the object has a borrowed copy\n@@ -336,7 +338,7 @@ void object_array_remove_duplicates(struct object_array *array);\n  */\n void object_array_clear(struct object_array *array);\n \n-void clear_object_flags(unsigned flags);\n+void clear_object_flags(struct repository *repo, unsigned flags);\n \n /*\n  * Clear the specified object flags from all in-core commit objects from\ndiff --git a/pack-bitmap.c b/pack-bitmap.c\nindex f0e2c000252..7fd78c634ef 100644\n--- a/pack-bitmap.c\n+++ b/pack-bitmap.c\n@@ -1301,7 +1301,7 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,\n \trevs->tag_objects = tmp_tags;\n \n \treset_revision_walk();\n-\tclear_object_flags(UNINTERESTING);\n+\tclear_object_flags(repo, UNINTERESTING);\n \n \t/*\n \t * Then add the boundary commit(s) as fill-in traversal tips.\n@@ -1935,7 +1935,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,\n \t\tstruct object *object = revs->pending.objects[i].item;\n \n \t\tif (object->type == OBJ_NONE)\n-\t\t\tparse_object_or_die(&object->oid, NULL);\n+\t\t\tparse_object_or_die(revs->repo, &object->oid, NULL);\n \n \t\twhile (object->type == OBJ_TAG) {\n \t\t\tstruct tag *tag = (struct tag *) object;\n@@ -1945,7 +1945,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,\n \t\t\telse\n \t\t\t\tobject_list_insert(object, &wants);\n \n-\t\t\tobject = parse_object_or_die(get_tagged_oid(tag), NULL);\n+\t\t\tobject = parse_object_or_die(revs->repo, get_tagged_oid(tag), NULL);\n \t\t\tobject->flags |= (tag->object.flags & UNINTERESTING);\n \t\t}\n \ndiff --git a/reachable.c b/reachable.c\nindex 9ee04c89ec6..1b26b9b1d76 100644\n--- a/reachable.c\n+++ b/reachable.c\n@@ -45,7 +45,7 @@ static void add_one_file(const char *path, struct rev_info *revs)\n \t}\n \tstrbuf_trim(&buf);\n \tif (!get_oid_hex(buf.buf, &oid)) {\n-\t\tobject = parse_object_or_die(&oid, buf.buf);\n+\t\tobject = parse_object_or_die(the_repository, &oid, buf.buf);\n \t\tadd_pending_object(revs, object, \"\");\n \t}\n \tstrbuf_release(&buf);\n@@ -94,7 +94,7 @@ static int add_one_ref(const char *path, const char *referent UNUSED, const stru\n \t\treturn 0;\n \t}\n \n-\tobject = parse_object_or_die(oid, path);\n+\tobject = parse_object_or_die(the_repository, oid, path);\n \tadd_pending_object(revs, object, \"\");\n \n \treturn 0;\n@@ -218,7 +218,7 @@ static void add_recent_object(const struct object_id *oid,\n \tswitch (type) {\n \tcase OBJ_TAG:\n \tcase OBJ_COMMIT:\n-\t\tobj = parse_object_or_die(oid, NULL);\n+\t\tobj = parse_object_or_die(the_repository, oid, NULL);\n \t\tbreak;\n \tcase OBJ_TREE:\n \t\tobj = (struct object *)lookup_tree(the_repository, oid);\ndiff --git a/revision.c b/revision.c\nindex c4390f0938c..b536c4a29ad 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -3612,7 +3612,8 @@ static void set_children(struct rev_info *revs)\n \n void reset_revision_walk(void)\n {\n-\tclear_object_flags(SEEN | ADDED | SHOWN | TOPO_WALK_EXPLORED | TOPO_WALK_INDEGREE);\n+\tclear_object_flags(the_repository,\n+\t\t\t   SEEN | ADDED | SHOWN | TOPO_WALK_EXPLORED | TOPO_WALK_INDEGREE);\n }\n \n static int mark_uninteresting(const struct object_id *oid,\ndiff --git a/shallow.c b/shallow.c\nindex 4bd9342c9a7..06c3266a3e0 100644\n--- a/shallow.c\n+++ b/shallow.c\n@@ -226,7 +226,7 @@ struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av,\n \t * SHALLOW (excluded) and NOT_SHALLOW (included) should not be\n \t * set at this point. But better be safe than sorry.\n \t */\n-\tclear_object_flags(both_flags);\n+\tclear_object_flags(the_repository, both_flags);\n \n \tis_repository_shallow(the_repository); /* make sure shallows are read */\n \n@@ -613,9 +613,9 @@ static void paint_down(struct paint_info *info, const struct object_id *oid,\n \t\t}\n \t}\n \n-\tnr = get_max_object_index();\n+\tnr = get_max_object_index(the_repository);\n \tfor (i = 0; i < nr; i++) {\n-\t\tstruct object *o = get_indexed_object(i);\n+\t\tstruct object *o = get_indexed_object(the_repository, i);\n \t\tif (o && o->type == OBJ_COMMIT)\n \t\t\to->flags &= ~SEEN;\n \t}\n@@ -675,9 +675,9 @@ void assign_shallow_commits_to_refs(struct shallow_info *info,\n \t * Prepare the commit graph to track what refs can reach what\n \t * (new) shallow commits.\n \t */\n-\tnr = get_max_object_index();\n+\tnr = get_max_object_index(the_repository);\n \tfor (i = 0; i < nr; i++) {\n-\t\tstruct object *o = get_indexed_object(i);\n+\t\tstruct object *o = get_indexed_object(the_repository, i);\n \t\tif (!o || o->type != OBJ_COMMIT)\n \t\t\tcontinue;\n \ndiff --git a/upload-pack.c b/upload-pack.c\nindex 728b2477fcc..7412d3c6ce8 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -662,8 +662,8 @@ static int do_reachable_revlist(struct child_process *cmd,\n \n \tcmd_in = xfdopen(cmd->in, \"w\");\n \n-\tfor (i = get_max_object_index(); 0 < i; ) {\n-\t\to = get_indexed_object(--i);\n+\tfor (i = get_max_object_index(the_repository); 0 < i; ) {\n+\t\to = get_indexed_object(the_repository, --i);\n \t\tif (!o)\n \t\t\tcontinue;\n \t\tif (reachable && o->type == OBJ_COMMIT)\n@@ -731,8 +731,8 @@ static int get_reachable_list(struct upload_pack_data *data,\n \t\t\to->flags &= ~TMP_MARK;\n \t\t}\n \t}\n-\tfor (i = get_max_object_index(); 0 < i; i--) {\n-\t\to = get_indexed_object(i - 1);\n+\tfor (i = get_max_object_index(the_repository); 0 < i; i--) {\n+\t\to = get_indexed_object(the_repository, i - 1);\n \t\tif (o && o->type == OBJ_COMMIT &&\n \t\t    (o->flags & TMP_MARK)) {\n \t\t\tadd_object_array(o, NULL, reachable);\n@@ -1554,7 +1554,7 @@ static int parse_want_ref(struct packet_writer *writer, const char *line,\n \t\t}\n \n \t\tif (!o)\n-\t\t\to = parse_object_or_die(&oid, refname_nons);\n+\t\t\to = parse_object_or_die(the_repository, &oid, refname_nons);\n \n \t\tif (!(o->flags & WANTED)) {\n \t\t\to->flags |= WANTED;\n@@ -1790,7 +1790,7 @@ int upload_pack_v2(struct repository *r, struct packet_reader *request)\n \tenum fetch_state state = FETCH_PROCESS_ARGS;\n \tstruct upload_pack_data data;\n \n-\tclear_object_flags(ALL_FLAGS);\n+\tclear_object_flags(the_repository, ALL_FLAGS);\n \n \tupload_pack_data_init(&data);\n \tdata.use_sideband = LARGE_PACKET_MAX;\n\n-- \n2.49.0.rc0.416.g627208d89d.dirty\n\n"},{"id":"513695","messageId":"20250306-b4-pks-objects-without-the-repository-v2-3-f3465327be69@pks.im","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","subject":"[PATCH v2 03/12] pack-write: stop depending on `the_repository` and `the_hash_algo`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T15:10:27Z","receivedAt":"2025-03-06T15:10:36Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are a couple of functions in \"pack-write.c\" that implicitly depend\non `the_repository` or `the_hash_algo`. Remove this dependency by\ninjecting the repository via a parameter and adapt callers accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fast-import.c  |  2 +-\n builtin/index-pack.c   |  4 ++--\n builtin/pack-objects.c |  4 ++--\n bulk-checkin.c         |  4 ++--\n midx-write.c           |  2 +-\n pack-write.c           | 55 +++++++++++++++++++++++++-------------------------\n pack.h                 | 11 +++++-----\n 7 files changed, 41 insertions(+), 41 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 86e6e754816..e1758aa9514 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -798,7 +798,7 @@ static const char *create_index(void)\n \tif (c != last)\n \t\tdie(\"internal consistency error creating the index\");\n \n-\ttmpfile = write_idx_file(the_hash_algo, NULL, idx, object_count,\n+\ttmpfile = write_idx_file(the_repository, NULL, idx, object_count,\n \t\t\t\t &pack_idx_opts, pack_data->hash);\n \tfree(idx);\n \treturn tmpfile;\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 1268032d769..174e03afa61 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -2088,10 +2088,10 @@ int cmd_index_pack(int argc,\n \tALLOC_ARRAY(idx_objects, nr_objects);\n \tfor (i = 0; i < nr_objects; i++)\n \t\tidx_objects[i] = &objects[i].idx;\n-\tcurr_index = write_idx_file(the_hash_algo, index_name, idx_objects,\n+\tcurr_index = write_idx_file(the_repository, index_name, idx_objects,\n \t\t\t\t    nr_objects, &opts, pack_hash);\n \tif (rev_index)\n-\t\tcurr_rev_index = write_rev_file(the_hash_algo, rev_index_name,\n+\t\tcurr_rev_index = write_rev_file(the_repository, rev_index_name,\n \t\t\t\t\t\tidx_objects, nr_objects,\n \t\t\t\t\t\tpack_hash, opts.flags);\n \tfree(idx_objects);\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex c3adbc94504..e05dfc4021e 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -1314,7 +1314,7 @@ static void write_pack_file(void)\n \t\t\tf = hashfd_throughput(the_repository->hash_algo, 1,\n \t\t\t\t\t      \"<stdout>\", progress_state);\n \t\telse\n-\t\t\tf = create_tmp_packfile(&pack_tmp_name);\n+\t\t\tf = create_tmp_packfile(the_repository, &pack_tmp_name);\n \n \t\toffset = write_pack_header(f, nr_remaining);\n \n@@ -1407,7 +1407,7 @@ static void write_pack_file(void)\n \t\t\tif (cruft)\n \t\t\t\tpack_idx_opts.flags |= WRITE_MTIMES;\n \n-\t\t\tstage_tmp_packfiles(the_hash_algo, &tmpname,\n+\t\t\tstage_tmp_packfiles(the_repository, &tmpname,\n \t\t\t\t\t    pack_tmp_name, written_list,\n \t\t\t\t\t    nr_written, &to_pack,\n \t\t\t\t\t    &pack_idx_opts, hash,\ndiff --git a/bulk-checkin.c b/bulk-checkin.c\nindex 20f2da67b93..23ac00ea0a6 100644\n--- a/bulk-checkin.c\n+++ b/bulk-checkin.c\n@@ -44,7 +44,7 @@ static void finish_tmp_packfile(struct strbuf *basename,\n {\n \tchar *idx_tmp_name = NULL;\n \n-\tstage_tmp_packfiles(the_hash_algo, basename, pack_tmp_name,\n+\tstage_tmp_packfiles(the_repository, basename, pack_tmp_name,\n \t\t\t    written_list, nr_written, NULL, pack_idx_opts, hash,\n \t\t\t    &idx_tmp_name);\n \trename_tmp_packfile_idx(basename, &idx_tmp_name);\n@@ -244,7 +244,7 @@ static void prepare_to_stream(struct bulk_checkin_packfile *state,\n \tif (!(flags & HASH_WRITE_OBJECT) || state->f)\n \t\treturn;\n \n-\tstate->f = create_tmp_packfile(&state->pack_tmp_name);\n+\tstate->f = create_tmp_packfile(the_repository, &state->pack_tmp_name);\n \treset_pack_idx_option(&state->pack_idx_opts);\n \n \t/* Pretend we are going to write only one object */\ndiff --git a/midx-write.c b/midx-write.c\nindex ac80a8298ed..a628ac24dcb 100644\n--- a/midx-write.c\n+++ b/midx-write.c\n@@ -658,7 +658,7 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash,\n \tstrbuf_addf(&buf, \"%s-%s.rev\", midx_name, hash_to_hex_algop(midx_hash,\n \t\t\t\t\t\t\t\t    ctx->repo->hash_algo));\n \n-\ttmp_file = write_rev_file_order(ctx->repo->hash_algo, NULL, ctx->pack_order,\n+\ttmp_file = write_rev_file_order(ctx->repo, NULL, ctx->pack_order,\n \t\t\t\t\tctx->entries_nr, midx_hash, WRITE_REV);\n \n \tif (finalize_object_file(tmp_file, buf.buf))\ndiff --git a/pack-write.c b/pack-write.c\nindex 5eb89f44cf4..6b06315f80a 100644\n--- a/pack-write.c\n+++ b/pack-write.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"gettext.h\"\n@@ -56,7 +54,7 @@ static int need_large_offset(off_t offset, const struct pack_idx_option *opts)\n  * The *sha1 contains the pack content SHA1 hash.\n  * The objects array passed in will be sorted by SHA1 on exit.\n  */\n-const char *write_idx_file(const struct git_hash_algo *hash_algo,\n+const char *write_idx_file(struct repository *repo,\n \t\t\t   const char *index_name, struct pack_idx_entry **objects,\n \t\t\t   int nr_objects, const struct pack_idx_option *opts,\n \t\t\t   const unsigned char *sha1)\n@@ -82,7 +80,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \n \tif (opts->flags & WRITE_IDX_VERIFY) {\n \t\tassert(index_name);\n-\t\tf = hashfd_check(the_repository->hash_algo, index_name);\n+\t\tf = hashfd_check(repo->hash_algo, index_name);\n \t} else {\n \t\tif (!index_name) {\n \t\t\tstruct strbuf tmp_file = STRBUF_INIT;\n@@ -92,7 +90,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\t\tunlink(index_name);\n \t\t\tfd = xopen(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t}\n-\t\tf = hashfd(the_repository->hash_algo, fd, index_name);\n+\t\tf = hashfd(repo->hash_algo, fd, index_name);\n \t}\n \n \t/* if last object's offset is >= 2^31 we should use index V2 */\n@@ -131,7 +129,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\tstruct pack_idx_entry *obj = *list++;\n \t\tif (index_version < 2)\n \t\t\thashwrite_be32(f, obj->offset);\n-\t\thashwrite(f, obj->oid.hash, hash_algo->rawsz);\n+\t\thashwrite(f, obj->oid.hash, repo->hash_algo->rawsz);\n \t\tif ((opts->flags & WRITE_IDX_STRICT) &&\n \t\t    (i && oideq(&list[-2]->oid, &obj->oid)))\n \t\t\tdie(\"The same object %s appears twice in the pack\",\n@@ -173,7 +171,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\t}\n \t}\n \n-\thashwrite(f, sha1, hash_algo->rawsz);\n+\thashwrite(f, sha1, repo->hash_algo->rawsz);\n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n \t\t\t  CSUM_HASH_IN_STREAM | CSUM_CLOSE |\n \t\t\t  ((opts->flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC));\n@@ -217,7 +215,7 @@ static void write_rev_trailer(const struct git_hash_algo *hash_algo,\n \thashwrite(f, hash, hash_algo->rawsz);\n }\n \n-char *write_rev_file(const struct git_hash_algo *hash_algo,\n+char *write_rev_file(struct repository *repo,\n \t\t     const char *rev_name,\n \t\t     struct pack_idx_entry **objects,\n \t\t     uint32_t nr_objects,\n@@ -236,7 +234,7 @@ char *write_rev_file(const struct git_hash_algo *hash_algo,\n \t\tpack_order[i] = i;\n \tQSORT_S(pack_order, nr_objects, pack_order_cmp, objects);\n \n-\tret = write_rev_file_order(hash_algo, rev_name, pack_order, nr_objects,\n+\tret = write_rev_file_order(repo, rev_name, pack_order, nr_objects,\n \t\t\t\t   hash, flags);\n \n \tfree(pack_order);\n@@ -244,7 +242,7 @@ char *write_rev_file(const struct git_hash_algo *hash_algo,\n \treturn ret;\n }\n \n-char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n+char *write_rev_file_order(struct repository *repo,\n \t\t\t   const char *rev_name,\n \t\t\t   uint32_t *pack_order,\n \t\t\t   uint32_t nr_objects,\n@@ -268,7 +266,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\tfd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t\tpath = xstrdup(rev_name);\n \t\t}\n-\t\tf = hashfd(the_repository->hash_algo, fd, path);\n+\t\tf = hashfd(repo->hash_algo, fd, path);\n \t} else if (flags & WRITE_REV_VERIFY) {\n \t\tstruct stat statbuf;\n \t\tif (stat(rev_name, &statbuf)) {\n@@ -278,18 +276,18 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\t} else\n \t\t\t\tdie_errno(_(\"could not stat: %s\"), rev_name);\n \t\t}\n-\t\tf = hashfd_check(the_repository->hash_algo, rev_name);\n+\t\tf = hashfd_check(repo->hash_algo, rev_name);\n \t\tpath = xstrdup(rev_name);\n \t} else {\n \t\treturn NULL;\n \t}\n \n-\twrite_rev_header(hash_algo, f);\n+\twrite_rev_header(repo->hash_algo, f);\n \n \twrite_rev_index_positions(f, pack_order, nr_objects);\n-\twrite_rev_trailer(hash_algo, f, hash);\n+\twrite_rev_trailer(repo->hash_algo, f, hash);\n \n-\tif (adjust_shared_perm(the_repository, path) < 0)\n+\tif (adjust_shared_perm(repo, path) < 0)\n \t\tdie(_(\"failed to make %s readable\"), path);\n \n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n@@ -330,7 +328,7 @@ static void write_mtimes_trailer(const struct git_hash_algo *hash_algo,\n \thashwrite(f, hash, hash_algo->rawsz);\n }\n \n-static char *write_mtimes_file(const struct git_hash_algo *hash_algo,\n+static char *write_mtimes_file(struct repository *repo,\n \t\t\t       struct packing_data *to_pack,\n \t\t\t       struct pack_idx_entry **objects,\n \t\t\t       uint32_t nr_objects,\n@@ -346,13 +344,13 @@ static char *write_mtimes_file(const struct git_hash_algo *hash_algo,\n \n \tfd = odb_mkstemp(&tmp_file, \"pack/tmp_mtimes_XXXXXX\");\n \tmtimes_name = strbuf_detach(&tmp_file, NULL);\n-\tf = hashfd(the_repository->hash_algo, fd, mtimes_name);\n+\tf = hashfd(repo->hash_algo, fd, mtimes_name);\n \n-\twrite_mtimes_header(hash_algo, f);\n+\twrite_mtimes_header(repo->hash_algo, f);\n \twrite_mtimes_objects(f, to_pack, objects, nr_objects);\n-\twrite_mtimes_trailer(hash_algo, f, hash);\n+\twrite_mtimes_trailer(repo->hash_algo, f, hash);\n \n-\tif (adjust_shared_perm(the_repository, mtimes_name) < 0)\n+\tif (adjust_shared_perm(repo, mtimes_name) < 0)\n \t\tdie(_(\"failed to make %s readable\"), mtimes_name);\n \n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n@@ -527,14 +525,15 @@ int encode_in_pack_object_header(unsigned char *hdr, int hdr_len,\n \treturn n;\n }\n \n-struct hashfile *create_tmp_packfile(char **pack_tmp_name)\n+struct hashfile *create_tmp_packfile(struct repository *repo,\n+\t\t\t\t     char **pack_tmp_name)\n {\n \tstruct strbuf tmpname = STRBUF_INIT;\n \tint fd;\n \n \tfd = odb_mkstemp(&tmpname, \"pack/tmp_pack_XXXXXX\");\n \t*pack_tmp_name = strbuf_detach(&tmpname, NULL);\n-\treturn hashfd(the_repository->hash_algo, fd, *pack_tmp_name);\n+\treturn hashfd(repo->hash_algo, fd, *pack_tmp_name);\n }\n \n static void rename_tmp_packfile(struct strbuf *name_prefix, const char *source,\n@@ -555,7 +554,7 @@ void rename_tmp_packfile_idx(struct strbuf *name_buffer,\n \trename_tmp_packfile(name_buffer, *idx_tmp_name, \"idx\");\n }\n \n-void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,\n+void stage_tmp_packfiles(struct repository *repo,\n \t\t\t struct strbuf *name_buffer,\n \t\t\t const char *pack_tmp_name,\n \t\t\t struct pack_idx_entry **written_list,\n@@ -568,19 +567,19 @@ void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,\n \tchar *rev_tmp_name = NULL;\n \tchar *mtimes_tmp_name = NULL;\n \n-\tif (adjust_shared_perm(the_repository, pack_tmp_name))\n+\tif (adjust_shared_perm(repo, pack_tmp_name))\n \t\tdie_errno(\"unable to make temporary pack file readable\");\n \n-\t*idx_tmp_name = (char *)write_idx_file(hash_algo, NULL, written_list,\n+\t*idx_tmp_name = (char *)write_idx_file(repo, NULL, written_list,\n \t\t\t\t\t       nr_written, pack_idx_opts, hash);\n-\tif (adjust_shared_perm(the_repository, *idx_tmp_name))\n+\tif (adjust_shared_perm(repo, *idx_tmp_name))\n \t\tdie_errno(\"unable to make temporary index file readable\");\n \n-\trev_tmp_name = write_rev_file(hash_algo, NULL, written_list, nr_written,\n+\trev_tmp_name = write_rev_file(repo, NULL, written_list, nr_written,\n \t\t\t\t      hash, pack_idx_opts->flags);\n \n \tif (pack_idx_opts->flags & WRITE_MTIMES) {\n-\t\tmtimes_tmp_name = write_mtimes_file(hash_algo, to_pack,\n+\t\tmtimes_tmp_name = write_mtimes_file(repo, to_pack,\n \t\t\t\t\t\t    written_list, nr_written,\n \t\t\t\t\t\t    hash);\n \t}\ndiff --git a/pack.h b/pack.h\nindex 9f1194ac13d..5d4393eaffe 100644\n--- a/pack.h\n+++ b/pack.h\n@@ -87,7 +87,7 @@ struct progress;\n /* Note, the data argument could be NULL if object type is blob */\n typedef int (*verify_fn)(const struct object_id *, enum object_type, unsigned long, void*, int*);\n \n-const char *write_idx_file(const struct git_hash_algo *hash_algo,\n+const char *write_idx_file(struct repository *repo,\n \t\t\t   const char *index_name,\n \t\t\t   struct pack_idx_entry **objects,\n \t\t\t   int nr_objects,\n@@ -106,13 +106,13 @@ struct ref;\n \n void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought);\n \n-char *write_rev_file(const struct git_hash_algo *hash_algo,\n+char *write_rev_file(struct repository *repo,\n \t\t     const char *rev_name,\n \t\t     struct pack_idx_entry **objects,\n \t\t     uint32_t nr_objects,\n \t\t     const unsigned char *hash,\n \t\t     unsigned flags);\n-char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n+char *write_rev_file_order(struct repository *repo,\n \t\t\t   const char *rev_name,\n \t\t\t   uint32_t *pack_order,\n \t\t\t   uint32_t nr_objects,\n@@ -134,8 +134,9 @@ int read_pack_header(int fd, struct pack_header *);\n \n struct packing_data;\n \n-struct hashfile *create_tmp_packfile(char **pack_tmp_name);\n-void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,\n+struct hashfile *create_tmp_packfile(struct repository *repo,\n+\t\t\t\t     char **pack_tmp_name);\n+void stage_tmp_packfiles(struct repository *repo,\n \t\t\t struct strbuf *name_buffer,\n \t\t\t const char *pack_tmp_name,\n \t\t\t struct pack_idx_entry **written_list,\n\n-- \n2.49.0.rc0.416.g627208d89d.dirty\n\n"},{"id":"513696","messageId":"20250306-b4-pks-objects-without-the-repository-v2-4-f3465327be69@pks.im","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","subject":"[PATCH v2 04/12] environment: move access to \"core.bigFileThreshold\" into repo settings","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T15:10:28Z","receivedAt":"2025-03-06T15:10:37Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The \"core.bigFileThreshold\" setting is stored in a global variable and\npopulated via `git_default_core_config()`. This may cause issues in\nthe case where one is handling multiple different repositories in a\nsingle process with different values for that config key, as we may or\nmay not see the correct value in that case. Furthermore, global state\nblocks our path towards libification.\n\nRefactor the code so that we instead store the value in `struct\nrepo_settings`, where the value is computed as-needed and cached.\n\nNote that this change requires us to adapt one test in t1050 that\nverifies that we die when parsing an invalid \"core.bigFileThreshold\"\nvalue. The exercised Git command doesn't use the value at all, and thus\nit won't hit the new code path that parses the value. This is addressed\nby using git-hash-object(1) instead, which does read the value.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n archive.c                |  2 +-\n builtin/fast-import.c    |  4 ++--\n builtin/index-pack.c     |  6 ++++--\n builtin/pack-objects.c   |  6 ++++--\n builtin/unpack-objects.c |  3 ++-\n config.c                 |  5 -----\n diff.c                   |  6 ++++--\n environment.c            |  1 -\n environment.h            |  1 -\n object-file.c            |  6 ++++--\n pack-check.c             |  3 ++-\n repo-settings.c          | 20 ++++++++++++++++++++\n repo-settings.h          |  5 +++++\n streaming.c              |  3 ++-\n t/t1050-large.sh         |  3 ++-\n 15 files changed, 52 insertions(+), 22 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex 8be4e7ac8db..f4331aeb49e 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -216,7 +216,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,\n \t/* Stream it? */\n \tif (S_ISREG(mode) && !args->convert &&\n \t    oid_object_info(args->repo, oid, &size) == OBJ_BLOB &&\n-\t    size > big_file_threshold)\n+\t    size > repo_settings_get_big_file_threshold(the_repository))\n \t\treturn write_entry(args, oid, path.buf, path.len, mode, NULL, size);\n \n \tbuffer = object_file_to_archive(args, path.buf, oid, mode, &type, &size);\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex e1758aa9514..ce52f78579d 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -2021,7 +2021,7 @@ static void parse_and_store_blob(\n \tstatic struct strbuf buf = STRBUF_INIT;\n \tuintmax_t len;\n \n-\tif (parse_data(&buf, big_file_threshold, &len))\n+\tif (parse_data(&buf, repo_settings_get_big_file_threshold(the_repository), &len))\n \t\tstore_object(OBJ_BLOB, &buf, last, oidout, mark);\n \telse {\n \t\tif (last) {\n@@ -3402,7 +3402,7 @@ static int parse_one_option(const char *option)\n \t\tunsigned long v;\n \t\tif (!git_parse_ulong(option, &v))\n \t\t\treturn 0;\n-\t\tbig_file_threshold = v;\n+\t\trepo_settings_set_big_file_threshold(the_repository, v);\n \t} else if (skip_prefix(option, \"depth=\", &option)) {\n \t\toption_depth(option);\n \t} else if (skip_prefix(option, \"active-branches=\", &option)) {\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 174e03afa61..09c0a8adf63 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -485,7 +485,8 @@ static void *unpack_entry_data(off_t offset, unsigned long size,\n \t\tgit_hash_update(&c, hdr, hdrlen);\n \t} else\n \t\toid = NULL;\n-\tif (type == OBJ_BLOB && size > big_file_threshold)\n+\tif (type == OBJ_BLOB &&\n+\t    size > repo_settings_get_big_file_threshold(the_repository))\n \t\tbuf = fixed_buf;\n \telse\n \t\tbuf = xmallocz(size);\n@@ -799,7 +800,8 @@ static int check_collison(struct object_entry *entry)\n \tenum object_type type;\n \tunsigned long size;\n \n-\tif (entry->size <= big_file_threshold || entry->type != OBJ_BLOB)\n+\tif (entry->size <= repo_settings_get_big_file_threshold(the_repository) ||\n+\t    entry->type != OBJ_BLOB)\n \t\treturn -1;\n \n \tmemset(&data, 0, sizeof(data));\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex e05dfc4021e..eefc6c78096 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -499,7 +499,8 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent\n \n \tif (!usable_delta) {\n \t\tif (oe_type(entry) == OBJ_BLOB &&\n-\t\t    oe_size_greater_than(&to_pack, entry, big_file_threshold) &&\n+\t\t    oe_size_greater_than(&to_pack, entry,\n+\t\t\t\t\t repo_settings_get_big_file_threshold(the_repository)) &&\n \t\t    (st = open_istream(the_repository, &entry->idx.oid, &type,\n \t\t\t\t       &size, NULL)) != NULL)\n \t\t\tbuf = NULL;\n@@ -2454,7 +2455,8 @@ static void get_object_details(void)\n \t\tstruct object_entry *entry = sorted_by_offset[i];\n \t\tcheck_object(entry, i);\n \t\tif (entry->type_valid &&\n-\t\t    oe_size_greater_than(&to_pack, entry, big_file_threshold))\n+\t\t    oe_size_greater_than(&to_pack, entry,\n+\t\t\t\t\t repo_settings_get_big_file_threshold(the_repository)))\n \t\t\tentry->no_try_delta = 1;\n \t\tdisplay_progress(progress_state, i + 1);\n \t}\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex 8383bcf4049..e20c120913e 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -553,7 +553,8 @@ static void unpack_one(unsigned nr)\n \n \tswitch (type) {\n \tcase OBJ_BLOB:\n-\t\tif (!dry_run && size > big_file_threshold) {\n+\t\tif (!dry_run &&\n+\t\t    size > repo_settings_get_big_file_threshold(the_repository)) {\n \t\t\tstream_blob(size, nr);\n \t\t\treturn;\n \t\t}\ndiff --git a/config.c b/config.c\nindex dfd03b9421c..dc95608f749 100644\n--- a/config.c\n+++ b/config.c\n@@ -1490,11 +1490,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.bigfilethreshold\")) {\n-\t\tbig_file_threshold = git_config_ulong(var, value, ctx->kvi);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.autocrlf\")) {\n \t\tif (value && !strcasecmp(value, \"input\")) {\n \t\t\tauto_crlf = AUTO_CRLF_INPUT;\ndiff --git a/diff.c b/diff.c\nindex c89c15d98e0..4f802b4251c 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -4193,7 +4193,8 @@ int diff_populate_filespec(struct repository *r,\n \t\t * is probably fine.\n \t\t */\n \t\tif (check_binary &&\n-\t\t    s->size > big_file_threshold && s->is_binary == -1) {\n+\t\t    s->size > repo_settings_get_big_file_threshold(the_repository) &&\n+\t\t    s->is_binary == -1) {\n \t\t\ts->is_binary = 1;\n \t\t\treturn 0;\n \t\t}\n@@ -4243,7 +4244,8 @@ int diff_populate_filespec(struct repository *r,\n \t\tif (size_only || check_binary) {\n \t\t\tif (size_only)\n \t\t\t\treturn 0;\n-\t\t\tif (s->size > big_file_threshold && s->is_binary == -1) {\n+\t\t\tif (s->size > repo_settings_get_big_file_threshold(the_repository) &&\n+\t\t\t    s->is_binary == -1) {\n \t\t\t\ts->is_binary = 1;\n \t\t\t\treturn 0;\n \t\t\t}\ndiff --git a/environment.c b/environment.c\nindex 9e4c7781be0..3c32367c28c 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -49,7 +49,6 @@ int fsync_object_files = -1;\n int use_fsync = -1;\n enum fsync_method fsync_method = FSYNC_METHOD_DEFAULT;\n enum fsync_component fsync_components = FSYNC_COMPONENTS_DEFAULT;\n-unsigned long big_file_threshold = 512 * 1024 * 1024;\n char *editor_program;\n char *askpass_program;\n char *excludes_file;\ndiff --git a/environment.h b/environment.h\nindex 45e690f203f..91d854dcb08 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -154,7 +154,6 @@ extern int zlib_compression_level;\n extern int pack_compression_level;\n extern size_t packed_git_window_size;\n extern size_t packed_git_limit;\n-extern unsigned long big_file_threshold;\n extern unsigned long pack_size_limit_cfg;\n extern int max_allowed_tree_depth;\n \ndiff --git a/object-file.c b/object-file.c\nindex 726e41a0475..b3e0276b2a4 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2803,7 +2803,8 @@ int index_fd(struct index_state *istate, struct object_id *oid,\n \t\tret = index_stream_convert_blob(istate, oid, fd, path, flags);\n \telse if (!S_ISREG(st->st_mode))\n \t\tret = index_pipe(istate, oid, fd, type, path, flags);\n-\telse if (st->st_size <= big_file_threshold || type != OBJ_BLOB ||\n+\telse if (st->st_size <= repo_settings_get_big_file_threshold(the_repository) ||\n+\t\t type != OBJ_BLOB ||\n \t\t (path && would_convert_to_git(istate, path)))\n \t\tret = index_core(istate, oid, fd, xsize_t(st->st_size),\n \t\t\t\t type, path, flags);\n@@ -3137,7 +3138,8 @@ int read_loose_object(const char *path,\n \t\tgoto out;\n \t}\n \n-\tif (*oi->typep == OBJ_BLOB && *size > big_file_threshold) {\n+\tif (*oi->typep == OBJ_BLOB &&\n+\t    *size > repo_settings_get_big_file_threshold(the_repository)) {\n \t\tif (check_stream_oid(&stream, hdr, *size, path, expected_oid) < 0)\n \t\t\tgoto out;\n \t} else {\ndiff --git a/pack-check.c b/pack-check.c\nindex 6bcadc1e679..017dc740f7b 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -131,7 +131,8 @@ static int verify_packfile(struct repository *r,\n \t\ttype = unpack_object_header(p, w_curs, &curpos, &size);\n \t\tunuse_pack(w_curs);\n \n-\t\tif (type == OBJ_BLOB && big_file_threshold <= size) {\n+\t\tif (type == OBJ_BLOB &&\n+\t\t    repo_settings_get_big_file_threshold(the_repository) <= size) {\n \t\t\t/*\n \t\t\t * Let stream_object_signature() check it with\n \t\t\t * the streaming interface; no point slurping\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 67e9cfd2e63..4129f8fb2b4 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -20,6 +20,13 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest,\n \t\t*dest = def;\n }\n \n+static void repo_cfg_ulong(struct repository *r, const char *key, unsigned long *dest,\n+\t\t\t   unsigned long def)\n+{\n+\tif (repo_config_get_ulong(r, key, dest))\n+\t\t*dest = def;\n+}\n+\n void prepare_repo_settings(struct repository *r)\n {\n \tint experimental;\n@@ -151,6 +158,19 @@ void repo_settings_clear(struct repository *r)\n \tr->settings = empty;\n }\n \n+unsigned long repo_settings_get_big_file_threshold(struct repository *repo)\n+{\n+\tif (!repo->settings.big_file_threshold)\n+\t\trepo_cfg_ulong(repo, \"core.bigfilethreshold\",\n+\t\t\t       &repo->settings.big_file_threshold, 512 * 1024 * 1024);\n+\treturn repo->settings.big_file_threshold;\n+}\n+\n+void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value)\n+{\n+\trepo->settings.big_file_threshold = value;\n+}\n+\n enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo)\n {\n \tconst char *value;\ndiff --git a/repo-settings.h b/repo-settings.h\nindex ddc11967e01..2bf24b25973 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -64,6 +64,7 @@ struct repo_settings {\n \tsize_t delta_base_cache_limit;\n \tsize_t packed_git_window_size;\n \tsize_t packed_git_limit;\n+\tunsigned long big_file_threshold;\n \n \tchar *hooks_path;\n };\n@@ -88,6 +89,10 @@ int repo_settings_get_warn_ambiguous_refs(struct repository *repo);\n /* Read the value for \"core.hooksPath\". */\n const char *repo_settings_get_hooks_path(struct repository *repo);\n \n+/* Read and set the value for \"core.bigFileThreshold\". */\n+unsigned long repo_settings_get_big_file_threshold(struct repository *repo);\n+void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value);\n+\n /* Read, set or reset the value for \"core.sharedRepository\". */\n int repo_settings_get_shared_repository(struct repository *repo);\n void repo_settings_set_shared_repository(struct repository *repo, int value);\ndiff --git a/streaming.c b/streaming.c\nindex 38839511afc..018b794d252 100644\n--- a/streaming.c\n+++ b/streaming.c\n@@ -431,7 +431,8 @@ static int istream_source(struct git_istream *st,\n \t\tst->open = open_istream_loose;\n \t\treturn 0;\n \tcase OI_PACKED:\n-\t\tif (!oi.u.packed.is_delta && big_file_threshold < size) {\n+\t\tif (!oi.u.packed.is_delta &&\n+\t\t    repo_settings_get_big_file_threshold(the_repository) < size) {\n \t\t\tst->u.in_pack.pack = oi.u.packed.pack;\n \t\t\tst->u.in_pack.pos = oi.u.packed.offset;\n \t\t\tst->open = open_istream_pack_non_delta;\ndiff --git a/t/t1050-large.sh b/t/t1050-large.sh\nindex c71932b0242..5be273611ad 100755\n--- a/t/t1050-large.sh\n+++ b/t/t1050-large.sh\n@@ -6,7 +6,8 @@ test_description='adding and checking out large blobs'\n . ./test-lib.sh\n \n test_expect_success 'core.bigFileThreshold must be non-negative' '\n-\ttest_must_fail git -c core.bigFileThreshold=-1 rev-parse >out 2>err &&\n+\t: >input &&\n+\ttest_must_fail git -c core.bigFileThreshold=-1 hash-object input >out 2>err &&\n \tgrep \"bad numeric config value\" err &&\n \ttest_must_be_empty out\n '\n\n-- \n2.49.0.rc0.416.g627208d89d.dirty\n\n"},{"id":"513697","messageId":"20250306-b4-pks-objects-without-the-repository-v2-5-f3465327be69@pks.im","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","subject":"[PATCH v2 05/12] pack-check: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T15:10:29Z","receivedAt":"2025-03-06T15:10:39Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"pack-check.c\" where we use the global\n`the_repository` variable, either explicitly or implicitly by using\n`the_hash_algo`. In all of those cases we already have a repository\navailable in the calling context though.\n\nRefactor the code to instead use the caller-provided repository and\nremove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n pack-check.c | 11 +++++------\n 1 file changed, 5 insertions(+), 6 deletions(-)\n\ndiff --git a/pack-check.c b/pack-check.c\nindex 017dc740f7b..95dcbbe9852 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -44,7 +43,7 @@ int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,\n \t} while (len);\n \n \tindex_crc = p->index_data;\n-\tindex_crc += 2 + 256 + (size_t)p->num_objects * (the_hash_algo->rawsz/4) + nr;\n+\tindex_crc += 2 + 256 + (size_t)p->num_objects * (p->repo->hash_algo->rawsz/4) + nr;\n \n \treturn data_crc != ntohl(*index_crc);\n }\n@@ -81,11 +80,11 @@ static int verify_packfile(struct repository *r,\n \t} while (offset < pack_sig_ofs);\n \tgit_hash_final(hash, &ctx);\n \tpack_sig = use_pack(p, w_curs, pack_sig_ofs, NULL);\n-\tif (!hasheq(hash, pack_sig, the_repository->hash_algo))\n+\tif (!hasheq(hash, pack_sig, r->hash_algo))\n \t\terr = error(\"%s pack checksum mismatch\",\n \t\t\t    p->pack_name);\n \tif (!hasheq(index_base + index_size - r->hash_algo->hexsz, pack_sig,\n-\t\t    the_repository->hash_algo))\n+\t\t    r->hash_algo))\n \t\terr = error(\"%s pack checksum does not match its index\",\n \t\t\t    p->pack_name);\n \tunuse_pack(w_curs);\n@@ -132,7 +131,7 @@ static int verify_packfile(struct repository *r,\n \t\tunuse_pack(w_curs);\n \n \t\tif (type == OBJ_BLOB &&\n-\t\t    repo_settings_get_big_file_threshold(the_repository) <= size) {\n+\t\t    repo_settings_get_big_file_threshold(r) <= size) {\n \t\t\t/*\n \t\t\t * Let stream_object_signature() check it with\n \t\t\t * the streaming interface; no point slurping\n@@ -181,7 +180,7 @@ int verify_pack_index(struct packed_git *p)\n \t\treturn error(\"packfile %s index not opened\", p->pack_name);\n \n \t/* Verify SHA1 sum of the index file */\n-\tif (!hashfile_checksum_valid(the_repository->hash_algo, p->index_data, p->index_size))\n+\tif (!hashfile_checksum_valid(p->repo->hash_algo, p->index_data, p->index_size))\n \t\terr = error(\"Packfile index for %s hash mismatch\",\n \t\t\t    p->pack_name);\n \treturn err;\n\n-- \n2.49.0.rc0.416.g627208d89d.dirty\n\n"},{"id":"513698","messageId":"20250306-b4-pks-objects-without-the-repository-v2-6-f3465327be69@pks.im","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","subject":"[PATCH v2 06/12] pack-revindex: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T15:10:30Z","receivedAt":"2025-03-06T15:10:40Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"pack-revindex.c\" where we use the global\n`the_repository` variable, either explicitly or implicitly by using\n`the_hash_algo`. In all of those cases we already have a repository\navailable in the calling context though.\n\nRefactor the code to instead use the caller-provided repository and\nremove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n pack-revindex.c | 34 ++++++++++++++++++++--------------\n 1 file changed, 20 insertions(+), 14 deletions(-)\n\ndiff --git a/pack-revindex.c b/pack-revindex.c\nindex 78139e3d7f5..038e0c96b1c 100644\n--- a/pack-revindex.c\n+++ b/pack-revindex.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"gettext.h\"\n #include \"pack-revindex.h\"\n@@ -9,6 +7,7 @@\n #include \"strbuf.h\"\n #include \"trace2.h\"\n #include \"parse.h\"\n+#include \"repository.h\"\n #include \"midx.h\"\n #include \"csum-file.h\"\n \n@@ -137,7 +136,7 @@ static void create_pack_revindex(struct packed_git *p)\n \tconst unsigned num_ent = p->num_objects;\n \tunsigned i;\n \tconst char *index = p->index_data;\n-\tconst unsigned hashsz = the_hash_algo->rawsz;\n+\tconst unsigned hashsz = p->repo->hash_algo->rawsz;\n \n \tALLOC_ARRAY(p->revindex, num_ent + 1);\n \tindex += 4 * 256;\n@@ -193,7 +192,11 @@ static char *pack_revindex_filename(struct packed_git *p)\n }\n \n #define RIDX_HEADER_SIZE (12)\n-#define RIDX_MIN_SIZE (RIDX_HEADER_SIZE + (2 * the_hash_algo->rawsz))\n+\n+static size_t ridx_min_size(const struct git_hash_algo *algo)\n+{\n+\treturn RIDX_HEADER_SIZE + (2 * algo->rawsz);\n+}\n \n struct revindex_header {\n \tuint32_t signature;\n@@ -201,7 +204,8 @@ struct revindex_header {\n \tuint32_t hash_id;\n };\n \n-static int load_revindex_from_disk(char *revindex_name,\n+static int load_revindex_from_disk(const struct git_hash_algo *algo,\n+\t\t\t\t   char *revindex_name,\n \t\t\t\t   uint32_t num_objects,\n \t\t\t\t   const uint32_t **data_p, size_t *len_p)\n {\n@@ -228,12 +232,12 @@ static int load_revindex_from_disk(char *revindex_name,\n \n \trevindex_size = xsize_t(st.st_size);\n \n-\tif (revindex_size < RIDX_MIN_SIZE) {\n+\tif (revindex_size < ridx_min_size(algo)) {\n \t\tret = error(_(\"reverse-index file %s is too small\"), revindex_name);\n \t\tgoto cleanup;\n \t}\n \n-\tif (revindex_size - RIDX_MIN_SIZE != st_mult(sizeof(uint32_t), num_objects)) {\n+\tif (revindex_size - ridx_min_size(algo) != st_mult(sizeof(uint32_t), num_objects)) {\n \t\tret = error(_(\"reverse-index file %s is corrupt\"), revindex_name);\n \t\tgoto cleanup;\n \t}\n@@ -279,7 +283,8 @@ int load_pack_revindex_from_disk(struct packed_git *p)\n \n \trevindex_name = pack_revindex_filename(p);\n \n-\tret = load_revindex_from_disk(revindex_name,\n+\tret = load_revindex_from_disk(p->repo->hash_algo,\n+\t\t\t\t      revindex_name,\n \t\t\t\t      p->num_objects,\n \t\t\t\t      &p->revindex_map,\n \t\t\t\t      &p->revindex_size);\n@@ -322,7 +327,7 @@ int verify_pack_revindex(struct packed_git *p)\n \tif (!p->revindex_map || !p->revindex_data)\n \t\treturn res;\n \n-\tif (!hashfile_checksum_valid(the_repository->hash_algo,\n+\tif (!hashfile_checksum_valid(p->repo->hash_algo,\n \t\t\t\t     (const unsigned char *)p->revindex_map, p->revindex_size)) {\n \t\terror(_(\"invalid checksum\"));\n \t\tres = -1;\n@@ -375,19 +380,20 @@ int load_midx_revindex(struct multi_pack_index *m)\n \t\t * not want to accidentally call munmap() in the middle of the\n \t\t * MIDX.\n \t\t */\n-\t\ttrace2_data_string(\"load_midx_revindex\", the_repository,\n+\t\ttrace2_data_string(\"load_midx_revindex\", m->repo,\n \t\t\t\t   \"source\", \"midx\");\n \t\tm->revindex_data = (const uint32_t *)m->chunk_revindex;\n \t\treturn 0;\n \t}\n \n-\ttrace2_data_string(\"load_midx_revindex\", the_repository,\n+\ttrace2_data_string(\"load_midx_revindex\", m->repo,\n \t\t\t   \"source\", \"rev\");\n \n \tget_midx_filename_ext(m->repo->hash_algo, &revindex_name, m->object_dir,\n \t\t\t      get_midx_checksum(m), MIDX_EXT_REV);\n \n-\tret = load_revindex_from_disk(revindex_name.buf,\n+\tret = load_revindex_from_disk(m->repo->hash_algo,\n+\t\t\t\t      revindex_name.buf,\n \t\t\t\t      m->num_objects,\n \t\t\t\t      &m->revindex_map,\n \t\t\t\t      &m->revindex_len);\n@@ -419,7 +425,7 @@ int offset_to_pack_pos(struct packed_git *p, off_t ofs, uint32_t *pos)\n {\n \tunsigned lo, hi;\n \n-\tif (load_pack_revindex(the_repository, p) < 0)\n+\tif (load_pack_revindex(p->repo, p) < 0)\n \t\treturn -1;\n \n \tlo = 0;\n@@ -465,7 +471,7 @@ off_t pack_pos_to_offset(struct packed_git *p, uint32_t pos)\n \tif (p->revindex)\n \t\treturn p->revindex[pos].offset;\n \telse if (pos == p->num_objects)\n-\t\treturn p->pack_size - the_hash_algo->rawsz;\n+\t\treturn p->pack_size - p->repo->hash_algo->rawsz;\n \telse\n \t\treturn nth_packed_object_offset(p, pack_pos_to_index(p, pos));\n }\n\n-- \n2.49.0.rc0.416.g627208d89d.dirty\n\n"},{"id":"513700","messageId":"20250306-b4-pks-objects-without-the-repository-v2-7-f3465327be69@pks.im","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","subject":"[PATCH v2 07/12] pack-bitmap-write: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T15:10:31Z","receivedAt":"2025-03-06T15:10:42Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"pack-bitmap-write.c\" where we use the\nglobal `the_repository` variable, either explicitly or implicitly by\nusing `the_hash_algo`.\n\nRefactor the code so that the `struct bitmap_writer` stores the\nrepository it is getting initialized with. Like this, we can adapt\ncallsites that use `the_repository` to instead use the repository\nprovided by the writer.\n\nRemove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n pack-bitmap-write.c | 36 ++++++++++++++++++------------------\n pack-bitmap.h       |  1 +\n 2 files changed, 19 insertions(+), 18 deletions(-)\n\ndiff --git a/pack-bitmap-write.c b/pack-bitmap-write.c\nindex 50e5c491ccb..6a97b52b36d 100644\n--- a/pack-bitmap-write.c\n+++ b/pack-bitmap-write.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -48,6 +47,7 @@ void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r,\n \tmemset(writer, 0, sizeof(struct bitmap_writer));\n \tif (writer->bitmaps)\n \t\tBUG(\"bitmap writer already initialized\");\n+\twriter->repo = r;\n \twriter->bitmaps = kh_init_oid_map();\n \twriter->pseudo_merge_commits = kh_init_oid_map();\n \twriter->to_pack = pdata;\n@@ -415,9 +415,9 @@ static void bitmap_builder_init(struct bitmap_builder *bb,\n \t\tbb->commits[bb->commits_nr++] = r->item;\n \t}\n \n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"num_selected_commits\", writer->selected_nr);\n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"num_maximal_commits\", num_maximal);\n \n \trelease_revisions(&revs);\n@@ -460,7 +460,7 @@ static int fill_bitmap_tree(struct bitmap_writer *writer,\n \t\tswitch (object_type(entry.mode)) {\n \t\tcase OBJ_TREE:\n \t\t\tif (fill_bitmap_tree(writer, bitmap,\n-\t\t\t\t\t     lookup_tree(the_repository, &entry.oid)) < 0)\n+\t\t\t\t\t     lookup_tree(writer->repo, &entry.oid)) < 0)\n \t\t\t\treturn -1;\n \t\t\tbreak;\n \t\tcase OBJ_BLOB:\n@@ -536,7 +536,7 @@ static int fill_bitmap_commit(struct bitmap_writer *writer,\n \t\t\t\treturn -1;\n \t\t\tbitmap_set(ent->bitmap, pos);\n \t\t\tprio_queue_put(tree_queue,\n-\t\t\t\t       repo_get_commit_tree(the_repository, c));\n+\t\t\t\t       repo_get_commit_tree(writer->repo, c));\n \t\t}\n \n \t\tfor (p = c->parents; p; p = p->next) {\n@@ -590,11 +590,11 @@ int bitmap_writer_build(struct bitmap_writer *writer)\n \tint closed = 1; /* until proven otherwise */\n \n \tif (writer->show_progress)\n-\t\twriter->progress = start_progress(the_repository,\n+\t\twriter->progress = start_progress(writer->repo,\n \t\t\t\t\t\t  \"Building bitmaps\",\n \t\t\t\t\t\t  writer->selected_nr);\n \ttrace2_region_enter(\"pack-bitmap-write\", \"building_bitmaps_total\",\n-\t\t\t    the_repository);\n+\t\t\t    writer->repo);\n \n \told_bitmap = prepare_bitmap_git(writer->to_pack->repo);\n \tif (old_bitmap)\n@@ -645,10 +645,10 @@ int bitmap_writer_build(struct bitmap_writer *writer)\n \tfree(mapping);\n \n \ttrace2_region_leave(\"pack-bitmap-write\", \"building_bitmaps_total\",\n-\t\t\t    the_repository);\n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\t\t\t    writer->repo);\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"building_bitmaps_reused\", reused_bitmaps_nr);\n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"building_bitmaps_pseudo_merge_reused\",\n \t\t\t   reused_pseudo_merge_bitmaps_nr);\n \n@@ -711,7 +711,7 @@ void bitmap_writer_select_commits(struct bitmap_writer *writer,\n \t}\n \n \tif (writer->show_progress)\n-\t\twriter->progress = start_progress(the_repository,\n+\t\twriter->progress = start_progress(writer->repo,\n \t\t\t\t\t\t  \"Selecting bitmap commits\", 0);\n \n \tfor (;;) {\n@@ -960,7 +960,7 @@ static void write_lookup_table(struct bitmap_writer *writer, struct hashfile *f,\n \tfor (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++)\n \t\ttable_inv[table[i]] = i;\n \n-\ttrace2_region_enter(\"pack-bitmap-write\", \"writing_lookup_table\", the_repository);\n+\ttrace2_region_enter(\"pack-bitmap-write\", \"writing_lookup_table\", writer->repo);\n \tfor (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) {\n \t\tstruct bitmapped_commit *selected = &writer->selected[table[i]];\n \t\tuint32_t xor_offset = selected->xor_offset;\n@@ -987,7 +987,7 @@ static void write_lookup_table(struct bitmap_writer *writer, struct hashfile *f,\n \t\thashwrite_be64(f, (uint64_t)offsets[table[i]]);\n \t\thashwrite_be32(f, xor_row);\n \t}\n-\ttrace2_region_leave(\"pack-bitmap-write\", \"writing_lookup_table\", the_repository);\n+\ttrace2_region_leave(\"pack-bitmap-write\", \"writing_lookup_table\", writer->repo);\n \n \tfree(table);\n \tfree(table_inv);\n@@ -1008,7 +1008,7 @@ static void write_hash_cache(struct hashfile *f,\n void bitmap_writer_set_checksum(struct bitmap_writer *writer,\n \t\t\t\tconst unsigned char *sha1)\n {\n-\thashcpy(writer->pack_checksum, sha1, the_repository->hash_algo);\n+\thashcpy(writer->pack_checksum, sha1, writer->repo->hash_algo);\n }\n \n void bitmap_writer_finish(struct bitmap_writer *writer,\n@@ -1030,15 +1030,15 @@ void bitmap_writer_finish(struct bitmap_writer *writer,\n \tif (writer->pseudo_merges_nr)\n \t\toptions |= BITMAP_OPT_PSEUDO_MERGES;\n \n-\tf = hashfd(the_repository->hash_algo, fd, tmp_file.buf);\n+\tf = hashfd(writer->repo->hash_algo, fd, tmp_file.buf);\n \n \tmemcpy(header.magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE));\n \theader.version = htons(default_version);\n \theader.options = htons(flags | options);\n \theader.entry_count = htonl(bitmap_writer_nr_selected_commits(writer));\n-\thashcpy(header.checksum, writer->pack_checksum, the_repository->hash_algo);\n+\thashcpy(header.checksum, writer->pack_checksum, writer->repo->hash_algo);\n \n-\thashwrite(f, &header, sizeof(header) - GIT_MAX_RAWSZ + the_hash_algo->rawsz);\n+\thashwrite(f, &header, sizeof(header) - GIT_MAX_RAWSZ + writer->repo->hash_algo->rawsz);\n \tdump_bitmap(f, writer->commits);\n \tdump_bitmap(f, writer->trees);\n \tdump_bitmap(f, writer->blobs);\n@@ -1072,7 +1072,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,\n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n \t\t\t  CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE);\n \n-\tif (adjust_shared_perm(the_repository, tmp_file.buf))\n+\tif (adjust_shared_perm(writer->repo, tmp_file.buf))\n \t\tdie_errno(\"unable to make temporary bitmap file readable\");\n \n \tif (rename(tmp_file.buf, filename))\ndiff --git a/pack-bitmap.h b/pack-bitmap.h\nindex d7f4b8b8e95..53cd42772f3 100644\n--- a/pack-bitmap.h\n+++ b/pack-bitmap.h\n@@ -104,6 +104,7 @@ int bitmap_has_oid_in_uninteresting(struct bitmap_index *, const struct object_i\n off_t get_disk_usage_from_bitmap(struct bitmap_index *, struct rev_info *);\n \n struct bitmap_writer {\n+\tstruct repository *repo;\n \tstruct ewah_bitmap *commits;\n \tstruct ewah_bitmap *trees;\n \tstruct ewah_bitmap *blobs;\n\n-- \n2.49.0.rc0.416.g627208d89d.dirty\n\n"},{"id":"513699","messageId":"20250306-b4-pks-objects-without-the-repository-v2-8-f3465327be69@pks.im","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","subject":"[PATCH v2 08/12] object-file-convert: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T15:10:32Z","receivedAt":"2025-03-06T15:10:43Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"object-file-convert.c\" where we use the\nglobal `the_repository` variable, either explicitly or implicitly by\nusing `the_hash_algo`. All of these callsites are transitively called\nfrom `convert_object_file()`, which indeed has no repo as input.\n\nRefactor the function so that it receives a repository as a parameter\nand pass it through to all internal functions to get rid of the\ndependency. Remove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/tag.c         |  2 +-\n commit.c              |  2 +-\n object-file-convert.c | 29 ++++++++++++++++-------------\n object-file-convert.h |  3 ++-\n object-file.c         |  7 ++++---\n 5 files changed, 24 insertions(+), 19 deletions(-)\n\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex d3e0943b734..7c173535cb3 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -172,7 +172,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,\n \tif (compat) {\n \t\tconst struct git_hash_algo *algo = the_repository->hash_algo;\n \n-\t\tif (convert_object_file(&compat_buf, algo, compat,\n+\t\tif (convert_object_file(the_repository ,&compat_buf, algo, compat,\n \t\t\t\t\tbuffer->buf, buffer->len, OBJ_TAG, 1))\n \t\t\tgoto out;\n \t\tif (sign_buffer(&compat_buf, &compat_sig, keyid))\ndiff --git a/commit.c b/commit.c\nindex 6efdb03997d..48aeefaad31 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1380,7 +1380,7 @@ static int convert_commit_extra_headers(const struct commit_extra_header *orig,\n \t\tstruct commit_extra_header *new;\n \t\tCALLOC_ARRAY(new, 1);\n \t\tif (!strcmp(orig->key, \"mergetag\")) {\n-\t\t\tif (convert_object_file(&out, algo, compat,\n+\t\t\tif (convert_object_file(the_repository, &out, algo, compat,\n \t\t\t\t\t\torig->value, orig->len,\n \t\t\t\t\t\tOBJ_TAG, 1)) {\n \t\t\t\tfree(new);\ndiff --git a/object-file-convert.c b/object-file-convert.c\nindex eba71955cf7..7ab875afe6c 100644\n--- a/object-file-convert.c\n+++ b/object-file-convert.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -63,7 +62,8 @@ static int decode_tree_entry_raw(struct object_id *oid, const char **path,\n \treturn 0;\n }\n \n-static int convert_tree_object(struct strbuf *out,\n+static int convert_tree_object(struct repository *repo,\n+\t\t\t       struct strbuf *out,\n \t\t\t       const struct git_hash_algo *from,\n \t\t\t       const struct git_hash_algo *to,\n \t\t\t       const char *buffer, size_t size)\n@@ -78,7 +78,7 @@ static int convert_tree_object(struct strbuf *out,\n \t\tif (decode_tree_entry_raw(&entry_oid, &path, &pathlen, from, p,\n \t\t\t\t\t  end - p))\n \t\t\treturn error(_(\"failed to decode tree entry\"));\n-\t\tif (repo_oid_to_algop(the_repository, &entry_oid, to, &mapped_oid))\n+\t\tif (repo_oid_to_algop(repo, &entry_oid, to, &mapped_oid))\n \t\t\treturn error(_(\"failed to map tree entry for %s\"), oid_to_hex(&entry_oid));\n \t\tstrbuf_add(out, p, path - p);\n \t\tstrbuf_add(out, path, pathlen);\n@@ -88,7 +88,8 @@ static int convert_tree_object(struct strbuf *out,\n \treturn 0;\n }\n \n-static int convert_tag_object(struct strbuf *out,\n+static int convert_tag_object(struct repository *repo,\n+\t\t\t      struct strbuf *out,\n \t\t\t      const struct git_hash_algo *from,\n \t\t\t      const struct git_hash_algo *to,\n \t\t\t      const char *buffer, size_t size)\n@@ -105,7 +106,7 @@ static int convert_tag_object(struct strbuf *out,\n \t\treturn error(\"bogus tag object\");\n \tif (parse_oid_hex_algop(buffer + 7, &oid, &p, from) < 0)\n \t\treturn error(\"bad tag object ID\");\n-\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n+\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n \t\treturn error(\"unable to map tree %s in tag object\",\n \t\t\t     oid_to_hex(&oid));\n \tsize -= ((p + 1) - buffer);\n@@ -139,7 +140,8 @@ static int convert_tag_object(struct strbuf *out,\n \treturn 0;\n }\n \n-static int convert_commit_object(struct strbuf *out,\n+static int convert_commit_object(struct repository *repo,\n+\t\t\t\t struct strbuf *out,\n \t\t\t\t const struct git_hash_algo *from,\n \t\t\t\t const struct git_hash_algo *to,\n \t\t\t\t const char *buffer, size_t size)\n@@ -165,7 +167,7 @@ static int convert_commit_object(struct strbuf *out,\n \t\t\t    (p != eol))\n \t\t\t\treturn error(_(\"bad %s in commit\"), \"tree\");\n \n-\t\t\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n+\t\t\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n \t\t\t\treturn error(_(\"unable to map %s %s in commit object\"),\n \t\t\t\t\t     \"tree\", oid_to_hex(&oid));\n \t\t\tstrbuf_addf(out, \"tree %s\\n\", oid_to_hex(&mapped_oid));\n@@ -177,7 +179,7 @@ static int convert_commit_object(struct strbuf *out,\n \t\t\t    (p != eol))\n \t\t\t\treturn error(_(\"bad %s in commit\"), \"parent\");\n \n-\t\t\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n+\t\t\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n \t\t\t\treturn error(_(\"unable to map %s %s in commit object\"),\n \t\t\t\t\t     \"parent\", oid_to_hex(&oid));\n \n@@ -202,7 +204,7 @@ static int convert_commit_object(struct strbuf *out,\n \t\t\t}\n \n \t\t\t/* Compute the new tag object */\n-\t\t\tif (convert_tag_object(&new_tag, from, to, tag.buf, tag.len)) {\n+\t\t\tif (convert_tag_object(repo, &new_tag, from, to, tag.buf, tag.len)) {\n \t\t\t\tstrbuf_release(&tag);\n \t\t\t\tstrbuf_release(&new_tag);\n \t\t\t\treturn -1;\n@@ -241,7 +243,8 @@ static int convert_commit_object(struct strbuf *out,\n \treturn 0;\n }\n \n-int convert_object_file(struct strbuf *outbuf,\n+int convert_object_file(struct repository *repo,\n+\t\t\tstruct strbuf *outbuf,\n \t\t\tconst struct git_hash_algo *from,\n \t\t\tconst struct git_hash_algo *to,\n \t\t\tconst void *buf, size_t len,\n@@ -256,13 +259,13 @@ int convert_object_file(struct strbuf *outbuf,\n \n \tswitch (type) {\n \tcase OBJ_COMMIT:\n-\t\tret = convert_commit_object(outbuf, from, to, buf, len);\n+\t\tret = convert_commit_object(repo, outbuf, from, to, buf, len);\n \t\tbreak;\n \tcase OBJ_TREE:\n-\t\tret = convert_tree_object(outbuf, from, to, buf, len);\n+\t\tret = convert_tree_object(repo, outbuf, from, to, buf, len);\n \t\tbreak;\n \tcase OBJ_TAG:\n-\t\tret = convert_tag_object(outbuf, from, to, buf, len);\n+\t\tret = convert_tag_object(repo, outbuf, from, to, buf, len);\n \t\tbreak;\n \tdefault:\n \t\t/* Not implemented yet, so fail. */\ndiff --git a/object-file-convert.h b/object-file-convert.h\nindex a4f802aa8ee..9b3cc5e533d 100644\n--- a/object-file-convert.h\n+++ b/object-file-convert.h\n@@ -14,7 +14,8 @@ int repo_oid_to_algop(struct repository *repo, const struct object_id *src,\n  * Convert an object file from one hash algorithm to another algorithm.\n  * Return -1 on failure, 0 on success.\n  */\n-int convert_object_file(struct strbuf *outbuf,\n+int convert_object_file(struct repository *repo,\n+\t\t\tstruct strbuf *outbuf,\n \t\t\tconst struct git_hash_algo *from,\n \t\t\tconst struct git_hash_algo *to,\n \t\t\tconst void *buf, size_t len,\ndiff --git a/object-file.c b/object-file.c\nindex b3e0276b2a4..b0e237a2acc 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1793,7 +1793,7 @@ static int oid_object_info_convert(struct repository *r,\n \t\tif (type == -1)\n \t\t\treturn -1;\n \t\tif (type != OBJ_BLOB) {\n-\t\t\tret = convert_object_file(&outbuf,\n+\t\t\tret = convert_object_file(the_repository, &outbuf,\n \t\t\t\t\t\t  the_hash_algo, input_algo,\n \t\t\t\t\t\t  content, size, type, !do_die);\n \t\t\tfree(content);\n@@ -2510,7 +2510,7 @@ int write_object_file_flags(const void *buf, unsigned long len,\n \t\t\thash_object_file(compat, buf, len, type, &compat_oid);\n \t\telse {\n \t\t\tstruct strbuf converted = STRBUF_INIT;\n-\t\t\tconvert_object_file(&converted, algo, compat,\n+\t\t\tconvert_object_file(the_repository, &converted, algo, compat,\n \t\t\t\t\t    buf, len, type, 0);\n \t\t\thash_object_file(compat, converted.buf, converted.len,\n \t\t\t\t\t type, &compat_oid);\n@@ -2550,7 +2550,8 @@ int write_object_file_literally(const void *buf, unsigned long len,\n \t\t\t\t\t &compat_oid);\n \t\telse if (compat_type != -1) {\n \t\t\tstruct strbuf converted = STRBUF_INIT;\n-\t\t\tconvert_object_file(&converted, algo, compat,\n+\t\t\tconvert_object_file(the_repository,\n+\t\t\t\t\t    &converted, algo, compat,\n \t\t\t\t\t    buf, len, compat_type, 0);\n \t\t\thash_object_file(compat, converted.buf, converted.len,\n \t\t\t\t\t compat_type, &compat_oid);\n\n-- \n2.49.0.rc0.416.g627208d89d.dirty\n\n"},{"id":"513701","messageId":"20250306-b4-pks-objects-without-the-repository-v2-9-f3465327be69@pks.im","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","subject":"[PATCH v2 09/12] delta-islands: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T15:10:33Z","receivedAt":"2025-03-06T15:10:43Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"delta-islands.c\" where we use the\nglobal `the_repository` variable, either explicitly or implicitly by\nusing `the_hash_algo`.\n\nRefactor the code to stop using `the_repository`. In most cases this is\ntrivial because we already had a repository available in the calling\ncontext, with the only exception being `propagate_island_marks()`. Adapt\nit so that the repository gets passed in via a parameter.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/pack-objects.c |  2 +-\n delta-islands.c        | 14 ++++++--------\n delta-islands.h        |  2 +-\n 3 files changed, 8 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex eefc6c78096..fba5db74656 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -3847,7 +3847,7 @@ static void show_commit(struct commit *commit, void *data UNUSED)\n \t\tindex_commit_for_bitmap(commit);\n \n \tif (use_delta_islands)\n-\t\tpropagate_island_marks(commit);\n+\t\tpropagate_island_marks(the_repository, commit);\n }\n \n static void show_object(struct object *obj, const char *name,\ndiff --git a/delta-islands.c b/delta-islands.c\nindex 3aec43fada3..36c94799d69 100644\n--- a/delta-islands.c\n+++ b/delta-islands.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -267,8 +266,7 @@ void resolve_tree_islands(struct repository *r,\n \tQSORT(todo, nr, tree_depth_compare);\n \n \tif (progress)\n-\t\tprogress_state = start_progress(the_repository,\n-\t\t\t\t\t\t_(\"Propagating island marks\"), nr);\n+\t\tprogress_state = start_progress(r, _(\"Propagating island marks\"), nr);\n \n \tfor (i = 0; i < nr; i++) {\n \t\tstruct object_entry *ent = todo[i].entry;\n@@ -490,9 +488,9 @@ void load_delta_islands(struct repository *r, int progress)\n \n \tisland_marks = kh_init_oid_map();\n \n-\tgit_config(island_config_callback, &ild);\n+\trepo_config(r, island_config_callback, &ild);\n \tild.remote_islands = kh_init_str();\n-\trefs_for_each_ref(get_main_ref_store(the_repository),\n+\trefs_for_each_ref(get_main_ref_store(r),\n \t\t\t  find_island_for_ref, &ild);\n \tfree_config_regexes(&ild);\n \tdeduplicate_islands(ild.remote_islands, r);\n@@ -502,7 +500,7 @@ void load_delta_islands(struct repository *r, int progress)\n \t\tfprintf(stderr, _(\"Marked %d islands, done.\\n\"), island_counter);\n }\n \n-void propagate_island_marks(struct commit *commit)\n+void propagate_island_marks(struct repository *r, struct commit *commit)\n {\n \tkhiter_t pos = kh_get_oid_map(island_marks, commit->object.oid);\n \n@@ -510,8 +508,8 @@ void propagate_island_marks(struct commit *commit)\n \t\tstruct commit_list *p;\n \t\tstruct island_bitmap *root_marks = kh_value(island_marks, pos);\n \n-\t\trepo_parse_commit(the_repository, commit);\n-\t\tset_island_marks(&repo_get_commit_tree(the_repository, commit)->object,\n+\t\trepo_parse_commit(r, commit);\n+\t\tset_island_marks(&repo_get_commit_tree(r, commit)->object,\n \t\t\t\t root_marks);\n \t\tfor (p = commit->parents; p; p = p->next)\n \t\t\tset_island_marks(&p->item->object, root_marks);\ndiff --git a/delta-islands.h b/delta-islands.h\nindex 8d1591ae28b..6107660306b 100644\n--- a/delta-islands.h\n+++ b/delta-islands.h\n@@ -12,7 +12,7 @@ void resolve_tree_islands(struct repository *r,\n \t\t\t  int progress,\n \t\t\t  struct packing_data *to_pack);\n void load_delta_islands(struct repository *r, int progress);\n-void propagate_island_marks(struct commit *commit);\n+void propagate_island_marks(struct repository *r, struct commit *commit);\n int compute_pack_layers(struct packing_data *to_pack);\n void free_island_marks(void);\n \n\n-- \n2.49.0.rc0.416.g627208d89d.dirty\n\n"},{"id":"513702","messageId":"20250306-b4-pks-objects-without-the-repository-v2-11-f3465327be69@pks.im","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","subject":"[PATCH v2 11/12] hash: fix \"-Wsign-compare\" warnings","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T15:10:35Z","receivedAt":"2025-03-06T15:10:44Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are a couple of trivial \"-Wsign-compare\" warnings in \"hash.c\". Fix\nthem.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n hash.c | 12 ++++--------\n hash.h |  2 +-\n 2 files changed, 5 insertions(+), 9 deletions(-)\n\ndiff --git a/hash.c b/hash.c\nindex dd5ac9d0eb2..4d9f98f72c2 100644\n--- a/hash.c\n+++ b/hash.c\n@@ -1,5 +1,4 @@\n #define USE_THE_REPOSITORY_VARIABLE\n-#define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n #include \"hash.h\"\n@@ -246,10 +245,9 @@ const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\n \n int hash_algo_by_name(const char *name)\n {\n-\tint i;\n \tif (!name)\n \t\treturn GIT_HASH_UNKNOWN;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\tfor (size_t i = 1; i < GIT_HASH_NALGOS; i++)\n \t\tif (!strcmp(name, hash_algos[i].name))\n \t\t\treturn i;\n \treturn GIT_HASH_UNKNOWN;\n@@ -257,17 +255,15 @@ int hash_algo_by_name(const char *name)\n \n int hash_algo_by_id(uint32_t format_id)\n {\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\tfor (size_t i = 1; i < GIT_HASH_NALGOS; i++)\n \t\tif (format_id == hash_algos[i].format_id)\n \t\t\treturn i;\n \treturn GIT_HASH_UNKNOWN;\n }\n \n-int hash_algo_by_length(int len)\n+int hash_algo_by_length(size_t len)\n {\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\tfor (size_t i = 1; i < GIT_HASH_NALGOS; i++)\n \t\tif (len == hash_algos[i].rawsz)\n \t\t\treturn i;\n \treturn GIT_HASH_UNKNOWN;\ndiff --git a/hash.h b/hash.h\nindex 4367acfec50..55d67ed83f3 100644\n--- a/hash.h\n+++ b/hash.h\n@@ -325,7 +325,7 @@ int hash_algo_by_name(const char *name);\n /* Identical, except based on the format ID. */\n int hash_algo_by_id(uint32_t format_id);\n /* Identical, except based on the length. */\n-int hash_algo_by_length(int len);\n+int hash_algo_by_length(size_t len);\n /* Identical, except for a pointer to struct git_hash_algo. */\n static inline int hash_algo_by_ptr(const struct git_hash_algo *p)\n {\n\n-- \n2.49.0.rc0.416.g627208d89d.dirty\n\n"},{"id":"513703","messageId":"20250306-b4-pks-objects-without-the-repository-v2-10-f3465327be69@pks.im","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","subject":"[PATCH v2 10/12] object-file: split out logic regarding hash algorithms","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T15:10:34Z","receivedAt":"2025-03-06T15:10:44Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"While we have a \"hash.h\" header, the actual implementation of the\nsubsystem is hosted by \"object-file.c\". This makes it harder than\nnecessary to find the actual implementation of the hash subsystem and\nintermingles the different concerns with one another.\n\nSplit out the implementation of hash algorithms into a new, separate\n\"hash.c\" file.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile      |   1 +\n hash.c        | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n meson.build   |   1 +\n object-file.c | 277 --------------------------------------------------------\n 4 files changed, 285 insertions(+), 277 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 6d45093089d..6dfe88322dd 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1041,6 +1041,7 @@ LIB_OBJS += gpg-interface.o\n LIB_OBJS += graph.o\n LIB_OBJS += grep.o\n LIB_OBJS += hash-lookup.o\n+LIB_OBJS += hash.o\n LIB_OBJS += hashmap.o\n LIB_OBJS += help.o\n LIB_OBJS += hex.o\ndiff --git a/hash.c b/hash.c\nnew file mode 100644\nindex 00000000000..dd5ac9d0eb2\n--- /dev/null\n+++ b/hash.c\n@@ -0,0 +1,283 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+#define DISABLE_SIGN_COMPARE_WARNINGS\n+\n+#include \"git-compat-util.h\"\n+#include \"hash.h\"\n+#include \"hex.h\"\n+\n+static const struct object_id empty_tree_oid = {\n+\t.hash = {\n+\t\t0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,\n+\t\t0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04\n+\t},\n+\t.algo = GIT_HASH_SHA1,\n+};\n+static const struct object_id empty_blob_oid = {\n+\t.hash = {\n+\t\t0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,\n+\t\t0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91\n+\t},\n+\t.algo = GIT_HASH_SHA1,\n+};\n+static const struct object_id null_oid_sha1 = {\n+\t.hash = {0},\n+\t.algo = GIT_HASH_SHA1,\n+};\n+static const struct object_id empty_tree_oid_sha256 = {\n+\t.hash = {\n+\t\t0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1,\n+\t\t0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5,\n+\t\t0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc,\n+\t\t0x53, 0x21\n+\t},\n+\t.algo = GIT_HASH_SHA256,\n+};\n+static const struct object_id empty_blob_oid_sha256 = {\n+\t.hash = {\n+\t\t0x47, 0x3a, 0x0f, 0x4c, 0x3b, 0xe8, 0xa9, 0x36, 0x81, 0xa2,\n+\t\t0x67, 0xe3, 0xb1, 0xe9, 0xa7, 0xdc, 0xda, 0x11, 0x85, 0x43,\n+\t\t0x6f, 0xe1, 0x41, 0xf7, 0x74, 0x91, 0x20, 0xa3, 0x03, 0x72,\n+\t\t0x18, 0x13\n+\t},\n+\t.algo = GIT_HASH_SHA256,\n+};\n+static const struct object_id null_oid_sha256 = {\n+\t.hash = {0},\n+\t.algo = GIT_HASH_SHA256,\n+};\n+\n+static void git_hash_sha1_init(struct git_hash_ctx *ctx)\n+{\n+\tctx->algop = &hash_algos[GIT_HASH_SHA1];\n+\tgit_SHA1_Init(&ctx->state.sha1);\n+}\n+\n+static void git_hash_sha1_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n+{\n+\tdst->algop = src->algop;\n+\tgit_SHA1_Clone(&dst->state.sha1, &src->state.sha1);\n+}\n+\n+static void git_hash_sha1_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n+{\n+\tgit_SHA1_Update(&ctx->state.sha1, data, len);\n+}\n+\n+static void git_hash_sha1_final(unsigned char *hash, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final(hash, &ctx->state.sha1);\n+}\n+\n+static void git_hash_sha1_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final(oid->hash, &ctx->state.sha1);\n+\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n+\toid->algo = GIT_HASH_SHA1;\n+}\n+\n+static void git_hash_sha1_init_unsafe(struct git_hash_ctx *ctx)\n+{\n+\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA1]);\n+\tgit_SHA1_Init_unsafe(&ctx->state.sha1_unsafe);\n+}\n+\n+static void git_hash_sha1_clone_unsafe(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n+{\n+\tdst->algop = src->algop;\n+\tgit_SHA1_Clone_unsafe(&dst->state.sha1_unsafe, &src->state.sha1_unsafe);\n+}\n+\n+static void git_hash_sha1_update_unsafe(struct git_hash_ctx *ctx, const void *data,\n+\t\t\t\t      size_t len)\n+{\n+\tgit_SHA1_Update_unsafe(&ctx->state.sha1_unsafe, data, len);\n+}\n+\n+static void git_hash_sha1_final_unsafe(unsigned char *hash, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final_unsafe(hash, &ctx->state.sha1_unsafe);\n+}\n+\n+static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final_unsafe(oid->hash, &ctx->state.sha1_unsafe);\n+\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n+\toid->algo = GIT_HASH_SHA1;\n+}\n+\n+static void git_hash_sha256_init(struct git_hash_ctx *ctx)\n+{\n+\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA256]);\n+\tgit_SHA256_Init(&ctx->state.sha256);\n+}\n+\n+static void git_hash_sha256_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n+{\n+\tdst->algop = src->algop;\n+\tgit_SHA256_Clone(&dst->state.sha256, &src->state.sha256);\n+}\n+\n+static void git_hash_sha256_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n+{\n+\tgit_SHA256_Update(&ctx->state.sha256, data, len);\n+}\n+\n+static void git_hash_sha256_final(unsigned char *hash, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA256_Final(hash, &ctx->state.sha256);\n+}\n+\n+static void git_hash_sha256_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA256_Final(oid->hash, &ctx->state.sha256);\n+\t/*\n+\t * This currently does nothing, so the compiler should optimize it out,\n+\t * but keep it in case we extend the hash size again.\n+\t */\n+\tmemset(oid->hash + GIT_SHA256_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA256_RAWSZ);\n+\toid->algo = GIT_HASH_SHA256;\n+}\n+\n+static void git_hash_unknown_init(struct git_hash_ctx *ctx UNUSED)\n+{\n+\tBUG(\"trying to init unknown hash\");\n+}\n+\n+static void git_hash_unknown_clone(struct git_hash_ctx *dst UNUSED,\n+\t\t\t\t   const struct git_hash_ctx *src UNUSED)\n+{\n+\tBUG(\"trying to clone unknown hash\");\n+}\n+\n+static void git_hash_unknown_update(struct git_hash_ctx *ctx UNUSED,\n+\t\t\t\t    const void *data UNUSED,\n+\t\t\t\t    size_t len UNUSED)\n+{\n+\tBUG(\"trying to update unknown hash\");\n+}\n+\n+static void git_hash_unknown_final(unsigned char *hash UNUSED,\n+\t\t\t\t   struct git_hash_ctx *ctx UNUSED)\n+{\n+\tBUG(\"trying to finalize unknown hash\");\n+}\n+\n+static void git_hash_unknown_final_oid(struct object_id *oid UNUSED,\n+\t\t\t\t       struct git_hash_ctx *ctx UNUSED)\n+{\n+\tBUG(\"trying to finalize unknown hash\");\n+}\n+\n+static const struct git_hash_algo sha1_unsafe_algo = {\n+\t.name = \"sha1\",\n+\t.format_id = GIT_SHA1_FORMAT_ID,\n+\t.rawsz = GIT_SHA1_RAWSZ,\n+\t.hexsz = GIT_SHA1_HEXSZ,\n+\t.blksz = GIT_SHA1_BLKSZ,\n+\t.init_fn = git_hash_sha1_init_unsafe,\n+\t.clone_fn = git_hash_sha1_clone_unsafe,\n+\t.update_fn = git_hash_sha1_update_unsafe,\n+\t.final_fn = git_hash_sha1_final_unsafe,\n+\t.final_oid_fn = git_hash_sha1_final_oid_unsafe,\n+\t.empty_tree = &empty_tree_oid,\n+\t.empty_blob = &empty_blob_oid,\n+\t.null_oid = &null_oid_sha1,\n+};\n+\n+const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n+\t{\n+\t\t.name = NULL,\n+\t\t.format_id = 0x00000000,\n+\t\t.rawsz = 0,\n+\t\t.hexsz = 0,\n+\t\t.blksz = 0,\n+\t\t.init_fn = git_hash_unknown_init,\n+\t\t.clone_fn = git_hash_unknown_clone,\n+\t\t.update_fn = git_hash_unknown_update,\n+\t\t.final_fn = git_hash_unknown_final,\n+\t\t.final_oid_fn = git_hash_unknown_final_oid,\n+\t\t.empty_tree = NULL,\n+\t\t.empty_blob = NULL,\n+\t\t.null_oid = NULL,\n+\t},\n+\t{\n+\t\t.name = \"sha1\",\n+\t\t.format_id = GIT_SHA1_FORMAT_ID,\n+\t\t.rawsz = GIT_SHA1_RAWSZ,\n+\t\t.hexsz = GIT_SHA1_HEXSZ,\n+\t\t.blksz = GIT_SHA1_BLKSZ,\n+\t\t.init_fn = git_hash_sha1_init,\n+\t\t.clone_fn = git_hash_sha1_clone,\n+\t\t.update_fn = git_hash_sha1_update,\n+\t\t.final_fn = git_hash_sha1_final,\n+\t\t.final_oid_fn = git_hash_sha1_final_oid,\n+\t\t.unsafe = &sha1_unsafe_algo,\n+\t\t.empty_tree = &empty_tree_oid,\n+\t\t.empty_blob = &empty_blob_oid,\n+\t\t.null_oid = &null_oid_sha1,\n+\t},\n+\t{\n+\t\t.name = \"sha256\",\n+\t\t.format_id = GIT_SHA256_FORMAT_ID,\n+\t\t.rawsz = GIT_SHA256_RAWSZ,\n+\t\t.hexsz = GIT_SHA256_HEXSZ,\n+\t\t.blksz = GIT_SHA256_BLKSZ,\n+\t\t.init_fn = git_hash_sha256_init,\n+\t\t.clone_fn = git_hash_sha256_clone,\n+\t\t.update_fn = git_hash_sha256_update,\n+\t\t.final_fn = git_hash_sha256_final,\n+\t\t.final_oid_fn = git_hash_sha256_final_oid,\n+\t\t.empty_tree = &empty_tree_oid_sha256,\n+\t\t.empty_blob = &empty_blob_oid_sha256,\n+\t\t.null_oid = &null_oid_sha256,\n+\t}\n+};\n+\n+const struct object_id *null_oid(void)\n+{\n+\treturn the_hash_algo->null_oid;\n+}\n+\n+const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\n+{\n+\tstatic char buf[GIT_MAX_HEXSZ + 1];\n+\treturn oid_to_hex_r(buf, algop->empty_tree);\n+}\n+\n+int hash_algo_by_name(const char *name)\n+{\n+\tint i;\n+\tif (!name)\n+\t\treturn GIT_HASH_UNKNOWN;\n+\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\t\tif (!strcmp(name, hash_algos[i].name))\n+\t\t\treturn i;\n+\treturn GIT_HASH_UNKNOWN;\n+}\n+\n+int hash_algo_by_id(uint32_t format_id)\n+{\n+\tint i;\n+\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\t\tif (format_id == hash_algos[i].format_id)\n+\t\t\treturn i;\n+\treturn GIT_HASH_UNKNOWN;\n+}\n+\n+int hash_algo_by_length(int len)\n+{\n+\tint i;\n+\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\t\tif (len == hash_algos[i].rawsz)\n+\t\t\treturn i;\n+\treturn GIT_HASH_UNKNOWN;\n+}\n+\n+const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop)\n+{\n+\t/* If we have a faster \"unsafe\" implementation, use that. */\n+\tif (algop->unsafe)\n+\t\treturn algop->unsafe;\n+\t/* Otherwise use the default one. */\n+\treturn algop;\n+}\ndiff --git a/meson.build b/meson.build\nindex 021a182135f..38568344953 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -311,6 +311,7 @@ libgit_sources = [\n   'graph.c',\n   'grep.c',\n   'hash-lookup.c',\n+  'hash.c',\n   'hashmap.c',\n   'help.c',\n   'hex.c',\ndiff --git a/object-file.c b/object-file.c\nindex b0e237a2acc..de603e2ca8c 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -45,283 +45,6 @@\n /* The maximum size for an object header. */\n #define MAX_HEADER_LEN 32\n \n-static const struct object_id empty_tree_oid = {\n-\t.hash = {\n-\t\t0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,\n-\t\t0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04\n-\t},\n-\t.algo = GIT_HASH_SHA1,\n-};\n-static const struct object_id empty_blob_oid = {\n-\t.hash = {\n-\t\t0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,\n-\t\t0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91\n-\t},\n-\t.algo = GIT_HASH_SHA1,\n-};\n-static const struct object_id null_oid_sha1 = {\n-\t.hash = {0},\n-\t.algo = GIT_HASH_SHA1,\n-};\n-static const struct object_id empty_tree_oid_sha256 = {\n-\t.hash = {\n-\t\t0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1,\n-\t\t0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5,\n-\t\t0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc,\n-\t\t0x53, 0x21\n-\t},\n-\t.algo = GIT_HASH_SHA256,\n-};\n-static const struct object_id empty_blob_oid_sha256 = {\n-\t.hash = {\n-\t\t0x47, 0x3a, 0x0f, 0x4c, 0x3b, 0xe8, 0xa9, 0x36, 0x81, 0xa2,\n-\t\t0x67, 0xe3, 0xb1, 0xe9, 0xa7, 0xdc, 0xda, 0x11, 0x85, 0x43,\n-\t\t0x6f, 0xe1, 0x41, 0xf7, 0x74, 0x91, 0x20, 0xa3, 0x03, 0x72,\n-\t\t0x18, 0x13\n-\t},\n-\t.algo = GIT_HASH_SHA256,\n-};\n-static const struct object_id null_oid_sha256 = {\n-\t.hash = {0},\n-\t.algo = GIT_HASH_SHA256,\n-};\n-\n-static void git_hash_sha1_init(struct git_hash_ctx *ctx)\n-{\n-\tctx->algop = &hash_algos[GIT_HASH_SHA1];\n-\tgit_SHA1_Init(&ctx->state.sha1);\n-}\n-\n-static void git_hash_sha1_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n-{\n-\tdst->algop = src->algop;\n-\tgit_SHA1_Clone(&dst->state.sha1, &src->state.sha1);\n-}\n-\n-static void git_hash_sha1_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n-{\n-\tgit_SHA1_Update(&ctx->state.sha1, data, len);\n-}\n-\n-static void git_hash_sha1_final(unsigned char *hash, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final(hash, &ctx->state.sha1);\n-}\n-\n-static void git_hash_sha1_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final(oid->hash, &ctx->state.sha1);\n-\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n-\toid->algo = GIT_HASH_SHA1;\n-}\n-\n-static void git_hash_sha1_init_unsafe(struct git_hash_ctx *ctx)\n-{\n-\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA1]);\n-\tgit_SHA1_Init_unsafe(&ctx->state.sha1_unsafe);\n-}\n-\n-static void git_hash_sha1_clone_unsafe(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n-{\n-\tdst->algop = src->algop;\n-\tgit_SHA1_Clone_unsafe(&dst->state.sha1_unsafe, &src->state.sha1_unsafe);\n-}\n-\n-static void git_hash_sha1_update_unsafe(struct git_hash_ctx *ctx, const void *data,\n-\t\t\t\t      size_t len)\n-{\n-\tgit_SHA1_Update_unsafe(&ctx->state.sha1_unsafe, data, len);\n-}\n-\n-static void git_hash_sha1_final_unsafe(unsigned char *hash, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final_unsafe(hash, &ctx->state.sha1_unsafe);\n-}\n-\n-static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final_unsafe(oid->hash, &ctx->state.sha1_unsafe);\n-\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n-\toid->algo = GIT_HASH_SHA1;\n-}\n-\n-static void git_hash_sha256_init(struct git_hash_ctx *ctx)\n-{\n-\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA256]);\n-\tgit_SHA256_Init(&ctx->state.sha256);\n-}\n-\n-static void git_hash_sha256_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n-{\n-\tdst->algop = src->algop;\n-\tgit_SHA256_Clone(&dst->state.sha256, &src->state.sha256);\n-}\n-\n-static void git_hash_sha256_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n-{\n-\tgit_SHA256_Update(&ctx->state.sha256, data, len);\n-}\n-\n-static void git_hash_sha256_final(unsigned char *hash, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA256_Final(hash, &ctx->state.sha256);\n-}\n-\n-static void git_hash_sha256_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA256_Final(oid->hash, &ctx->state.sha256);\n-\t/*\n-\t * This currently does nothing, so the compiler should optimize it out,\n-\t * but keep it in case we extend the hash size again.\n-\t */\n-\tmemset(oid->hash + GIT_SHA256_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA256_RAWSZ);\n-\toid->algo = GIT_HASH_SHA256;\n-}\n-\n-static void git_hash_unknown_init(struct git_hash_ctx *ctx UNUSED)\n-{\n-\tBUG(\"trying to init unknown hash\");\n-}\n-\n-static void git_hash_unknown_clone(struct git_hash_ctx *dst UNUSED,\n-\t\t\t\t   const struct git_hash_ctx *src UNUSED)\n-{\n-\tBUG(\"trying to clone unknown hash\");\n-}\n-\n-static void git_hash_unknown_update(struct git_hash_ctx *ctx UNUSED,\n-\t\t\t\t    const void *data UNUSED,\n-\t\t\t\t    size_t len UNUSED)\n-{\n-\tBUG(\"trying to update unknown hash\");\n-}\n-\n-static void git_hash_unknown_final(unsigned char *hash UNUSED,\n-\t\t\t\t   struct git_hash_ctx *ctx UNUSED)\n-{\n-\tBUG(\"trying to finalize unknown hash\");\n-}\n-\n-static void git_hash_unknown_final_oid(struct object_id *oid UNUSED,\n-\t\t\t\t       struct git_hash_ctx *ctx UNUSED)\n-{\n-\tBUG(\"trying to finalize unknown hash\");\n-}\n-\n-static const struct git_hash_algo sha1_unsafe_algo = {\n-\t.name = \"sha1\",\n-\t.format_id = GIT_SHA1_FORMAT_ID,\n-\t.rawsz = GIT_SHA1_RAWSZ,\n-\t.hexsz = GIT_SHA1_HEXSZ,\n-\t.blksz = GIT_SHA1_BLKSZ,\n-\t.init_fn = git_hash_sha1_init_unsafe,\n-\t.clone_fn = git_hash_sha1_clone_unsafe,\n-\t.update_fn = git_hash_sha1_update_unsafe,\n-\t.final_fn = git_hash_sha1_final_unsafe,\n-\t.final_oid_fn = git_hash_sha1_final_oid_unsafe,\n-\t.empty_tree = &empty_tree_oid,\n-\t.empty_blob = &empty_blob_oid,\n-\t.null_oid = &null_oid_sha1,\n-};\n-\n-const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n-\t{\n-\t\t.name = NULL,\n-\t\t.format_id = 0x00000000,\n-\t\t.rawsz = 0,\n-\t\t.hexsz = 0,\n-\t\t.blksz = 0,\n-\t\t.init_fn = git_hash_unknown_init,\n-\t\t.clone_fn = git_hash_unknown_clone,\n-\t\t.update_fn = git_hash_unknown_update,\n-\t\t.final_fn = git_hash_unknown_final,\n-\t\t.final_oid_fn = git_hash_unknown_final_oid,\n-\t\t.empty_tree = NULL,\n-\t\t.empty_blob = NULL,\n-\t\t.null_oid = NULL,\n-\t},\n-\t{\n-\t\t.name = \"sha1\",\n-\t\t.format_id = GIT_SHA1_FORMAT_ID,\n-\t\t.rawsz = GIT_SHA1_RAWSZ,\n-\t\t.hexsz = GIT_SHA1_HEXSZ,\n-\t\t.blksz = GIT_SHA1_BLKSZ,\n-\t\t.init_fn = git_hash_sha1_init,\n-\t\t.clone_fn = git_hash_sha1_clone,\n-\t\t.update_fn = git_hash_sha1_update,\n-\t\t.final_fn = git_hash_sha1_final,\n-\t\t.final_oid_fn = git_hash_sha1_final_oid,\n-\t\t.unsafe = &sha1_unsafe_algo,\n-\t\t.empty_tree = &empty_tree_oid,\n-\t\t.empty_blob = &empty_blob_oid,\n-\t\t.null_oid = &null_oid_sha1,\n-\t},\n-\t{\n-\t\t.name = \"sha256\",\n-\t\t.format_id = GIT_SHA256_FORMAT_ID,\n-\t\t.rawsz = GIT_SHA256_RAWSZ,\n-\t\t.hexsz = GIT_SHA256_HEXSZ,\n-\t\t.blksz = GIT_SHA256_BLKSZ,\n-\t\t.init_fn = git_hash_sha256_init,\n-\t\t.clone_fn = git_hash_sha256_clone,\n-\t\t.update_fn = git_hash_sha256_update,\n-\t\t.final_fn = git_hash_sha256_final,\n-\t\t.final_oid_fn = git_hash_sha256_final_oid,\n-\t\t.empty_tree = &empty_tree_oid_sha256,\n-\t\t.empty_blob = &empty_blob_oid_sha256,\n-\t\t.null_oid = &null_oid_sha256,\n-\t}\n-};\n-\n-const struct object_id *null_oid(void)\n-{\n-\treturn the_hash_algo->null_oid;\n-}\n-\n-const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\n-{\n-\tstatic char buf[GIT_MAX_HEXSZ + 1];\n-\treturn oid_to_hex_r(buf, algop->empty_tree);\n-}\n-\n-int hash_algo_by_name(const char *name)\n-{\n-\tint i;\n-\tif (!name)\n-\t\treturn GIT_HASH_UNKNOWN;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n-\t\tif (!strcmp(name, hash_algos[i].name))\n-\t\t\treturn i;\n-\treturn GIT_HASH_UNKNOWN;\n-}\n-\n-int hash_algo_by_id(uint32_t format_id)\n-{\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n-\t\tif (format_id == hash_algos[i].format_id)\n-\t\t\treturn i;\n-\treturn GIT_HASH_UNKNOWN;\n-}\n-\n-int hash_algo_by_length(int len)\n-{\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n-\t\tif (len == hash_algos[i].rawsz)\n-\t\t\treturn i;\n-\treturn GIT_HASH_UNKNOWN;\n-}\n-\n-const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop)\n-{\n-\t/* If we have a faster \"unsafe\" implementation, use that. */\n-\tif (algop->unsafe)\n-\t\treturn algop->unsafe;\n-\t/* Otherwise use the default one. */\n-\treturn algop;\n-}\n-\n /*\n  * This is meant to hold a *small* number of objects that you would\n  * want repo_read_object_file() to be able to return, but yet you do not want\n\n-- \n2.49.0.rc0.416.g627208d89d.dirty\n\n"},{"id":"513704","messageId":"20250306-b4-pks-objects-without-the-repository-v2-12-f3465327be69@pks.im","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","subject":"[PATCH v2 12/12] hash: stop depending on `the_repository` in `null_oid()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-06T15:10:36Z","receivedAt":"2025-03-06T15:10:45Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `null_oid()` function returns the object ID that only consists of\nzeroes. Naturally, this ID also depends on the hash algorithm used, as\nthe number of zeroes is different between SHA1 and SHA256. Consequently,\nthe function returns the hash-algorithm-specific null object ID.\n\nThis is currently done by depending on `the_hash_algo`, which implicitly\nmakes us depend on `the_repository`. Refactor the function to instead\npass in the hash algorithm for which we want to retrieve the null object\nID. Adapt callsites accordingly by passing in `the_repository`, thus\nbubbling up the dependency on that global variable by one layer.\n\nThere are a couple of trivial exceptions for subsystems that already got\nrid of `the_repository`. These subsystems instead use the repository\nthat is available via the calling context:\n\n  - \"builtin/grep.c\"\n  - \"grep.c\"\n  - \"refs/debug.c\"\n\nThere is also a single non-trivial exception with \"diff-no-index.c\".\nHere we know that we may not have a repository initialized at all, so we\ncannot rely on `the_repository`. Instead, we adapt `diff_no_index()` to\nget a `struct git_hash_algo` as parameter. The only caller is located in\n\"builtin/diff.c\", where we know to call `repo_set_hash_algo()` in case\nwe're running outside of a Git repository. Consequently, it is fine to\ncontinue passing `the_repository->hash_algo` even in this case.\n\nThis means that we could in theory just not bother about this edge case\nat all and just use `the_repository` in \"diff-no-index.c\". But doing so\nwould feel misdesigned.\n\nRemove the `USE_THE_REPOSITORY_VARIABLE` preprocessor define in\n\"hash.c\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n archive.c                                    |  2 +-\n blame.c                                      |  2 +-\n branch.c                                     |  2 +-\n builtin/checkout.c                           |  6 ++---\n builtin/clone.c                              |  2 +-\n builtin/describe.c                           |  2 +-\n builtin/diff.c                               |  5 ++--\n builtin/fast-export.c                        | 10 ++++----\n builtin/fsck.c                               |  2 +-\n builtin/grep.c                               |  2 +-\n builtin/ls-files.c                           |  2 +-\n builtin/rebase.c                             |  2 +-\n builtin/receive-pack.c                       |  2 +-\n builtin/submodule--helper.c                  | 36 ++++++++++++++--------------\n builtin/unpack-objects.c                     |  2 +-\n builtin/update-ref.c                         |  2 +-\n builtin/worktree.c                           |  2 +-\n combine-diff.c                               |  2 +-\n diff-lib.c                                   | 10 ++++----\n diff-no-index.c                              | 28 +++++++++++-----------\n diff.c                                       |  8 +++----\n diff.h                                       |  2 +-\n dir.c                                        |  2 +-\n grep.c                                       |  2 +-\n hash.c                                       |  6 ++---\n hash.h                                       |  2 +-\n log-tree.c                                   |  2 +-\n merge-ort.c                                  | 26 ++++++++++----------\n merge-recursive.c                            | 12 +++++-----\n notes-merge.c                                |  2 +-\n notes.c                                      |  2 +-\n object-file.c                                |  2 +-\n parse-options-cb.c                           |  2 +-\n range-diff.c                                 |  2 +-\n read-cache.c                                 |  2 +-\n refs.c                                       | 12 +++++-----\n refs/debug.c                                 |  2 +-\n refs/files-backend.c                         |  2 +-\n reset.c                                      |  2 +-\n sequencer.c                                  | 10 ++++----\n submodule-config.c                           |  2 +-\n submodule.c                                  | 28 +++++++++++-----------\n t/helper/test-ref-store.c                    |  2 +-\n t/helper/test-submodule-nested-repo-config.c |  2 +-\n tree-diff.c                                  |  4 ++--\n upload-pack.c                                |  2 +-\n wt-status.c                                  |  4 ++--\n xdiff-interface.c                            |  2 +-\n 48 files changed, 135 insertions(+), 136 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex f4331aeb49e..c95e3981524 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -312,7 +312,7 @@ int write_archive_entries(struct archiver_args *args,\n \tstruct object_id fake_oid;\n \tint i;\n \n-\toidcpy(&fake_oid, null_oid());\n+\toidcpy(&fake_oid, null_oid(the_hash_algo));\n \n \tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n \t\tsize_t len = args->baselen;\ndiff --git a/blame.c b/blame.c\nindex a15ddf93335..703dab43e78 100644\n--- a/blame.c\n+++ b/blame.c\n@@ -255,7 +255,7 @@ static struct commit *fake_working_tree_commit(struct repository *r,\n \t\tswitch (st.st_mode & S_IFMT) {\n \t\tcase S_IFREG:\n \t\t\tif (opt->flags.allow_textconv &&\n-\t\t\t    textconv_object(r, read_from, mode, null_oid(), 0, &buf_ptr, &buf_len))\n+\t\t\t    textconv_object(r, read_from, mode, null_oid(the_hash_algo), 0, &buf_ptr, &buf_len))\n \t\t\t\tstrbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1);\n \t\t\telse if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)\n \t\t\t\tdie_errno(\"cannot open or read '%s'\", read_from);\ndiff --git a/branch.c b/branch.c\nindex 91297d55ac9..6d01d7d6bdb 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -633,7 +633,7 @@ void create_branch(struct repository *r,\n \t\t\t\t\t\t  0, &err);\n \tif (!transaction ||\n \t\tref_transaction_update(transaction, ref.buf,\n-\t\t\t\t\t&oid, forcing ? NULL : null_oid(),\n+\t\t\t\t\t&oid, forcing ? NULL : null_oid(the_hash_algo),\n \t\t\t\t\tNULL, NULL, flags, msg, &err) ||\n \t\tref_transaction_commit(transaction, &err))\n \t\tdie(\"%s\", err.buf);\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 01ea9ff8b28..2e7486cf658 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -130,8 +130,8 @@ static int post_checkout_hook(struct commit *old_commit, struct commit *new_comm\n \t\t\t      int changed)\n {\n \treturn run_hooks_l(the_repository, \"post-checkout\",\n-\t\t\t   oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()),\n-\t\t\t   oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()),\n+\t\t\t   oid_to_hex(old_commit ? &old_commit->object.oid : null_oid(the_hash_algo)),\n+\t\t\t   oid_to_hex(new_commit ? &new_commit->object.oid : null_oid(the_hash_algo)),\n \t\t\t   changed ? \"1\" : \"0\", NULL);\n \t/* \"new_commit\" can be NULL when checking out from the index before\n \t   a commit exists. */\n@@ -710,7 +710,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,\n \topts.src_index = the_repository->index;\n \topts.dst_index = the_repository->index;\n \tinit_checkout_metadata(&opts.meta, info->refname,\n-\t\t\t       info->commit ? &info->commit->object.oid : null_oid(),\n+\t\t\t       info->commit ? &info->commit->object.oid : null_oid(the_hash_algo),\n \t\t\t       NULL);\n \tif (parse_tree(tree) < 0)\n \t\treturn 128;\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex f14229abf45..36aba65e06c 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -690,7 +690,7 @@ static int checkout(int submodule_progress, int filter_submodules,\n \tif (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))\n \t\tdie(_(\"unable to write new index file\"));\n \n-\terr |= run_hooks_l(the_repository, \"post-checkout\", oid_to_hex(null_oid()),\n+\terr |= run_hooks_l(the_repository, \"post-checkout\", oid_to_hex(null_oid(the_hash_algo)),\n \t\t\t   oid_to_hex(&oid), \"1\", NULL);\n \n \tif (!err && (option_recurse_submodules.nr > 0)) {\ndiff --git a/builtin/describe.c b/builtin/describe.c\nindex e2e73f3d757..23df333fd04 100644\n--- a/builtin/describe.c\n+++ b/builtin/describe.c\n@@ -518,7 +518,7 @@ static void describe_blob(struct object_id oid, struct strbuf *dst)\n {\n \tstruct rev_info revs;\n \tstruct strvec args = STRVEC_INIT;\n-\tstruct process_commit_data pcd = { *null_oid(), oid, dst, &revs};\n+\tstruct process_commit_data pcd = { *null_oid(the_hash_algo), oid, dst, &revs};\n \n \tstrvec_pushl(&args, \"internal: The first arg is not parsed\",\n \t\t     \"--objects\", \"--in-commit-order\", \"--reverse\", \"HEAD\",\ndiff --git a/builtin/diff.c b/builtin/diff.c\nindex a4fffee42c6..fa963808c31 100644\n--- a/builtin/diff.c\n+++ b/builtin/diff.c\n@@ -104,7 +104,7 @@ static void builtin_diff_b_f(struct rev_info *revs,\n \n \tstuff_change(&revs->diffopt,\n \t\t     blob[0]->mode, canon_mode(st.st_mode),\n-\t\t     &blob[0]->item->oid, null_oid(),\n+\t\t     &blob[0]->item->oid, null_oid(the_hash_algo),\n \t\t     1, 0,\n \t\t     blob[0]->path ? blob[0]->path : path,\n \t\t     path);\n@@ -498,7 +498,8 @@ int cmd_diff(int argc,\n \n \t/* If this is a no-index diff, just run it and exit there. */\n \tif (no_index)\n-\t\texit(diff_no_index(&rev, no_index == DIFF_NO_INDEX_IMPLICIT,\n+\t\texit(diff_no_index(&rev, the_repository->hash_algo,\n+\t\t\t\t   no_index == DIFF_NO_INDEX_IMPLICIT,\n \t\t\t\t   argc, argv));\n \n \ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex a5c82eef1de..7a5c2925cd2 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -869,7 +869,7 @@ static void handle_tag(const char *name, struct tag *tag)\n \t\t\t\tp = rewrite_commit((struct commit *)tagged);\n \t\t\t\tif (!p) {\n \t\t\t\t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\t\t       name, oid_to_hex(null_oid()));\n+\t\t\t\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t\t\t\t\tfree(buf);\n \t\t\t\t\treturn;\n \t\t\t\t}\n@@ -883,7 +883,7 @@ static void handle_tag(const char *name, struct tag *tag)\n \n \tif (tagged->type == OBJ_TAG) {\n \t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t       name, oid_to_hex(null_oid()));\n+\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t}\n \tskip_prefix(name, \"refs/tags/\", &name);\n \tprintf(\"tag %s\\n\", name);\n@@ -1023,7 +1023,7 @@ static void handle_tags_and_duplicates(struct string_list *extras)\n \t\t\t\t * it.\n \t\t\t\t */\n \t\t\t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\t       name, oid_to_hex(null_oid()));\n+\t\t\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t\t\t\tcontinue;\n \t\t\t}\n \n@@ -1042,7 +1042,7 @@ static void handle_tags_and_duplicates(struct string_list *extras)\n \t\t\t\tif (!reference_excluded_commits) {\n \t\t\t\t\t/* delete the ref */\n \t\t\t\t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\t\t       name, oid_to_hex(null_oid()));\n+\t\t\t\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t\t\t\t\tcontinue;\n \t\t\t\t}\n \t\t\t\t/* set ref to commit using oid, not mark */\n@@ -1153,7 +1153,7 @@ static void handle_deletes(void)\n \t\t\tcontinue;\n \n \t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\trefspec->dst, oid_to_hex(null_oid()));\n+\t\t\t\trefspec->dst, oid_to_hex(null_oid(the_hash_algo)));\n \t}\n }\n \ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex 62c7494bbda..f86ecd8eaa5 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -625,7 +625,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)\n \tvoid *contents = NULL;\n \tint eaten;\n \tstruct object_info oi = OBJECT_INFO_INIT;\n-\tstruct object_id real_oid = *null_oid();\n+\tstruct object_id real_oid = *null_oid(the_hash_algo);\n \tint err = 0;\n \n \tstrbuf_reset(&cb_data->obj_type);\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex cbbf6f26439..283d64cab80 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -453,7 +453,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t\treturn 0;\n \n \tsubrepo = xmalloc(sizeof(*subrepo));\n-\tif (repo_submodule_init(subrepo, superproject, path, null_oid())) {\n+\tif (repo_submodule_init(subrepo, superproject, path, null_oid(opt->repo->hash_algo))) {\n \t\tfree(subrepo);\n \t\treturn 0;\n \t}\ndiff --git a/builtin/ls-files.c b/builtin/ls-files.c\nindex a4431429b7d..2d2e90bc23a 100644\n--- a/builtin/ls-files.c\n+++ b/builtin/ls-files.c\n@@ -234,7 +234,7 @@ static void show_submodule(struct repository *superproject,\n {\n \tstruct repository subrepo;\n \n-\tif (repo_submodule_init(&subrepo, superproject, path, null_oid()))\n+\tif (repo_submodule_init(&subrepo, superproject, path, null_oid(the_hash_algo)))\n \t\treturn;\n \n \tif (repo_read_index(&subrepo) < 0)\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex d4715ed35d7..1cd802dd92a 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -925,7 +925,7 @@ static void fill_branch_base(struct rebase_options *options,\n \t\t\t\t options->orig_head, &merge_bases) < 0)\n \t\texit(128);\n \tif (!merge_bases || merge_bases->next)\n-\t\toidcpy(branch_base, null_oid());\n+\t\toidcpy(branch_base, null_oid(the_hash_algo));\n \telse\n \t\toidcpy(branch_base, &merge_bases->item->object.oid);\n \ndiff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\nindex 7b28fc9df6e..b3e2a9d0c60 100644\n--- a/builtin/receive-pack.c\n+++ b/builtin/receive-pack.c\n@@ -363,7 +363,7 @@ static void write_head_info(void)\n \tstrvec_clear(&excludes_vector);\n \n \tif (!sent_capabilities)\n-\t\tshow_ref(\"capabilities^{}\", null_oid());\n+\t\tshow_ref(\"capabilities^{}\", null_oid(the_hash_algo));\n \n \tadvertise_shallow_grafts(1);\n \ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex c1a8029714b..570226ea166 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -78,7 +78,7 @@ static int get_default_remote_submodule(const char *module_path, char **default_\n \tint ret;\n \n \tif (repo_submodule_init(&subrepo, the_repository, module_path,\n-\t\t\t\tnull_oid()) < 0)\n+\t\t\t\tnull_oid(the_hash_algo)) < 0)\n \t\treturn die_message(_(\"could not get a repository handle for submodule '%s'\"),\n \t\t\t\t   module_path);\n \tret = repo_get_default_remote(&subrepo, default_remote);\n@@ -308,7 +308,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,\n \tdisplaypath = get_submodule_displaypath(path, info->prefix,\n \t\t\t\t\t\tinfo->super_prefix);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n@@ -468,7 +468,7 @@ static void init_submodule(const char *path, const char *prefix,\n \n \tdisplaypath = get_submodule_displaypath(path, prefix, super_prefix);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n@@ -645,14 +645,14 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,\n \tif (validate_submodule_path(path) < 0)\n \t\texit(128);\n \n-\tif (!submodule_from_path(the_repository, null_oid(), path))\n+\tif (!submodule_from_path(the_repository, null_oid(the_hash_algo), path))\n \t\tdie(_(\"no submodule mapping found in .gitmodules for path '%s'\"),\n \t\t      path);\n \n \tdisplaypath = get_submodule_displaypath(path, prefix, super_prefix);\n \n \tif ((CE_STAGEMASK & ce_flags) >> CE_STAGESHIFT) {\n-\t\tprint_status(flags, 'U', path, null_oid(), displaypath);\n+\t\tprint_status(flags, 'U', path, null_oid(the_hash_algo), displaypath);\n \t\tgoto cleanup;\n \t}\n \n@@ -912,7 +912,7 @@ static void generate_submodule_summary(struct summary_cb *info,\n \tstruct strbuf errmsg = STRBUF_INIT;\n \tint total_commits = -1;\n \n-\tif (!info->cached && oideq(&p->oid_dst, null_oid())) {\n+\tif (!info->cached && oideq(&p->oid_dst, null_oid(the_hash_algo))) {\n \t\tif (S_ISGITLINK(p->mod_dst)) {\n \t\t\tstruct ref_store *refs = repo_get_submodule_ref_store(the_repository,\n \t\t\t\t\t\t\t\t\t      p->sm_path);\n@@ -1051,7 +1051,7 @@ static void prepare_submodule_summary(struct summary_cb *info,\n \n \t\tif (info->for_status && p->status != 'A' &&\n \t\t    (sub = submodule_from_path(the_repository,\n-\t\t\t\t\t       null_oid(), p->sm_path))) {\n+\t\t\t\t\t       null_oid(the_hash_algo), p->sm_path))) {\n \t\t\tchar *config_key = NULL;\n \t\t\tconst char *value;\n \t\t\tint ignore_all = 0;\n@@ -1259,7 +1259,7 @@ static void sync_submodule(const char *path, const char *prefix,\n \tif (validate_submodule_path(path) < 0)\n \t\texit(128);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (sub && sub->url) {\n \t\tif (starts_with_dot_dot_slash(sub->url) ||\n@@ -1404,7 +1404,7 @@ static void deinit_submodule(const char *path, const char *prefix,\n \tif (validate_submodule_path(path) < 0)\n \t\texit(128);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub || !sub->name)\n \t\tgoto cleanup;\n@@ -1929,7 +1929,7 @@ static int determine_submodule_update_strategy(struct repository *r,\n \t\t\t\t\t       enum submodule_update_type update,\n \t\t\t\t\t       struct submodule_update_strategy *out)\n {\n-\tconst struct submodule *sub = submodule_from_path(r, null_oid(), path);\n+\tconst struct submodule *sub = submodule_from_path(r, null_oid(the_hash_algo), path);\n \tchar *key;\n \tconst char *val;\n \tint ret;\n@@ -2089,7 +2089,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\tgoto cleanup;\n \t}\n \n-\tsub = submodule_from_path(the_repository, null_oid(), ce->name);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), ce->name);\n \n \tif (!sub) {\n \t\tnext_submodule_warn_missing(suc, out, displaypath);\n@@ -2485,7 +2485,7 @@ static int remote_submodule_branch(const char *path, const char **branch)\n \tchar *key;\n \t*branch = NULL;\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \tif (!sub)\n \t\treturn die_message(_(\"could not initialize submodule at path '%s'\"),\n \t\t\t\t   path);\n@@ -2531,7 +2531,7 @@ static int ensure_core_worktree(const char *path)\n \tconst char *cw;\n \tstruct repository subrepo;\n \n-\tif (repo_submodule_init(&subrepo, the_repository, path, null_oid()))\n+\tif (repo_submodule_init(&subrepo, the_repository, path, null_oid(the_hash_algo)))\n \t\treturn die_message(_(\"could not get a repository handle for submodule '%s'\"),\n \t\t\t\t   path);\n \n@@ -2644,7 +2644,7 @@ static int update_submodule(struct update_data *update_data)\n \t\treturn ret;\n \n \tif (update_data->just_cloned)\n-\t\toidcpy(&update_data->suboid, null_oid());\n+\t\toidcpy(&update_data->suboid, null_oid(the_hash_algo));\n \telse if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path,\n \t\t\t\t\t  \"HEAD\", &update_data->suboid))\n \t\treturn die_message(_(\"Unable to find current revision in submodule path '%s'\"),\n@@ -2697,8 +2697,8 @@ static int update_submodule(struct update_data *update_data)\n \t\tstruct update_data next = *update_data;\n \n \t\tnext.prefix = NULL;\n-\t\toidcpy(&next.oid, null_oid());\n-\t\toidcpy(&next.suboid, null_oid());\n+\t\toidcpy(&next.oid, null_oid(the_hash_algo));\n+\t\toidcpy(&next.suboid, null_oid(the_hash_algo));\n \n \t\tcp.dir = update_data->sm_path;\n \t\tcp.git_cmd = 1;\n@@ -3057,7 +3057,7 @@ static int module_set_url(int argc, const char **argv, const char *prefix,\n \tif (argc != 2 || !(path = argv[0]) || !(newurl = argv[1]))\n \t\tusage_with_options(usage, options);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"no submodule mapping found in .gitmodules for path '%s'\"),\n@@ -3113,7 +3113,7 @@ static int module_set_branch(int argc, const char **argv, const char *prefix,\n \tif (argc != 1 || !(path = argv[0]))\n \t\tusage_with_options(usage, options);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"no submodule mapping found in .gitmodules for path '%s'\"),\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex e20c120913e..73d431a0dde 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -505,7 +505,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,\n \t\t\t * has not been resolved yet.\n \t\t\t */\n \t\t\toidclr(&obj_list[nr].oid, the_repository->hash_algo);\n-\t\t\tadd_delta_to_list(nr, null_oid(), base_offset,\n+\t\t\tadd_delta_to_list(nr, null_oid(the_hash_algo), base_offset,\n \t\t\t\t\t  delta_data, delta_size);\n \t\t\treturn;\n \t\t}\ndiff --git a/builtin/update-ref.c b/builtin/update-ref.c\nindex 4d35bdc4b4b..3796b9844d1 100644\n--- a/builtin/update-ref.c\n+++ b/builtin/update-ref.c\n@@ -500,7 +500,7 @@ static void parse_cmd_symref_verify(struct ref_transaction *transaction,\n \t */\n \told_target = parse_next_refname(&next);\n \tif (!old_target)\n-\t\toidcpy(&old_oid, null_oid());\n+\t\toidcpy(&old_oid, null_oid(the_hash_algo));\n \n \tif (*next != line_termination)\n \t\tdie(\"symref-verify %s: extra input: %s\", refname, next);\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 48448a83550..87ccd47794c 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -578,7 +578,7 @@ static int add_worktree(const char *path, const char *refname,\n \n \t\tstrvec_pushl(&opt.env, \"GIT_DIR\", \"GIT_WORK_TREE\", NULL);\n \t\tstrvec_pushl(&opt.args,\n-\t\t\t     oid_to_hex(null_oid()),\n+\t\t\t     oid_to_hex(null_oid(the_hash_algo)),\n \t\t\t     oid_to_hex(&commit->object.oid),\n \t\t\t     \"1\",\n \t\t\t     NULL);\ndiff --git a/combine-diff.c b/combine-diff.c\nindex 9527f3160d8..553bf59fed6 100644\n--- a/combine-diff.c\n+++ b/combine-diff.c\n@@ -1066,7 +1066,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,\n \t\t\t\t\t\t   &result_size, NULL, NULL);\n \t\t} else if (textconv) {\n \t\t\tstruct diff_filespec *df = alloc_filespec(elem->path);\n-\t\t\tfill_filespec(df, null_oid(), 0, st.st_mode);\n+\t\t\tfill_filespec(df, null_oid(the_hash_algo), 0, st.st_mode);\n \t\t\tresult_size = fill_textconv(opt->repo, textconv, df, &result);\n \t\t\tfree_filespec(df);\n \t\t} else if (0 <= (fd = open(elem->path, O_RDONLY))) {\ndiff --git a/diff-lib.c b/diff-lib.c\nindex 353b473ed52..244468dd1a2 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -172,7 +172,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t\t * these from (stage - 2).\n \t\t\t */\n \t\t\tdpath = combine_diff_path_new(ce->name, ce_namelen(ce),\n-\t\t\t\t\t\t      wt_mode, null_oid(), 2);\n+\t\t\t\t\t\t      wt_mode, null_oid(the_hash_algo), 2);\n \n \t\t\twhile (i < entries) {\n \t\t\t\tstruct cache_entry *nce = istate->cache[i];\n@@ -257,7 +257,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t\t\t   ce_intent_to_add(ce)) {\n \t\t\t\tnewmode = ce_mode_from_stat(ce, st.st_mode);\n \t\t\t\tdiff_addremove(&revs->diffopt, '+', newmode,\n-\t\t\t\t\t       null_oid(), 0, ce->name, 0);\n+\t\t\t\t\t       null_oid(the_hash_algo), 0, ce->name, 0);\n \t\t\t\tcontinue;\n \t\t\t}\n \n@@ -274,7 +274,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t}\n \t\toldmode = ce->ce_mode;\n \t\told_oid = &ce->oid;\n-\t\tnew_oid = changed ? null_oid() : &ce->oid;\n+\t\tnew_oid = changed ? null_oid(the_hash_algo) : &ce->oid;\n \t\tdiff_change(&revs->diffopt, oldmode, newmode,\n \t\t\t    old_oid, new_oid,\n \t\t\t    !is_null_oid(old_oid),\n@@ -330,7 +330,7 @@ static int get_stat_data(const struct cache_entry *ce,\n \t\t\t\t\t\t    0, dirty_submodule);\n \t\tif (changed) {\n \t\t\tmode = ce_mode_from_stat(ce, st.st_mode);\n-\t\t\toid = null_oid();\n+\t\t\toid = null_oid(the_hash_algo);\n \t\t}\n \t}\n \n@@ -402,7 +402,7 @@ static int show_modified(struct rev_info *revs,\n \n \t\tp = combine_diff_path_new(new_entry->name,\n \t\t\t\t\t  ce_namelen(new_entry),\n-\t\t\t\t\t  mode, null_oid(), 2);\n+\t\t\t\t\t  mode, null_oid(the_hash_algo), 2);\n \t\tp->parent[0].status = DIFF_STATUS_MODIFIED;\n \t\tp->parent[0].mode = new_entry->ce_mode;\n \t\toidcpy(&p->parent[0].oid, &new_entry->oid);\ndiff --git a/diff-no-index.c b/diff-no-index.c\nindex 6f277892d3a..9739b2b268b 100644\n--- a/diff-no-index.c\n+++ b/diff-no-index.c\n@@ -113,7 +113,8 @@ static void populate_from_stdin(struct diff_filespec *s)\n \tpopulate_common(s, &buf);\n }\n \n-static struct diff_filespec *noindex_filespec(const char *name, int mode,\n+static struct diff_filespec *noindex_filespec(const struct git_hash_algo *algop,\n+\t\t\t\t\t      const char *name, int mode,\n \t\t\t\t\t      enum special special)\n {\n \tstruct diff_filespec *s;\n@@ -121,7 +122,7 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode,\n \tif (!name)\n \t\tname = \"/dev/null\";\n \ts = alloc_filespec(name);\n-\tfill_filespec(s, null_oid(), 0, mode);\n+\tfill_filespec(s, null_oid(algop), 0, mode);\n \tif (special == SPECIAL_STDIN)\n \t\tpopulate_from_stdin(s);\n \telse if (special == SPECIAL_PIPE)\n@@ -129,7 +130,7 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode,\n \treturn s;\n }\n \n-static int queue_diff(struct diff_options *o,\n+static int queue_diff(struct diff_options *o, const struct git_hash_algo *algop,\n \t\t      const char *name1, const char *name2, int recursing)\n {\n \tint mode1 = 0, mode2 = 0;\n@@ -145,14 +146,14 @@ static int queue_diff(struct diff_options *o,\n \n \t\tif (S_ISDIR(mode1)) {\n \t\t\t/* 2 is file that is created */\n-\t\t\td1 = noindex_filespec(NULL, 0, SPECIAL_NONE);\n-\t\t\td2 = noindex_filespec(name2, mode2, special2);\n+\t\t\td1 = noindex_filespec(algop, NULL, 0, SPECIAL_NONE);\n+\t\t\td2 = noindex_filespec(algop, name2, mode2, special2);\n \t\t\tname2 = NULL;\n \t\t\tmode2 = 0;\n \t\t} else {\n \t\t\t/* 1 is file that is deleted */\n-\t\t\td1 = noindex_filespec(name1, mode1, special1);\n-\t\t\td2 = noindex_filespec(NULL, 0, SPECIAL_NONE);\n+\t\t\td1 = noindex_filespec(algop, name1, mode1, special1);\n+\t\t\td2 = noindex_filespec(algop, NULL, 0, SPECIAL_NONE);\n \t\t\tname1 = NULL;\n \t\t\tmode1 = 0;\n \t\t}\n@@ -217,7 +218,7 @@ static int queue_diff(struct diff_options *o,\n \t\t\t\tn2 = buffer2.buf;\n \t\t\t}\n \n-\t\t\tret = queue_diff(o, n1, n2, 1);\n+\t\t\tret = queue_diff(o, algop, n1, n2, 1);\n \t\t}\n \t\tstring_list_clear(&p1, 0);\n \t\tstring_list_clear(&p2, 0);\n@@ -234,8 +235,8 @@ static int queue_diff(struct diff_options *o,\n \t\t\tSWAP(special1, special2);\n \t\t}\n \n-\t\td1 = noindex_filespec(name1, mode1, special1);\n-\t\td2 = noindex_filespec(name2, mode2, special2);\n+\t\td1 = noindex_filespec(algop, name1, mode1, special1);\n+\t\td2 = noindex_filespec(algop, name2, mode2, special2);\n \t\tdiff_queue(&diff_queued_diff, d1, d2);\n \t\treturn 0;\n \t}\n@@ -297,9 +298,8 @@ static const char * const diff_no_index_usage[] = {\n \tNULL\n };\n \n-int diff_no_index(struct rev_info *revs,\n-\t\t  int implicit_no_index,\n-\t\t  int argc, const char **argv)\n+int diff_no_index(struct rev_info *revs, const struct git_hash_algo *algop,\n+\t\t  int implicit_no_index, int argc, const char **argv)\n {\n \tint i, no_index;\n \tint ret = 1;\n@@ -354,7 +354,7 @@ int diff_no_index(struct rev_info *revs,\n \tsetup_diff_pager(&revs->diffopt);\n \trevs->diffopt.flags.exit_with_status = 1;\n \n-\tif (queue_diff(&revs->diffopt, paths[0], paths[1], 0))\n+\tif (queue_diff(&revs->diffopt, algop, paths[0], paths[1], 0))\n \t\tgoto out;\n \tdiff_set_mnemonic_prefix(&revs->diffopt, \"1/\", \"2/\");\n \tdiffcore_std(&revs->diffopt);\ndiff --git a/diff.c b/diff.c\nindex 4f802b4251c..4ce5933a442 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -4346,7 +4346,7 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r,\n \t\t\t\tdie_errno(\"readlink(%s)\", one->path);\n \t\t\tprep_temp_blob(r->index, one->path, temp, sb.buf, sb.len,\n \t\t\t\t       (one->oid_valid ?\n-\t\t\t\t\t&one->oid : null_oid()),\n+\t\t\t\t\t&one->oid : null_oid(the_hash_algo)),\n \t\t\t\t       (one->oid_valid ?\n \t\t\t\t\tone->mode : S_IFLNK));\n \t\t\tstrbuf_release(&sb);\n@@ -4355,7 +4355,7 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r,\n \t\t\t/* we can borrow from the file in the work tree */\n \t\t\ttemp->name = one->path;\n \t\t\tif (!one->oid_valid)\n-\t\t\t\toid_to_hex_r(temp->hex, null_oid());\n+\t\t\t\toid_to_hex_r(temp->hex, null_oid(the_hash_algo));\n \t\t\telse\n \t\t\t\toid_to_hex_r(temp->hex, &one->oid);\n \t\t\t/* Even though we may sometimes borrow the\n@@ -6649,8 +6649,8 @@ static void create_filepairs_for_header_only_notifications(struct diff_options *\n \n \t\t\tone = alloc_filespec(e->key);\n \t\t\ttwo = alloc_filespec(e->key);\n-\t\t\tfill_filespec(one, null_oid(), 0, 0);\n-\t\t\tfill_filespec(two, null_oid(), 0, 0);\n+\t\t\tfill_filespec(one, null_oid(the_hash_algo), 0, 0);\n+\t\t\tfill_filespec(two, null_oid(the_hash_algo), 0, 0);\n \t\t\tp = diff_queue(q, one, two);\n \t\t\tp->status = DIFF_STATUS_MODIFIED;\n \t\t}\ndiff --git a/diff.h b/diff.h\nindex 0a566f5531a..0822111c62a 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -656,7 +656,7 @@ void flush_one_hunk(struct object_id *result, struct git_hash_ctx *ctx);\n \n int diff_result_code(struct rev_info *);\n \n-int diff_no_index(struct rev_info *,\n+int diff_no_index(struct rev_info *, const struct git_hash_algo *algop,\n \t\t  int implicit_no_index, int, const char **);\n \n int index_differs_from(struct repository *r, const char *def,\ndiff --git a/dir.c b/dir.c\nindex cbd82be6c91..28b0e03feb4 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -4035,7 +4035,7 @@ static void connect_wt_gitdir_in_nested(const char *sub_worktree,\n \t\t\t */\n \t\t\ti++;\n \n-\t\tsub = submodule_from_path(&subrepo, null_oid(), ce->name);\n+\t\tsub = submodule_from_path(&subrepo, null_oid(the_hash_algo), ce->name);\n \t\tif (!sub || !is_submodule_active(&subrepo, ce->name))\n \t\t\t/* .gitmodules broken or inactive sub */\n \t\t\tcontinue;\ndiff --git a/grep.c b/grep.c\nindex 4e155ee9e66..9284b5741f5 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -1517,7 +1517,7 @@ static int fill_textconv_grep(struct repository *r,\n \t\tfill_filespec(df, gs->identifier, 1, 0100644);\n \t\tbreak;\n \tcase GREP_SOURCE_FILE:\n-\t\tfill_filespec(df, null_oid(), 0, 0100644);\n+\t\tfill_filespec(df, null_oid(r->hash_algo), 0, 0100644);\n \t\tbreak;\n \tdefault:\n \t\tBUG(\"attempt to textconv something without a path?\");\ndiff --git a/hash.c b/hash.c\nindex 4d9f98f72c2..4a04ecb50e8 100644\n--- a/hash.c\n+++ b/hash.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"hash.h\"\n #include \"hex.h\"\n@@ -232,9 +230,9 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n \t}\n };\n \n-const struct object_id *null_oid(void)\n+const struct object_id *null_oid(const struct git_hash_algo *algop)\n {\n-\treturn the_hash_algo->null_oid;\n+\treturn algop->null_oid;\n }\n \n const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\ndiff --git a/hash.h b/hash.h\nindex 55d67ed83f3..a9ef76fc8e7 100644\n--- a/hash.h\n+++ b/hash.h\n@@ -340,7 +340,7 @@ static inline int hash_algo_by_ptr(const struct git_hash_algo *p)\n \n const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop);\n \n-const struct object_id *null_oid(void);\n+const struct object_id *null_oid(const struct git_hash_algo *algop);\n \n static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)\n {\ndiff --git a/log-tree.c b/log-tree.c\nindex 8b184d67763..5dd1b63076f 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -499,7 +499,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,\n {\n \tstruct strbuf headers = STRBUF_INIT;\n \tconst char *name = oid_to_hex(opt->zero_commit ?\n-\t\t\t\t      null_oid() : &commit->object.oid);\n+\t\t\t\t      null_oid(the_hash_algo) : &commit->object.oid);\n \n \t*need_8bit_cte_p = 0; /* unknown */\n \ndiff --git a/merge-ort.c b/merge-ort.c\nindex 46e78c3ffa6..eb3a834652a 100644\n--- a/merge-ort.c\n+++ b/merge-ort.c\n@@ -1817,7 +1817,7 @@ static int merge_submodule(struct merge_options *opt,\n \t\tBUG(\"submodule deleted on one side; this should be handled outside of merge_submodule()\");\n \n \tif ((sub_not_initialized = repo_submodule_init(&subrepo,\n-\t\topt->repo, path, null_oid()))) {\n+\t\topt->repo, path, null_oid(the_hash_algo)))) {\n \t\tpath_msg(opt, CONFLICT_SUBMODULE_NOT_INITIALIZED, 0,\n \t\t\t path, NULL, NULL, NULL,\n \t\t\t _(\"Failed to merge submodule %s (not checked out)\"),\n@@ -2199,7 +2199,7 @@ static int handle_content_merge(struct merge_options *opt,\n \t\ttwo_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));\n \n \t\tmerge_status = merge_3way(opt, path,\n-\t\t\t\t\t  two_way ? null_oid() : &o->oid,\n+\t\t\t\t\t  two_way ? null_oid(the_hash_algo) : &o->oid,\n \t\t\t\t\t  &a->oid, &b->oid,\n \t\t\t\t\t  pathnames, extra_marker_size,\n \t\t\t\t\t  &result_buf);\n@@ -2231,7 +2231,7 @@ static int handle_content_merge(struct merge_options *opt,\n \t} else if (S_ISGITLINK(a->mode)) {\n \t\tint two_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));\n \t\tclean = merge_submodule(opt, pathnames[0],\n-\t\t\t\t\ttwo_way ? null_oid() : &o->oid,\n+\t\t\t\t\ttwo_way ? null_oid(the_hash_algo) : &o->oid,\n \t\t\t\t\t&a->oid, &b->oid, &result->oid);\n \t\tif (clean < 0)\n \t\t\treturn -1;\n@@ -2739,7 +2739,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt,\n \t\tassert(!new_ci->match_mask);\n \t\tnew_ci->dirmask = 0;\n \t\tnew_ci->stages[1].mode = 0;\n-\t\toidcpy(&new_ci->stages[1].oid, null_oid());\n+\t\toidcpy(&new_ci->stages[1].oid, null_oid(the_hash_algo));\n \n \t\t/*\n \t\t * Now that we have the file information in new_ci, make sure\n@@ -2752,7 +2752,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt,\n \t\t\t\tcontinue;\n \t\t\t/* zero out any entries related to files */\n \t\t\tci->stages[i].mode = 0;\n-\t\t\toidcpy(&ci->stages[i].oid, null_oid());\n+\t\t\toidcpy(&ci->stages[i].oid, null_oid(the_hash_algo));\n \t\t}\n \n \t\t/* Now we want to focus on new_ci, so reassign ci to it. */\n@@ -3122,7 +3122,7 @@ static int process_renames(struct merge_options *opt,\n \t\t\tif (type_changed) {\n \t\t\t\t/* rename vs. typechange */\n \t\t\t\t/* Mark the original as resolved by removal */\n-\t\t\t\tmemcpy(&oldinfo->stages[0].oid, null_oid(),\n+\t\t\t\tmemcpy(&oldinfo->stages[0].oid, null_oid(the_hash_algo),\n \t\t\t\t       sizeof(oldinfo->stages[0].oid));\n \t\t\t\toldinfo->stages[0].mode = 0;\n \t\t\t\toldinfo->filemask &= 0x06;\n@@ -3994,7 +3994,7 @@ static int process_entry(struct merge_options *opt,\n \t\t\tif (ci->filemask & (1 << i))\n \t\t\t\tcontinue;\n \t\t\tci->stages[i].mode = 0;\n-\t\t\toidcpy(&ci->stages[i].oid, null_oid());\n+\t\t\toidcpy(&ci->stages[i].oid, null_oid(the_hash_algo));\n \t\t}\n \t} else if (ci->df_conflict && ci->merged.result.mode != 0) {\n \t\t/*\n@@ -4041,7 +4041,7 @@ static int process_entry(struct merge_options *opt,\n \t\t\t\tcontinue;\n \t\t\t/* zero out any entries related to directories */\n \t\t\tnew_ci->stages[i].mode = 0;\n-\t\t\toidcpy(&new_ci->stages[i].oid, null_oid());\n+\t\t\toidcpy(&new_ci->stages[i].oid, null_oid(the_hash_algo));\n \t\t}\n \n \t\t/*\n@@ -4163,11 +4163,11 @@ static int process_entry(struct merge_options *opt,\n \t\t\tnew_ci->merged.result.mode = ci->stages[2].mode;\n \t\t\toidcpy(&new_ci->merged.result.oid, &ci->stages[2].oid);\n \t\t\tnew_ci->stages[1].mode = 0;\n-\t\t\toidcpy(&new_ci->stages[1].oid, null_oid());\n+\t\t\toidcpy(&new_ci->stages[1].oid, null_oid(the_hash_algo));\n \t\t\tnew_ci->filemask = 5;\n \t\t\tif ((S_IFMT & b_mode) != (S_IFMT & o_mode)) {\n \t\t\t\tnew_ci->stages[0].mode = 0;\n-\t\t\t\toidcpy(&new_ci->stages[0].oid, null_oid());\n+\t\t\t\toidcpy(&new_ci->stages[0].oid, null_oid(the_hash_algo));\n \t\t\t\tnew_ci->filemask = 4;\n \t\t\t}\n \n@@ -4175,11 +4175,11 @@ static int process_entry(struct merge_options *opt,\n \t\t\tci->merged.result.mode = ci->stages[1].mode;\n \t\t\toidcpy(&ci->merged.result.oid, &ci->stages[1].oid);\n \t\t\tci->stages[2].mode = 0;\n-\t\t\toidcpy(&ci->stages[2].oid, null_oid());\n+\t\t\toidcpy(&ci->stages[2].oid, null_oid(the_hash_algo));\n \t\t\tci->filemask = 3;\n \t\t\tif ((S_IFMT & a_mode) != (S_IFMT & o_mode)) {\n \t\t\t\tci->stages[0].mode = 0;\n-\t\t\t\toidcpy(&ci->stages[0].oid, null_oid());\n+\t\t\t\toidcpy(&ci->stages[0].oid, null_oid(the_hash_algo));\n \t\t\t\tci->filemask = 2;\n \t\t\t}\n \n@@ -4304,7 +4304,7 @@ static int process_entry(struct merge_options *opt,\n \t\t/* Deleted on both sides */\n \t\tci->merged.is_null = 1;\n \t\tci->merged.result.mode = 0;\n-\t\toidcpy(&ci->merged.result.oid, null_oid());\n+\t\toidcpy(&ci->merged.result.oid, null_oid(the_hash_algo));\n \t\tassert(!ci->df_conflict);\n \t\tci->merged.clean = !ci->path_conflict;\n \t}\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 5dfaf32b2c1..d88e61b07a9 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -502,7 +502,7 @@ static int get_tree_entry_if_blob(struct repository *r,\n \n \tret = get_tree_entry(r, tree, path, &dfs->oid, &dfs->mode);\n \tif (S_ISDIR(dfs->mode)) {\n-\t\toidcpy(&dfs->oid, null_oid());\n+\t\toidcpy(&dfs->oid, null_oid(the_hash_algo));\n \t\tdfs->mode = 0;\n \t}\n \treturn ret;\n@@ -1238,7 +1238,7 @@ static int merge_submodule(struct merge_options *opt,\n \tif (is_null_oid(b))\n \t\treturn 0;\n \n-\tif (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) {\n+\tif (repo_submodule_init(&subrepo, opt->repo, path, null_oid(the_hash_algo))) {\n \t\toutput(opt, 1, _(\"Failed to merge submodule %s (not checked out)\"), path);\n \t\treturn 0;\n \t}\n@@ -1698,7 +1698,7 @@ static int handle_file_collision(struct merge_options *opt,\n \n \t/* Store things in diff_filespecs for functions that need it */\n \tnull.path = (char *)collide_path;\n-\toidcpy(&null.oid, null_oid());\n+\toidcpy(&null.oid, null_oid(the_hash_algo));\n \tnull.mode = 0;\n \n \tif (merge_mode_and_contents(opt, &null, a, b, collide_path,\n@@ -2898,14 +2898,14 @@ static int process_renames(struct merge_options *opt,\n \t\t\tdst_other.mode = ren1->dst_entry->stages[other_stage].mode;\n \t\t\ttry_merge = 0;\n \n-\t\t\tif (oideq(&src_other.oid, null_oid()) &&\n+\t\t\tif (oideq(&src_other.oid, null_oid(the_hash_algo)) &&\n \t\t\t    ren1->dir_rename_original_type == 'A') {\n \t\t\t\tsetup_rename_conflict_info(RENAME_VIA_DIR,\n \t\t\t\t\t\t\t   opt, ren1, NULL);\n \t\t\t} else if (renamed_to_self) {\n \t\t\t\tsetup_rename_conflict_info(RENAME_NORMAL,\n \t\t\t\t\t\t\t   opt, ren1, NULL);\n-\t\t\t} else if (oideq(&src_other.oid, null_oid())) {\n+\t\t\t} else if (oideq(&src_other.oid, null_oid(the_hash_algo))) {\n \t\t\t\tsetup_rename_conflict_info(RENAME_DELETE,\n \t\t\t\t\t\t\t   opt, ren1, NULL);\n \t\t\t} else if ((dst_other.mode == ren1->pair->two->mode) &&\n@@ -2924,7 +2924,7 @@ static int process_renames(struct merge_options *opt,\n \t\t\t\t\t\t      1, /* update_cache */\n \t\t\t\t\t\t      0  /* update_wd    */))\n \t\t\t\t\tclean_merge = -1;\n-\t\t\t} else if (!oideq(&dst_other.oid, null_oid())) {\n+\t\t\t} else if (!oideq(&dst_other.oid, null_oid(the_hash_algo))) {\n \t\t\t\t/*\n \t\t\t\t * Probably not a clean merge, but it's\n \t\t\t\t * premature to set clean_merge to 0 here,\ndiff --git a/notes-merge.c b/notes-merge.c\nindex 67a472020de..5008faef450 100644\n--- a/notes-merge.c\n+++ b/notes-merge.c\n@@ -617,7 +617,7 @@ int notes_merge(struct notes_merge_options *o,\n \tif (repo_get_merge_bases(the_repository, local, remote, &bases) < 0)\n \t\texit(128);\n \tif (!bases) {\n-\t\tbase_oid = null_oid();\n+\t\tbase_oid = null_oid(the_hash_algo);\n \t\tbase_tree_oid = the_hash_algo->empty_tree;\n \t\tif (o->verbosity >= 4)\n \t\t\tprintf(\"No merge base found; doing history-less merge\\n\");\ndiff --git a/notes.c b/notes.c\nindex f5344230505..ce5a1006a83 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -1353,7 +1353,7 @@ int copy_note(struct notes_tree *t,\n \tif (note)\n \t\treturn add_note(t, to_obj, note, combine_notes);\n \telse if (existing_note)\n-\t\treturn add_note(t, to_obj, null_oid(), combine_notes);\n+\t\treturn add_note(t, to_obj, null_oid(the_hash_algo), combine_notes);\n \n \treturn 0;\n }\ndiff --git a/object-file.c b/object-file.c\nindex de603e2ca8c..772c311f188 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2405,7 +2405,7 @@ static int index_mem(struct index_state *istate,\n \n \t\topts.strict = 1;\n \t\topts.error_func = hash_format_check_report;\n-\t\tif (fsck_buffer(null_oid(), type, buf, size, &opts))\n+\t\tif (fsck_buffer(null_oid(the_hash_algo), type, buf, size, &opts))\n \t\t\tdie(_(\"refusing to create malformed object\"));\n \t\tfsck_finish(&opts);\n \t}\ndiff --git a/parse-options-cb.c b/parse-options-cb.c\nindex 166d35e0ebd..50c8afe4121 100644\n--- a/parse-options-cb.c\n+++ b/parse-options-cb.c\n@@ -145,7 +145,7 @@ int parse_opt_object_id(const struct option *opt, const char *arg, int unset)\n \tstruct object_id *target = opt->value;\n \n \tif (unset) {\n-\t\toidcpy(target, null_oid());\n+\t\toidcpy(target, null_oid(the_hash_algo));\n \t\treturn 0;\n \t}\n \tif (!arg)\ndiff --git a/range-diff.c b/range-diff.c\nindex 9501c358a84..8a2dcbee322 100644\n--- a/range-diff.c\n+++ b/range-diff.c\n@@ -467,7 +467,7 @@ static struct diff_filespec *get_filespec(const char *name, const char *p)\n {\n \tstruct diff_filespec *spec = alloc_filespec(name);\n \n-\tfill_filespec(spec, null_oid(), 0, 0100644);\n+\tfill_filespec(spec, null_oid(the_hash_algo), 0, 0100644);\n \tspec->data = (char *)p;\n \tspec->size = strlen(p);\n \tspec->should_munmap = 0;\ndiff --git a/read-cache.c b/read-cache.c\nindex a012cb22368..2f9e21c897d 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1735,7 +1735,7 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)\n \tend = (unsigned char *)hdr + size;\n \tstart = end - the_hash_algo->rawsz;\n \toidread(&oid, start, the_repository->hash_algo);\n-\tif (oideq(&oid, null_oid()))\n+\tif (oideq(&oid, null_oid(the_hash_algo)))\n \t\treturn 0;\n \n \tthe_hash_algo->init_fn(&c);\ndiff --git a/refs.c b/refs.c\nindex 118465271d7..215294115b4 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1377,7 +1377,7 @@ int ref_transaction_create(struct ref_transaction *transaction,\n \t\treturn 1;\n \t}\n \treturn ref_transaction_update(transaction, refname, new_oid,\n-\t\t\t\t      null_oid(), new_target, NULL, flags,\n+\t\t\t\t      null_oid(the_hash_algo), new_target, NULL, flags,\n \t\t\t\t      msg, err);\n }\n \n@@ -1396,7 +1396,7 @@ int ref_transaction_delete(struct ref_transaction *transaction,\n \tif (old_target && !(flags & REF_NO_DEREF))\n \t\tBUG(\"delete cannot operate on symrefs with deref mode\");\n \treturn ref_transaction_update(transaction, refname,\n-\t\t\t\t      null_oid(), old_oid,\n+\t\t\t\t      null_oid(the_hash_algo), old_oid,\n \t\t\t\t      NULL, old_target, flags,\n \t\t\t\t      msg, err);\n }\n@@ -2160,7 +2160,7 @@ struct ref_store *repo_get_submodule_ref_store(struct repository *repo,\n \tsubrepo = xmalloc(sizeof(*subrepo));\n \n \tif (repo_submodule_init(subrepo, repo, submodule,\n-\t\t\t\tnull_oid())) {\n+\t\t\t\tnull_oid(the_hash_algo))) {\n \t\tfree(subrepo);\n \t\tgoto done;\n \t}\n@@ -2345,14 +2345,14 @@ static int run_transaction_hook(struct ref_transaction *transaction,\n \t\tstrbuf_reset(&buf);\n \n \t\tif (!(update->flags & REF_HAVE_OLD))\n-\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid()));\n+\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid(the_hash_algo)));\n \t\telse if (update->old_target)\n \t\t\tstrbuf_addf(&buf, \"ref:%s \", update->old_target);\n \t\telse\n \t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(&update->old_oid));\n \n \t\tif (!(update->flags & REF_HAVE_NEW))\n-\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid()));\n+\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid(the_hash_algo)));\n \t\telse if (update->new_target)\n \t\t\tstrbuf_addf(&buf, \"ref:%s \", update->new_target);\n \t\telse\n@@ -2794,7 +2794,7 @@ static int migrate_one_ref(const char *refname, const char *referent UNUSED, con\n \t\tif (ret < 0)\n \t\t\tgoto done;\n \n-\t\tret = ref_transaction_update(data->transaction, refname, NULL, null_oid(),\n+\t\tret = ref_transaction_update(data->transaction, refname, NULL, null_oid(the_hash_algo),\n \t\t\t\t\t     symref_target.buf, NULL,\n \t\t\t\t\t     REF_SKIP_CREATE_REFLOG | REF_NO_DEREF, NULL, data->errbuf);\n \t\tif (ret < 0)\ndiff --git a/refs/debug.c b/refs/debug.c\nindex fbc4df08b43..7c61b775e4e 100644\n--- a/refs/debug.c\n+++ b/refs/debug.c\n@@ -217,7 +217,7 @@ static int debug_read_raw_ref(struct ref_store *ref_store, const char *refname,\n \tstruct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;\n \tint res = 0;\n \n-\toidcpy(oid, null_oid());\n+\toidcpy(oid, null_oid(ref_store->repo->hash_algo));\n \tres = drefs->refs->be->read_raw_ref(drefs->refs, refname, oid, referent,\n \t\t\t\t\t    type, failure_errno);\n \ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 6c6e67dc1c4..ba31cfdb93f 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1270,7 +1270,7 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r)\n \tref_transaction_add_update(\n \t\t\ttransaction, r->name,\n \t\t\tREF_NO_DEREF | REF_HAVE_NEW | REF_HAVE_OLD | REF_IS_PRUNING,\n-\t\t\tnull_oid(), &r->oid, NULL, NULL, NULL, NULL);\n+\t\t\tnull_oid(the_hash_algo), &r->oid, NULL, NULL, NULL, NULL);\n \tif (ref_transaction_commit(transaction, &err))\n \t\tgoto cleanup;\n \ndiff --git a/reset.c b/reset.c\nindex b22b1be792d..bb590271811 100644\n--- a/reset.c\n+++ b/reset.c\n@@ -80,7 +80,7 @@ static int update_refs(const struct reset_head_opts *opts,\n \t}\n \tif (!ret && run_hook)\n \t\trun_hooks_l(the_repository, \"post-checkout\",\n-\t\t\t    oid_to_hex(head ? head : null_oid()),\n+\t\t\t    oid_to_hex(head ? head : null_oid(the_hash_algo)),\n \t\t\t    oid_to_hex(oid), \"1\", NULL);\n \tstrbuf_release(&msg);\n \treturn ret;\ndiff --git a/sequencer.c b/sequencer.c\nindex ad0ab75c8d4..c112d2e1c43 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -265,8 +265,8 @@ static struct update_ref_record *init_update_ref_record(const char *ref)\n \n \tCALLOC_ARRAY(rec, 1);\n \n-\toidcpy(&rec->before, null_oid());\n-\toidcpy(&rec->after, null_oid());\n+\toidcpy(&rec->before, null_oid(the_hash_algo));\n+\toidcpy(&rec->after, null_oid(the_hash_algo));\n \n \t/* This may fail, but that's fine, we will keep the null OID. */\n \trefs_read_ref(get_main_ref_store(the_repository), ref, &rec->before);\n@@ -667,7 +667,7 @@ static int fast_forward_to(struct repository *r,\n \tif (!transaction ||\n \t    ref_transaction_update(transaction, \"HEAD\",\n \t\t\t\t   to, unborn && !is_rebase_i(opts) ?\n-\t\t\t\t   null_oid() : from, NULL, NULL,\n+\t\t\t\t   null_oid(the_hash_algo) : from, NULL, NULL,\n \t\t\t\t   0, sb.buf, &err) ||\n \t    ref_transaction_commit(transaction, &err)) {\n \t\tref_transaction_free(transaction);\n@@ -1301,7 +1301,7 @@ int update_head_with_reflog(const struct commit *old_head,\n \t\t\t\t\t\t  0, err);\n \tif (!transaction ||\n \t    ref_transaction_update(transaction, \"HEAD\", new_head,\n-\t\t\t\t   old_head ? &old_head->object.oid : null_oid(),\n+\t\t\t\t   old_head ? &old_head->object.oid : null_oid(the_hash_algo),\n \t\t\t\t   NULL, NULL, 0, sb.buf, err) ||\n \t    ref_transaction_commit(transaction, err)) {\n \t\tret = -1;\n@@ -4683,7 +4683,7 @@ static void create_autostash_internal(struct repository *r,\n \t\t\twrite_file(path, \"%s\", oid_to_hex(&oid));\n \t\t} else {\n \t\t\trefs_update_ref(get_main_ref_store(r), \"\", refname,\n-\t\t\t\t\t&oid, null_oid(), 0, UPDATE_REFS_DIE_ON_ERR);\n+\t\t\t\t\t&oid, null_oid(the_hash_algo), 0, UPDATE_REFS_DIE_ON_ERR);\n \t\t}\n \n \t\tprintf(_(\"Created autostash: %s\\n\"), buf.buf);\ndiff --git a/submodule-config.c b/submodule-config.c\nindex a25059ed7f8..d82b404b73e 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -831,7 +831,7 @@ static int gitmodules_cb(const char *var, const char *value,\n \n \tparameter.cache = repo->submodule_cache;\n \tparameter.treeish_name = NULL;\n-\tparameter.gitmodules_oid = null_oid();\n+\tparameter.gitmodules_oid = null_oid(the_hash_algo);\n \tparameter.overwrite = 1;\n \n \treturn parse_config(var, value, ctx, &parameter);\ndiff --git a/submodule.c b/submodule.c\nindex 0530e8cf24e..0821507ecaa 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -124,7 +124,7 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)\n \tif (is_gitmodules_unmerged(the_repository->index))\n \t\tdie(_(\"Cannot change unmerged .gitmodules, resolve merge conflicts first\"));\n \n-\tsubmodule = submodule_from_path(the_repository, null_oid(), oldpath);\n+\tsubmodule = submodule_from_path(the_repository, null_oid(the_hash_algo), oldpath);\n \tif (!submodule || !submodule->name) {\n \t\twarning(_(\"Could not find section in .gitmodules where path=%s\"), oldpath);\n \t\treturn -1;\n@@ -153,7 +153,7 @@ int remove_path_from_gitmodules(const char *path)\n \tif (is_gitmodules_unmerged(the_repository->index))\n \t\tdie(_(\"Cannot change unmerged .gitmodules, resolve merge conflicts first\"));\n \n-\tsubmodule = submodule_from_path(the_repository, null_oid(), path);\n+\tsubmodule = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \tif (!submodule || !submodule->name) {\n \t\twarning(_(\"Could not find section in .gitmodules where path=%s\"), path);\n \t\treturn -1;\n@@ -204,7 +204,7 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,\n \t\t\t\t\t     const char *path)\n {\n \tconst struct submodule *submodule = submodule_from_path(the_repository,\n-\t\t\t\t\t\t\t\tnull_oid(),\n+\t\t\t\t\t\t\t\tnull_oid(the_hash_algo),\n \t\t\t\t\t\t\t\tpath);\n \tif (submodule) {\n \t\tconst char *ignore;\n@@ -312,7 +312,7 @@ int is_tree_submodule_active(struct repository *repo,\n \n int is_submodule_active(struct repository *repo, const char *path)\n {\n-\treturn is_tree_submodule_active(repo, null_oid(), path);\n+\treturn is_tree_submodule_active(repo, null_oid(the_hash_algo), path);\n }\n \n int is_submodule_populated_gently(const char *path, int *return_error_code)\n@@ -778,7 +778,7 @@ const struct submodule *submodule_from_ce(const struct cache_entry *ce)\n \tif (!should_update_submodules())\n \t\treturn NULL;\n \n-\treturn submodule_from_path(the_repository, null_oid(), ce->name);\n+\treturn submodule_from_path(the_repository, null_oid(the_hash_algo), ce->name);\n }\n \n \n@@ -1062,7 +1062,7 @@ static int submodule_needs_pushing(struct repository *r,\n \t\t\t\t   const char *path,\n \t\t\t\t   struct oid_array *commits)\n {\n-\tif (!submodule_has_commits(r, path, null_oid(), commits))\n+\tif (!submodule_has_commits(r, path, null_oid(the_hash_algo), commits))\n \t\t/*\n \t\t * NOTE: We do consider it safe to return \"no\" here. The\n \t\t * correct answer would be \"We do not know\" instead of\n@@ -1126,7 +1126,7 @@ int find_unpushed_submodules(struct repository *r,\n \t\tconst struct submodule *submodule;\n \t\tconst char *path = NULL;\n \n-\t\tsubmodule = submodule_from_name(r, null_oid(), name->string);\n+\t\tsubmodule = submodule_from_name(r, null_oid(the_hash_algo), name->string);\n \t\tif (submodule)\n \t\t\tpath = submodule->path;\n \t\telse\n@@ -1351,7 +1351,7 @@ static void calculate_changed_submodule_paths(struct repository *r,\n \t\tconst struct submodule *submodule;\n \t\tconst char *path = NULL;\n \n-\t\tsubmodule = submodule_from_name(r, null_oid(), name->string);\n+\t\tsubmodule = submodule_from_name(r, null_oid(the_hash_algo), name->string);\n \t\tif (submodule)\n \t\t\tpath = submodule->path;\n \t\telse\n@@ -1360,7 +1360,7 @@ static void calculate_changed_submodule_paths(struct repository *r,\n \t\tif (!path)\n \t\t\tcontinue;\n \n-\t\tif (submodule_has_commits(r, path, null_oid(), &cs_data->new_commits)) {\n+\t\tif (submodule_has_commits(r, path, null_oid(the_hash_algo), &cs_data->new_commits)) {\n \t\t\tchanged_submodule_data_clear(cs_data);\n \t\t\t*name->string = '\\0';\n \t\t}\n@@ -1602,7 +1602,7 @@ get_fetch_task_from_index(struct submodule_parallel_fetch *spf,\n \t\tif (!S_ISGITLINK(ce->ce_mode))\n \t\t\tcontinue;\n \n-\t\ttask = fetch_task_create(spf, ce->name, null_oid());\n+\t\ttask = fetch_task_create(spf, ce->name, null_oid(the_hash_algo));\n \t\tif (!task)\n \t\t\tcontinue;\n \n@@ -2166,7 +2166,7 @@ int submodule_move_head(const char *path, const char *super_prefix,\n \tif (old_head && !is_submodule_populated_gently(path, error_code_ptr))\n \t\treturn 0;\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tBUG(\"could not get submodule information for '%s'\", path);\n@@ -2376,7 +2376,7 @@ static void relocate_single_git_dir_into_superproject(const char *path,\n \n \treal_old_git_dir = real_pathdup(old_git_dir, 1);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \tif (!sub)\n \t\tdie(_(\"could not lookup name for submodule '%s'\"), path);\n \n@@ -2462,7 +2462,7 @@ void absorb_git_dir_into_superproject(const char *path,\n \t\t* superproject did not rewrite the git file links yet,\n \t\t* fix it now.\n \t\t*/\n-\t\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\t\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \t\tif (!sub)\n \t\t\tdie(_(\"could not lookup name for submodule '%s'\"), path);\n \t\tsubmodule_name_to_gitdir(&sub_gitdir, the_repository, sub->name);\n@@ -2594,7 +2594,7 @@ int submodule_to_gitdir(struct repository *repo,\n \t\tstrbuf_addstr(buf, git_dir);\n \t}\n \tif (!is_git_directory(buf->buf)) {\n-\t\tsub = submodule_from_path(repo, null_oid(), submodule);\n+\t\tsub = submodule_from_path(repo, null_oid(the_hash_algo), submodule);\n \t\tif (!sub) {\n \t\t\tret = -1;\n \t\t\tgoto cleanup;\ndiff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c\nindex e00fce592b1..2ff67c067ac 100644\n--- a/t/helper/test-ref-store.c\n+++ b/t/helper/test-ref-store.c\n@@ -179,7 +179,7 @@ static int cmd_for_each_ref__exclude(struct ref_store *refs, const char **argv)\n \n static int cmd_resolve_ref(struct ref_store *refs, const char **argv)\n {\n-\tstruct object_id oid = *null_oid();\n+\tstruct object_id oid = *null_oid(the_hash_algo);\n \tconst char *refname = notnull(*argv++, \"refname\");\n \tint resolve_flags = arg_flags(*argv++, \"resolve-flags\", empty_flags);\n \tint flags;\ndiff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c\nindex 6dce9571531..2710341cd5d 100644\n--- a/t/helper/test-submodule-nested-repo-config.c\n+++ b/t/helper/test-submodule-nested-repo-config.c\n@@ -21,7 +21,7 @@ int cmd__submodule_nested_repo_config(int argc, const char **argv)\n \n \tsetup_git_directory();\n \n-\tif (repo_submodule_init(&subrepo, the_repository, argv[1], null_oid())) {\n+\tif (repo_submodule_init(&subrepo, the_repository, argv[1], null_oid(the_hash_algo))) {\n \t\tdie_usage(argv, \"Submodule not found.\");\n \t}\n \ndiff --git a/tree-diff.c b/tree-diff.c\nindex 60c558c2b56..e00fc2f450d 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -181,7 +181,7 @@ static void emit_path(struct combine_diff_path ***tail,\n \n \t\tstrbuf_add(base, path, pathlen);\n \t\tp = combine_diff_path_new(base->buf, base->len, mode,\n-\t\t\t\t\t  oid ? oid : null_oid(),\n+\t\t\t\t\t  oid ? oid : null_oid(the_hash_algo),\n \t\t\t\t\t  nparent);\n \t\tstrbuf_setlen(base, old_baselen);\n \n@@ -206,7 +206,7 @@ static void emit_path(struct combine_diff_path ***tail,\n \t\t\t\tmode_i = tp[i].entry.mode;\n \t\t\t}\n \t\t\telse {\n-\t\t\t\toid_i = null_oid();\n+\t\t\t\toid_i = null_oid(the_hash_algo);\n \t\t\t\tmode_i = 0;\n \t\t\t}\n \ndiff --git a/upload-pack.c b/upload-pack.c\nindex 7412d3c6ce8..0fa8fbdd6de 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -1446,7 +1446,7 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,\n \t\tfor_each_namespaced_ref_1(send_ref, &data);\n \t\tif (!data.sent_capabilities) {\n \t\t\tconst char *refname = \"capabilities^{}\";\n-\t\t\twrite_v0_ref(&data, refname, refname, null_oid());\n+\t\t\twrite_v0_ref(&data, refname, refname, null_oid(the_hash_algo));\n \t\t}\n \t\t/*\n \t\t * fflush stdout before calling advertise_shallow_grafts because send_ref\ndiff --git a/wt-status.c b/wt-status.c\nindex 1da5732f57b..454601afa15 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1824,10 +1824,10 @@ void wt_status_get_state(struct repository *r,\n \tif (!sequencer_get_last_command(r, &action)) {\n \t\tif (action == REPLAY_PICK && !state->cherry_pick_in_progress) {\n \t\t\tstate->cherry_pick_in_progress = 1;\n-\t\t\toidcpy(&state->cherry_pick_head_oid, null_oid());\n+\t\t\toidcpy(&state->cherry_pick_head_oid, null_oid(the_hash_algo));\n \t\t} else if (action == REPLAY_REVERT && !state->revert_in_progress) {\n \t\t\tstate->revert_in_progress = 1;\n-\t\t\toidcpy(&state->revert_head_oid, null_oid());\n+\t\t\toidcpy(&state->revert_head_oid, null_oid(the_hash_algo));\n \t\t}\n \t}\n \tif (get_detached_from)\ndiff --git a/xdiff-interface.c b/xdiff-interface.c\nindex 3bd61f26e90..77712811ff1 100644\n--- a/xdiff-interface.c\n+++ b/xdiff-interface.c\n@@ -181,7 +181,7 @@ void read_mmblob(mmfile_t *ptr, const struct object_id *oid)\n \tunsigned long size;\n \tenum object_type type;\n \n-\tif (oideq(oid, null_oid())) {\n+\tif (oideq(oid, null_oid(the_hash_algo))) {\n \t\tptr->ptr = xstrdup(\"\");\n \t\tptr->size = 0;\n \t\treturn;\n\n-- \n2.49.0.rc0.416.g627208d89d.dirty\n\n"},{"id":"513707","messageId":"CAOLa=ZTcn5ibmejf3AcEsvQV3YjY4ZaY07jqX_YATxUvSWLp-w@mail.gmail.com","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im","subject":"Re: [PATCH v2 00/12] Stop depending on `the_repository` in object-related subsystems","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-03-06T15:29:38Z","receivedAt":"2025-03-06T15:29:41Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> Hi,\n>\n> this patch series is another step to remove our dependency on the global\n> `the_repository` variable. The series focusses on subsystems related to\n> objects.\n>\n> The intent here is to work towards libification of the whole subsystem\n> so that we can start splitting out something like an object \"backend\".\n> It is thus part of a set of refactorings aimed at allowing pluggable\n> object databases eventually. I'm not discussing that bigger effort yet,\n> mostly because it's still taking shape. So these patch series contains\n> things that make sense standalone, even if pluggable ODBs never get to\n> be a thing.\n>\n> Note that this patch series stop short of dropping `the_repository` in\n> \"object-file.c\". This is a bigger undertaking, so I'm pushing that into\n> the next patch series.\n>\n> The series is built on top of cb0ae672aea (A bit more post -rc0,\n> 2025-02-27) with ps/path-sans-the-repository at 028f618658e (path:\n> adjust last remaining users of `the_repository`, 2025-02-07) merged into\n> it.\n>\n> Changes in v2:\n>   - Point out why t1050 had to be adapted.\n>   - Drop the rename of `get_max_object_index()` and\n>     `get_indexed_object()`.\n>   - Fix a couple of commit message typos.\n>   - Link to v1: https://lore.kernel.org/r/20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im\n>\n\nNo further comments from my side, the changelog and range-diff looks\ngood. Thanks!\n\n[snip]\n"},{"id":"513727","messageId":"xmqqr03ageej.fsf@gitster.g","threadId":"63046","inReplyTo":"20250306-b4-pks-objects-without-the-repository-v2-12-f3465327be69@pks.im","subject":"Re: [PATCH v2 12/12] hash: stop depending on `the_repository` in `null_oid()`","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-03-06T19:14:28Z","receivedAt":"2025-03-06T19:14:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> diff --git a/builtin/ls-files.c b/builtin/ls-files.c\n> index a4431429b7d..2d2e90bc23a 100644\n> --- a/builtin/ls-files.c\n> +++ b/builtin/ls-files.c\n> @@ -234,7 +234,7 @@ static void show_submodule(struct repository *superproject,\n>  {\n>  \tstruct repository subrepo;\n>  \n> -\tif (repo_submodule_init(&subrepo, superproject, path, null_oid()))\n> +\tif (repo_submodule_init(&subrepo, superproject, path, null_oid(the_hash_algo)))\n>  \t\treturn;\n>  \n>  \tif (repo_read_index(&subrepo) < 0)\n\nThis has an obvious semantic interaction with what is done in\nUsman's series <20250306143629.1267358-7-usmanakinyemi202@gmail.com>\nwhere builtin/ls-files.c claims that it got rid of its dependence on\nthe_repository.\n\nThe resulting ls-files still calls null_oid() here, hence it depends\non the_hash_algo hence indirectly on the_repository.  When these\ntopics are merged together, builtin/ls-files.c again needs to be\nmarked that it still needs the_repository variable in order to see\nthe_hash_algo.\n\nI _think_ the subrepo is not allowed to use different hash from the\nsuperproject, so we can pass superproject->hash_algo instead in this\nseries to make it easier on the other topic?\n\nWhat do you think?\n\nPerhaps we should have hidden null_oid() as requiring the_repository\njust like the_hash_algo is guarded like so\n\n        #ifdef USE_THE_REPOSITORY_VARIABLE\n        # include \"repository.h\"\n        # define the_hash_algo the_repository->hash_algo\n        #endif\n\nin <hash.h>.\n\nIn other words, I wish we had the following patch already applied,\nbefore Usman started working on the other topic.\n\nBut with this topic getting solidified, it would become a moot point\nto do that in the longer term.  This series removes null_oid() that\nhad the implicit dependency anyway.\n\ndiff --git c/hash.h w/hash.h\nindex 4367acfec5..3c9ccb550d 100644\n--- c/hash.h\n+++ w/hash.h\n@@ -340,7 +340,9 @@ static inline int hash_algo_by_ptr(const struct git_hash_algo *p)\n \n const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop);\n \n+#ifdef USE_THE_REPOSITORY_VARIABLE\n const struct object_id *null_oid(void);\n+#endif\n \n static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)\n {\n\n\n"},{"id":"513738","messageId":"Z8q3nzhl3DHETZgf@pks.im","threadId":"63046","inReplyTo":"xmqqr03ageej.fsf@gitster.g","subject":"Re: [PATCH v2 12/12] hash: stop depending on `the_repository` in `null_oid()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T09:08:47Z","receivedAt":"2025-03-07T09:08:56Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Mar 06, 2025 at 11:14:28AM -0800, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> > diff --git a/builtin/ls-files.c b/builtin/ls-files.c\n> > index a4431429b7d..2d2e90bc23a 100644\n> > --- a/builtin/ls-files.c\n> > +++ b/builtin/ls-files.c\n> > @@ -234,7 +234,7 @@ static void show_submodule(struct repository *superproject,\n> >  {\n> >  \tstruct repository subrepo;\n> >  \n> > -\tif (repo_submodule_init(&subrepo, superproject, path, null_oid()))\n> > +\tif (repo_submodule_init(&subrepo, superproject, path, null_oid(the_hash_algo)))\n> >  \t\treturn;\n> >  \n> >  \tif (repo_read_index(&subrepo) < 0)\n> \n> This has an obvious semantic interaction with what is done in\n> Usman's series <20250306143629.1267358-7-usmanakinyemi202@gmail.com>\n> where builtin/ls-files.c claims that it got rid of its dependence on\n> the_repository.\n> \n> The resulting ls-files still calls null_oid() here, hence it depends\n> on the_hash_algo hence indirectly on the_repository.  When these\n> topics are merged together, builtin/ls-files.c again needs to be\n> marked that it still needs the_repository variable in order to see\n> the_hash_algo.\n\nAh, thanks for catching this!\n\n> I _think_ the subrepo is not allowed to use different hash from the\n> superproject, so we can pass superproject->hash_algo instead in this\n> series to make it easier on the other topic?\n\nThat's actually a very good question -- I have no idea. My gut says that\nit probably won't work, but on a conceptual level I think it would be\nnice if it did. Reality lies somewhere between. The following commands\nwork alright:\n\n    $ git init --object-format=sha256 repo\n    $ cd repo\n    $ git commit --allow-empty --message initial\n    $ git submodule add https://github.com/git/git.git\n    $ git -C git rev-parse --show-object-info HEAD\n    sha1\n    a36e024e989f4d35f35987a60e3af8022cac3420\n\nWe end up with a SHA1 submodule in a SHA256 repository. So far so good.\nHow does it look like?\n\n    $ git diff --cached\n    diff --git a/.gitmodules b/.gitmodules\n    new file mode 100644\n    index 0000000..3594794\n    --- /dev/null\n    +++ b/.gitmodules\n    @@ -0,0 +1,3 @@\n    +[submodule \"git\"]\n    +\tpath = git\n    +\turl = https://github.com/git/git.git\n    diff --git a/git b/git\n    new file mode 160000\n    index 0000000..a36e024\n    --- /dev/null\n    +++ b/git\n    @@ -0,0 +1 @@\n    +Subproject commit a36e024e989f4d35f35987a60e3af8022cac3420000000000000000000000000\n\nWell, now it starts to become weird, as the commit hash is obviously\nwrong. Can we update the submodule?\n\n    $ git -C git switch next\n    $ git diff\n    diff --git a/git b/git\n    index a36e024..4cd3354 160000\n    --- a/git\n    +++ b/git\n    @@ -1 +1 @@\n    -Subproject commit a36e024e989f4d35f35987a60e3af8022cac3420000000000000000000000000\n    +Subproject commit 4cd33545ba4fa82324b454aa5bf2748b40a572fb\n\nWell, that diff at least looks somewhat better than expected? Let's\ncommit it.\n\n    $ git commit -m update\n    $ git diff HEAD~\n    diff --git a/git b/git\n    index a36e024..4cd3354 160000\n    --- a/git\n    +++ b/git\n    @@ -1 +1 @@\n    -Subproject commit a36e024e989f4d35f35987a60e3af8022cac3420000000000000000000000000\n    +Subproject commit 4cd33545ba4fa82324b454aa5bf2748b40a572fb000000000000000000000000\n\nOh, well... so, what happens if we ask git-log(1) to recurse into the\nsubmodule?\n\n    $ git log --submodule=diff --patch\n    Segmentation fault (core dumped)\n\nYeah, no, that's not really working.\n\nSo in theory, I don't really think there is anything that keeps us from\nmixing object formats, and I even think that this is a necessary feature\nto have once people start to migrate their repositories to SHA256. There\nare people out there who use submodules, and it may not be feasible for\nthem to wait until all of their submodules have been converted to SHA256\nto migrate their own repositories.\n\nFrom my perspective, we should thus treat it as a bug that the above\ndoes not work.\n\n> What do you think?\n\nAnyway, that was a bit of a tangent to your initial question: which hash\nshould we be passing in the first place? As it turns out, we should be\npassing the superproject's null OID indeed. The object ID we pass to\n`repo_submodule_init()` does not describe any object in the submodule\nitself, but rather indicates which tree-ish the submodule information\nshould be parsed from in the superproject. As such, it refers to an\nobject in the superproject itself and should thus use its object hash.\n\nI'll include such a change in my patch series to resolve the semantic\nconflict.\n\n> Perhaps we should have hidden null_oid() as requiring the_repository\n> just like the_hash_algo is guarded like so\n> \n>         #ifdef USE_THE_REPOSITORY_VARIABLE\n>         # include \"repository.h\"\n>         # define the_hash_algo the_repository->hash_algo\n>         #endif\n> \n> in <hash.h>.\n> \n> In other words, I wish we had the following patch already applied,\n> before Usman started working on the other topic.\n\nTrue. `USE_THE_REPOSITORY_VARIABLE` has always been best effort, and it\nwas clear from the beginning that it won't catch all functions that\nimplicitly depend on `the_repository`. The good news is that we uncover\nand convert more and more of those implicit dependencies, so as time\nprogresses it becomes more accurate.\n\n> But with this topic getting solidified, it would become a moot point\n> to do that in the longer term.  This series removes null_oid() that\n> had the implicit dependency anyway.\n\nIndeed.\n\nPatrick\n"},{"id":"513761","messageId":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH v3 00/12] Stop depending on `the_repository` in object-related subsystems","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T14:18:53Z","receivedAt":"2025-03-07T14:19:02Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis patch series is another step to remove our dependency on the global\n`the_repository` variable. The series focusses on subsystems related to\nobjects.\n\nThe intent here is to work towards libification of the whole subsystem\nso that we can start splitting out something like an object \"backend\".\nIt is thus part of a set of refactorings aimed at allowing pluggable\nobject databases eventually. I'm not discussing that bigger effort yet,\nmostly because it's still taking shape. So these patch series contains\nthings that make sense standalone, even if pluggable ODBs never get to\nbe a thing.\n\nNote that this patch series stop short of dropping `the_repository` in\n\"object-file.c\". This is a bigger undertaking, so I'm pushing that into\nthe next patch series.\n\nThe series is built on top of cb0ae672aea (A bit more post -rc0,\n2025-02-27) with ps/path-sans-the-repository at 028f618658e (path:\nadjust last remaining users of `the_repository`, 2025-02-07) merged into\nit.\n\nChanges in v2:\n  - Point out why t1050 had to be adapted.\n  - Drop the rename of `get_max_object_index()` and\n    `get_indexed_object()`.\n  - Fix a couple of commit message typos.\n  - Link to v1: https://lore.kernel.org/r/20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im\n\nChanges in v3:\n  - Fix a semantic conflict with an in-flight patch series.\n  - Link to v2: https://lore.kernel.org/r/20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (12):\n      csum-file: stop depending on `the_repository`\n      object: stop depending on `the_repository`\n      pack-write: stop depending on `the_repository` and `the_hash_algo`\n      environment: move access to \"core.bigFileThreshold\" into repo settings\n      pack-check: stop depending on `the_repository`\n      pack-revindex: stop depending on `the_repository`\n      pack-bitmap-write: stop depending on `the_repository`\n      object-file-convert: stop depending on `the_repository`\n      delta-islands: stop depending on `the_repository`\n      object-file: split out logic regarding hash algorithms\n      hash: fix \"-Wsign-compare\" warnings\n      hash: stop depending on `the_repository` in `null_oid()`\n\n Makefile                                     |   1 +\n archive.c                                    |   4 +-\n blame.c                                      |   2 +-\n branch.c                                     |   2 +-\n builtin/checkout.c                           |   6 +-\n builtin/clone.c                              |   2 +-\n builtin/describe.c                           |   2 +-\n builtin/diff.c                               |   5 +-\n builtin/fast-export.c                        |  10 +-\n builtin/fast-import.c                        |   8 +-\n builtin/fsck.c                               |   6 +-\n builtin/grep.c                               |   4 +-\n builtin/index-pack.c                         |  16 +-\n builtin/log.c                                |   2 +-\n builtin/ls-files.c                           |   3 +-\n builtin/name-rev.c                           |   4 +-\n builtin/pack-objects.c                       |  17 +-\n builtin/prune.c                              |   2 +-\n builtin/rebase.c                             |   2 +-\n builtin/receive-pack.c                       |   2 +-\n builtin/submodule--helper.c                  |  36 ++--\n builtin/tag.c                                |   2 +-\n builtin/unpack-objects.c                     |   5 +-\n builtin/update-ref.c                         |   2 +-\n builtin/worktree.c                           |   2 +-\n bulk-checkin.c                               |   4 +-\n combine-diff.c                               |   2 +-\n commit-graph.c                               |   9 +-\n commit.c                                     |   2 +-\n config.c                                     |   5 -\n csum-file.c                                  |  28 +--\n csum-file.h                                  |  12 +-\n delta-islands.c                              |  14 +-\n delta-islands.h                              |   2 +-\n diff-lib.c                                   |  10 +-\n diff-no-index.c                              |  28 +--\n diff.c                                       |  14 +-\n diff.h                                       |   2 +-\n dir.c                                        |   2 +-\n environment.c                                |   1 -\n environment.h                                |   1 -\n grep.c                                       |   2 +-\n hash.c                                       | 277 +++++++++++++++++++++++++\n hash.h                                       |   4 +-\n log-tree.c                                   |   2 +-\n merge-ort.c                                  |  26 +--\n merge-recursive.c                            |  12 +-\n meson.build                                  |   1 +\n midx-write.c                                 |  12 +-\n midx.c                                       |   3 +-\n notes-merge.c                                |   2 +-\n notes.c                                      |   2 +-\n object-file-convert.c                        |  29 +--\n object-file-convert.h                        |   3 +-\n object-file.c                                | 292 +--------------------------\n object.c                                     |  21 +-\n object.h                                     |  10 +-\n pack-bitmap-write.c                          |  36 ++--\n pack-bitmap.c                                |  15 +-\n pack-bitmap.h                                |   1 +\n pack-check.c                                 |  12 +-\n pack-revindex.c                              |  35 ++--\n pack-write.c                                 |  55 +++--\n pack.h                                       |  11 +-\n parse-options-cb.c                           |   2 +-\n range-diff.c                                 |   2 +-\n reachable.c                                  |   6 +-\n read-cache.c                                 |   4 +-\n refs.c                                       |  12 +-\n refs/debug.c                                 |   2 +-\n refs/files-backend.c                         |   2 +-\n repo-settings.c                              |  20 ++\n repo-settings.h                              |   5 +\n reset.c                                      |   2 +-\n revision.c                                   |   3 +-\n sequencer.c                                  |  10 +-\n shallow.c                                    |  10 +-\n streaming.c                                  |   3 +-\n submodule-config.c                           |   2 +-\n submodule.c                                  |  28 +--\n t/helper/test-ref-store.c                    |   2 +-\n t/helper/test-submodule-nested-repo-config.c |   2 +-\n t/t1050-large.sh                             |   3 +-\n tree-diff.c                                  |   4 +-\n upload-pack.c                                |  14 +-\n wt-status.c                                  |   4 +-\n xdiff-interface.c                            |   2 +-\n 87 files changed, 677 insertions(+), 613 deletions(-)\n\nRange-diff versus v2:\n\n 1:  94dfdecf59d =  1:  2b8ac989731 csum-file: stop depending on `the_repository`\n 2:  c456c1a057b =  2:  f70f85a194b object: stop depending on `the_repository`\n 3:  4eb651128e2 =  3:  af03d83d7f0 pack-write: stop depending on `the_repository` and `the_hash_algo`\n 4:  0632bc5c186 =  4:  19a8ee01385 environment: move access to \"core.bigFileThreshold\" into repo settings\n 5:  86214482421 =  5:  ec9b0012242 pack-check: stop depending on `the_repository`\n 6:  3fda249b16a =  6:  f15148e3aee pack-revindex: stop depending on `the_repository`\n 7:  99dbafed649 =  7:  ce1255da4aa pack-bitmap-write: stop depending on `the_repository`\n 8:  a3843270ce0 =  8:  2f6d7b93dc9 object-file-convert: stop depending on `the_repository`\n 9:  8d141a24804 =  9:  28e2dac294d delta-islands: stop depending on `the_repository`\n10:  4671a252952 = 10:  813da442eee object-file: split out logic regarding hash algorithms\n11:  2b81a7d91fd = 11:  7432ecb550b hash: fix \"-Wsign-compare\" warnings\n12:  6e8f5f8987b ! 12:  8d88ef2aab7 hash: stop depending on `the_repository` in `null_oid()`\n    @@ Commit message\n           - \"grep.c\"\n           - \"refs/debug.c\"\n     \n    -    There is also a single non-trivial exception with \"diff-no-index.c\".\n    -    Here we know that we may not have a repository initialized at all, so we\n    -    cannot rely on `the_repository`. Instead, we adapt `diff_no_index()` to\n    -    get a `struct git_hash_algo` as parameter. The only caller is located in\n    -    \"builtin/diff.c\", where we know to call `repo_set_hash_algo()` in case\n    -    we're running outside of a Git repository. Consequently, it is fine to\n    -    continue passing `the_repository->hash_algo` even in this case.\n    +    There are also two non-trivial exceptions:\n    +\n    +      - \"diff-no-index.c\": Here we know that we may not have a repository\n    +        initialized at all, so we cannot rely on `the_repository`. Instead,\n    +        we adapt `diff_no_index()` to get a `struct git_hash_algo` as\n    +        parameter. The only caller is located in \"builtin/diff.c\", where we\n    +        know to call `repo_set_hash_algo()` in case we're running outside of\n    +        a Git repository. Consequently, it is fine to continue passing\n    +        `the_repository->hash_algo` even in this case.\n    +\n    +      - \"builtin/ls-files.c\": There is an in-flight patch series that drops\n    +        `USE_THE_REPOSITORY_VARIABLE` in this file, which causes a semantic\n    +        conflict because we use `null_oid()` in `show_submodule()`. The\n    +        value is passed to `repo_submodule_init()`, which may use the object\n    +        ID to resolve a tree-ish in the superproject from which we want to\n    +        read the submodule config. As such, the object ID should refer to an\n    +        object in the superproject, and consequently we need to use its hash\n    +        algorithm.\n     \n         This means that we could in theory just not bother about this edge case\n         at all and just use `the_repository` in \"diff-no-index.c\". But doing so\n    @@ builtin/ls-files.c: static void show_submodule(struct repository *superproject,\n      \tstruct repository subrepo;\n      \n     -\tif (repo_submodule_init(&subrepo, superproject, path, null_oid()))\n    -+\tif (repo_submodule_init(&subrepo, superproject, path, null_oid(the_hash_algo)))\n    ++\tif (repo_submodule_init(&subrepo, superproject, path,\n    ++\t\t\t\tnull_oid(superproject->hash_algo)))\n      \t\treturn;\n      \n      \tif (repo_read_index(&subrepo) < 0)\n\n---\nbase-commit: e2cb568e11f4ceb427ba4205e6b8a4426d26be12\nchange-id: 20250210-b4-pks-objects-without-the-repository-6ba8398f7cc0\n\n"},{"id":"513762","messageId":"20250307-b4-pks-objects-without-the-repository-v3-2-7bccf408731e@pks.im","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","subject":"[PATCH v3 02/12] object: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T14:18:55Z","receivedAt":"2025-03-07T14:19:03Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are a couple of functions exposed by \"object.c\" that implicitly\ndepend on `the_repository`. Remove this dependency by injecting the\nrepository via a parameter. Adapt callers accordingly by simply using\n`the_repository`, except in cases where the subsystem is already free of\nthe repository. In that case, we instead pass the repository provided by\nthe caller's context.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fsck.c         |  4 ++--\n builtin/grep.c         |  2 +-\n builtin/index-pack.c   |  4 ++--\n builtin/log.c          |  2 +-\n builtin/name-rev.c     |  4 ++--\n builtin/pack-objects.c |  2 +-\n builtin/prune.c        |  2 +-\n midx-write.c           |  4 ++--\n object.c               | 21 +++++++++++----------\n object.h               | 10 ++++++----\n pack-bitmap.c          |  6 +++---\n reachable.c            |  6 +++---\n revision.c             |  3 ++-\n shallow.c              | 10 +++++-----\n upload-pack.c          | 12 ++++++------\n 15 files changed, 48 insertions(+), 44 deletions(-)\n\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex eea1d43647f..62c7494bbda 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -399,12 +399,12 @@ static void check_connectivity(void)\n \t}\n \n \t/* Look up all the requirements, warn about missing objects.. */\n-\tmax = get_max_object_index();\n+\tmax = get_max_object_index(the_repository);\n \tif (verbose)\n \t\tfprintf_ln(stderr, _(\"Checking connectivity (%d objects)\"), max);\n \n \tfor (i = 0; i < max; i++) {\n-\t\tstruct object *obj = get_indexed_object(i);\n+\t\tstruct object *obj = get_indexed_object(the_repository, i);\n \n \t\tif (obj)\n \t\t\tcheck_object(obj);\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex d1427290f77..cbbf6f26439 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -1144,7 +1144,7 @@ int cmd_grep(int argc,\n \t\t\tbreak;\n \t\t}\n \n-\t\tobject = parse_object_or_die(&oid, arg);\n+\t\tobject = parse_object_or_die(the_repository, &oid, arg);\n \t\tif (!seen_dashdash)\n \t\t\tverify_non_filename(prefix, arg);\n \t\tadd_object_array_with_path(object, arg, &list, oc.mode, oc.path);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 3eb5af20950..1268032d769 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -279,14 +279,14 @@ static unsigned check_objects(void)\n {\n \tunsigned i, max, foreign_nr = 0;\n \n-\tmax = get_max_object_index();\n+\tmax = get_max_object_index(the_repository);\n \n \tif (verbose)\n \t\tprogress = start_delayed_progress(the_repository,\n \t\t\t\t\t\t  _(\"Checking objects\"), max);\n \n \tfor (i = 0; i < max; i++) {\n-\t\tforeign_nr += check_object(get_indexed_object(i));\n+\t\tforeign_nr += check_object(get_indexed_object(the_repository, i));\n \t\tdisplay_progress(progress, i + 1);\n \t}\n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 04a6ef97bc1..0d4c579dad7 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -2468,7 +2468,7 @@ int cmd_format_patch(int argc,\n \tbase = get_base_commit(&cfg, list, nr);\n \tif (base) {\n \t\treset_revision_walk();\n-\t\tclear_object_flags(UNINTERESTING);\n+\t\tclear_object_flags(the_repository, UNINTERESTING);\n \t\tprepare_bases(&bases, base, list, nr);\n \t}\n \ndiff --git a/builtin/name-rev.c b/builtin/name-rev.c\nindex beac166b5cb..2fe82c839ba 100644\n--- a/builtin/name-rev.c\n+++ b/builtin/name-rev.c\n@@ -667,9 +667,9 @@ int cmd_name_rev(int argc,\n \t} else if (all) {\n \t\tint i, max;\n \n-\t\tmax = get_max_object_index();\n+\t\tmax = get_max_object_index(the_repository);\n \t\tfor (i = 0; i < max; i++) {\n-\t\t\tstruct object *obj = get_indexed_object(i);\n+\t\t\tstruct object *obj = get_indexed_object(the_repository, i);\n \t\t\tif (!obj || obj->type != OBJ_COMMIT)\n \t\t\t\tcontinue;\n \t\t\tshow_name(obj, NULL,\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 8e282f2a980..c3adbc94504 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -4161,7 +4161,7 @@ static int mark_bitmap_preferred_tip(const char *refname,\n \tif (!peel_iterated_oid(the_repository, oid, &peeled))\n \t\toid = &peeled;\n \n-\tobject = parse_object_or_die(oid, refname);\n+\tobject = parse_object_or_die(the_repository, oid, refname);\n \tif (object->type == OBJ_COMMIT)\n \t\tobject->flags |= NEEDS_BITMAP;\n \ndiff --git a/builtin/prune.c b/builtin/prune.c\nindex 1c357fffd8c..8f52da8bd66 100644\n--- a/builtin/prune.c\n+++ b/builtin/prune.c\n@@ -185,7 +185,7 @@ int cmd_prune(int argc,\n \t\tconst char *name = *argv++;\n \n \t\tif (!repo_get_oid(the_repository, name, &oid)) {\n-\t\t\tstruct object *object = parse_object_or_die(&oid,\n+\t\t\tstruct object *object = parse_object_or_die(the_repository, &oid,\n \t\t\t\t\t\t\t\t    name);\n \t\t\tadd_pending_object(&revs, object, \"\");\n \t\t}\ndiff --git a/midx-write.c b/midx-write.c\nindex 26d9d8bb148..ac80a8298ed 100644\n--- a/midx-write.c\n+++ b/midx-write.c\n@@ -708,7 +708,7 @@ static int add_ref_to_pending(const char *refname, const char *referent UNUSED,\n \tif (!peel_iterated_oid(revs->repo, oid, &peeled))\n \t\toid = &peeled;\n \n-\tobject = parse_object_or_die(oid, refname);\n+\tobject = parse_object_or_die(revs->repo, oid, refname);\n \tif (object->type != OBJ_COMMIT)\n \t\treturn 0;\n \n@@ -768,7 +768,7 @@ static int read_refs_snapshot(const char *refs_snapshot,\n \t\tif (*end)\n \t\t\tdie(_(\"malformed line: %s\"), buf.buf);\n \n-\t\tobject = parse_object_or_die(&oid, NULL);\n+\t\tobject = parse_object_or_die(revs->repo, &oid, NULL);\n \t\tif (preferred)\n \t\t\tobject->flags |= NEEDS_BITMAP;\n \ndiff --git a/object.c b/object.c\nindex 100bf9b8d12..154525a4972 100644\n--- a/object.c\n+++ b/object.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -18,14 +17,15 @@\n #include \"commit-graph.h\"\n #include \"loose.h\"\n \n-unsigned int get_max_object_index(void)\n+unsigned int get_max_object_index(const struct repository *repo)\n {\n-\treturn the_repository->parsed_objects->obj_hash_size;\n+\treturn repo->parsed_objects->obj_hash_size;\n }\n \n-struct object *get_indexed_object(unsigned int idx)\n+struct object *get_indexed_object(const struct repository *repo,\n+\t\t\t\t       unsigned int idx)\n {\n-\treturn the_repository->parsed_objects->obj_hash[idx];\n+\treturn repo->parsed_objects->obj_hash[idx];\n }\n \n static const char *object_type_strings[] = {\n@@ -283,10 +283,11 @@ struct object *parse_object_buffer(struct repository *r, const struct object_id\n \treturn obj;\n }\n \n-struct object *parse_object_or_die(const struct object_id *oid,\n+struct object *parse_object_or_die(struct repository *repo,\n+\t\t\t\t   const struct object_id *oid,\n \t\t\t\t   const char *name)\n {\n-\tstruct object *o = parse_object(the_repository, oid);\n+\tstruct object *o = parse_object(repo, oid);\n \tif (o)\n \t\treturn o;\n \n@@ -524,12 +525,12 @@ void object_array_remove_duplicates(struct object_array *array)\n \t}\n }\n \n-void clear_object_flags(unsigned flags)\n+void clear_object_flags(struct repository *repo, unsigned flags)\n {\n \tint i;\n \n-\tfor (i=0; i < the_repository->parsed_objects->obj_hash_size; i++) {\n-\t\tstruct object *obj = the_repository->parsed_objects->obj_hash[i];\n+\tfor (i=0; i < repo->parsed_objects->obj_hash_size; i++) {\n+\t\tstruct object *obj = repo->parsed_objects->obj_hash[i];\n \t\tif (obj)\n \t\t\tobj->flags &= ~flags;\n \t}\ndiff --git a/object.h b/object.h\nindex 17f32f1103e..a3040939799 100644\n--- a/object.h\n+++ b/object.h\n@@ -169,12 +169,13 @@ int type_from_string_gently(const char *str, ssize_t, int gentle);\n /*\n  * Return the current number of buckets in the object hashmap.\n  */\n-unsigned int get_max_object_index(void);\n+unsigned int get_max_object_index(const struct repository *repo);\n \n /*\n  * Return the object from the specified bucket in the object hashmap.\n  */\n-struct object *get_indexed_object(unsigned int);\n+struct object *get_indexed_object(const struct repository *repo,\n+\t\t\t\t       unsigned int);\n \n /*\n  * This can be used to see if we have heard of the object before, but\n@@ -231,7 +232,8 @@ struct object *parse_object_with_flags(struct repository *r,\n  * \"name\" parameter is not NULL, it is included in the error message\n  * (otherwise, the hex object ID is given).\n  */\n-struct object *parse_object_or_die(const struct object_id *oid, const char *name);\n+struct object *parse_object_or_die(struct repository *repo, const struct object_id *oid,\n+\t\t\t\t   const char *name);\n \n /* Given the result of read_sha1_file(), returns the object after\n  * parsing it.  eaten_p indicates if the object has a borrowed copy\n@@ -336,7 +338,7 @@ void object_array_remove_duplicates(struct object_array *array);\n  */\n void object_array_clear(struct object_array *array);\n \n-void clear_object_flags(unsigned flags);\n+void clear_object_flags(struct repository *repo, unsigned flags);\n \n /*\n  * Clear the specified object flags from all in-core commit objects from\ndiff --git a/pack-bitmap.c b/pack-bitmap.c\nindex f0e2c000252..7fd78c634ef 100644\n--- a/pack-bitmap.c\n+++ b/pack-bitmap.c\n@@ -1301,7 +1301,7 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,\n \trevs->tag_objects = tmp_tags;\n \n \treset_revision_walk();\n-\tclear_object_flags(UNINTERESTING);\n+\tclear_object_flags(repo, UNINTERESTING);\n \n \t/*\n \t * Then add the boundary commit(s) as fill-in traversal tips.\n@@ -1935,7 +1935,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,\n \t\tstruct object *object = revs->pending.objects[i].item;\n \n \t\tif (object->type == OBJ_NONE)\n-\t\t\tparse_object_or_die(&object->oid, NULL);\n+\t\t\tparse_object_or_die(revs->repo, &object->oid, NULL);\n \n \t\twhile (object->type == OBJ_TAG) {\n \t\t\tstruct tag *tag = (struct tag *) object;\n@@ -1945,7 +1945,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,\n \t\t\telse\n \t\t\t\tobject_list_insert(object, &wants);\n \n-\t\t\tobject = parse_object_or_die(get_tagged_oid(tag), NULL);\n+\t\t\tobject = parse_object_or_die(revs->repo, get_tagged_oid(tag), NULL);\n \t\t\tobject->flags |= (tag->object.flags & UNINTERESTING);\n \t\t}\n \ndiff --git a/reachable.c b/reachable.c\nindex 9ee04c89ec6..1b26b9b1d76 100644\n--- a/reachable.c\n+++ b/reachable.c\n@@ -45,7 +45,7 @@ static void add_one_file(const char *path, struct rev_info *revs)\n \t}\n \tstrbuf_trim(&buf);\n \tif (!get_oid_hex(buf.buf, &oid)) {\n-\t\tobject = parse_object_or_die(&oid, buf.buf);\n+\t\tobject = parse_object_or_die(the_repository, &oid, buf.buf);\n \t\tadd_pending_object(revs, object, \"\");\n \t}\n \tstrbuf_release(&buf);\n@@ -94,7 +94,7 @@ static int add_one_ref(const char *path, const char *referent UNUSED, const stru\n \t\treturn 0;\n \t}\n \n-\tobject = parse_object_or_die(oid, path);\n+\tobject = parse_object_or_die(the_repository, oid, path);\n \tadd_pending_object(revs, object, \"\");\n \n \treturn 0;\n@@ -218,7 +218,7 @@ static void add_recent_object(const struct object_id *oid,\n \tswitch (type) {\n \tcase OBJ_TAG:\n \tcase OBJ_COMMIT:\n-\t\tobj = parse_object_or_die(oid, NULL);\n+\t\tobj = parse_object_or_die(the_repository, oid, NULL);\n \t\tbreak;\n \tcase OBJ_TREE:\n \t\tobj = (struct object *)lookup_tree(the_repository, oid);\ndiff --git a/revision.c b/revision.c\nindex c4390f0938c..b536c4a29ad 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -3612,7 +3612,8 @@ static void set_children(struct rev_info *revs)\n \n void reset_revision_walk(void)\n {\n-\tclear_object_flags(SEEN | ADDED | SHOWN | TOPO_WALK_EXPLORED | TOPO_WALK_INDEGREE);\n+\tclear_object_flags(the_repository,\n+\t\t\t   SEEN | ADDED | SHOWN | TOPO_WALK_EXPLORED | TOPO_WALK_INDEGREE);\n }\n \n static int mark_uninteresting(const struct object_id *oid,\ndiff --git a/shallow.c b/shallow.c\nindex 4bd9342c9a7..06c3266a3e0 100644\n--- a/shallow.c\n+++ b/shallow.c\n@@ -226,7 +226,7 @@ struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av,\n \t * SHALLOW (excluded) and NOT_SHALLOW (included) should not be\n \t * set at this point. But better be safe than sorry.\n \t */\n-\tclear_object_flags(both_flags);\n+\tclear_object_flags(the_repository, both_flags);\n \n \tis_repository_shallow(the_repository); /* make sure shallows are read */\n \n@@ -613,9 +613,9 @@ static void paint_down(struct paint_info *info, const struct object_id *oid,\n \t\t}\n \t}\n \n-\tnr = get_max_object_index();\n+\tnr = get_max_object_index(the_repository);\n \tfor (i = 0; i < nr; i++) {\n-\t\tstruct object *o = get_indexed_object(i);\n+\t\tstruct object *o = get_indexed_object(the_repository, i);\n \t\tif (o && o->type == OBJ_COMMIT)\n \t\t\to->flags &= ~SEEN;\n \t}\n@@ -675,9 +675,9 @@ void assign_shallow_commits_to_refs(struct shallow_info *info,\n \t * Prepare the commit graph to track what refs can reach what\n \t * (new) shallow commits.\n \t */\n-\tnr = get_max_object_index();\n+\tnr = get_max_object_index(the_repository);\n \tfor (i = 0; i < nr; i++) {\n-\t\tstruct object *o = get_indexed_object(i);\n+\t\tstruct object *o = get_indexed_object(the_repository, i);\n \t\tif (!o || o->type != OBJ_COMMIT)\n \t\t\tcontinue;\n \ndiff --git a/upload-pack.c b/upload-pack.c\nindex 728b2477fcc..7412d3c6ce8 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -662,8 +662,8 @@ static int do_reachable_revlist(struct child_process *cmd,\n \n \tcmd_in = xfdopen(cmd->in, \"w\");\n \n-\tfor (i = get_max_object_index(); 0 < i; ) {\n-\t\to = get_indexed_object(--i);\n+\tfor (i = get_max_object_index(the_repository); 0 < i; ) {\n+\t\to = get_indexed_object(the_repository, --i);\n \t\tif (!o)\n \t\t\tcontinue;\n \t\tif (reachable && o->type == OBJ_COMMIT)\n@@ -731,8 +731,8 @@ static int get_reachable_list(struct upload_pack_data *data,\n \t\t\to->flags &= ~TMP_MARK;\n \t\t}\n \t}\n-\tfor (i = get_max_object_index(); 0 < i; i--) {\n-\t\to = get_indexed_object(i - 1);\n+\tfor (i = get_max_object_index(the_repository); 0 < i; i--) {\n+\t\to = get_indexed_object(the_repository, i - 1);\n \t\tif (o && o->type == OBJ_COMMIT &&\n \t\t    (o->flags & TMP_MARK)) {\n \t\t\tadd_object_array(o, NULL, reachable);\n@@ -1554,7 +1554,7 @@ static int parse_want_ref(struct packet_writer *writer, const char *line,\n \t\t}\n \n \t\tif (!o)\n-\t\t\to = parse_object_or_die(&oid, refname_nons);\n+\t\t\to = parse_object_or_die(the_repository, &oid, refname_nons);\n \n \t\tif (!(o->flags & WANTED)) {\n \t\t\to->flags |= WANTED;\n@@ -1790,7 +1790,7 @@ int upload_pack_v2(struct repository *r, struct packet_reader *request)\n \tenum fetch_state state = FETCH_PROCESS_ARGS;\n \tstruct upload_pack_data data;\n \n-\tclear_object_flags(ALL_FLAGS);\n+\tclear_object_flags(the_repository, ALL_FLAGS);\n \n \tupload_pack_data_init(&data);\n \tdata.use_sideband = LARGE_PACKET_MAX;\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513764","messageId":"20250307-b4-pks-objects-without-the-repository-v3-1-7bccf408731e@pks.im","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","subject":"[PATCH v3 01/12] csum-file: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T14:18:54Z","receivedAt":"2025-03-07T14:19:03Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"csum-file.c\" where we use the global\n`the_repository` variable, either explicitly or implicitly by using\n`the_hash_algo`.\n\nRefactor the code to stop using `the_repository` by adapting functions\nto receive required data as parameters. Adapt callsites accordingly by\neither using `the_repository->hash_algo`, or by using a context-provided\nhash algorithm in case the subsystem already got rid of its dependency\non `the_repository`.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fast-import.c  |  2 +-\n builtin/index-pack.c   |  2 +-\n builtin/pack-objects.c |  3 ++-\n commit-graph.c         |  9 ++++++---\n csum-file.c            | 28 ++++++++++++++++------------\n csum-file.h            | 12 ++++++++----\n midx-write.c           |  6 ++++--\n midx.c                 |  3 ++-\n pack-bitmap-write.c    |  2 +-\n pack-bitmap.c          |  9 +++++----\n pack-check.c           |  2 +-\n pack-revindex.c        |  3 ++-\n pack-write.c           | 12 ++++++------\n read-cache.c           |  2 +-\n 14 files changed, 56 insertions(+), 39 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 397a6f46ad8..86e6e754816 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -770,7 +770,7 @@ static void start_packfile(void)\n \tp->pack_fd = pack_fd;\n \tp->do_not_close = 1;\n \tp->repo = the_repository;\n-\tpack_file = hashfd(pack_fd, p->pack_name);\n+\tpack_file = hashfd(the_repository->hash_algo, pack_fd, p->pack_name);\n \n \tpack_data = p;\n \tpack_size = write_pack_header(pack_file, 0);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 52cc97d52cb..3eb5af20950 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -1381,7 +1381,7 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha\n \t\tREALLOC_ARRAY(objects, nr_objects + nr_unresolved + 1);\n \t\tmemset(objects + nr_objects + 1, 0,\n \t\t       nr_unresolved * sizeof(*objects));\n-\t\tf = hashfd(output_fd, curr_pack);\n+\t\tf = hashfd(the_repository->hash_algo, output_fd, curr_pack);\n \t\tfix_unresolved_deltas(f);\n \t\tstrbuf_addf(&msg, Q_(\"completed with %d local object\",\n \t\t\t\t     \"completed with %d local objects\",\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 58a9b161262..8e282f2a980 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -1311,7 +1311,8 @@ static void write_pack_file(void)\n \t\tchar *pack_tmp_name = NULL;\n \n \t\tif (pack_to_stdout)\n-\t\t\tf = hashfd_throughput(1, \"<stdout>\", progress_state);\n+\t\t\tf = hashfd_throughput(the_repository->hash_algo, 1,\n+\t\t\t\t\t      \"<stdout>\", progress_state);\n \t\telse\n \t\t\tf = create_tmp_packfile(&pack_tmp_name);\n \ndiff --git a/commit-graph.c b/commit-graph.c\nindex 1021ccb983d..8286d5dda24 100644\n--- a/commit-graph.c\n+++ b/commit-graph.c\n@@ -2090,11 +2090,13 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)\n \t\t\treturn -1;\n \t\t}\n \n-\t\tf = hashfd(get_tempfile_fd(graph_layer), get_tempfile_path(graph_layer));\n+\t\tf = hashfd(the_repository->hash_algo,\n+\t\t\t   get_tempfile_fd(graph_layer), get_tempfile_path(graph_layer));\n \t} else {\n \t\thold_lock_file_for_update_mode(&lk, ctx->graph_name,\n \t\t\t\t\t       LOCK_DIE_ON_ERROR, 0444);\n-\t\tf = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk));\n+\t\tf = hashfd(the_repository->hash_algo,\n+\t\t\t   get_lock_file_fd(&lk), get_lock_file_path(&lk));\n \t}\n \n \tcf = init_chunkfile(f);\n@@ -2716,7 +2718,8 @@ static void graph_report(const char *fmt, ...)\n \n static int commit_graph_checksum_valid(struct commit_graph *g)\n {\n-\treturn hashfile_checksum_valid(g->data, g->data_len);\n+\treturn hashfile_checksum_valid(the_repository->hash_algo,\n+\t\t\t\t       g->data, g->data_len);\n }\n \n static int verify_one_commit_graph(struct repository *r,\ndiff --git a/csum-file.c b/csum-file.c\nindex b58c183a4f0..6e21e3cac8a 100644\n--- a/csum-file.c\n+++ b/csum-file.c\n@@ -8,8 +8,6 @@\n  * able to verify hasn't been messed with afterwards.\n  */\n \n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"csum-file.h\"\n #include \"git-zlib.h\"\n@@ -148,21 +146,23 @@ void hashwrite(struct hashfile *f, const void *buf, unsigned int count)\n \t}\n }\n \n-struct hashfile *hashfd_check(const char *name)\n+struct hashfile *hashfd_check(const struct git_hash_algo *algop,\n+\t\t\t      const char *name)\n {\n \tint sink, check;\n \tstruct hashfile *f;\n \n \tsink = xopen(\"/dev/null\", O_WRONLY);\n \tcheck = xopen(name, O_RDONLY);\n-\tf = hashfd(sink, name);\n+\tf = hashfd(algop, sink, name);\n \tf->check_fd = check;\n \tf->check_buffer = xmalloc(f->buffer_len);\n \n \treturn f;\n }\n \n-static struct hashfile *hashfd_internal(int fd, const char *name,\n+static struct hashfile *hashfd_internal(const struct git_hash_algo *algop,\n+\t\t\t\t\tint fd, const char *name,\n \t\t\t\t\tstruct progress *tp,\n \t\t\t\t\tsize_t buffer_len)\n {\n@@ -176,7 +176,7 @@ static struct hashfile *hashfd_internal(int fd, const char *name,\n \tf->do_crc = 0;\n \tf->skip_hash = 0;\n \n-\tf->algop = unsafe_hash_algo(the_hash_algo);\n+\tf->algop = unsafe_hash_algo(algop);\n \tf->algop->init_fn(&f->ctx);\n \n \tf->buffer_len = buffer_len;\n@@ -186,17 +186,19 @@ static struct hashfile *hashfd_internal(int fd, const char *name,\n \treturn f;\n }\n \n-struct hashfile *hashfd(int fd, const char *name)\n+struct hashfile *hashfd(const struct git_hash_algo *algop,\n+\t\t\tint fd, const char *name)\n {\n \t/*\n \t * Since we are not going to use a progress meter to\n \t * measure the rate of data passing through this hashfile,\n \t * use a larger buffer size to reduce fsync() calls.\n \t */\n-\treturn hashfd_internal(fd, name, NULL, 128 * 1024);\n+\treturn hashfd_internal(algop, fd, name, NULL, 128 * 1024);\n }\n \n-struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp)\n+struct hashfile *hashfd_throughput(const struct git_hash_algo *algop,\n+\t\t\t\t   int fd, const char *name, struct progress *tp)\n {\n \t/*\n \t * Since we are expecting to report progress of the\n@@ -204,7 +206,7 @@ struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp\n \t * size so the progress indicators arrive at a more\n \t * frequent rate.\n \t */\n-\treturn hashfd_internal(fd, name, tp, 8 * 1024);\n+\treturn hashfd_internal(algop, fd, name, tp, 8 * 1024);\n }\n \n void hashfile_checkpoint_init(struct hashfile *f,\n@@ -246,13 +248,15 @@ uint32_t crc32_end(struct hashfile *f)\n \treturn f->crc32;\n }\n \n-int hashfile_checksum_valid(const unsigned char *data, size_t total_len)\n+int hashfile_checksum_valid(const struct git_hash_algo *algop,\n+\t\t\t    const unsigned char *data, size_t total_len)\n {\n \tunsigned char got[GIT_MAX_RAWSZ];\n \tstruct git_hash_ctx ctx;\n-\tconst struct git_hash_algo *algop = unsafe_hash_algo(the_hash_algo);\n \tsize_t data_len = total_len - algop->rawsz;\n \n+\talgop = unsafe_hash_algo(algop);\n+\n \tif (total_len < algop->rawsz)\n \t\treturn 0; /* say \"too short\"? */\n \ndiff --git a/csum-file.h b/csum-file.h\nindex ffccbf09966..07ae11024af 100644\n--- a/csum-file.h\n+++ b/csum-file.h\n@@ -45,9 +45,12 @@ int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *);\n #define CSUM_FSYNC\t\t2\n #define CSUM_HASH_IN_STREAM\t4\n \n-struct hashfile *hashfd(int fd, const char *name);\n-struct hashfile *hashfd_check(const char *name);\n-struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp);\n+struct hashfile *hashfd(const struct git_hash_algo *algop,\n+\t\t\tint fd, const char *name);\n+struct hashfile *hashfd_check(const struct git_hash_algo *algop,\n+\t\t\t      const char *name);\n+struct hashfile *hashfd_throughput(const struct git_hash_algo *algop,\n+\t\t\t\t   int fd, const char *name, struct progress *tp);\n \n /*\n  * Free the hashfile without flushing its contents to disk. This only\n@@ -66,7 +69,8 @@ void crc32_begin(struct hashfile *);\n uint32_t crc32_end(struct hashfile *);\n \n /* Verify checksum validity while reading. Returns non-zero on success. */\n-int hashfile_checksum_valid(const unsigned char *data, size_t len);\n+int hashfile_checksum_valid(const struct git_hash_algo *algop,\n+\t\t\t    const unsigned char *data, size_t len);\n \n /*\n  * Returns the total number of bytes fed to the hashfile so far (including ones\ndiff --git a/midx-write.c b/midx-write.c\nindex 48d6558253e..26d9d8bb148 100644\n--- a/midx-write.c\n+++ b/midx-write.c\n@@ -1342,10 +1342,12 @@ static int write_midx_internal(struct repository *r, const char *object_dir,\n \t\t\treturn -1;\n \t\t}\n \n-\t\tf = hashfd(get_tempfile_fd(incr), get_tempfile_path(incr));\n+\t\tf = hashfd(r->hash_algo, get_tempfile_fd(incr),\n+\t\t\t   get_tempfile_path(incr));\n \t} else {\n \t\thold_lock_file_for_update(&lk, midx_name.buf, LOCK_DIE_ON_ERROR);\n-\t\tf = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk));\n+\t\tf = hashfd(r->hash_algo, get_lock_file_fd(&lk),\n+\t\t\t   get_lock_file_path(&lk));\n \t}\n \n \tcf = init_chunkfile(f);\ndiff --git a/midx.c b/midx.c\nindex d91088efb87..807fdf72f7b 100644\n--- a/midx.c\n+++ b/midx.c\n@@ -747,7 +747,8 @@ int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, i\n \n int midx_checksum_valid(struct multi_pack_index *m)\n {\n-\treturn hashfile_checksum_valid(m->data, m->data_len);\n+\treturn hashfile_checksum_valid(m->repo->hash_algo,\n+\t\t\t\t       m->data, m->data_len);\n }\n \n struct clear_midx_data {\ndiff --git a/pack-bitmap-write.c b/pack-bitmap-write.c\nindex 34e86d49947..50e5c491ccb 100644\n--- a/pack-bitmap-write.c\n+++ b/pack-bitmap-write.c\n@@ -1030,7 +1030,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,\n \tif (writer->pseudo_merges_nr)\n \t\toptions |= BITMAP_OPT_PSEUDO_MERGES;\n \n-\tf = hashfd(fd, tmp_file.buf);\n+\tf = hashfd(the_repository->hash_algo, fd, tmp_file.buf);\n \n \tmemcpy(header.magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE));\n \theader.version = htons(default_version);\ndiff --git a/pack-bitmap.c b/pack-bitmap.c\nindex 6406953d322..f0e2c000252 100644\n--- a/pack-bitmap.c\n+++ b/pack-bitmap.c\n@@ -3024,7 +3024,8 @@ int bitmap_is_preferred_refname(struct repository *r, const char *refname)\n \treturn 0;\n }\n \n-static int verify_bitmap_file(const char *name)\n+static int verify_bitmap_file(const struct git_hash_algo *algop,\n+\t\t\t      const char *name)\n {\n \tstruct stat st;\n \tunsigned char *data;\n@@ -3040,7 +3041,7 @@ static int verify_bitmap_file(const char *name)\n \n \tdata = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);\n \tclose(fd);\n-\tif (!hashfile_checksum_valid(data, st.st_size))\n+\tif (!hashfile_checksum_valid(algop, data, st.st_size))\n \t\tres = error(_(\"bitmap file '%s' has invalid checksum\"),\n \t\t\t    name);\n \n@@ -3055,14 +3056,14 @@ int verify_bitmap_files(struct repository *r)\n \tfor (struct multi_pack_index *m = get_multi_pack_index(r);\n \t     m; m = m->next) {\n \t\tchar *midx_bitmap_name = midx_bitmap_filename(m);\n-\t\tres |= verify_bitmap_file(midx_bitmap_name);\n+\t\tres |= verify_bitmap_file(r->hash_algo, midx_bitmap_name);\n \t\tfree(midx_bitmap_name);\n \t}\n \n \tfor (struct packed_git *p = get_all_packs(r);\n \t     p; p = p->next) {\n \t\tchar *pack_bitmap_name = pack_bitmap_filename(p);\n-\t\tres |= verify_bitmap_file(pack_bitmap_name);\n+\t\tres |= verify_bitmap_file(r->hash_algo, pack_bitmap_name);\n \t\tfree(pack_bitmap_name);\n \t}\n \ndiff --git a/pack-check.c b/pack-check.c\nindex d0aeb5ec412..6bcadc1e679 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -180,7 +180,7 @@ int verify_pack_index(struct packed_git *p)\n \t\treturn error(\"packfile %s index not opened\", p->pack_name);\n \n \t/* Verify SHA1 sum of the index file */\n-\tif (!hashfile_checksum_valid(p->index_data, p->index_size))\n+\tif (!hashfile_checksum_valid(the_repository->hash_algo, p->index_data, p->index_size))\n \t\terr = error(\"Packfile index for %s hash mismatch\",\n \t\t\t    p->pack_name);\n \treturn err;\ndiff --git a/pack-revindex.c b/pack-revindex.c\nindex d3832478d99..78139e3d7f5 100644\n--- a/pack-revindex.c\n+++ b/pack-revindex.c\n@@ -322,7 +322,8 @@ int verify_pack_revindex(struct packed_git *p)\n \tif (!p->revindex_map || !p->revindex_data)\n \t\treturn res;\n \n-\tif (!hashfile_checksum_valid((const unsigned char *)p->revindex_map, p->revindex_size)) {\n+\tif (!hashfile_checksum_valid(the_repository->hash_algo,\n+\t\t\t\t     (const unsigned char *)p->revindex_map, p->revindex_size)) {\n \t\terror(_(\"invalid checksum\"));\n \t\tres = -1;\n \t}\ndiff --git a/pack-write.c b/pack-write.c\nindex 823e40b42f2..5eb89f44cf4 100644\n--- a/pack-write.c\n+++ b/pack-write.c\n@@ -82,7 +82,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \n \tif (opts->flags & WRITE_IDX_VERIFY) {\n \t\tassert(index_name);\n-\t\tf = hashfd_check(index_name);\n+\t\tf = hashfd_check(the_repository->hash_algo, index_name);\n \t} else {\n \t\tif (!index_name) {\n \t\t\tstruct strbuf tmp_file = STRBUF_INIT;\n@@ -92,7 +92,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\t\tunlink(index_name);\n \t\t\tfd = xopen(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t}\n-\t\tf = hashfd(fd, index_name);\n+\t\tf = hashfd(the_repository->hash_algo, fd, index_name);\n \t}\n \n \t/* if last object's offset is >= 2^31 we should use index V2 */\n@@ -268,7 +268,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\tfd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t\tpath = xstrdup(rev_name);\n \t\t}\n-\t\tf = hashfd(fd, path);\n+\t\tf = hashfd(the_repository->hash_algo, fd, path);\n \t} else if (flags & WRITE_REV_VERIFY) {\n \t\tstruct stat statbuf;\n \t\tif (stat(rev_name, &statbuf)) {\n@@ -278,7 +278,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\t} else\n \t\t\t\tdie_errno(_(\"could not stat: %s\"), rev_name);\n \t\t}\n-\t\tf = hashfd_check(rev_name);\n+\t\tf = hashfd_check(the_repository->hash_algo, rev_name);\n \t\tpath = xstrdup(rev_name);\n \t} else {\n \t\treturn NULL;\n@@ -346,7 +346,7 @@ static char *write_mtimes_file(const struct git_hash_algo *hash_algo,\n \n \tfd = odb_mkstemp(&tmp_file, \"pack/tmp_mtimes_XXXXXX\");\n \tmtimes_name = strbuf_detach(&tmp_file, NULL);\n-\tf = hashfd(fd, mtimes_name);\n+\tf = hashfd(the_repository->hash_algo, fd, mtimes_name);\n \n \twrite_mtimes_header(hash_algo, f);\n \twrite_mtimes_objects(f, to_pack, objects, nr_objects);\n@@ -534,7 +534,7 @@ struct hashfile *create_tmp_packfile(char **pack_tmp_name)\n \n \tfd = odb_mkstemp(&tmpname, \"pack/tmp_pack_XXXXXX\");\n \t*pack_tmp_name = strbuf_detach(&tmpname, NULL);\n-\treturn hashfd(fd, *pack_tmp_name);\n+\treturn hashfd(the_repository->hash_algo, fd, *pack_tmp_name);\n }\n \n static void rename_tmp_packfile(struct strbuf *name_prefix, const char *source,\ndiff --git a/read-cache.c b/read-cache.c\nindex e678c13e8f1..a012cb22368 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -2848,7 +2848,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,\n \tstruct strbuf sb = STRBUF_INIT;\n \tint nr, nr_threads, ret;\n \n-\tf = hashfd(tempfile->fd, tempfile->filename.buf);\n+\tf = hashfd(the_repository->hash_algo, tempfile->fd, tempfile->filename.buf);\n \n \tprepare_repo_settings(r);\n \tf->skip_hash = r->settings.index_skip_hash;\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513763","messageId":"20250307-b4-pks-objects-without-the-repository-v3-3-7bccf408731e@pks.im","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","subject":"[PATCH v3 03/12] pack-write: stop depending on `the_repository` and `the_hash_algo`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T14:18:56Z","receivedAt":"2025-03-07T14:19:05Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are a couple of functions in \"pack-write.c\" that implicitly depend\non `the_repository` or `the_hash_algo`. Remove this dependency by\ninjecting the repository via a parameter and adapt callers accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fast-import.c  |  2 +-\n builtin/index-pack.c   |  4 ++--\n builtin/pack-objects.c |  4 ++--\n bulk-checkin.c         |  4 ++--\n midx-write.c           |  2 +-\n pack-write.c           | 55 +++++++++++++++++++++++++-------------------------\n pack.h                 | 11 +++++-----\n 7 files changed, 41 insertions(+), 41 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 86e6e754816..e1758aa9514 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -798,7 +798,7 @@ static const char *create_index(void)\n \tif (c != last)\n \t\tdie(\"internal consistency error creating the index\");\n \n-\ttmpfile = write_idx_file(the_hash_algo, NULL, idx, object_count,\n+\ttmpfile = write_idx_file(the_repository, NULL, idx, object_count,\n \t\t\t\t &pack_idx_opts, pack_data->hash);\n \tfree(idx);\n \treturn tmpfile;\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 1268032d769..174e03afa61 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -2088,10 +2088,10 @@ int cmd_index_pack(int argc,\n \tALLOC_ARRAY(idx_objects, nr_objects);\n \tfor (i = 0; i < nr_objects; i++)\n \t\tidx_objects[i] = &objects[i].idx;\n-\tcurr_index = write_idx_file(the_hash_algo, index_name, idx_objects,\n+\tcurr_index = write_idx_file(the_repository, index_name, idx_objects,\n \t\t\t\t    nr_objects, &opts, pack_hash);\n \tif (rev_index)\n-\t\tcurr_rev_index = write_rev_file(the_hash_algo, rev_index_name,\n+\t\tcurr_rev_index = write_rev_file(the_repository, rev_index_name,\n \t\t\t\t\t\tidx_objects, nr_objects,\n \t\t\t\t\t\tpack_hash, opts.flags);\n \tfree(idx_objects);\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex c3adbc94504..e05dfc4021e 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -1314,7 +1314,7 @@ static void write_pack_file(void)\n \t\t\tf = hashfd_throughput(the_repository->hash_algo, 1,\n \t\t\t\t\t      \"<stdout>\", progress_state);\n \t\telse\n-\t\t\tf = create_tmp_packfile(&pack_tmp_name);\n+\t\t\tf = create_tmp_packfile(the_repository, &pack_tmp_name);\n \n \t\toffset = write_pack_header(f, nr_remaining);\n \n@@ -1407,7 +1407,7 @@ static void write_pack_file(void)\n \t\t\tif (cruft)\n \t\t\t\tpack_idx_opts.flags |= WRITE_MTIMES;\n \n-\t\t\tstage_tmp_packfiles(the_hash_algo, &tmpname,\n+\t\t\tstage_tmp_packfiles(the_repository, &tmpname,\n \t\t\t\t\t    pack_tmp_name, written_list,\n \t\t\t\t\t    nr_written, &to_pack,\n \t\t\t\t\t    &pack_idx_opts, hash,\ndiff --git a/bulk-checkin.c b/bulk-checkin.c\nindex 20f2da67b93..23ac00ea0a6 100644\n--- a/bulk-checkin.c\n+++ b/bulk-checkin.c\n@@ -44,7 +44,7 @@ static void finish_tmp_packfile(struct strbuf *basename,\n {\n \tchar *idx_tmp_name = NULL;\n \n-\tstage_tmp_packfiles(the_hash_algo, basename, pack_tmp_name,\n+\tstage_tmp_packfiles(the_repository, basename, pack_tmp_name,\n \t\t\t    written_list, nr_written, NULL, pack_idx_opts, hash,\n \t\t\t    &idx_tmp_name);\n \trename_tmp_packfile_idx(basename, &idx_tmp_name);\n@@ -244,7 +244,7 @@ static void prepare_to_stream(struct bulk_checkin_packfile *state,\n \tif (!(flags & HASH_WRITE_OBJECT) || state->f)\n \t\treturn;\n \n-\tstate->f = create_tmp_packfile(&state->pack_tmp_name);\n+\tstate->f = create_tmp_packfile(the_repository, &state->pack_tmp_name);\n \treset_pack_idx_option(&state->pack_idx_opts);\n \n \t/* Pretend we are going to write only one object */\ndiff --git a/midx-write.c b/midx-write.c\nindex ac80a8298ed..a628ac24dcb 100644\n--- a/midx-write.c\n+++ b/midx-write.c\n@@ -658,7 +658,7 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash,\n \tstrbuf_addf(&buf, \"%s-%s.rev\", midx_name, hash_to_hex_algop(midx_hash,\n \t\t\t\t\t\t\t\t    ctx->repo->hash_algo));\n \n-\ttmp_file = write_rev_file_order(ctx->repo->hash_algo, NULL, ctx->pack_order,\n+\ttmp_file = write_rev_file_order(ctx->repo, NULL, ctx->pack_order,\n \t\t\t\t\tctx->entries_nr, midx_hash, WRITE_REV);\n \n \tif (finalize_object_file(tmp_file, buf.buf))\ndiff --git a/pack-write.c b/pack-write.c\nindex 5eb89f44cf4..6b06315f80a 100644\n--- a/pack-write.c\n+++ b/pack-write.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"gettext.h\"\n@@ -56,7 +54,7 @@ static int need_large_offset(off_t offset, const struct pack_idx_option *opts)\n  * The *sha1 contains the pack content SHA1 hash.\n  * The objects array passed in will be sorted by SHA1 on exit.\n  */\n-const char *write_idx_file(const struct git_hash_algo *hash_algo,\n+const char *write_idx_file(struct repository *repo,\n \t\t\t   const char *index_name, struct pack_idx_entry **objects,\n \t\t\t   int nr_objects, const struct pack_idx_option *opts,\n \t\t\t   const unsigned char *sha1)\n@@ -82,7 +80,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \n \tif (opts->flags & WRITE_IDX_VERIFY) {\n \t\tassert(index_name);\n-\t\tf = hashfd_check(the_repository->hash_algo, index_name);\n+\t\tf = hashfd_check(repo->hash_algo, index_name);\n \t} else {\n \t\tif (!index_name) {\n \t\t\tstruct strbuf tmp_file = STRBUF_INIT;\n@@ -92,7 +90,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\t\tunlink(index_name);\n \t\t\tfd = xopen(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t}\n-\t\tf = hashfd(the_repository->hash_algo, fd, index_name);\n+\t\tf = hashfd(repo->hash_algo, fd, index_name);\n \t}\n \n \t/* if last object's offset is >= 2^31 we should use index V2 */\n@@ -131,7 +129,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\tstruct pack_idx_entry *obj = *list++;\n \t\tif (index_version < 2)\n \t\t\thashwrite_be32(f, obj->offset);\n-\t\thashwrite(f, obj->oid.hash, hash_algo->rawsz);\n+\t\thashwrite(f, obj->oid.hash, repo->hash_algo->rawsz);\n \t\tif ((opts->flags & WRITE_IDX_STRICT) &&\n \t\t    (i && oideq(&list[-2]->oid, &obj->oid)))\n \t\t\tdie(\"The same object %s appears twice in the pack\",\n@@ -173,7 +171,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\t}\n \t}\n \n-\thashwrite(f, sha1, hash_algo->rawsz);\n+\thashwrite(f, sha1, repo->hash_algo->rawsz);\n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n \t\t\t  CSUM_HASH_IN_STREAM | CSUM_CLOSE |\n \t\t\t  ((opts->flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC));\n@@ -217,7 +215,7 @@ static void write_rev_trailer(const struct git_hash_algo *hash_algo,\n \thashwrite(f, hash, hash_algo->rawsz);\n }\n \n-char *write_rev_file(const struct git_hash_algo *hash_algo,\n+char *write_rev_file(struct repository *repo,\n \t\t     const char *rev_name,\n \t\t     struct pack_idx_entry **objects,\n \t\t     uint32_t nr_objects,\n@@ -236,7 +234,7 @@ char *write_rev_file(const struct git_hash_algo *hash_algo,\n \t\tpack_order[i] = i;\n \tQSORT_S(pack_order, nr_objects, pack_order_cmp, objects);\n \n-\tret = write_rev_file_order(hash_algo, rev_name, pack_order, nr_objects,\n+\tret = write_rev_file_order(repo, rev_name, pack_order, nr_objects,\n \t\t\t\t   hash, flags);\n \n \tfree(pack_order);\n@@ -244,7 +242,7 @@ char *write_rev_file(const struct git_hash_algo *hash_algo,\n \treturn ret;\n }\n \n-char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n+char *write_rev_file_order(struct repository *repo,\n \t\t\t   const char *rev_name,\n \t\t\t   uint32_t *pack_order,\n \t\t\t   uint32_t nr_objects,\n@@ -268,7 +266,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\tfd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t\tpath = xstrdup(rev_name);\n \t\t}\n-\t\tf = hashfd(the_repository->hash_algo, fd, path);\n+\t\tf = hashfd(repo->hash_algo, fd, path);\n \t} else if (flags & WRITE_REV_VERIFY) {\n \t\tstruct stat statbuf;\n \t\tif (stat(rev_name, &statbuf)) {\n@@ -278,18 +276,18 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\t} else\n \t\t\t\tdie_errno(_(\"could not stat: %s\"), rev_name);\n \t\t}\n-\t\tf = hashfd_check(the_repository->hash_algo, rev_name);\n+\t\tf = hashfd_check(repo->hash_algo, rev_name);\n \t\tpath = xstrdup(rev_name);\n \t} else {\n \t\treturn NULL;\n \t}\n \n-\twrite_rev_header(hash_algo, f);\n+\twrite_rev_header(repo->hash_algo, f);\n \n \twrite_rev_index_positions(f, pack_order, nr_objects);\n-\twrite_rev_trailer(hash_algo, f, hash);\n+\twrite_rev_trailer(repo->hash_algo, f, hash);\n \n-\tif (adjust_shared_perm(the_repository, path) < 0)\n+\tif (adjust_shared_perm(repo, path) < 0)\n \t\tdie(_(\"failed to make %s readable\"), path);\n \n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n@@ -330,7 +328,7 @@ static void write_mtimes_trailer(const struct git_hash_algo *hash_algo,\n \thashwrite(f, hash, hash_algo->rawsz);\n }\n \n-static char *write_mtimes_file(const struct git_hash_algo *hash_algo,\n+static char *write_mtimes_file(struct repository *repo,\n \t\t\t       struct packing_data *to_pack,\n \t\t\t       struct pack_idx_entry **objects,\n \t\t\t       uint32_t nr_objects,\n@@ -346,13 +344,13 @@ static char *write_mtimes_file(const struct git_hash_algo *hash_algo,\n \n \tfd = odb_mkstemp(&tmp_file, \"pack/tmp_mtimes_XXXXXX\");\n \tmtimes_name = strbuf_detach(&tmp_file, NULL);\n-\tf = hashfd(the_repository->hash_algo, fd, mtimes_name);\n+\tf = hashfd(repo->hash_algo, fd, mtimes_name);\n \n-\twrite_mtimes_header(hash_algo, f);\n+\twrite_mtimes_header(repo->hash_algo, f);\n \twrite_mtimes_objects(f, to_pack, objects, nr_objects);\n-\twrite_mtimes_trailer(hash_algo, f, hash);\n+\twrite_mtimes_trailer(repo->hash_algo, f, hash);\n \n-\tif (adjust_shared_perm(the_repository, mtimes_name) < 0)\n+\tif (adjust_shared_perm(repo, mtimes_name) < 0)\n \t\tdie(_(\"failed to make %s readable\"), mtimes_name);\n \n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n@@ -527,14 +525,15 @@ int encode_in_pack_object_header(unsigned char *hdr, int hdr_len,\n \treturn n;\n }\n \n-struct hashfile *create_tmp_packfile(char **pack_tmp_name)\n+struct hashfile *create_tmp_packfile(struct repository *repo,\n+\t\t\t\t     char **pack_tmp_name)\n {\n \tstruct strbuf tmpname = STRBUF_INIT;\n \tint fd;\n \n \tfd = odb_mkstemp(&tmpname, \"pack/tmp_pack_XXXXXX\");\n \t*pack_tmp_name = strbuf_detach(&tmpname, NULL);\n-\treturn hashfd(the_repository->hash_algo, fd, *pack_tmp_name);\n+\treturn hashfd(repo->hash_algo, fd, *pack_tmp_name);\n }\n \n static void rename_tmp_packfile(struct strbuf *name_prefix, const char *source,\n@@ -555,7 +554,7 @@ void rename_tmp_packfile_idx(struct strbuf *name_buffer,\n \trename_tmp_packfile(name_buffer, *idx_tmp_name, \"idx\");\n }\n \n-void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,\n+void stage_tmp_packfiles(struct repository *repo,\n \t\t\t struct strbuf *name_buffer,\n \t\t\t const char *pack_tmp_name,\n \t\t\t struct pack_idx_entry **written_list,\n@@ -568,19 +567,19 @@ void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,\n \tchar *rev_tmp_name = NULL;\n \tchar *mtimes_tmp_name = NULL;\n \n-\tif (adjust_shared_perm(the_repository, pack_tmp_name))\n+\tif (adjust_shared_perm(repo, pack_tmp_name))\n \t\tdie_errno(\"unable to make temporary pack file readable\");\n \n-\t*idx_tmp_name = (char *)write_idx_file(hash_algo, NULL, written_list,\n+\t*idx_tmp_name = (char *)write_idx_file(repo, NULL, written_list,\n \t\t\t\t\t       nr_written, pack_idx_opts, hash);\n-\tif (adjust_shared_perm(the_repository, *idx_tmp_name))\n+\tif (adjust_shared_perm(repo, *idx_tmp_name))\n \t\tdie_errno(\"unable to make temporary index file readable\");\n \n-\trev_tmp_name = write_rev_file(hash_algo, NULL, written_list, nr_written,\n+\trev_tmp_name = write_rev_file(repo, NULL, written_list, nr_written,\n \t\t\t\t      hash, pack_idx_opts->flags);\n \n \tif (pack_idx_opts->flags & WRITE_MTIMES) {\n-\t\tmtimes_tmp_name = write_mtimes_file(hash_algo, to_pack,\n+\t\tmtimes_tmp_name = write_mtimes_file(repo, to_pack,\n \t\t\t\t\t\t    written_list, nr_written,\n \t\t\t\t\t\t    hash);\n \t}\ndiff --git a/pack.h b/pack.h\nindex 9f1194ac13d..5d4393eaffe 100644\n--- a/pack.h\n+++ b/pack.h\n@@ -87,7 +87,7 @@ struct progress;\n /* Note, the data argument could be NULL if object type is blob */\n typedef int (*verify_fn)(const struct object_id *, enum object_type, unsigned long, void*, int*);\n \n-const char *write_idx_file(const struct git_hash_algo *hash_algo,\n+const char *write_idx_file(struct repository *repo,\n \t\t\t   const char *index_name,\n \t\t\t   struct pack_idx_entry **objects,\n \t\t\t   int nr_objects,\n@@ -106,13 +106,13 @@ struct ref;\n \n void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought);\n \n-char *write_rev_file(const struct git_hash_algo *hash_algo,\n+char *write_rev_file(struct repository *repo,\n \t\t     const char *rev_name,\n \t\t     struct pack_idx_entry **objects,\n \t\t     uint32_t nr_objects,\n \t\t     const unsigned char *hash,\n \t\t     unsigned flags);\n-char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n+char *write_rev_file_order(struct repository *repo,\n \t\t\t   const char *rev_name,\n \t\t\t   uint32_t *pack_order,\n \t\t\t   uint32_t nr_objects,\n@@ -134,8 +134,9 @@ int read_pack_header(int fd, struct pack_header *);\n \n struct packing_data;\n \n-struct hashfile *create_tmp_packfile(char **pack_tmp_name);\n-void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,\n+struct hashfile *create_tmp_packfile(struct repository *repo,\n+\t\t\t\t     char **pack_tmp_name);\n+void stage_tmp_packfiles(struct repository *repo,\n \t\t\t struct strbuf *name_buffer,\n \t\t\t const char *pack_tmp_name,\n \t\t\t struct pack_idx_entry **written_list,\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513765","messageId":"20250307-b4-pks-objects-without-the-repository-v3-5-7bccf408731e@pks.im","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","subject":"[PATCH v3 05/12] pack-check: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T14:18:58Z","receivedAt":"2025-03-07T14:19:05Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"pack-check.c\" where we use the global\n`the_repository` variable, either explicitly or implicitly by using\n`the_hash_algo`. In all of those cases we already have a repository\navailable in the calling context though.\n\nRefactor the code to instead use the caller-provided repository and\nremove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n pack-check.c | 11 +++++------\n 1 file changed, 5 insertions(+), 6 deletions(-)\n\ndiff --git a/pack-check.c b/pack-check.c\nindex 017dc740f7b..95dcbbe9852 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -44,7 +43,7 @@ int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,\n \t} while (len);\n \n \tindex_crc = p->index_data;\n-\tindex_crc += 2 + 256 + (size_t)p->num_objects * (the_hash_algo->rawsz/4) + nr;\n+\tindex_crc += 2 + 256 + (size_t)p->num_objects * (p->repo->hash_algo->rawsz/4) + nr;\n \n \treturn data_crc != ntohl(*index_crc);\n }\n@@ -81,11 +80,11 @@ static int verify_packfile(struct repository *r,\n \t} while (offset < pack_sig_ofs);\n \tgit_hash_final(hash, &ctx);\n \tpack_sig = use_pack(p, w_curs, pack_sig_ofs, NULL);\n-\tif (!hasheq(hash, pack_sig, the_repository->hash_algo))\n+\tif (!hasheq(hash, pack_sig, r->hash_algo))\n \t\terr = error(\"%s pack checksum mismatch\",\n \t\t\t    p->pack_name);\n \tif (!hasheq(index_base + index_size - r->hash_algo->hexsz, pack_sig,\n-\t\t    the_repository->hash_algo))\n+\t\t    r->hash_algo))\n \t\terr = error(\"%s pack checksum does not match its index\",\n \t\t\t    p->pack_name);\n \tunuse_pack(w_curs);\n@@ -132,7 +131,7 @@ static int verify_packfile(struct repository *r,\n \t\tunuse_pack(w_curs);\n \n \t\tif (type == OBJ_BLOB &&\n-\t\t    repo_settings_get_big_file_threshold(the_repository) <= size) {\n+\t\t    repo_settings_get_big_file_threshold(r) <= size) {\n \t\t\t/*\n \t\t\t * Let stream_object_signature() check it with\n \t\t\t * the streaming interface; no point slurping\n@@ -181,7 +180,7 @@ int verify_pack_index(struct packed_git *p)\n \t\treturn error(\"packfile %s index not opened\", p->pack_name);\n \n \t/* Verify SHA1 sum of the index file */\n-\tif (!hashfile_checksum_valid(the_repository->hash_algo, p->index_data, p->index_size))\n+\tif (!hashfile_checksum_valid(p->repo->hash_algo, p->index_data, p->index_size))\n \t\terr = error(\"Packfile index for %s hash mismatch\",\n \t\t\t    p->pack_name);\n \treturn err;\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513768","messageId":"20250307-b4-pks-objects-without-the-repository-v3-4-7bccf408731e@pks.im","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","subject":"[PATCH v3 04/12] environment: move access to \"core.bigFileThreshold\" into repo settings","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T14:18:57Z","receivedAt":"2025-03-07T14:19:05Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The \"core.bigFileThreshold\" setting is stored in a global variable and\npopulated via `git_default_core_config()`. This may cause issues in\nthe case where one is handling multiple different repositories in a\nsingle process with different values for that config key, as we may or\nmay not see the correct value in that case. Furthermore, global state\nblocks our path towards libification.\n\nRefactor the code so that we instead store the value in `struct\nrepo_settings`, where the value is computed as-needed and cached.\n\nNote that this change requires us to adapt one test in t1050 that\nverifies that we die when parsing an invalid \"core.bigFileThreshold\"\nvalue. The exercised Git command doesn't use the value at all, and thus\nit won't hit the new code path that parses the value. This is addressed\nby using git-hash-object(1) instead, which does read the value.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n archive.c                |  2 +-\n builtin/fast-import.c    |  4 ++--\n builtin/index-pack.c     |  6 ++++--\n builtin/pack-objects.c   |  6 ++++--\n builtin/unpack-objects.c |  3 ++-\n config.c                 |  5 -----\n diff.c                   |  6 ++++--\n environment.c            |  1 -\n environment.h            |  1 -\n object-file.c            |  6 ++++--\n pack-check.c             |  3 ++-\n repo-settings.c          | 20 ++++++++++++++++++++\n repo-settings.h          |  5 +++++\n streaming.c              |  3 ++-\n t/t1050-large.sh         |  3 ++-\n 15 files changed, 52 insertions(+), 22 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex 8be4e7ac8db..f4331aeb49e 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -216,7 +216,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,\n \t/* Stream it? */\n \tif (S_ISREG(mode) && !args->convert &&\n \t    oid_object_info(args->repo, oid, &size) == OBJ_BLOB &&\n-\t    size > big_file_threshold)\n+\t    size > repo_settings_get_big_file_threshold(the_repository))\n \t\treturn write_entry(args, oid, path.buf, path.len, mode, NULL, size);\n \n \tbuffer = object_file_to_archive(args, path.buf, oid, mode, &type, &size);\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex e1758aa9514..ce52f78579d 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -2021,7 +2021,7 @@ static void parse_and_store_blob(\n \tstatic struct strbuf buf = STRBUF_INIT;\n \tuintmax_t len;\n \n-\tif (parse_data(&buf, big_file_threshold, &len))\n+\tif (parse_data(&buf, repo_settings_get_big_file_threshold(the_repository), &len))\n \t\tstore_object(OBJ_BLOB, &buf, last, oidout, mark);\n \telse {\n \t\tif (last) {\n@@ -3402,7 +3402,7 @@ static int parse_one_option(const char *option)\n \t\tunsigned long v;\n \t\tif (!git_parse_ulong(option, &v))\n \t\t\treturn 0;\n-\t\tbig_file_threshold = v;\n+\t\trepo_settings_set_big_file_threshold(the_repository, v);\n \t} else if (skip_prefix(option, \"depth=\", &option)) {\n \t\toption_depth(option);\n \t} else if (skip_prefix(option, \"active-branches=\", &option)) {\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 174e03afa61..09c0a8adf63 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -485,7 +485,8 @@ static void *unpack_entry_data(off_t offset, unsigned long size,\n \t\tgit_hash_update(&c, hdr, hdrlen);\n \t} else\n \t\toid = NULL;\n-\tif (type == OBJ_BLOB && size > big_file_threshold)\n+\tif (type == OBJ_BLOB &&\n+\t    size > repo_settings_get_big_file_threshold(the_repository))\n \t\tbuf = fixed_buf;\n \telse\n \t\tbuf = xmallocz(size);\n@@ -799,7 +800,8 @@ static int check_collison(struct object_entry *entry)\n \tenum object_type type;\n \tunsigned long size;\n \n-\tif (entry->size <= big_file_threshold || entry->type != OBJ_BLOB)\n+\tif (entry->size <= repo_settings_get_big_file_threshold(the_repository) ||\n+\t    entry->type != OBJ_BLOB)\n \t\treturn -1;\n \n \tmemset(&data, 0, sizeof(data));\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex e05dfc4021e..eefc6c78096 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -499,7 +499,8 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent\n \n \tif (!usable_delta) {\n \t\tif (oe_type(entry) == OBJ_BLOB &&\n-\t\t    oe_size_greater_than(&to_pack, entry, big_file_threshold) &&\n+\t\t    oe_size_greater_than(&to_pack, entry,\n+\t\t\t\t\t repo_settings_get_big_file_threshold(the_repository)) &&\n \t\t    (st = open_istream(the_repository, &entry->idx.oid, &type,\n \t\t\t\t       &size, NULL)) != NULL)\n \t\t\tbuf = NULL;\n@@ -2454,7 +2455,8 @@ static void get_object_details(void)\n \t\tstruct object_entry *entry = sorted_by_offset[i];\n \t\tcheck_object(entry, i);\n \t\tif (entry->type_valid &&\n-\t\t    oe_size_greater_than(&to_pack, entry, big_file_threshold))\n+\t\t    oe_size_greater_than(&to_pack, entry,\n+\t\t\t\t\t repo_settings_get_big_file_threshold(the_repository)))\n \t\t\tentry->no_try_delta = 1;\n \t\tdisplay_progress(progress_state, i + 1);\n \t}\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex 8383bcf4049..e20c120913e 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -553,7 +553,8 @@ static void unpack_one(unsigned nr)\n \n \tswitch (type) {\n \tcase OBJ_BLOB:\n-\t\tif (!dry_run && size > big_file_threshold) {\n+\t\tif (!dry_run &&\n+\t\t    size > repo_settings_get_big_file_threshold(the_repository)) {\n \t\t\tstream_blob(size, nr);\n \t\t\treturn;\n \t\t}\ndiff --git a/config.c b/config.c\nindex dfd03b9421c..dc95608f749 100644\n--- a/config.c\n+++ b/config.c\n@@ -1490,11 +1490,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.bigfilethreshold\")) {\n-\t\tbig_file_threshold = git_config_ulong(var, value, ctx->kvi);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.autocrlf\")) {\n \t\tif (value && !strcasecmp(value, \"input\")) {\n \t\t\tauto_crlf = AUTO_CRLF_INPUT;\ndiff --git a/diff.c b/diff.c\nindex c89c15d98e0..4f802b4251c 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -4193,7 +4193,8 @@ int diff_populate_filespec(struct repository *r,\n \t\t * is probably fine.\n \t\t */\n \t\tif (check_binary &&\n-\t\t    s->size > big_file_threshold && s->is_binary == -1) {\n+\t\t    s->size > repo_settings_get_big_file_threshold(the_repository) &&\n+\t\t    s->is_binary == -1) {\n \t\t\ts->is_binary = 1;\n \t\t\treturn 0;\n \t\t}\n@@ -4243,7 +4244,8 @@ int diff_populate_filespec(struct repository *r,\n \t\tif (size_only || check_binary) {\n \t\t\tif (size_only)\n \t\t\t\treturn 0;\n-\t\t\tif (s->size > big_file_threshold && s->is_binary == -1) {\n+\t\t\tif (s->size > repo_settings_get_big_file_threshold(the_repository) &&\n+\t\t\t    s->is_binary == -1) {\n \t\t\t\ts->is_binary = 1;\n \t\t\t\treturn 0;\n \t\t\t}\ndiff --git a/environment.c b/environment.c\nindex 9e4c7781be0..3c32367c28c 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -49,7 +49,6 @@ int fsync_object_files = -1;\n int use_fsync = -1;\n enum fsync_method fsync_method = FSYNC_METHOD_DEFAULT;\n enum fsync_component fsync_components = FSYNC_COMPONENTS_DEFAULT;\n-unsigned long big_file_threshold = 512 * 1024 * 1024;\n char *editor_program;\n char *askpass_program;\n char *excludes_file;\ndiff --git a/environment.h b/environment.h\nindex 45e690f203f..91d854dcb08 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -154,7 +154,6 @@ extern int zlib_compression_level;\n extern int pack_compression_level;\n extern size_t packed_git_window_size;\n extern size_t packed_git_limit;\n-extern unsigned long big_file_threshold;\n extern unsigned long pack_size_limit_cfg;\n extern int max_allowed_tree_depth;\n \ndiff --git a/object-file.c b/object-file.c\nindex 726e41a0475..b3e0276b2a4 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2803,7 +2803,8 @@ int index_fd(struct index_state *istate, struct object_id *oid,\n \t\tret = index_stream_convert_blob(istate, oid, fd, path, flags);\n \telse if (!S_ISREG(st->st_mode))\n \t\tret = index_pipe(istate, oid, fd, type, path, flags);\n-\telse if (st->st_size <= big_file_threshold || type != OBJ_BLOB ||\n+\telse if (st->st_size <= repo_settings_get_big_file_threshold(the_repository) ||\n+\t\t type != OBJ_BLOB ||\n \t\t (path && would_convert_to_git(istate, path)))\n \t\tret = index_core(istate, oid, fd, xsize_t(st->st_size),\n \t\t\t\t type, path, flags);\n@@ -3137,7 +3138,8 @@ int read_loose_object(const char *path,\n \t\tgoto out;\n \t}\n \n-\tif (*oi->typep == OBJ_BLOB && *size > big_file_threshold) {\n+\tif (*oi->typep == OBJ_BLOB &&\n+\t    *size > repo_settings_get_big_file_threshold(the_repository)) {\n \t\tif (check_stream_oid(&stream, hdr, *size, path, expected_oid) < 0)\n \t\t\tgoto out;\n \t} else {\ndiff --git a/pack-check.c b/pack-check.c\nindex 6bcadc1e679..017dc740f7b 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -131,7 +131,8 @@ static int verify_packfile(struct repository *r,\n \t\ttype = unpack_object_header(p, w_curs, &curpos, &size);\n \t\tunuse_pack(w_curs);\n \n-\t\tif (type == OBJ_BLOB && big_file_threshold <= size) {\n+\t\tif (type == OBJ_BLOB &&\n+\t\t    repo_settings_get_big_file_threshold(the_repository) <= size) {\n \t\t\t/*\n \t\t\t * Let stream_object_signature() check it with\n \t\t\t * the streaming interface; no point slurping\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 67e9cfd2e63..4129f8fb2b4 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -20,6 +20,13 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest,\n \t\t*dest = def;\n }\n \n+static void repo_cfg_ulong(struct repository *r, const char *key, unsigned long *dest,\n+\t\t\t   unsigned long def)\n+{\n+\tif (repo_config_get_ulong(r, key, dest))\n+\t\t*dest = def;\n+}\n+\n void prepare_repo_settings(struct repository *r)\n {\n \tint experimental;\n@@ -151,6 +158,19 @@ void repo_settings_clear(struct repository *r)\n \tr->settings = empty;\n }\n \n+unsigned long repo_settings_get_big_file_threshold(struct repository *repo)\n+{\n+\tif (!repo->settings.big_file_threshold)\n+\t\trepo_cfg_ulong(repo, \"core.bigfilethreshold\",\n+\t\t\t       &repo->settings.big_file_threshold, 512 * 1024 * 1024);\n+\treturn repo->settings.big_file_threshold;\n+}\n+\n+void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value)\n+{\n+\trepo->settings.big_file_threshold = value;\n+}\n+\n enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo)\n {\n \tconst char *value;\ndiff --git a/repo-settings.h b/repo-settings.h\nindex ddc11967e01..2bf24b25973 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -64,6 +64,7 @@ struct repo_settings {\n \tsize_t delta_base_cache_limit;\n \tsize_t packed_git_window_size;\n \tsize_t packed_git_limit;\n+\tunsigned long big_file_threshold;\n \n \tchar *hooks_path;\n };\n@@ -88,6 +89,10 @@ int repo_settings_get_warn_ambiguous_refs(struct repository *repo);\n /* Read the value for \"core.hooksPath\". */\n const char *repo_settings_get_hooks_path(struct repository *repo);\n \n+/* Read and set the value for \"core.bigFileThreshold\". */\n+unsigned long repo_settings_get_big_file_threshold(struct repository *repo);\n+void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value);\n+\n /* Read, set or reset the value for \"core.sharedRepository\". */\n int repo_settings_get_shared_repository(struct repository *repo);\n void repo_settings_set_shared_repository(struct repository *repo, int value);\ndiff --git a/streaming.c b/streaming.c\nindex 38839511afc..018b794d252 100644\n--- a/streaming.c\n+++ b/streaming.c\n@@ -431,7 +431,8 @@ static int istream_source(struct git_istream *st,\n \t\tst->open = open_istream_loose;\n \t\treturn 0;\n \tcase OI_PACKED:\n-\t\tif (!oi.u.packed.is_delta && big_file_threshold < size) {\n+\t\tif (!oi.u.packed.is_delta &&\n+\t\t    repo_settings_get_big_file_threshold(the_repository) < size) {\n \t\t\tst->u.in_pack.pack = oi.u.packed.pack;\n \t\t\tst->u.in_pack.pos = oi.u.packed.offset;\n \t\t\tst->open = open_istream_pack_non_delta;\ndiff --git a/t/t1050-large.sh b/t/t1050-large.sh\nindex c71932b0242..5be273611ad 100755\n--- a/t/t1050-large.sh\n+++ b/t/t1050-large.sh\n@@ -6,7 +6,8 @@ test_description='adding and checking out large blobs'\n . ./test-lib.sh\n \n test_expect_success 'core.bigFileThreshold must be non-negative' '\n-\ttest_must_fail git -c core.bigFileThreshold=-1 rev-parse >out 2>err &&\n+\t: >input &&\n+\ttest_must_fail git -c core.bigFileThreshold=-1 hash-object input >out 2>err &&\n \tgrep \"bad numeric config value\" err &&\n \ttest_must_be_empty out\n '\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513766","messageId":"20250307-b4-pks-objects-without-the-repository-v3-6-7bccf408731e@pks.im","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","subject":"[PATCH v3 06/12] pack-revindex: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T14:18:59Z","receivedAt":"2025-03-07T14:19:06Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"pack-revindex.c\" where we use the global\n`the_repository` variable, either explicitly or implicitly by using\n`the_hash_algo`. In all of those cases we already have a repository\navailable in the calling context though.\n\nRefactor the code to instead use the caller-provided repository and\nremove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n pack-revindex.c | 34 ++++++++++++++++++++--------------\n 1 file changed, 20 insertions(+), 14 deletions(-)\n\ndiff --git a/pack-revindex.c b/pack-revindex.c\nindex 78139e3d7f5..038e0c96b1c 100644\n--- a/pack-revindex.c\n+++ b/pack-revindex.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"gettext.h\"\n #include \"pack-revindex.h\"\n@@ -9,6 +7,7 @@\n #include \"strbuf.h\"\n #include \"trace2.h\"\n #include \"parse.h\"\n+#include \"repository.h\"\n #include \"midx.h\"\n #include \"csum-file.h\"\n \n@@ -137,7 +136,7 @@ static void create_pack_revindex(struct packed_git *p)\n \tconst unsigned num_ent = p->num_objects;\n \tunsigned i;\n \tconst char *index = p->index_data;\n-\tconst unsigned hashsz = the_hash_algo->rawsz;\n+\tconst unsigned hashsz = p->repo->hash_algo->rawsz;\n \n \tALLOC_ARRAY(p->revindex, num_ent + 1);\n \tindex += 4 * 256;\n@@ -193,7 +192,11 @@ static char *pack_revindex_filename(struct packed_git *p)\n }\n \n #define RIDX_HEADER_SIZE (12)\n-#define RIDX_MIN_SIZE (RIDX_HEADER_SIZE + (2 * the_hash_algo->rawsz))\n+\n+static size_t ridx_min_size(const struct git_hash_algo *algo)\n+{\n+\treturn RIDX_HEADER_SIZE + (2 * algo->rawsz);\n+}\n \n struct revindex_header {\n \tuint32_t signature;\n@@ -201,7 +204,8 @@ struct revindex_header {\n \tuint32_t hash_id;\n };\n \n-static int load_revindex_from_disk(char *revindex_name,\n+static int load_revindex_from_disk(const struct git_hash_algo *algo,\n+\t\t\t\t   char *revindex_name,\n \t\t\t\t   uint32_t num_objects,\n \t\t\t\t   const uint32_t **data_p, size_t *len_p)\n {\n@@ -228,12 +232,12 @@ static int load_revindex_from_disk(char *revindex_name,\n \n \trevindex_size = xsize_t(st.st_size);\n \n-\tif (revindex_size < RIDX_MIN_SIZE) {\n+\tif (revindex_size < ridx_min_size(algo)) {\n \t\tret = error(_(\"reverse-index file %s is too small\"), revindex_name);\n \t\tgoto cleanup;\n \t}\n \n-\tif (revindex_size - RIDX_MIN_SIZE != st_mult(sizeof(uint32_t), num_objects)) {\n+\tif (revindex_size - ridx_min_size(algo) != st_mult(sizeof(uint32_t), num_objects)) {\n \t\tret = error(_(\"reverse-index file %s is corrupt\"), revindex_name);\n \t\tgoto cleanup;\n \t}\n@@ -279,7 +283,8 @@ int load_pack_revindex_from_disk(struct packed_git *p)\n \n \trevindex_name = pack_revindex_filename(p);\n \n-\tret = load_revindex_from_disk(revindex_name,\n+\tret = load_revindex_from_disk(p->repo->hash_algo,\n+\t\t\t\t      revindex_name,\n \t\t\t\t      p->num_objects,\n \t\t\t\t      &p->revindex_map,\n \t\t\t\t      &p->revindex_size);\n@@ -322,7 +327,7 @@ int verify_pack_revindex(struct packed_git *p)\n \tif (!p->revindex_map || !p->revindex_data)\n \t\treturn res;\n \n-\tif (!hashfile_checksum_valid(the_repository->hash_algo,\n+\tif (!hashfile_checksum_valid(p->repo->hash_algo,\n \t\t\t\t     (const unsigned char *)p->revindex_map, p->revindex_size)) {\n \t\terror(_(\"invalid checksum\"));\n \t\tres = -1;\n@@ -375,19 +380,20 @@ int load_midx_revindex(struct multi_pack_index *m)\n \t\t * not want to accidentally call munmap() in the middle of the\n \t\t * MIDX.\n \t\t */\n-\t\ttrace2_data_string(\"load_midx_revindex\", the_repository,\n+\t\ttrace2_data_string(\"load_midx_revindex\", m->repo,\n \t\t\t\t   \"source\", \"midx\");\n \t\tm->revindex_data = (const uint32_t *)m->chunk_revindex;\n \t\treturn 0;\n \t}\n \n-\ttrace2_data_string(\"load_midx_revindex\", the_repository,\n+\ttrace2_data_string(\"load_midx_revindex\", m->repo,\n \t\t\t   \"source\", \"rev\");\n \n \tget_midx_filename_ext(m->repo->hash_algo, &revindex_name, m->object_dir,\n \t\t\t      get_midx_checksum(m), MIDX_EXT_REV);\n \n-\tret = load_revindex_from_disk(revindex_name.buf,\n+\tret = load_revindex_from_disk(m->repo->hash_algo,\n+\t\t\t\t      revindex_name.buf,\n \t\t\t\t      m->num_objects,\n \t\t\t\t      &m->revindex_map,\n \t\t\t\t      &m->revindex_len);\n@@ -419,7 +425,7 @@ int offset_to_pack_pos(struct packed_git *p, off_t ofs, uint32_t *pos)\n {\n \tunsigned lo, hi;\n \n-\tif (load_pack_revindex(the_repository, p) < 0)\n+\tif (load_pack_revindex(p->repo, p) < 0)\n \t\treturn -1;\n \n \tlo = 0;\n@@ -465,7 +471,7 @@ off_t pack_pos_to_offset(struct packed_git *p, uint32_t pos)\n \tif (p->revindex)\n \t\treturn p->revindex[pos].offset;\n \telse if (pos == p->num_objects)\n-\t\treturn p->pack_size - the_hash_algo->rawsz;\n+\t\treturn p->pack_size - p->repo->hash_algo->rawsz;\n \telse\n \t\treturn nth_packed_object_offset(p, pack_pos_to_index(p, pos));\n }\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513767","messageId":"20250307-b4-pks-objects-without-the-repository-v3-7-7bccf408731e@pks.im","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","subject":"[PATCH v3 07/12] pack-bitmap-write: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T14:19:00Z","receivedAt":"2025-03-07T14:19:06Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"pack-bitmap-write.c\" where we use the\nglobal `the_repository` variable, either explicitly or implicitly by\nusing `the_hash_algo`.\n\nRefactor the code so that the `struct bitmap_writer` stores the\nrepository it is getting initialized with. Like this, we can adapt\ncallsites that use `the_repository` to instead use the repository\nprovided by the writer.\n\nRemove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n pack-bitmap-write.c | 36 ++++++++++++++++++------------------\n pack-bitmap.h       |  1 +\n 2 files changed, 19 insertions(+), 18 deletions(-)\n\ndiff --git a/pack-bitmap-write.c b/pack-bitmap-write.c\nindex 50e5c491ccb..6a97b52b36d 100644\n--- a/pack-bitmap-write.c\n+++ b/pack-bitmap-write.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -48,6 +47,7 @@ void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r,\n \tmemset(writer, 0, sizeof(struct bitmap_writer));\n \tif (writer->bitmaps)\n \t\tBUG(\"bitmap writer already initialized\");\n+\twriter->repo = r;\n \twriter->bitmaps = kh_init_oid_map();\n \twriter->pseudo_merge_commits = kh_init_oid_map();\n \twriter->to_pack = pdata;\n@@ -415,9 +415,9 @@ static void bitmap_builder_init(struct bitmap_builder *bb,\n \t\tbb->commits[bb->commits_nr++] = r->item;\n \t}\n \n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"num_selected_commits\", writer->selected_nr);\n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"num_maximal_commits\", num_maximal);\n \n \trelease_revisions(&revs);\n@@ -460,7 +460,7 @@ static int fill_bitmap_tree(struct bitmap_writer *writer,\n \t\tswitch (object_type(entry.mode)) {\n \t\tcase OBJ_TREE:\n \t\t\tif (fill_bitmap_tree(writer, bitmap,\n-\t\t\t\t\t     lookup_tree(the_repository, &entry.oid)) < 0)\n+\t\t\t\t\t     lookup_tree(writer->repo, &entry.oid)) < 0)\n \t\t\t\treturn -1;\n \t\t\tbreak;\n \t\tcase OBJ_BLOB:\n@@ -536,7 +536,7 @@ static int fill_bitmap_commit(struct bitmap_writer *writer,\n \t\t\t\treturn -1;\n \t\t\tbitmap_set(ent->bitmap, pos);\n \t\t\tprio_queue_put(tree_queue,\n-\t\t\t\t       repo_get_commit_tree(the_repository, c));\n+\t\t\t\t       repo_get_commit_tree(writer->repo, c));\n \t\t}\n \n \t\tfor (p = c->parents; p; p = p->next) {\n@@ -590,11 +590,11 @@ int bitmap_writer_build(struct bitmap_writer *writer)\n \tint closed = 1; /* until proven otherwise */\n \n \tif (writer->show_progress)\n-\t\twriter->progress = start_progress(the_repository,\n+\t\twriter->progress = start_progress(writer->repo,\n \t\t\t\t\t\t  \"Building bitmaps\",\n \t\t\t\t\t\t  writer->selected_nr);\n \ttrace2_region_enter(\"pack-bitmap-write\", \"building_bitmaps_total\",\n-\t\t\t    the_repository);\n+\t\t\t    writer->repo);\n \n \told_bitmap = prepare_bitmap_git(writer->to_pack->repo);\n \tif (old_bitmap)\n@@ -645,10 +645,10 @@ int bitmap_writer_build(struct bitmap_writer *writer)\n \tfree(mapping);\n \n \ttrace2_region_leave(\"pack-bitmap-write\", \"building_bitmaps_total\",\n-\t\t\t    the_repository);\n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\t\t\t    writer->repo);\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"building_bitmaps_reused\", reused_bitmaps_nr);\n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"building_bitmaps_pseudo_merge_reused\",\n \t\t\t   reused_pseudo_merge_bitmaps_nr);\n \n@@ -711,7 +711,7 @@ void bitmap_writer_select_commits(struct bitmap_writer *writer,\n \t}\n \n \tif (writer->show_progress)\n-\t\twriter->progress = start_progress(the_repository,\n+\t\twriter->progress = start_progress(writer->repo,\n \t\t\t\t\t\t  \"Selecting bitmap commits\", 0);\n \n \tfor (;;) {\n@@ -960,7 +960,7 @@ static void write_lookup_table(struct bitmap_writer *writer, struct hashfile *f,\n \tfor (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++)\n \t\ttable_inv[table[i]] = i;\n \n-\ttrace2_region_enter(\"pack-bitmap-write\", \"writing_lookup_table\", the_repository);\n+\ttrace2_region_enter(\"pack-bitmap-write\", \"writing_lookup_table\", writer->repo);\n \tfor (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) {\n \t\tstruct bitmapped_commit *selected = &writer->selected[table[i]];\n \t\tuint32_t xor_offset = selected->xor_offset;\n@@ -987,7 +987,7 @@ static void write_lookup_table(struct bitmap_writer *writer, struct hashfile *f,\n \t\thashwrite_be64(f, (uint64_t)offsets[table[i]]);\n \t\thashwrite_be32(f, xor_row);\n \t}\n-\ttrace2_region_leave(\"pack-bitmap-write\", \"writing_lookup_table\", the_repository);\n+\ttrace2_region_leave(\"pack-bitmap-write\", \"writing_lookup_table\", writer->repo);\n \n \tfree(table);\n \tfree(table_inv);\n@@ -1008,7 +1008,7 @@ static void write_hash_cache(struct hashfile *f,\n void bitmap_writer_set_checksum(struct bitmap_writer *writer,\n \t\t\t\tconst unsigned char *sha1)\n {\n-\thashcpy(writer->pack_checksum, sha1, the_repository->hash_algo);\n+\thashcpy(writer->pack_checksum, sha1, writer->repo->hash_algo);\n }\n \n void bitmap_writer_finish(struct bitmap_writer *writer,\n@@ -1030,15 +1030,15 @@ void bitmap_writer_finish(struct bitmap_writer *writer,\n \tif (writer->pseudo_merges_nr)\n \t\toptions |= BITMAP_OPT_PSEUDO_MERGES;\n \n-\tf = hashfd(the_repository->hash_algo, fd, tmp_file.buf);\n+\tf = hashfd(writer->repo->hash_algo, fd, tmp_file.buf);\n \n \tmemcpy(header.magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE));\n \theader.version = htons(default_version);\n \theader.options = htons(flags | options);\n \theader.entry_count = htonl(bitmap_writer_nr_selected_commits(writer));\n-\thashcpy(header.checksum, writer->pack_checksum, the_repository->hash_algo);\n+\thashcpy(header.checksum, writer->pack_checksum, writer->repo->hash_algo);\n \n-\thashwrite(f, &header, sizeof(header) - GIT_MAX_RAWSZ + the_hash_algo->rawsz);\n+\thashwrite(f, &header, sizeof(header) - GIT_MAX_RAWSZ + writer->repo->hash_algo->rawsz);\n \tdump_bitmap(f, writer->commits);\n \tdump_bitmap(f, writer->trees);\n \tdump_bitmap(f, writer->blobs);\n@@ -1072,7 +1072,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,\n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n \t\t\t  CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE);\n \n-\tif (adjust_shared_perm(the_repository, tmp_file.buf))\n+\tif (adjust_shared_perm(writer->repo, tmp_file.buf))\n \t\tdie_errno(\"unable to make temporary bitmap file readable\");\n \n \tif (rename(tmp_file.buf, filename))\ndiff --git a/pack-bitmap.h b/pack-bitmap.h\nindex d7f4b8b8e95..53cd42772f3 100644\n--- a/pack-bitmap.h\n+++ b/pack-bitmap.h\n@@ -104,6 +104,7 @@ int bitmap_has_oid_in_uninteresting(struct bitmap_index *, const struct object_i\n off_t get_disk_usage_from_bitmap(struct bitmap_index *, struct rev_info *);\n \n struct bitmap_writer {\n+\tstruct repository *repo;\n \tstruct ewah_bitmap *commits;\n \tstruct ewah_bitmap *trees;\n \tstruct ewah_bitmap *blobs;\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513769","messageId":"20250307-b4-pks-objects-without-the-repository-v3-8-7bccf408731e@pks.im","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","subject":"[PATCH v3 08/12] object-file-convert: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T14:19:01Z","receivedAt":"2025-03-07T14:19:06Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"object-file-convert.c\" where we use the\nglobal `the_repository` variable, either explicitly or implicitly by\nusing `the_hash_algo`. All of these callsites are transitively called\nfrom `convert_object_file()`, which indeed has no repo as input.\n\nRefactor the function so that it receives a repository as a parameter\nand pass it through to all internal functions to get rid of the\ndependency. Remove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/tag.c         |  2 +-\n commit.c              |  2 +-\n object-file-convert.c | 29 ++++++++++++++++-------------\n object-file-convert.h |  3 ++-\n object-file.c         |  7 ++++---\n 5 files changed, 24 insertions(+), 19 deletions(-)\n\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex d3e0943b734..7c173535cb3 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -172,7 +172,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,\n \tif (compat) {\n \t\tconst struct git_hash_algo *algo = the_repository->hash_algo;\n \n-\t\tif (convert_object_file(&compat_buf, algo, compat,\n+\t\tif (convert_object_file(the_repository ,&compat_buf, algo, compat,\n \t\t\t\t\tbuffer->buf, buffer->len, OBJ_TAG, 1))\n \t\t\tgoto out;\n \t\tif (sign_buffer(&compat_buf, &compat_sig, keyid))\ndiff --git a/commit.c b/commit.c\nindex 6efdb03997d..48aeefaad31 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1380,7 +1380,7 @@ static int convert_commit_extra_headers(const struct commit_extra_header *orig,\n \t\tstruct commit_extra_header *new;\n \t\tCALLOC_ARRAY(new, 1);\n \t\tif (!strcmp(orig->key, \"mergetag\")) {\n-\t\t\tif (convert_object_file(&out, algo, compat,\n+\t\t\tif (convert_object_file(the_repository, &out, algo, compat,\n \t\t\t\t\t\torig->value, orig->len,\n \t\t\t\t\t\tOBJ_TAG, 1)) {\n \t\t\t\tfree(new);\ndiff --git a/object-file-convert.c b/object-file-convert.c\nindex eba71955cf7..7ab875afe6c 100644\n--- a/object-file-convert.c\n+++ b/object-file-convert.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -63,7 +62,8 @@ static int decode_tree_entry_raw(struct object_id *oid, const char **path,\n \treturn 0;\n }\n \n-static int convert_tree_object(struct strbuf *out,\n+static int convert_tree_object(struct repository *repo,\n+\t\t\t       struct strbuf *out,\n \t\t\t       const struct git_hash_algo *from,\n \t\t\t       const struct git_hash_algo *to,\n \t\t\t       const char *buffer, size_t size)\n@@ -78,7 +78,7 @@ static int convert_tree_object(struct strbuf *out,\n \t\tif (decode_tree_entry_raw(&entry_oid, &path, &pathlen, from, p,\n \t\t\t\t\t  end - p))\n \t\t\treturn error(_(\"failed to decode tree entry\"));\n-\t\tif (repo_oid_to_algop(the_repository, &entry_oid, to, &mapped_oid))\n+\t\tif (repo_oid_to_algop(repo, &entry_oid, to, &mapped_oid))\n \t\t\treturn error(_(\"failed to map tree entry for %s\"), oid_to_hex(&entry_oid));\n \t\tstrbuf_add(out, p, path - p);\n \t\tstrbuf_add(out, path, pathlen);\n@@ -88,7 +88,8 @@ static int convert_tree_object(struct strbuf *out,\n \treturn 0;\n }\n \n-static int convert_tag_object(struct strbuf *out,\n+static int convert_tag_object(struct repository *repo,\n+\t\t\t      struct strbuf *out,\n \t\t\t      const struct git_hash_algo *from,\n \t\t\t      const struct git_hash_algo *to,\n \t\t\t      const char *buffer, size_t size)\n@@ -105,7 +106,7 @@ static int convert_tag_object(struct strbuf *out,\n \t\treturn error(\"bogus tag object\");\n \tif (parse_oid_hex_algop(buffer + 7, &oid, &p, from) < 0)\n \t\treturn error(\"bad tag object ID\");\n-\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n+\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n \t\treturn error(\"unable to map tree %s in tag object\",\n \t\t\t     oid_to_hex(&oid));\n \tsize -= ((p + 1) - buffer);\n@@ -139,7 +140,8 @@ static int convert_tag_object(struct strbuf *out,\n \treturn 0;\n }\n \n-static int convert_commit_object(struct strbuf *out,\n+static int convert_commit_object(struct repository *repo,\n+\t\t\t\t struct strbuf *out,\n \t\t\t\t const struct git_hash_algo *from,\n \t\t\t\t const struct git_hash_algo *to,\n \t\t\t\t const char *buffer, size_t size)\n@@ -165,7 +167,7 @@ static int convert_commit_object(struct strbuf *out,\n \t\t\t    (p != eol))\n \t\t\t\treturn error(_(\"bad %s in commit\"), \"tree\");\n \n-\t\t\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n+\t\t\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n \t\t\t\treturn error(_(\"unable to map %s %s in commit object\"),\n \t\t\t\t\t     \"tree\", oid_to_hex(&oid));\n \t\t\tstrbuf_addf(out, \"tree %s\\n\", oid_to_hex(&mapped_oid));\n@@ -177,7 +179,7 @@ static int convert_commit_object(struct strbuf *out,\n \t\t\t    (p != eol))\n \t\t\t\treturn error(_(\"bad %s in commit\"), \"parent\");\n \n-\t\t\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n+\t\t\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n \t\t\t\treturn error(_(\"unable to map %s %s in commit object\"),\n \t\t\t\t\t     \"parent\", oid_to_hex(&oid));\n \n@@ -202,7 +204,7 @@ static int convert_commit_object(struct strbuf *out,\n \t\t\t}\n \n \t\t\t/* Compute the new tag object */\n-\t\t\tif (convert_tag_object(&new_tag, from, to, tag.buf, tag.len)) {\n+\t\t\tif (convert_tag_object(repo, &new_tag, from, to, tag.buf, tag.len)) {\n \t\t\t\tstrbuf_release(&tag);\n \t\t\t\tstrbuf_release(&new_tag);\n \t\t\t\treturn -1;\n@@ -241,7 +243,8 @@ static int convert_commit_object(struct strbuf *out,\n \treturn 0;\n }\n \n-int convert_object_file(struct strbuf *outbuf,\n+int convert_object_file(struct repository *repo,\n+\t\t\tstruct strbuf *outbuf,\n \t\t\tconst struct git_hash_algo *from,\n \t\t\tconst struct git_hash_algo *to,\n \t\t\tconst void *buf, size_t len,\n@@ -256,13 +259,13 @@ int convert_object_file(struct strbuf *outbuf,\n \n \tswitch (type) {\n \tcase OBJ_COMMIT:\n-\t\tret = convert_commit_object(outbuf, from, to, buf, len);\n+\t\tret = convert_commit_object(repo, outbuf, from, to, buf, len);\n \t\tbreak;\n \tcase OBJ_TREE:\n-\t\tret = convert_tree_object(outbuf, from, to, buf, len);\n+\t\tret = convert_tree_object(repo, outbuf, from, to, buf, len);\n \t\tbreak;\n \tcase OBJ_TAG:\n-\t\tret = convert_tag_object(outbuf, from, to, buf, len);\n+\t\tret = convert_tag_object(repo, outbuf, from, to, buf, len);\n \t\tbreak;\n \tdefault:\n \t\t/* Not implemented yet, so fail. */\ndiff --git a/object-file-convert.h b/object-file-convert.h\nindex a4f802aa8ee..9b3cc5e533d 100644\n--- a/object-file-convert.h\n+++ b/object-file-convert.h\n@@ -14,7 +14,8 @@ int repo_oid_to_algop(struct repository *repo, const struct object_id *src,\n  * Convert an object file from one hash algorithm to another algorithm.\n  * Return -1 on failure, 0 on success.\n  */\n-int convert_object_file(struct strbuf *outbuf,\n+int convert_object_file(struct repository *repo,\n+\t\t\tstruct strbuf *outbuf,\n \t\t\tconst struct git_hash_algo *from,\n \t\t\tconst struct git_hash_algo *to,\n \t\t\tconst void *buf, size_t len,\ndiff --git a/object-file.c b/object-file.c\nindex b3e0276b2a4..b0e237a2acc 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1793,7 +1793,7 @@ static int oid_object_info_convert(struct repository *r,\n \t\tif (type == -1)\n \t\t\treturn -1;\n \t\tif (type != OBJ_BLOB) {\n-\t\t\tret = convert_object_file(&outbuf,\n+\t\t\tret = convert_object_file(the_repository, &outbuf,\n \t\t\t\t\t\t  the_hash_algo, input_algo,\n \t\t\t\t\t\t  content, size, type, !do_die);\n \t\t\tfree(content);\n@@ -2510,7 +2510,7 @@ int write_object_file_flags(const void *buf, unsigned long len,\n \t\t\thash_object_file(compat, buf, len, type, &compat_oid);\n \t\telse {\n \t\t\tstruct strbuf converted = STRBUF_INIT;\n-\t\t\tconvert_object_file(&converted, algo, compat,\n+\t\t\tconvert_object_file(the_repository, &converted, algo, compat,\n \t\t\t\t\t    buf, len, type, 0);\n \t\t\thash_object_file(compat, converted.buf, converted.len,\n \t\t\t\t\t type, &compat_oid);\n@@ -2550,7 +2550,8 @@ int write_object_file_literally(const void *buf, unsigned long len,\n \t\t\t\t\t &compat_oid);\n \t\telse if (compat_type != -1) {\n \t\t\tstruct strbuf converted = STRBUF_INIT;\n-\t\t\tconvert_object_file(&converted, algo, compat,\n+\t\t\tconvert_object_file(the_repository,\n+\t\t\t\t\t    &converted, algo, compat,\n \t\t\t\t\t    buf, len, compat_type, 0);\n \t\t\thash_object_file(compat, converted.buf, converted.len,\n \t\t\t\t\t compat_type, &compat_oid);\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513770","messageId":"20250307-b4-pks-objects-without-the-repository-v3-9-7bccf408731e@pks.im","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","subject":"[PATCH v3 09/12] delta-islands: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T14:19:02Z","receivedAt":"2025-03-07T14:19:07Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"delta-islands.c\" where we use the\nglobal `the_repository` variable, either explicitly or implicitly by\nusing `the_hash_algo`.\n\nRefactor the code to stop using `the_repository`. In most cases this is\ntrivial because we already had a repository available in the calling\ncontext, with the only exception being `propagate_island_marks()`. Adapt\nit so that the repository gets passed in via a parameter.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/pack-objects.c |  2 +-\n delta-islands.c        | 14 ++++++--------\n delta-islands.h        |  2 +-\n 3 files changed, 8 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex eefc6c78096..fba5db74656 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -3847,7 +3847,7 @@ static void show_commit(struct commit *commit, void *data UNUSED)\n \t\tindex_commit_for_bitmap(commit);\n \n \tif (use_delta_islands)\n-\t\tpropagate_island_marks(commit);\n+\t\tpropagate_island_marks(the_repository, commit);\n }\n \n static void show_object(struct object *obj, const char *name,\ndiff --git a/delta-islands.c b/delta-islands.c\nindex 3aec43fada3..36c94799d69 100644\n--- a/delta-islands.c\n+++ b/delta-islands.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -267,8 +266,7 @@ void resolve_tree_islands(struct repository *r,\n \tQSORT(todo, nr, tree_depth_compare);\n \n \tif (progress)\n-\t\tprogress_state = start_progress(the_repository,\n-\t\t\t\t\t\t_(\"Propagating island marks\"), nr);\n+\t\tprogress_state = start_progress(r, _(\"Propagating island marks\"), nr);\n \n \tfor (i = 0; i < nr; i++) {\n \t\tstruct object_entry *ent = todo[i].entry;\n@@ -490,9 +488,9 @@ void load_delta_islands(struct repository *r, int progress)\n \n \tisland_marks = kh_init_oid_map();\n \n-\tgit_config(island_config_callback, &ild);\n+\trepo_config(r, island_config_callback, &ild);\n \tild.remote_islands = kh_init_str();\n-\trefs_for_each_ref(get_main_ref_store(the_repository),\n+\trefs_for_each_ref(get_main_ref_store(r),\n \t\t\t  find_island_for_ref, &ild);\n \tfree_config_regexes(&ild);\n \tdeduplicate_islands(ild.remote_islands, r);\n@@ -502,7 +500,7 @@ void load_delta_islands(struct repository *r, int progress)\n \t\tfprintf(stderr, _(\"Marked %d islands, done.\\n\"), island_counter);\n }\n \n-void propagate_island_marks(struct commit *commit)\n+void propagate_island_marks(struct repository *r, struct commit *commit)\n {\n \tkhiter_t pos = kh_get_oid_map(island_marks, commit->object.oid);\n \n@@ -510,8 +508,8 @@ void propagate_island_marks(struct commit *commit)\n \t\tstruct commit_list *p;\n \t\tstruct island_bitmap *root_marks = kh_value(island_marks, pos);\n \n-\t\trepo_parse_commit(the_repository, commit);\n-\t\tset_island_marks(&repo_get_commit_tree(the_repository, commit)->object,\n+\t\trepo_parse_commit(r, commit);\n+\t\tset_island_marks(&repo_get_commit_tree(r, commit)->object,\n \t\t\t\t root_marks);\n \t\tfor (p = commit->parents; p; p = p->next)\n \t\t\tset_island_marks(&p->item->object, root_marks);\ndiff --git a/delta-islands.h b/delta-islands.h\nindex 8d1591ae28b..6107660306b 100644\n--- a/delta-islands.h\n+++ b/delta-islands.h\n@@ -12,7 +12,7 @@ void resolve_tree_islands(struct repository *r,\n \t\t\t  int progress,\n \t\t\t  struct packing_data *to_pack);\n void load_delta_islands(struct repository *r, int progress);\n-void propagate_island_marks(struct commit *commit);\n+void propagate_island_marks(struct repository *r, struct commit *commit);\n int compute_pack_layers(struct packing_data *to_pack);\n void free_island_marks(void);\n \n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513771","messageId":"20250307-b4-pks-objects-without-the-repository-v3-10-7bccf408731e@pks.im","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","subject":"[PATCH v3 10/12] object-file: split out logic regarding hash algorithms","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T14:19:03Z","receivedAt":"2025-03-07T14:19:09Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"While we have a \"hash.h\" header, the actual implementation of the\nsubsystem is hosted by \"object-file.c\". This makes it harder than\nnecessary to find the actual implementation of the hash subsystem and\nintermingles the different concerns with one another.\n\nSplit out the implementation of hash algorithms into a new, separate\n\"hash.c\" file.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile      |   1 +\n hash.c        | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n meson.build   |   1 +\n object-file.c | 277 --------------------------------------------------------\n 4 files changed, 285 insertions(+), 277 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 6d45093089d..6dfe88322dd 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1041,6 +1041,7 @@ LIB_OBJS += gpg-interface.o\n LIB_OBJS += graph.o\n LIB_OBJS += grep.o\n LIB_OBJS += hash-lookup.o\n+LIB_OBJS += hash.o\n LIB_OBJS += hashmap.o\n LIB_OBJS += help.o\n LIB_OBJS += hex.o\ndiff --git a/hash.c b/hash.c\nnew file mode 100644\nindex 00000000000..dd5ac9d0eb2\n--- /dev/null\n+++ b/hash.c\n@@ -0,0 +1,283 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+#define DISABLE_SIGN_COMPARE_WARNINGS\n+\n+#include \"git-compat-util.h\"\n+#include \"hash.h\"\n+#include \"hex.h\"\n+\n+static const struct object_id empty_tree_oid = {\n+\t.hash = {\n+\t\t0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,\n+\t\t0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04\n+\t},\n+\t.algo = GIT_HASH_SHA1,\n+};\n+static const struct object_id empty_blob_oid = {\n+\t.hash = {\n+\t\t0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,\n+\t\t0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91\n+\t},\n+\t.algo = GIT_HASH_SHA1,\n+};\n+static const struct object_id null_oid_sha1 = {\n+\t.hash = {0},\n+\t.algo = GIT_HASH_SHA1,\n+};\n+static const struct object_id empty_tree_oid_sha256 = {\n+\t.hash = {\n+\t\t0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1,\n+\t\t0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5,\n+\t\t0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc,\n+\t\t0x53, 0x21\n+\t},\n+\t.algo = GIT_HASH_SHA256,\n+};\n+static const struct object_id empty_blob_oid_sha256 = {\n+\t.hash = {\n+\t\t0x47, 0x3a, 0x0f, 0x4c, 0x3b, 0xe8, 0xa9, 0x36, 0x81, 0xa2,\n+\t\t0x67, 0xe3, 0xb1, 0xe9, 0xa7, 0xdc, 0xda, 0x11, 0x85, 0x43,\n+\t\t0x6f, 0xe1, 0x41, 0xf7, 0x74, 0x91, 0x20, 0xa3, 0x03, 0x72,\n+\t\t0x18, 0x13\n+\t},\n+\t.algo = GIT_HASH_SHA256,\n+};\n+static const struct object_id null_oid_sha256 = {\n+\t.hash = {0},\n+\t.algo = GIT_HASH_SHA256,\n+};\n+\n+static void git_hash_sha1_init(struct git_hash_ctx *ctx)\n+{\n+\tctx->algop = &hash_algos[GIT_HASH_SHA1];\n+\tgit_SHA1_Init(&ctx->state.sha1);\n+}\n+\n+static void git_hash_sha1_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n+{\n+\tdst->algop = src->algop;\n+\tgit_SHA1_Clone(&dst->state.sha1, &src->state.sha1);\n+}\n+\n+static void git_hash_sha1_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n+{\n+\tgit_SHA1_Update(&ctx->state.sha1, data, len);\n+}\n+\n+static void git_hash_sha1_final(unsigned char *hash, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final(hash, &ctx->state.sha1);\n+}\n+\n+static void git_hash_sha1_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final(oid->hash, &ctx->state.sha1);\n+\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n+\toid->algo = GIT_HASH_SHA1;\n+}\n+\n+static void git_hash_sha1_init_unsafe(struct git_hash_ctx *ctx)\n+{\n+\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA1]);\n+\tgit_SHA1_Init_unsafe(&ctx->state.sha1_unsafe);\n+}\n+\n+static void git_hash_sha1_clone_unsafe(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n+{\n+\tdst->algop = src->algop;\n+\tgit_SHA1_Clone_unsafe(&dst->state.sha1_unsafe, &src->state.sha1_unsafe);\n+}\n+\n+static void git_hash_sha1_update_unsafe(struct git_hash_ctx *ctx, const void *data,\n+\t\t\t\t      size_t len)\n+{\n+\tgit_SHA1_Update_unsafe(&ctx->state.sha1_unsafe, data, len);\n+}\n+\n+static void git_hash_sha1_final_unsafe(unsigned char *hash, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final_unsafe(hash, &ctx->state.sha1_unsafe);\n+}\n+\n+static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final_unsafe(oid->hash, &ctx->state.sha1_unsafe);\n+\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n+\toid->algo = GIT_HASH_SHA1;\n+}\n+\n+static void git_hash_sha256_init(struct git_hash_ctx *ctx)\n+{\n+\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA256]);\n+\tgit_SHA256_Init(&ctx->state.sha256);\n+}\n+\n+static void git_hash_sha256_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n+{\n+\tdst->algop = src->algop;\n+\tgit_SHA256_Clone(&dst->state.sha256, &src->state.sha256);\n+}\n+\n+static void git_hash_sha256_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n+{\n+\tgit_SHA256_Update(&ctx->state.sha256, data, len);\n+}\n+\n+static void git_hash_sha256_final(unsigned char *hash, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA256_Final(hash, &ctx->state.sha256);\n+}\n+\n+static void git_hash_sha256_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA256_Final(oid->hash, &ctx->state.sha256);\n+\t/*\n+\t * This currently does nothing, so the compiler should optimize it out,\n+\t * but keep it in case we extend the hash size again.\n+\t */\n+\tmemset(oid->hash + GIT_SHA256_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA256_RAWSZ);\n+\toid->algo = GIT_HASH_SHA256;\n+}\n+\n+static void git_hash_unknown_init(struct git_hash_ctx *ctx UNUSED)\n+{\n+\tBUG(\"trying to init unknown hash\");\n+}\n+\n+static void git_hash_unknown_clone(struct git_hash_ctx *dst UNUSED,\n+\t\t\t\t   const struct git_hash_ctx *src UNUSED)\n+{\n+\tBUG(\"trying to clone unknown hash\");\n+}\n+\n+static void git_hash_unknown_update(struct git_hash_ctx *ctx UNUSED,\n+\t\t\t\t    const void *data UNUSED,\n+\t\t\t\t    size_t len UNUSED)\n+{\n+\tBUG(\"trying to update unknown hash\");\n+}\n+\n+static void git_hash_unknown_final(unsigned char *hash UNUSED,\n+\t\t\t\t   struct git_hash_ctx *ctx UNUSED)\n+{\n+\tBUG(\"trying to finalize unknown hash\");\n+}\n+\n+static void git_hash_unknown_final_oid(struct object_id *oid UNUSED,\n+\t\t\t\t       struct git_hash_ctx *ctx UNUSED)\n+{\n+\tBUG(\"trying to finalize unknown hash\");\n+}\n+\n+static const struct git_hash_algo sha1_unsafe_algo = {\n+\t.name = \"sha1\",\n+\t.format_id = GIT_SHA1_FORMAT_ID,\n+\t.rawsz = GIT_SHA1_RAWSZ,\n+\t.hexsz = GIT_SHA1_HEXSZ,\n+\t.blksz = GIT_SHA1_BLKSZ,\n+\t.init_fn = git_hash_sha1_init_unsafe,\n+\t.clone_fn = git_hash_sha1_clone_unsafe,\n+\t.update_fn = git_hash_sha1_update_unsafe,\n+\t.final_fn = git_hash_sha1_final_unsafe,\n+\t.final_oid_fn = git_hash_sha1_final_oid_unsafe,\n+\t.empty_tree = &empty_tree_oid,\n+\t.empty_blob = &empty_blob_oid,\n+\t.null_oid = &null_oid_sha1,\n+};\n+\n+const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n+\t{\n+\t\t.name = NULL,\n+\t\t.format_id = 0x00000000,\n+\t\t.rawsz = 0,\n+\t\t.hexsz = 0,\n+\t\t.blksz = 0,\n+\t\t.init_fn = git_hash_unknown_init,\n+\t\t.clone_fn = git_hash_unknown_clone,\n+\t\t.update_fn = git_hash_unknown_update,\n+\t\t.final_fn = git_hash_unknown_final,\n+\t\t.final_oid_fn = git_hash_unknown_final_oid,\n+\t\t.empty_tree = NULL,\n+\t\t.empty_blob = NULL,\n+\t\t.null_oid = NULL,\n+\t},\n+\t{\n+\t\t.name = \"sha1\",\n+\t\t.format_id = GIT_SHA1_FORMAT_ID,\n+\t\t.rawsz = GIT_SHA1_RAWSZ,\n+\t\t.hexsz = GIT_SHA1_HEXSZ,\n+\t\t.blksz = GIT_SHA1_BLKSZ,\n+\t\t.init_fn = git_hash_sha1_init,\n+\t\t.clone_fn = git_hash_sha1_clone,\n+\t\t.update_fn = git_hash_sha1_update,\n+\t\t.final_fn = git_hash_sha1_final,\n+\t\t.final_oid_fn = git_hash_sha1_final_oid,\n+\t\t.unsafe = &sha1_unsafe_algo,\n+\t\t.empty_tree = &empty_tree_oid,\n+\t\t.empty_blob = &empty_blob_oid,\n+\t\t.null_oid = &null_oid_sha1,\n+\t},\n+\t{\n+\t\t.name = \"sha256\",\n+\t\t.format_id = GIT_SHA256_FORMAT_ID,\n+\t\t.rawsz = GIT_SHA256_RAWSZ,\n+\t\t.hexsz = GIT_SHA256_HEXSZ,\n+\t\t.blksz = GIT_SHA256_BLKSZ,\n+\t\t.init_fn = git_hash_sha256_init,\n+\t\t.clone_fn = git_hash_sha256_clone,\n+\t\t.update_fn = git_hash_sha256_update,\n+\t\t.final_fn = git_hash_sha256_final,\n+\t\t.final_oid_fn = git_hash_sha256_final_oid,\n+\t\t.empty_tree = &empty_tree_oid_sha256,\n+\t\t.empty_blob = &empty_blob_oid_sha256,\n+\t\t.null_oid = &null_oid_sha256,\n+\t}\n+};\n+\n+const struct object_id *null_oid(void)\n+{\n+\treturn the_hash_algo->null_oid;\n+}\n+\n+const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\n+{\n+\tstatic char buf[GIT_MAX_HEXSZ + 1];\n+\treturn oid_to_hex_r(buf, algop->empty_tree);\n+}\n+\n+int hash_algo_by_name(const char *name)\n+{\n+\tint i;\n+\tif (!name)\n+\t\treturn GIT_HASH_UNKNOWN;\n+\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\t\tif (!strcmp(name, hash_algos[i].name))\n+\t\t\treturn i;\n+\treturn GIT_HASH_UNKNOWN;\n+}\n+\n+int hash_algo_by_id(uint32_t format_id)\n+{\n+\tint i;\n+\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\t\tif (format_id == hash_algos[i].format_id)\n+\t\t\treturn i;\n+\treturn GIT_HASH_UNKNOWN;\n+}\n+\n+int hash_algo_by_length(int len)\n+{\n+\tint i;\n+\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\t\tif (len == hash_algos[i].rawsz)\n+\t\t\treturn i;\n+\treturn GIT_HASH_UNKNOWN;\n+}\n+\n+const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop)\n+{\n+\t/* If we have a faster \"unsafe\" implementation, use that. */\n+\tif (algop->unsafe)\n+\t\treturn algop->unsafe;\n+\t/* Otherwise use the default one. */\n+\treturn algop;\n+}\ndiff --git a/meson.build b/meson.build\nindex 021a182135f..38568344953 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -311,6 +311,7 @@ libgit_sources = [\n   'graph.c',\n   'grep.c',\n   'hash-lookup.c',\n+  'hash.c',\n   'hashmap.c',\n   'help.c',\n   'hex.c',\ndiff --git a/object-file.c b/object-file.c\nindex b0e237a2acc..de603e2ca8c 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -45,283 +45,6 @@\n /* The maximum size for an object header. */\n #define MAX_HEADER_LEN 32\n \n-static const struct object_id empty_tree_oid = {\n-\t.hash = {\n-\t\t0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,\n-\t\t0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04\n-\t},\n-\t.algo = GIT_HASH_SHA1,\n-};\n-static const struct object_id empty_blob_oid = {\n-\t.hash = {\n-\t\t0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,\n-\t\t0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91\n-\t},\n-\t.algo = GIT_HASH_SHA1,\n-};\n-static const struct object_id null_oid_sha1 = {\n-\t.hash = {0},\n-\t.algo = GIT_HASH_SHA1,\n-};\n-static const struct object_id empty_tree_oid_sha256 = {\n-\t.hash = {\n-\t\t0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1,\n-\t\t0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5,\n-\t\t0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc,\n-\t\t0x53, 0x21\n-\t},\n-\t.algo = GIT_HASH_SHA256,\n-};\n-static const struct object_id empty_blob_oid_sha256 = {\n-\t.hash = {\n-\t\t0x47, 0x3a, 0x0f, 0x4c, 0x3b, 0xe8, 0xa9, 0x36, 0x81, 0xa2,\n-\t\t0x67, 0xe3, 0xb1, 0xe9, 0xa7, 0xdc, 0xda, 0x11, 0x85, 0x43,\n-\t\t0x6f, 0xe1, 0x41, 0xf7, 0x74, 0x91, 0x20, 0xa3, 0x03, 0x72,\n-\t\t0x18, 0x13\n-\t},\n-\t.algo = GIT_HASH_SHA256,\n-};\n-static const struct object_id null_oid_sha256 = {\n-\t.hash = {0},\n-\t.algo = GIT_HASH_SHA256,\n-};\n-\n-static void git_hash_sha1_init(struct git_hash_ctx *ctx)\n-{\n-\tctx->algop = &hash_algos[GIT_HASH_SHA1];\n-\tgit_SHA1_Init(&ctx->state.sha1);\n-}\n-\n-static void git_hash_sha1_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n-{\n-\tdst->algop = src->algop;\n-\tgit_SHA1_Clone(&dst->state.sha1, &src->state.sha1);\n-}\n-\n-static void git_hash_sha1_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n-{\n-\tgit_SHA1_Update(&ctx->state.sha1, data, len);\n-}\n-\n-static void git_hash_sha1_final(unsigned char *hash, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final(hash, &ctx->state.sha1);\n-}\n-\n-static void git_hash_sha1_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final(oid->hash, &ctx->state.sha1);\n-\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n-\toid->algo = GIT_HASH_SHA1;\n-}\n-\n-static void git_hash_sha1_init_unsafe(struct git_hash_ctx *ctx)\n-{\n-\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA1]);\n-\tgit_SHA1_Init_unsafe(&ctx->state.sha1_unsafe);\n-}\n-\n-static void git_hash_sha1_clone_unsafe(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n-{\n-\tdst->algop = src->algop;\n-\tgit_SHA1_Clone_unsafe(&dst->state.sha1_unsafe, &src->state.sha1_unsafe);\n-}\n-\n-static void git_hash_sha1_update_unsafe(struct git_hash_ctx *ctx, const void *data,\n-\t\t\t\t      size_t len)\n-{\n-\tgit_SHA1_Update_unsafe(&ctx->state.sha1_unsafe, data, len);\n-}\n-\n-static void git_hash_sha1_final_unsafe(unsigned char *hash, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final_unsafe(hash, &ctx->state.sha1_unsafe);\n-}\n-\n-static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final_unsafe(oid->hash, &ctx->state.sha1_unsafe);\n-\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n-\toid->algo = GIT_HASH_SHA1;\n-}\n-\n-static void git_hash_sha256_init(struct git_hash_ctx *ctx)\n-{\n-\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA256]);\n-\tgit_SHA256_Init(&ctx->state.sha256);\n-}\n-\n-static void git_hash_sha256_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n-{\n-\tdst->algop = src->algop;\n-\tgit_SHA256_Clone(&dst->state.sha256, &src->state.sha256);\n-}\n-\n-static void git_hash_sha256_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n-{\n-\tgit_SHA256_Update(&ctx->state.sha256, data, len);\n-}\n-\n-static void git_hash_sha256_final(unsigned char *hash, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA256_Final(hash, &ctx->state.sha256);\n-}\n-\n-static void git_hash_sha256_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA256_Final(oid->hash, &ctx->state.sha256);\n-\t/*\n-\t * This currently does nothing, so the compiler should optimize it out,\n-\t * but keep it in case we extend the hash size again.\n-\t */\n-\tmemset(oid->hash + GIT_SHA256_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA256_RAWSZ);\n-\toid->algo = GIT_HASH_SHA256;\n-}\n-\n-static void git_hash_unknown_init(struct git_hash_ctx *ctx UNUSED)\n-{\n-\tBUG(\"trying to init unknown hash\");\n-}\n-\n-static void git_hash_unknown_clone(struct git_hash_ctx *dst UNUSED,\n-\t\t\t\t   const struct git_hash_ctx *src UNUSED)\n-{\n-\tBUG(\"trying to clone unknown hash\");\n-}\n-\n-static void git_hash_unknown_update(struct git_hash_ctx *ctx UNUSED,\n-\t\t\t\t    const void *data UNUSED,\n-\t\t\t\t    size_t len UNUSED)\n-{\n-\tBUG(\"trying to update unknown hash\");\n-}\n-\n-static void git_hash_unknown_final(unsigned char *hash UNUSED,\n-\t\t\t\t   struct git_hash_ctx *ctx UNUSED)\n-{\n-\tBUG(\"trying to finalize unknown hash\");\n-}\n-\n-static void git_hash_unknown_final_oid(struct object_id *oid UNUSED,\n-\t\t\t\t       struct git_hash_ctx *ctx UNUSED)\n-{\n-\tBUG(\"trying to finalize unknown hash\");\n-}\n-\n-static const struct git_hash_algo sha1_unsafe_algo = {\n-\t.name = \"sha1\",\n-\t.format_id = GIT_SHA1_FORMAT_ID,\n-\t.rawsz = GIT_SHA1_RAWSZ,\n-\t.hexsz = GIT_SHA1_HEXSZ,\n-\t.blksz = GIT_SHA1_BLKSZ,\n-\t.init_fn = git_hash_sha1_init_unsafe,\n-\t.clone_fn = git_hash_sha1_clone_unsafe,\n-\t.update_fn = git_hash_sha1_update_unsafe,\n-\t.final_fn = git_hash_sha1_final_unsafe,\n-\t.final_oid_fn = git_hash_sha1_final_oid_unsafe,\n-\t.empty_tree = &empty_tree_oid,\n-\t.empty_blob = &empty_blob_oid,\n-\t.null_oid = &null_oid_sha1,\n-};\n-\n-const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n-\t{\n-\t\t.name = NULL,\n-\t\t.format_id = 0x00000000,\n-\t\t.rawsz = 0,\n-\t\t.hexsz = 0,\n-\t\t.blksz = 0,\n-\t\t.init_fn = git_hash_unknown_init,\n-\t\t.clone_fn = git_hash_unknown_clone,\n-\t\t.update_fn = git_hash_unknown_update,\n-\t\t.final_fn = git_hash_unknown_final,\n-\t\t.final_oid_fn = git_hash_unknown_final_oid,\n-\t\t.empty_tree = NULL,\n-\t\t.empty_blob = NULL,\n-\t\t.null_oid = NULL,\n-\t},\n-\t{\n-\t\t.name = \"sha1\",\n-\t\t.format_id = GIT_SHA1_FORMAT_ID,\n-\t\t.rawsz = GIT_SHA1_RAWSZ,\n-\t\t.hexsz = GIT_SHA1_HEXSZ,\n-\t\t.blksz = GIT_SHA1_BLKSZ,\n-\t\t.init_fn = git_hash_sha1_init,\n-\t\t.clone_fn = git_hash_sha1_clone,\n-\t\t.update_fn = git_hash_sha1_update,\n-\t\t.final_fn = git_hash_sha1_final,\n-\t\t.final_oid_fn = git_hash_sha1_final_oid,\n-\t\t.unsafe = &sha1_unsafe_algo,\n-\t\t.empty_tree = &empty_tree_oid,\n-\t\t.empty_blob = &empty_blob_oid,\n-\t\t.null_oid = &null_oid_sha1,\n-\t},\n-\t{\n-\t\t.name = \"sha256\",\n-\t\t.format_id = GIT_SHA256_FORMAT_ID,\n-\t\t.rawsz = GIT_SHA256_RAWSZ,\n-\t\t.hexsz = GIT_SHA256_HEXSZ,\n-\t\t.blksz = GIT_SHA256_BLKSZ,\n-\t\t.init_fn = git_hash_sha256_init,\n-\t\t.clone_fn = git_hash_sha256_clone,\n-\t\t.update_fn = git_hash_sha256_update,\n-\t\t.final_fn = git_hash_sha256_final,\n-\t\t.final_oid_fn = git_hash_sha256_final_oid,\n-\t\t.empty_tree = &empty_tree_oid_sha256,\n-\t\t.empty_blob = &empty_blob_oid_sha256,\n-\t\t.null_oid = &null_oid_sha256,\n-\t}\n-};\n-\n-const struct object_id *null_oid(void)\n-{\n-\treturn the_hash_algo->null_oid;\n-}\n-\n-const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\n-{\n-\tstatic char buf[GIT_MAX_HEXSZ + 1];\n-\treturn oid_to_hex_r(buf, algop->empty_tree);\n-}\n-\n-int hash_algo_by_name(const char *name)\n-{\n-\tint i;\n-\tif (!name)\n-\t\treturn GIT_HASH_UNKNOWN;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n-\t\tif (!strcmp(name, hash_algos[i].name))\n-\t\t\treturn i;\n-\treturn GIT_HASH_UNKNOWN;\n-}\n-\n-int hash_algo_by_id(uint32_t format_id)\n-{\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n-\t\tif (format_id == hash_algos[i].format_id)\n-\t\t\treturn i;\n-\treturn GIT_HASH_UNKNOWN;\n-}\n-\n-int hash_algo_by_length(int len)\n-{\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n-\t\tif (len == hash_algos[i].rawsz)\n-\t\t\treturn i;\n-\treturn GIT_HASH_UNKNOWN;\n-}\n-\n-const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop)\n-{\n-\t/* If we have a faster \"unsafe\" implementation, use that. */\n-\tif (algop->unsafe)\n-\t\treturn algop->unsafe;\n-\t/* Otherwise use the default one. */\n-\treturn algop;\n-}\n-\n /*\n  * This is meant to hold a *small* number of objects that you would\n  * want repo_read_object_file() to be able to return, but yet you do not want\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513772","messageId":"20250307-b4-pks-objects-without-the-repository-v3-11-7bccf408731e@pks.im","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","subject":"[PATCH v3 11/12] hash: fix \"-Wsign-compare\" warnings","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T14:19:04Z","receivedAt":"2025-03-07T14:19:10Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are a couple of trivial \"-Wsign-compare\" warnings in \"hash.c\". Fix\nthem.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n hash.c | 12 ++++--------\n hash.h |  2 +-\n 2 files changed, 5 insertions(+), 9 deletions(-)\n\ndiff --git a/hash.c b/hash.c\nindex dd5ac9d0eb2..4d9f98f72c2 100644\n--- a/hash.c\n+++ b/hash.c\n@@ -1,5 +1,4 @@\n #define USE_THE_REPOSITORY_VARIABLE\n-#define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n #include \"hash.h\"\n@@ -246,10 +245,9 @@ const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\n \n int hash_algo_by_name(const char *name)\n {\n-\tint i;\n \tif (!name)\n \t\treturn GIT_HASH_UNKNOWN;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\tfor (size_t i = 1; i < GIT_HASH_NALGOS; i++)\n \t\tif (!strcmp(name, hash_algos[i].name))\n \t\t\treturn i;\n \treturn GIT_HASH_UNKNOWN;\n@@ -257,17 +255,15 @@ int hash_algo_by_name(const char *name)\n \n int hash_algo_by_id(uint32_t format_id)\n {\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\tfor (size_t i = 1; i < GIT_HASH_NALGOS; i++)\n \t\tif (format_id == hash_algos[i].format_id)\n \t\t\treturn i;\n \treturn GIT_HASH_UNKNOWN;\n }\n \n-int hash_algo_by_length(int len)\n+int hash_algo_by_length(size_t len)\n {\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\tfor (size_t i = 1; i < GIT_HASH_NALGOS; i++)\n \t\tif (len == hash_algos[i].rawsz)\n \t\t\treturn i;\n \treturn GIT_HASH_UNKNOWN;\ndiff --git a/hash.h b/hash.h\nindex 4367acfec50..55d67ed83f3 100644\n--- a/hash.h\n+++ b/hash.h\n@@ -325,7 +325,7 @@ int hash_algo_by_name(const char *name);\n /* Identical, except based on the format ID. */\n int hash_algo_by_id(uint32_t format_id);\n /* Identical, except based on the length. */\n-int hash_algo_by_length(int len);\n+int hash_algo_by_length(size_t len);\n /* Identical, except for a pointer to struct git_hash_algo. */\n static inline int hash_algo_by_ptr(const struct git_hash_algo *p)\n {\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513773","messageId":"20250307-b4-pks-objects-without-the-repository-v3-12-7bccf408731e@pks.im","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","subject":"[PATCH v3 12/12] hash: stop depending on `the_repository` in `null_oid()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-07T14:19:05Z","receivedAt":"2025-03-07T14:19:11Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `null_oid()` function returns the object ID that only consists of\nzeroes. Naturally, this ID also depends on the hash algorithm used, as\nthe number of zeroes is different between SHA1 and SHA256. Consequently,\nthe function returns the hash-algorithm-specific null object ID.\n\nThis is currently done by depending on `the_hash_algo`, which implicitly\nmakes us depend on `the_repository`. Refactor the function to instead\npass in the hash algorithm for which we want to retrieve the null object\nID. Adapt callsites accordingly by passing in `the_repository`, thus\nbubbling up the dependency on that global variable by one layer.\n\nThere are a couple of trivial exceptions for subsystems that already got\nrid of `the_repository`. These subsystems instead use the repository\nthat is available via the calling context:\n\n  - \"builtin/grep.c\"\n  - \"grep.c\"\n  - \"refs/debug.c\"\n\nThere are also two non-trivial exceptions:\n\n  - \"diff-no-index.c\": Here we know that we may not have a repository\n    initialized at all, so we cannot rely on `the_repository`. Instead,\n    we adapt `diff_no_index()` to get a `struct git_hash_algo` as\n    parameter. The only caller is located in \"builtin/diff.c\", where we\n    know to call `repo_set_hash_algo()` in case we're running outside of\n    a Git repository. Consequently, it is fine to continue passing\n    `the_repository->hash_algo` even in this case.\n\n  - \"builtin/ls-files.c\": There is an in-flight patch series that drops\n    `USE_THE_REPOSITORY_VARIABLE` in this file, which causes a semantic\n    conflict because we use `null_oid()` in `show_submodule()`. The\n    value is passed to `repo_submodule_init()`, which may use the object\n    ID to resolve a tree-ish in the superproject from which we want to\n    read the submodule config. As such, the object ID should refer to an\n    object in the superproject, and consequently we need to use its hash\n    algorithm.\n\nThis means that we could in theory just not bother about this edge case\nat all and just use `the_repository` in \"diff-no-index.c\". But doing so\nwould feel misdesigned.\n\nRemove the `USE_THE_REPOSITORY_VARIABLE` preprocessor define in\n\"hash.c\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n archive.c                                    |  2 +-\n blame.c                                      |  2 +-\n branch.c                                     |  2 +-\n builtin/checkout.c                           |  6 ++---\n builtin/clone.c                              |  2 +-\n builtin/describe.c                           |  2 +-\n builtin/diff.c                               |  5 ++--\n builtin/fast-export.c                        | 10 ++++----\n builtin/fsck.c                               |  2 +-\n builtin/grep.c                               |  2 +-\n builtin/ls-files.c                           |  3 ++-\n builtin/rebase.c                             |  2 +-\n builtin/receive-pack.c                       |  2 +-\n builtin/submodule--helper.c                  | 36 ++++++++++++++--------------\n builtin/unpack-objects.c                     |  2 +-\n builtin/update-ref.c                         |  2 +-\n builtin/worktree.c                           |  2 +-\n combine-diff.c                               |  2 +-\n diff-lib.c                                   | 10 ++++----\n diff-no-index.c                              | 28 +++++++++++-----------\n diff.c                                       |  8 +++----\n diff.h                                       |  2 +-\n dir.c                                        |  2 +-\n grep.c                                       |  2 +-\n hash.c                                       |  6 ++---\n hash.h                                       |  2 +-\n log-tree.c                                   |  2 +-\n merge-ort.c                                  | 26 ++++++++++----------\n merge-recursive.c                            | 12 +++++-----\n notes-merge.c                                |  2 +-\n notes.c                                      |  2 +-\n object-file.c                                |  2 +-\n parse-options-cb.c                           |  2 +-\n range-diff.c                                 |  2 +-\n read-cache.c                                 |  2 +-\n refs.c                                       | 12 +++++-----\n refs/debug.c                                 |  2 +-\n refs/files-backend.c                         |  2 +-\n reset.c                                      |  2 +-\n sequencer.c                                  | 10 ++++----\n submodule-config.c                           |  2 +-\n submodule.c                                  | 28 +++++++++++-----------\n t/helper/test-ref-store.c                    |  2 +-\n t/helper/test-submodule-nested-repo-config.c |  2 +-\n tree-diff.c                                  |  4 ++--\n upload-pack.c                                |  2 +-\n wt-status.c                                  |  4 ++--\n xdiff-interface.c                            |  2 +-\n 48 files changed, 136 insertions(+), 136 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex f4331aeb49e..c95e3981524 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -312,7 +312,7 @@ int write_archive_entries(struct archiver_args *args,\n \tstruct object_id fake_oid;\n \tint i;\n \n-\toidcpy(&fake_oid, null_oid());\n+\toidcpy(&fake_oid, null_oid(the_hash_algo));\n \n \tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n \t\tsize_t len = args->baselen;\ndiff --git a/blame.c b/blame.c\nindex a15ddf93335..703dab43e78 100644\n--- a/blame.c\n+++ b/blame.c\n@@ -255,7 +255,7 @@ static struct commit *fake_working_tree_commit(struct repository *r,\n \t\tswitch (st.st_mode & S_IFMT) {\n \t\tcase S_IFREG:\n \t\t\tif (opt->flags.allow_textconv &&\n-\t\t\t    textconv_object(r, read_from, mode, null_oid(), 0, &buf_ptr, &buf_len))\n+\t\t\t    textconv_object(r, read_from, mode, null_oid(the_hash_algo), 0, &buf_ptr, &buf_len))\n \t\t\t\tstrbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1);\n \t\t\telse if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)\n \t\t\t\tdie_errno(\"cannot open or read '%s'\", read_from);\ndiff --git a/branch.c b/branch.c\nindex 91297d55ac9..6d01d7d6bdb 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -633,7 +633,7 @@ void create_branch(struct repository *r,\n \t\t\t\t\t\t  0, &err);\n \tif (!transaction ||\n \t\tref_transaction_update(transaction, ref.buf,\n-\t\t\t\t\t&oid, forcing ? NULL : null_oid(),\n+\t\t\t\t\t&oid, forcing ? NULL : null_oid(the_hash_algo),\n \t\t\t\t\tNULL, NULL, flags, msg, &err) ||\n \t\tref_transaction_commit(transaction, &err))\n \t\tdie(\"%s\", err.buf);\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 01ea9ff8b28..2e7486cf658 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -130,8 +130,8 @@ static int post_checkout_hook(struct commit *old_commit, struct commit *new_comm\n \t\t\t      int changed)\n {\n \treturn run_hooks_l(the_repository, \"post-checkout\",\n-\t\t\t   oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()),\n-\t\t\t   oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()),\n+\t\t\t   oid_to_hex(old_commit ? &old_commit->object.oid : null_oid(the_hash_algo)),\n+\t\t\t   oid_to_hex(new_commit ? &new_commit->object.oid : null_oid(the_hash_algo)),\n \t\t\t   changed ? \"1\" : \"0\", NULL);\n \t/* \"new_commit\" can be NULL when checking out from the index before\n \t   a commit exists. */\n@@ -710,7 +710,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,\n \topts.src_index = the_repository->index;\n \topts.dst_index = the_repository->index;\n \tinit_checkout_metadata(&opts.meta, info->refname,\n-\t\t\t       info->commit ? &info->commit->object.oid : null_oid(),\n+\t\t\t       info->commit ? &info->commit->object.oid : null_oid(the_hash_algo),\n \t\t\t       NULL);\n \tif (parse_tree(tree) < 0)\n \t\treturn 128;\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex f14229abf45..36aba65e06c 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -690,7 +690,7 @@ static int checkout(int submodule_progress, int filter_submodules,\n \tif (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))\n \t\tdie(_(\"unable to write new index file\"));\n \n-\terr |= run_hooks_l(the_repository, \"post-checkout\", oid_to_hex(null_oid()),\n+\terr |= run_hooks_l(the_repository, \"post-checkout\", oid_to_hex(null_oid(the_hash_algo)),\n \t\t\t   oid_to_hex(&oid), \"1\", NULL);\n \n \tif (!err && (option_recurse_submodules.nr > 0)) {\ndiff --git a/builtin/describe.c b/builtin/describe.c\nindex e2e73f3d757..23df333fd04 100644\n--- a/builtin/describe.c\n+++ b/builtin/describe.c\n@@ -518,7 +518,7 @@ static void describe_blob(struct object_id oid, struct strbuf *dst)\n {\n \tstruct rev_info revs;\n \tstruct strvec args = STRVEC_INIT;\n-\tstruct process_commit_data pcd = { *null_oid(), oid, dst, &revs};\n+\tstruct process_commit_data pcd = { *null_oid(the_hash_algo), oid, dst, &revs};\n \n \tstrvec_pushl(&args, \"internal: The first arg is not parsed\",\n \t\t     \"--objects\", \"--in-commit-order\", \"--reverse\", \"HEAD\",\ndiff --git a/builtin/diff.c b/builtin/diff.c\nindex a4fffee42c6..fa963808c31 100644\n--- a/builtin/diff.c\n+++ b/builtin/diff.c\n@@ -104,7 +104,7 @@ static void builtin_diff_b_f(struct rev_info *revs,\n \n \tstuff_change(&revs->diffopt,\n \t\t     blob[0]->mode, canon_mode(st.st_mode),\n-\t\t     &blob[0]->item->oid, null_oid(),\n+\t\t     &blob[0]->item->oid, null_oid(the_hash_algo),\n \t\t     1, 0,\n \t\t     blob[0]->path ? blob[0]->path : path,\n \t\t     path);\n@@ -498,7 +498,8 @@ int cmd_diff(int argc,\n \n \t/* If this is a no-index diff, just run it and exit there. */\n \tif (no_index)\n-\t\texit(diff_no_index(&rev, no_index == DIFF_NO_INDEX_IMPLICIT,\n+\t\texit(diff_no_index(&rev, the_repository->hash_algo,\n+\t\t\t\t   no_index == DIFF_NO_INDEX_IMPLICIT,\n \t\t\t\t   argc, argv));\n \n \ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex a5c82eef1de..7a5c2925cd2 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -869,7 +869,7 @@ static void handle_tag(const char *name, struct tag *tag)\n \t\t\t\tp = rewrite_commit((struct commit *)tagged);\n \t\t\t\tif (!p) {\n \t\t\t\t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\t\t       name, oid_to_hex(null_oid()));\n+\t\t\t\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t\t\t\t\tfree(buf);\n \t\t\t\t\treturn;\n \t\t\t\t}\n@@ -883,7 +883,7 @@ static void handle_tag(const char *name, struct tag *tag)\n \n \tif (tagged->type == OBJ_TAG) {\n \t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t       name, oid_to_hex(null_oid()));\n+\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t}\n \tskip_prefix(name, \"refs/tags/\", &name);\n \tprintf(\"tag %s\\n\", name);\n@@ -1023,7 +1023,7 @@ static void handle_tags_and_duplicates(struct string_list *extras)\n \t\t\t\t * it.\n \t\t\t\t */\n \t\t\t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\t       name, oid_to_hex(null_oid()));\n+\t\t\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t\t\t\tcontinue;\n \t\t\t}\n \n@@ -1042,7 +1042,7 @@ static void handle_tags_and_duplicates(struct string_list *extras)\n \t\t\t\tif (!reference_excluded_commits) {\n \t\t\t\t\t/* delete the ref */\n \t\t\t\t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\t\t       name, oid_to_hex(null_oid()));\n+\t\t\t\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t\t\t\t\tcontinue;\n \t\t\t\t}\n \t\t\t\t/* set ref to commit using oid, not mark */\n@@ -1153,7 +1153,7 @@ static void handle_deletes(void)\n \t\t\tcontinue;\n \n \t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\trefspec->dst, oid_to_hex(null_oid()));\n+\t\t\t\trefspec->dst, oid_to_hex(null_oid(the_hash_algo)));\n \t}\n }\n \ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex 62c7494bbda..f86ecd8eaa5 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -625,7 +625,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)\n \tvoid *contents = NULL;\n \tint eaten;\n \tstruct object_info oi = OBJECT_INFO_INIT;\n-\tstruct object_id real_oid = *null_oid();\n+\tstruct object_id real_oid = *null_oid(the_hash_algo);\n \tint err = 0;\n \n \tstrbuf_reset(&cb_data->obj_type);\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex cbbf6f26439..283d64cab80 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -453,7 +453,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t\treturn 0;\n \n \tsubrepo = xmalloc(sizeof(*subrepo));\n-\tif (repo_submodule_init(subrepo, superproject, path, null_oid())) {\n+\tif (repo_submodule_init(subrepo, superproject, path, null_oid(opt->repo->hash_algo))) {\n \t\tfree(subrepo);\n \t\treturn 0;\n \t}\ndiff --git a/builtin/ls-files.c b/builtin/ls-files.c\nindex a4431429b7d..7bc418be5d4 100644\n--- a/builtin/ls-files.c\n+++ b/builtin/ls-files.c\n@@ -234,7 +234,8 @@ static void show_submodule(struct repository *superproject,\n {\n \tstruct repository subrepo;\n \n-\tif (repo_submodule_init(&subrepo, superproject, path, null_oid()))\n+\tif (repo_submodule_init(&subrepo, superproject, path,\n+\t\t\t\tnull_oid(superproject->hash_algo)))\n \t\treturn;\n \n \tif (repo_read_index(&subrepo) < 0)\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex d4715ed35d7..1cd802dd92a 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -925,7 +925,7 @@ static void fill_branch_base(struct rebase_options *options,\n \t\t\t\t options->orig_head, &merge_bases) < 0)\n \t\texit(128);\n \tif (!merge_bases || merge_bases->next)\n-\t\toidcpy(branch_base, null_oid());\n+\t\toidcpy(branch_base, null_oid(the_hash_algo));\n \telse\n \t\toidcpy(branch_base, &merge_bases->item->object.oid);\n \ndiff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\nindex 7b28fc9df6e..b3e2a9d0c60 100644\n--- a/builtin/receive-pack.c\n+++ b/builtin/receive-pack.c\n@@ -363,7 +363,7 @@ static void write_head_info(void)\n \tstrvec_clear(&excludes_vector);\n \n \tif (!sent_capabilities)\n-\t\tshow_ref(\"capabilities^{}\", null_oid());\n+\t\tshow_ref(\"capabilities^{}\", null_oid(the_hash_algo));\n \n \tadvertise_shallow_grafts(1);\n \ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex c1a8029714b..570226ea166 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -78,7 +78,7 @@ static int get_default_remote_submodule(const char *module_path, char **default_\n \tint ret;\n \n \tif (repo_submodule_init(&subrepo, the_repository, module_path,\n-\t\t\t\tnull_oid()) < 0)\n+\t\t\t\tnull_oid(the_hash_algo)) < 0)\n \t\treturn die_message(_(\"could not get a repository handle for submodule '%s'\"),\n \t\t\t\t   module_path);\n \tret = repo_get_default_remote(&subrepo, default_remote);\n@@ -308,7 +308,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,\n \tdisplaypath = get_submodule_displaypath(path, info->prefix,\n \t\t\t\t\t\tinfo->super_prefix);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n@@ -468,7 +468,7 @@ static void init_submodule(const char *path, const char *prefix,\n \n \tdisplaypath = get_submodule_displaypath(path, prefix, super_prefix);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n@@ -645,14 +645,14 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,\n \tif (validate_submodule_path(path) < 0)\n \t\texit(128);\n \n-\tif (!submodule_from_path(the_repository, null_oid(), path))\n+\tif (!submodule_from_path(the_repository, null_oid(the_hash_algo), path))\n \t\tdie(_(\"no submodule mapping found in .gitmodules for path '%s'\"),\n \t\t      path);\n \n \tdisplaypath = get_submodule_displaypath(path, prefix, super_prefix);\n \n \tif ((CE_STAGEMASK & ce_flags) >> CE_STAGESHIFT) {\n-\t\tprint_status(flags, 'U', path, null_oid(), displaypath);\n+\t\tprint_status(flags, 'U', path, null_oid(the_hash_algo), displaypath);\n \t\tgoto cleanup;\n \t}\n \n@@ -912,7 +912,7 @@ static void generate_submodule_summary(struct summary_cb *info,\n \tstruct strbuf errmsg = STRBUF_INIT;\n \tint total_commits = -1;\n \n-\tif (!info->cached && oideq(&p->oid_dst, null_oid())) {\n+\tif (!info->cached && oideq(&p->oid_dst, null_oid(the_hash_algo))) {\n \t\tif (S_ISGITLINK(p->mod_dst)) {\n \t\t\tstruct ref_store *refs = repo_get_submodule_ref_store(the_repository,\n \t\t\t\t\t\t\t\t\t      p->sm_path);\n@@ -1051,7 +1051,7 @@ static void prepare_submodule_summary(struct summary_cb *info,\n \n \t\tif (info->for_status && p->status != 'A' &&\n \t\t    (sub = submodule_from_path(the_repository,\n-\t\t\t\t\t       null_oid(), p->sm_path))) {\n+\t\t\t\t\t       null_oid(the_hash_algo), p->sm_path))) {\n \t\t\tchar *config_key = NULL;\n \t\t\tconst char *value;\n \t\t\tint ignore_all = 0;\n@@ -1259,7 +1259,7 @@ static void sync_submodule(const char *path, const char *prefix,\n \tif (validate_submodule_path(path) < 0)\n \t\texit(128);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (sub && sub->url) {\n \t\tif (starts_with_dot_dot_slash(sub->url) ||\n@@ -1404,7 +1404,7 @@ static void deinit_submodule(const char *path, const char *prefix,\n \tif (validate_submodule_path(path) < 0)\n \t\texit(128);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub || !sub->name)\n \t\tgoto cleanup;\n@@ -1929,7 +1929,7 @@ static int determine_submodule_update_strategy(struct repository *r,\n \t\t\t\t\t       enum submodule_update_type update,\n \t\t\t\t\t       struct submodule_update_strategy *out)\n {\n-\tconst struct submodule *sub = submodule_from_path(r, null_oid(), path);\n+\tconst struct submodule *sub = submodule_from_path(r, null_oid(the_hash_algo), path);\n \tchar *key;\n \tconst char *val;\n \tint ret;\n@@ -2089,7 +2089,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\tgoto cleanup;\n \t}\n \n-\tsub = submodule_from_path(the_repository, null_oid(), ce->name);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), ce->name);\n \n \tif (!sub) {\n \t\tnext_submodule_warn_missing(suc, out, displaypath);\n@@ -2485,7 +2485,7 @@ static int remote_submodule_branch(const char *path, const char **branch)\n \tchar *key;\n \t*branch = NULL;\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \tif (!sub)\n \t\treturn die_message(_(\"could not initialize submodule at path '%s'\"),\n \t\t\t\t   path);\n@@ -2531,7 +2531,7 @@ static int ensure_core_worktree(const char *path)\n \tconst char *cw;\n \tstruct repository subrepo;\n \n-\tif (repo_submodule_init(&subrepo, the_repository, path, null_oid()))\n+\tif (repo_submodule_init(&subrepo, the_repository, path, null_oid(the_hash_algo)))\n \t\treturn die_message(_(\"could not get a repository handle for submodule '%s'\"),\n \t\t\t\t   path);\n \n@@ -2644,7 +2644,7 @@ static int update_submodule(struct update_data *update_data)\n \t\treturn ret;\n \n \tif (update_data->just_cloned)\n-\t\toidcpy(&update_data->suboid, null_oid());\n+\t\toidcpy(&update_data->suboid, null_oid(the_hash_algo));\n \telse if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path,\n \t\t\t\t\t  \"HEAD\", &update_data->suboid))\n \t\treturn die_message(_(\"Unable to find current revision in submodule path '%s'\"),\n@@ -2697,8 +2697,8 @@ static int update_submodule(struct update_data *update_data)\n \t\tstruct update_data next = *update_data;\n \n \t\tnext.prefix = NULL;\n-\t\toidcpy(&next.oid, null_oid());\n-\t\toidcpy(&next.suboid, null_oid());\n+\t\toidcpy(&next.oid, null_oid(the_hash_algo));\n+\t\toidcpy(&next.suboid, null_oid(the_hash_algo));\n \n \t\tcp.dir = update_data->sm_path;\n \t\tcp.git_cmd = 1;\n@@ -3057,7 +3057,7 @@ static int module_set_url(int argc, const char **argv, const char *prefix,\n \tif (argc != 2 || !(path = argv[0]) || !(newurl = argv[1]))\n \t\tusage_with_options(usage, options);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"no submodule mapping found in .gitmodules for path '%s'\"),\n@@ -3113,7 +3113,7 @@ static int module_set_branch(int argc, const char **argv, const char *prefix,\n \tif (argc != 1 || !(path = argv[0]))\n \t\tusage_with_options(usage, options);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"no submodule mapping found in .gitmodules for path '%s'\"),\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex e20c120913e..73d431a0dde 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -505,7 +505,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,\n \t\t\t * has not been resolved yet.\n \t\t\t */\n \t\t\toidclr(&obj_list[nr].oid, the_repository->hash_algo);\n-\t\t\tadd_delta_to_list(nr, null_oid(), base_offset,\n+\t\t\tadd_delta_to_list(nr, null_oid(the_hash_algo), base_offset,\n \t\t\t\t\t  delta_data, delta_size);\n \t\t\treturn;\n \t\t}\ndiff --git a/builtin/update-ref.c b/builtin/update-ref.c\nindex 4d35bdc4b4b..3796b9844d1 100644\n--- a/builtin/update-ref.c\n+++ b/builtin/update-ref.c\n@@ -500,7 +500,7 @@ static void parse_cmd_symref_verify(struct ref_transaction *transaction,\n \t */\n \told_target = parse_next_refname(&next);\n \tif (!old_target)\n-\t\toidcpy(&old_oid, null_oid());\n+\t\toidcpy(&old_oid, null_oid(the_hash_algo));\n \n \tif (*next != line_termination)\n \t\tdie(\"symref-verify %s: extra input: %s\", refname, next);\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 48448a83550..87ccd47794c 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -578,7 +578,7 @@ static int add_worktree(const char *path, const char *refname,\n \n \t\tstrvec_pushl(&opt.env, \"GIT_DIR\", \"GIT_WORK_TREE\", NULL);\n \t\tstrvec_pushl(&opt.args,\n-\t\t\t     oid_to_hex(null_oid()),\n+\t\t\t     oid_to_hex(null_oid(the_hash_algo)),\n \t\t\t     oid_to_hex(&commit->object.oid),\n \t\t\t     \"1\",\n \t\t\t     NULL);\ndiff --git a/combine-diff.c b/combine-diff.c\nindex 9527f3160d8..553bf59fed6 100644\n--- a/combine-diff.c\n+++ b/combine-diff.c\n@@ -1066,7 +1066,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,\n \t\t\t\t\t\t   &result_size, NULL, NULL);\n \t\t} else if (textconv) {\n \t\t\tstruct diff_filespec *df = alloc_filespec(elem->path);\n-\t\t\tfill_filespec(df, null_oid(), 0, st.st_mode);\n+\t\t\tfill_filespec(df, null_oid(the_hash_algo), 0, st.st_mode);\n \t\t\tresult_size = fill_textconv(opt->repo, textconv, df, &result);\n \t\t\tfree_filespec(df);\n \t\t} else if (0 <= (fd = open(elem->path, O_RDONLY))) {\ndiff --git a/diff-lib.c b/diff-lib.c\nindex 353b473ed52..244468dd1a2 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -172,7 +172,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t\t * these from (stage - 2).\n \t\t\t */\n \t\t\tdpath = combine_diff_path_new(ce->name, ce_namelen(ce),\n-\t\t\t\t\t\t      wt_mode, null_oid(), 2);\n+\t\t\t\t\t\t      wt_mode, null_oid(the_hash_algo), 2);\n \n \t\t\twhile (i < entries) {\n \t\t\t\tstruct cache_entry *nce = istate->cache[i];\n@@ -257,7 +257,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t\t\t   ce_intent_to_add(ce)) {\n \t\t\t\tnewmode = ce_mode_from_stat(ce, st.st_mode);\n \t\t\t\tdiff_addremove(&revs->diffopt, '+', newmode,\n-\t\t\t\t\t       null_oid(), 0, ce->name, 0);\n+\t\t\t\t\t       null_oid(the_hash_algo), 0, ce->name, 0);\n \t\t\t\tcontinue;\n \t\t\t}\n \n@@ -274,7 +274,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t}\n \t\toldmode = ce->ce_mode;\n \t\told_oid = &ce->oid;\n-\t\tnew_oid = changed ? null_oid() : &ce->oid;\n+\t\tnew_oid = changed ? null_oid(the_hash_algo) : &ce->oid;\n \t\tdiff_change(&revs->diffopt, oldmode, newmode,\n \t\t\t    old_oid, new_oid,\n \t\t\t    !is_null_oid(old_oid),\n@@ -330,7 +330,7 @@ static int get_stat_data(const struct cache_entry *ce,\n \t\t\t\t\t\t    0, dirty_submodule);\n \t\tif (changed) {\n \t\t\tmode = ce_mode_from_stat(ce, st.st_mode);\n-\t\t\toid = null_oid();\n+\t\t\toid = null_oid(the_hash_algo);\n \t\t}\n \t}\n \n@@ -402,7 +402,7 @@ static int show_modified(struct rev_info *revs,\n \n \t\tp = combine_diff_path_new(new_entry->name,\n \t\t\t\t\t  ce_namelen(new_entry),\n-\t\t\t\t\t  mode, null_oid(), 2);\n+\t\t\t\t\t  mode, null_oid(the_hash_algo), 2);\n \t\tp->parent[0].status = DIFF_STATUS_MODIFIED;\n \t\tp->parent[0].mode = new_entry->ce_mode;\n \t\toidcpy(&p->parent[0].oid, &new_entry->oid);\ndiff --git a/diff-no-index.c b/diff-no-index.c\nindex 6f277892d3a..9739b2b268b 100644\n--- a/diff-no-index.c\n+++ b/diff-no-index.c\n@@ -113,7 +113,8 @@ static void populate_from_stdin(struct diff_filespec *s)\n \tpopulate_common(s, &buf);\n }\n \n-static struct diff_filespec *noindex_filespec(const char *name, int mode,\n+static struct diff_filespec *noindex_filespec(const struct git_hash_algo *algop,\n+\t\t\t\t\t      const char *name, int mode,\n \t\t\t\t\t      enum special special)\n {\n \tstruct diff_filespec *s;\n@@ -121,7 +122,7 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode,\n \tif (!name)\n \t\tname = \"/dev/null\";\n \ts = alloc_filespec(name);\n-\tfill_filespec(s, null_oid(), 0, mode);\n+\tfill_filespec(s, null_oid(algop), 0, mode);\n \tif (special == SPECIAL_STDIN)\n \t\tpopulate_from_stdin(s);\n \telse if (special == SPECIAL_PIPE)\n@@ -129,7 +130,7 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode,\n \treturn s;\n }\n \n-static int queue_diff(struct diff_options *o,\n+static int queue_diff(struct diff_options *o, const struct git_hash_algo *algop,\n \t\t      const char *name1, const char *name2, int recursing)\n {\n \tint mode1 = 0, mode2 = 0;\n@@ -145,14 +146,14 @@ static int queue_diff(struct diff_options *o,\n \n \t\tif (S_ISDIR(mode1)) {\n \t\t\t/* 2 is file that is created */\n-\t\t\td1 = noindex_filespec(NULL, 0, SPECIAL_NONE);\n-\t\t\td2 = noindex_filespec(name2, mode2, special2);\n+\t\t\td1 = noindex_filespec(algop, NULL, 0, SPECIAL_NONE);\n+\t\t\td2 = noindex_filespec(algop, name2, mode2, special2);\n \t\t\tname2 = NULL;\n \t\t\tmode2 = 0;\n \t\t} else {\n \t\t\t/* 1 is file that is deleted */\n-\t\t\td1 = noindex_filespec(name1, mode1, special1);\n-\t\t\td2 = noindex_filespec(NULL, 0, SPECIAL_NONE);\n+\t\t\td1 = noindex_filespec(algop, name1, mode1, special1);\n+\t\t\td2 = noindex_filespec(algop, NULL, 0, SPECIAL_NONE);\n \t\t\tname1 = NULL;\n \t\t\tmode1 = 0;\n \t\t}\n@@ -217,7 +218,7 @@ static int queue_diff(struct diff_options *o,\n \t\t\t\tn2 = buffer2.buf;\n \t\t\t}\n \n-\t\t\tret = queue_diff(o, n1, n2, 1);\n+\t\t\tret = queue_diff(o, algop, n1, n2, 1);\n \t\t}\n \t\tstring_list_clear(&p1, 0);\n \t\tstring_list_clear(&p2, 0);\n@@ -234,8 +235,8 @@ static int queue_diff(struct diff_options *o,\n \t\t\tSWAP(special1, special2);\n \t\t}\n \n-\t\td1 = noindex_filespec(name1, mode1, special1);\n-\t\td2 = noindex_filespec(name2, mode2, special2);\n+\t\td1 = noindex_filespec(algop, name1, mode1, special1);\n+\t\td2 = noindex_filespec(algop, name2, mode2, special2);\n \t\tdiff_queue(&diff_queued_diff, d1, d2);\n \t\treturn 0;\n \t}\n@@ -297,9 +298,8 @@ static const char * const diff_no_index_usage[] = {\n \tNULL\n };\n \n-int diff_no_index(struct rev_info *revs,\n-\t\t  int implicit_no_index,\n-\t\t  int argc, const char **argv)\n+int diff_no_index(struct rev_info *revs, const struct git_hash_algo *algop,\n+\t\t  int implicit_no_index, int argc, const char **argv)\n {\n \tint i, no_index;\n \tint ret = 1;\n@@ -354,7 +354,7 @@ int diff_no_index(struct rev_info *revs,\n \tsetup_diff_pager(&revs->diffopt);\n \trevs->diffopt.flags.exit_with_status = 1;\n \n-\tif (queue_diff(&revs->diffopt, paths[0], paths[1], 0))\n+\tif (queue_diff(&revs->diffopt, algop, paths[0], paths[1], 0))\n \t\tgoto out;\n \tdiff_set_mnemonic_prefix(&revs->diffopt, \"1/\", \"2/\");\n \tdiffcore_std(&revs->diffopt);\ndiff --git a/diff.c b/diff.c\nindex 4f802b4251c..4ce5933a442 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -4346,7 +4346,7 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r,\n \t\t\t\tdie_errno(\"readlink(%s)\", one->path);\n \t\t\tprep_temp_blob(r->index, one->path, temp, sb.buf, sb.len,\n \t\t\t\t       (one->oid_valid ?\n-\t\t\t\t\t&one->oid : null_oid()),\n+\t\t\t\t\t&one->oid : null_oid(the_hash_algo)),\n \t\t\t\t       (one->oid_valid ?\n \t\t\t\t\tone->mode : S_IFLNK));\n \t\t\tstrbuf_release(&sb);\n@@ -4355,7 +4355,7 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r,\n \t\t\t/* we can borrow from the file in the work tree */\n \t\t\ttemp->name = one->path;\n \t\t\tif (!one->oid_valid)\n-\t\t\t\toid_to_hex_r(temp->hex, null_oid());\n+\t\t\t\toid_to_hex_r(temp->hex, null_oid(the_hash_algo));\n \t\t\telse\n \t\t\t\toid_to_hex_r(temp->hex, &one->oid);\n \t\t\t/* Even though we may sometimes borrow the\n@@ -6649,8 +6649,8 @@ static void create_filepairs_for_header_only_notifications(struct diff_options *\n \n \t\t\tone = alloc_filespec(e->key);\n \t\t\ttwo = alloc_filespec(e->key);\n-\t\t\tfill_filespec(one, null_oid(), 0, 0);\n-\t\t\tfill_filespec(two, null_oid(), 0, 0);\n+\t\t\tfill_filespec(one, null_oid(the_hash_algo), 0, 0);\n+\t\t\tfill_filespec(two, null_oid(the_hash_algo), 0, 0);\n \t\t\tp = diff_queue(q, one, two);\n \t\t\tp->status = DIFF_STATUS_MODIFIED;\n \t\t}\ndiff --git a/diff.h b/diff.h\nindex 0a566f5531a..0822111c62a 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -656,7 +656,7 @@ void flush_one_hunk(struct object_id *result, struct git_hash_ctx *ctx);\n \n int diff_result_code(struct rev_info *);\n \n-int diff_no_index(struct rev_info *,\n+int diff_no_index(struct rev_info *, const struct git_hash_algo *algop,\n \t\t  int implicit_no_index, int, const char **);\n \n int index_differs_from(struct repository *r, const char *def,\ndiff --git a/dir.c b/dir.c\nindex cbd82be6c91..28b0e03feb4 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -4035,7 +4035,7 @@ static void connect_wt_gitdir_in_nested(const char *sub_worktree,\n \t\t\t */\n \t\t\ti++;\n \n-\t\tsub = submodule_from_path(&subrepo, null_oid(), ce->name);\n+\t\tsub = submodule_from_path(&subrepo, null_oid(the_hash_algo), ce->name);\n \t\tif (!sub || !is_submodule_active(&subrepo, ce->name))\n \t\t\t/* .gitmodules broken or inactive sub */\n \t\t\tcontinue;\ndiff --git a/grep.c b/grep.c\nindex 4e155ee9e66..9284b5741f5 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -1517,7 +1517,7 @@ static int fill_textconv_grep(struct repository *r,\n \t\tfill_filespec(df, gs->identifier, 1, 0100644);\n \t\tbreak;\n \tcase GREP_SOURCE_FILE:\n-\t\tfill_filespec(df, null_oid(), 0, 0100644);\n+\t\tfill_filespec(df, null_oid(r->hash_algo), 0, 0100644);\n \t\tbreak;\n \tdefault:\n \t\tBUG(\"attempt to textconv something without a path?\");\ndiff --git a/hash.c b/hash.c\nindex 4d9f98f72c2..4a04ecb50e8 100644\n--- a/hash.c\n+++ b/hash.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"hash.h\"\n #include \"hex.h\"\n@@ -232,9 +230,9 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n \t}\n };\n \n-const struct object_id *null_oid(void)\n+const struct object_id *null_oid(const struct git_hash_algo *algop)\n {\n-\treturn the_hash_algo->null_oid;\n+\treturn algop->null_oid;\n }\n \n const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\ndiff --git a/hash.h b/hash.h\nindex 55d67ed83f3..a9ef76fc8e7 100644\n--- a/hash.h\n+++ b/hash.h\n@@ -340,7 +340,7 @@ static inline int hash_algo_by_ptr(const struct git_hash_algo *p)\n \n const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop);\n \n-const struct object_id *null_oid(void);\n+const struct object_id *null_oid(const struct git_hash_algo *algop);\n \n static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)\n {\ndiff --git a/log-tree.c b/log-tree.c\nindex 8b184d67763..5dd1b63076f 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -499,7 +499,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,\n {\n \tstruct strbuf headers = STRBUF_INIT;\n \tconst char *name = oid_to_hex(opt->zero_commit ?\n-\t\t\t\t      null_oid() : &commit->object.oid);\n+\t\t\t\t      null_oid(the_hash_algo) : &commit->object.oid);\n \n \t*need_8bit_cte_p = 0; /* unknown */\n \ndiff --git a/merge-ort.c b/merge-ort.c\nindex 46e78c3ffa6..eb3a834652a 100644\n--- a/merge-ort.c\n+++ b/merge-ort.c\n@@ -1817,7 +1817,7 @@ static int merge_submodule(struct merge_options *opt,\n \t\tBUG(\"submodule deleted on one side; this should be handled outside of merge_submodule()\");\n \n \tif ((sub_not_initialized = repo_submodule_init(&subrepo,\n-\t\topt->repo, path, null_oid()))) {\n+\t\topt->repo, path, null_oid(the_hash_algo)))) {\n \t\tpath_msg(opt, CONFLICT_SUBMODULE_NOT_INITIALIZED, 0,\n \t\t\t path, NULL, NULL, NULL,\n \t\t\t _(\"Failed to merge submodule %s (not checked out)\"),\n@@ -2199,7 +2199,7 @@ static int handle_content_merge(struct merge_options *opt,\n \t\ttwo_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));\n \n \t\tmerge_status = merge_3way(opt, path,\n-\t\t\t\t\t  two_way ? null_oid() : &o->oid,\n+\t\t\t\t\t  two_way ? null_oid(the_hash_algo) : &o->oid,\n \t\t\t\t\t  &a->oid, &b->oid,\n \t\t\t\t\t  pathnames, extra_marker_size,\n \t\t\t\t\t  &result_buf);\n@@ -2231,7 +2231,7 @@ static int handle_content_merge(struct merge_options *opt,\n \t} else if (S_ISGITLINK(a->mode)) {\n \t\tint two_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));\n \t\tclean = merge_submodule(opt, pathnames[0],\n-\t\t\t\t\ttwo_way ? null_oid() : &o->oid,\n+\t\t\t\t\ttwo_way ? null_oid(the_hash_algo) : &o->oid,\n \t\t\t\t\t&a->oid, &b->oid, &result->oid);\n \t\tif (clean < 0)\n \t\t\treturn -1;\n@@ -2739,7 +2739,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt,\n \t\tassert(!new_ci->match_mask);\n \t\tnew_ci->dirmask = 0;\n \t\tnew_ci->stages[1].mode = 0;\n-\t\toidcpy(&new_ci->stages[1].oid, null_oid());\n+\t\toidcpy(&new_ci->stages[1].oid, null_oid(the_hash_algo));\n \n \t\t/*\n \t\t * Now that we have the file information in new_ci, make sure\n@@ -2752,7 +2752,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt,\n \t\t\t\tcontinue;\n \t\t\t/* zero out any entries related to files */\n \t\t\tci->stages[i].mode = 0;\n-\t\t\toidcpy(&ci->stages[i].oid, null_oid());\n+\t\t\toidcpy(&ci->stages[i].oid, null_oid(the_hash_algo));\n \t\t}\n \n \t\t/* Now we want to focus on new_ci, so reassign ci to it. */\n@@ -3122,7 +3122,7 @@ static int process_renames(struct merge_options *opt,\n \t\t\tif (type_changed) {\n \t\t\t\t/* rename vs. typechange */\n \t\t\t\t/* Mark the original as resolved by removal */\n-\t\t\t\tmemcpy(&oldinfo->stages[0].oid, null_oid(),\n+\t\t\t\tmemcpy(&oldinfo->stages[0].oid, null_oid(the_hash_algo),\n \t\t\t\t       sizeof(oldinfo->stages[0].oid));\n \t\t\t\toldinfo->stages[0].mode = 0;\n \t\t\t\toldinfo->filemask &= 0x06;\n@@ -3994,7 +3994,7 @@ static int process_entry(struct merge_options *opt,\n \t\t\tif (ci->filemask & (1 << i))\n \t\t\t\tcontinue;\n \t\t\tci->stages[i].mode = 0;\n-\t\t\toidcpy(&ci->stages[i].oid, null_oid());\n+\t\t\toidcpy(&ci->stages[i].oid, null_oid(the_hash_algo));\n \t\t}\n \t} else if (ci->df_conflict && ci->merged.result.mode != 0) {\n \t\t/*\n@@ -4041,7 +4041,7 @@ static int process_entry(struct merge_options *opt,\n \t\t\t\tcontinue;\n \t\t\t/* zero out any entries related to directories */\n \t\t\tnew_ci->stages[i].mode = 0;\n-\t\t\toidcpy(&new_ci->stages[i].oid, null_oid());\n+\t\t\toidcpy(&new_ci->stages[i].oid, null_oid(the_hash_algo));\n \t\t}\n \n \t\t/*\n@@ -4163,11 +4163,11 @@ static int process_entry(struct merge_options *opt,\n \t\t\tnew_ci->merged.result.mode = ci->stages[2].mode;\n \t\t\toidcpy(&new_ci->merged.result.oid, &ci->stages[2].oid);\n \t\t\tnew_ci->stages[1].mode = 0;\n-\t\t\toidcpy(&new_ci->stages[1].oid, null_oid());\n+\t\t\toidcpy(&new_ci->stages[1].oid, null_oid(the_hash_algo));\n \t\t\tnew_ci->filemask = 5;\n \t\t\tif ((S_IFMT & b_mode) != (S_IFMT & o_mode)) {\n \t\t\t\tnew_ci->stages[0].mode = 0;\n-\t\t\t\toidcpy(&new_ci->stages[0].oid, null_oid());\n+\t\t\t\toidcpy(&new_ci->stages[0].oid, null_oid(the_hash_algo));\n \t\t\t\tnew_ci->filemask = 4;\n \t\t\t}\n \n@@ -4175,11 +4175,11 @@ static int process_entry(struct merge_options *opt,\n \t\t\tci->merged.result.mode = ci->stages[1].mode;\n \t\t\toidcpy(&ci->merged.result.oid, &ci->stages[1].oid);\n \t\t\tci->stages[2].mode = 0;\n-\t\t\toidcpy(&ci->stages[2].oid, null_oid());\n+\t\t\toidcpy(&ci->stages[2].oid, null_oid(the_hash_algo));\n \t\t\tci->filemask = 3;\n \t\t\tif ((S_IFMT & a_mode) != (S_IFMT & o_mode)) {\n \t\t\t\tci->stages[0].mode = 0;\n-\t\t\t\toidcpy(&ci->stages[0].oid, null_oid());\n+\t\t\t\toidcpy(&ci->stages[0].oid, null_oid(the_hash_algo));\n \t\t\t\tci->filemask = 2;\n \t\t\t}\n \n@@ -4304,7 +4304,7 @@ static int process_entry(struct merge_options *opt,\n \t\t/* Deleted on both sides */\n \t\tci->merged.is_null = 1;\n \t\tci->merged.result.mode = 0;\n-\t\toidcpy(&ci->merged.result.oid, null_oid());\n+\t\toidcpy(&ci->merged.result.oid, null_oid(the_hash_algo));\n \t\tassert(!ci->df_conflict);\n \t\tci->merged.clean = !ci->path_conflict;\n \t}\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 5dfaf32b2c1..d88e61b07a9 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -502,7 +502,7 @@ static int get_tree_entry_if_blob(struct repository *r,\n \n \tret = get_tree_entry(r, tree, path, &dfs->oid, &dfs->mode);\n \tif (S_ISDIR(dfs->mode)) {\n-\t\toidcpy(&dfs->oid, null_oid());\n+\t\toidcpy(&dfs->oid, null_oid(the_hash_algo));\n \t\tdfs->mode = 0;\n \t}\n \treturn ret;\n@@ -1238,7 +1238,7 @@ static int merge_submodule(struct merge_options *opt,\n \tif (is_null_oid(b))\n \t\treturn 0;\n \n-\tif (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) {\n+\tif (repo_submodule_init(&subrepo, opt->repo, path, null_oid(the_hash_algo))) {\n \t\toutput(opt, 1, _(\"Failed to merge submodule %s (not checked out)\"), path);\n \t\treturn 0;\n \t}\n@@ -1698,7 +1698,7 @@ static int handle_file_collision(struct merge_options *opt,\n \n \t/* Store things in diff_filespecs for functions that need it */\n \tnull.path = (char *)collide_path;\n-\toidcpy(&null.oid, null_oid());\n+\toidcpy(&null.oid, null_oid(the_hash_algo));\n \tnull.mode = 0;\n \n \tif (merge_mode_and_contents(opt, &null, a, b, collide_path,\n@@ -2898,14 +2898,14 @@ static int process_renames(struct merge_options *opt,\n \t\t\tdst_other.mode = ren1->dst_entry->stages[other_stage].mode;\n \t\t\ttry_merge = 0;\n \n-\t\t\tif (oideq(&src_other.oid, null_oid()) &&\n+\t\t\tif (oideq(&src_other.oid, null_oid(the_hash_algo)) &&\n \t\t\t    ren1->dir_rename_original_type == 'A') {\n \t\t\t\tsetup_rename_conflict_info(RENAME_VIA_DIR,\n \t\t\t\t\t\t\t   opt, ren1, NULL);\n \t\t\t} else if (renamed_to_self) {\n \t\t\t\tsetup_rename_conflict_info(RENAME_NORMAL,\n \t\t\t\t\t\t\t   opt, ren1, NULL);\n-\t\t\t} else if (oideq(&src_other.oid, null_oid())) {\n+\t\t\t} else if (oideq(&src_other.oid, null_oid(the_hash_algo))) {\n \t\t\t\tsetup_rename_conflict_info(RENAME_DELETE,\n \t\t\t\t\t\t\t   opt, ren1, NULL);\n \t\t\t} else if ((dst_other.mode == ren1->pair->two->mode) &&\n@@ -2924,7 +2924,7 @@ static int process_renames(struct merge_options *opt,\n \t\t\t\t\t\t      1, /* update_cache */\n \t\t\t\t\t\t      0  /* update_wd    */))\n \t\t\t\t\tclean_merge = -1;\n-\t\t\t} else if (!oideq(&dst_other.oid, null_oid())) {\n+\t\t\t} else if (!oideq(&dst_other.oid, null_oid(the_hash_algo))) {\n \t\t\t\t/*\n \t\t\t\t * Probably not a clean merge, but it's\n \t\t\t\t * premature to set clean_merge to 0 here,\ndiff --git a/notes-merge.c b/notes-merge.c\nindex 67a472020de..5008faef450 100644\n--- a/notes-merge.c\n+++ b/notes-merge.c\n@@ -617,7 +617,7 @@ int notes_merge(struct notes_merge_options *o,\n \tif (repo_get_merge_bases(the_repository, local, remote, &bases) < 0)\n \t\texit(128);\n \tif (!bases) {\n-\t\tbase_oid = null_oid();\n+\t\tbase_oid = null_oid(the_hash_algo);\n \t\tbase_tree_oid = the_hash_algo->empty_tree;\n \t\tif (o->verbosity >= 4)\n \t\t\tprintf(\"No merge base found; doing history-less merge\\n\");\ndiff --git a/notes.c b/notes.c\nindex f5344230505..ce5a1006a83 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -1353,7 +1353,7 @@ int copy_note(struct notes_tree *t,\n \tif (note)\n \t\treturn add_note(t, to_obj, note, combine_notes);\n \telse if (existing_note)\n-\t\treturn add_note(t, to_obj, null_oid(), combine_notes);\n+\t\treturn add_note(t, to_obj, null_oid(the_hash_algo), combine_notes);\n \n \treturn 0;\n }\ndiff --git a/object-file.c b/object-file.c\nindex de603e2ca8c..772c311f188 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2405,7 +2405,7 @@ static int index_mem(struct index_state *istate,\n \n \t\topts.strict = 1;\n \t\topts.error_func = hash_format_check_report;\n-\t\tif (fsck_buffer(null_oid(), type, buf, size, &opts))\n+\t\tif (fsck_buffer(null_oid(the_hash_algo), type, buf, size, &opts))\n \t\t\tdie(_(\"refusing to create malformed object\"));\n \t\tfsck_finish(&opts);\n \t}\ndiff --git a/parse-options-cb.c b/parse-options-cb.c\nindex 166d35e0ebd..50c8afe4121 100644\n--- a/parse-options-cb.c\n+++ b/parse-options-cb.c\n@@ -145,7 +145,7 @@ int parse_opt_object_id(const struct option *opt, const char *arg, int unset)\n \tstruct object_id *target = opt->value;\n \n \tif (unset) {\n-\t\toidcpy(target, null_oid());\n+\t\toidcpy(target, null_oid(the_hash_algo));\n \t\treturn 0;\n \t}\n \tif (!arg)\ndiff --git a/range-diff.c b/range-diff.c\nindex 9501c358a84..8a2dcbee322 100644\n--- a/range-diff.c\n+++ b/range-diff.c\n@@ -467,7 +467,7 @@ static struct diff_filespec *get_filespec(const char *name, const char *p)\n {\n \tstruct diff_filespec *spec = alloc_filespec(name);\n \n-\tfill_filespec(spec, null_oid(), 0, 0100644);\n+\tfill_filespec(spec, null_oid(the_hash_algo), 0, 0100644);\n \tspec->data = (char *)p;\n \tspec->size = strlen(p);\n \tspec->should_munmap = 0;\ndiff --git a/read-cache.c b/read-cache.c\nindex a012cb22368..2f9e21c897d 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1735,7 +1735,7 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)\n \tend = (unsigned char *)hdr + size;\n \tstart = end - the_hash_algo->rawsz;\n \toidread(&oid, start, the_repository->hash_algo);\n-\tif (oideq(&oid, null_oid()))\n+\tif (oideq(&oid, null_oid(the_hash_algo)))\n \t\treturn 0;\n \n \tthe_hash_algo->init_fn(&c);\ndiff --git a/refs.c b/refs.c\nindex 118465271d7..215294115b4 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1377,7 +1377,7 @@ int ref_transaction_create(struct ref_transaction *transaction,\n \t\treturn 1;\n \t}\n \treturn ref_transaction_update(transaction, refname, new_oid,\n-\t\t\t\t      null_oid(), new_target, NULL, flags,\n+\t\t\t\t      null_oid(the_hash_algo), new_target, NULL, flags,\n \t\t\t\t      msg, err);\n }\n \n@@ -1396,7 +1396,7 @@ int ref_transaction_delete(struct ref_transaction *transaction,\n \tif (old_target && !(flags & REF_NO_DEREF))\n \t\tBUG(\"delete cannot operate on symrefs with deref mode\");\n \treturn ref_transaction_update(transaction, refname,\n-\t\t\t\t      null_oid(), old_oid,\n+\t\t\t\t      null_oid(the_hash_algo), old_oid,\n \t\t\t\t      NULL, old_target, flags,\n \t\t\t\t      msg, err);\n }\n@@ -2160,7 +2160,7 @@ struct ref_store *repo_get_submodule_ref_store(struct repository *repo,\n \tsubrepo = xmalloc(sizeof(*subrepo));\n \n \tif (repo_submodule_init(subrepo, repo, submodule,\n-\t\t\t\tnull_oid())) {\n+\t\t\t\tnull_oid(the_hash_algo))) {\n \t\tfree(subrepo);\n \t\tgoto done;\n \t}\n@@ -2345,14 +2345,14 @@ static int run_transaction_hook(struct ref_transaction *transaction,\n \t\tstrbuf_reset(&buf);\n \n \t\tif (!(update->flags & REF_HAVE_OLD))\n-\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid()));\n+\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid(the_hash_algo)));\n \t\telse if (update->old_target)\n \t\t\tstrbuf_addf(&buf, \"ref:%s \", update->old_target);\n \t\telse\n \t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(&update->old_oid));\n \n \t\tif (!(update->flags & REF_HAVE_NEW))\n-\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid()));\n+\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid(the_hash_algo)));\n \t\telse if (update->new_target)\n \t\t\tstrbuf_addf(&buf, \"ref:%s \", update->new_target);\n \t\telse\n@@ -2794,7 +2794,7 @@ static int migrate_one_ref(const char *refname, const char *referent UNUSED, con\n \t\tif (ret < 0)\n \t\t\tgoto done;\n \n-\t\tret = ref_transaction_update(data->transaction, refname, NULL, null_oid(),\n+\t\tret = ref_transaction_update(data->transaction, refname, NULL, null_oid(the_hash_algo),\n \t\t\t\t\t     symref_target.buf, NULL,\n \t\t\t\t\t     REF_SKIP_CREATE_REFLOG | REF_NO_DEREF, NULL, data->errbuf);\n \t\tif (ret < 0)\ndiff --git a/refs/debug.c b/refs/debug.c\nindex fbc4df08b43..7c61b775e4e 100644\n--- a/refs/debug.c\n+++ b/refs/debug.c\n@@ -217,7 +217,7 @@ static int debug_read_raw_ref(struct ref_store *ref_store, const char *refname,\n \tstruct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;\n \tint res = 0;\n \n-\toidcpy(oid, null_oid());\n+\toidcpy(oid, null_oid(ref_store->repo->hash_algo));\n \tres = drefs->refs->be->read_raw_ref(drefs->refs, refname, oid, referent,\n \t\t\t\t\t    type, failure_errno);\n \ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 6c6e67dc1c4..ba31cfdb93f 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1270,7 +1270,7 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r)\n \tref_transaction_add_update(\n \t\t\ttransaction, r->name,\n \t\t\tREF_NO_DEREF | REF_HAVE_NEW | REF_HAVE_OLD | REF_IS_PRUNING,\n-\t\t\tnull_oid(), &r->oid, NULL, NULL, NULL, NULL);\n+\t\t\tnull_oid(the_hash_algo), &r->oid, NULL, NULL, NULL, NULL);\n \tif (ref_transaction_commit(transaction, &err))\n \t\tgoto cleanup;\n \ndiff --git a/reset.c b/reset.c\nindex b22b1be792d..bb590271811 100644\n--- a/reset.c\n+++ b/reset.c\n@@ -80,7 +80,7 @@ static int update_refs(const struct reset_head_opts *opts,\n \t}\n \tif (!ret && run_hook)\n \t\trun_hooks_l(the_repository, \"post-checkout\",\n-\t\t\t    oid_to_hex(head ? head : null_oid()),\n+\t\t\t    oid_to_hex(head ? head : null_oid(the_hash_algo)),\n \t\t\t    oid_to_hex(oid), \"1\", NULL);\n \tstrbuf_release(&msg);\n \treturn ret;\ndiff --git a/sequencer.c b/sequencer.c\nindex ad0ab75c8d4..c112d2e1c43 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -265,8 +265,8 @@ static struct update_ref_record *init_update_ref_record(const char *ref)\n \n \tCALLOC_ARRAY(rec, 1);\n \n-\toidcpy(&rec->before, null_oid());\n-\toidcpy(&rec->after, null_oid());\n+\toidcpy(&rec->before, null_oid(the_hash_algo));\n+\toidcpy(&rec->after, null_oid(the_hash_algo));\n \n \t/* This may fail, but that's fine, we will keep the null OID. */\n \trefs_read_ref(get_main_ref_store(the_repository), ref, &rec->before);\n@@ -667,7 +667,7 @@ static int fast_forward_to(struct repository *r,\n \tif (!transaction ||\n \t    ref_transaction_update(transaction, \"HEAD\",\n \t\t\t\t   to, unborn && !is_rebase_i(opts) ?\n-\t\t\t\t   null_oid() : from, NULL, NULL,\n+\t\t\t\t   null_oid(the_hash_algo) : from, NULL, NULL,\n \t\t\t\t   0, sb.buf, &err) ||\n \t    ref_transaction_commit(transaction, &err)) {\n \t\tref_transaction_free(transaction);\n@@ -1301,7 +1301,7 @@ int update_head_with_reflog(const struct commit *old_head,\n \t\t\t\t\t\t  0, err);\n \tif (!transaction ||\n \t    ref_transaction_update(transaction, \"HEAD\", new_head,\n-\t\t\t\t   old_head ? &old_head->object.oid : null_oid(),\n+\t\t\t\t   old_head ? &old_head->object.oid : null_oid(the_hash_algo),\n \t\t\t\t   NULL, NULL, 0, sb.buf, err) ||\n \t    ref_transaction_commit(transaction, err)) {\n \t\tret = -1;\n@@ -4683,7 +4683,7 @@ static void create_autostash_internal(struct repository *r,\n \t\t\twrite_file(path, \"%s\", oid_to_hex(&oid));\n \t\t} else {\n \t\t\trefs_update_ref(get_main_ref_store(r), \"\", refname,\n-\t\t\t\t\t&oid, null_oid(), 0, UPDATE_REFS_DIE_ON_ERR);\n+\t\t\t\t\t&oid, null_oid(the_hash_algo), 0, UPDATE_REFS_DIE_ON_ERR);\n \t\t}\n \n \t\tprintf(_(\"Created autostash: %s\\n\"), buf.buf);\ndiff --git a/submodule-config.c b/submodule-config.c\nindex a25059ed7f8..d82b404b73e 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -831,7 +831,7 @@ static int gitmodules_cb(const char *var, const char *value,\n \n \tparameter.cache = repo->submodule_cache;\n \tparameter.treeish_name = NULL;\n-\tparameter.gitmodules_oid = null_oid();\n+\tparameter.gitmodules_oid = null_oid(the_hash_algo);\n \tparameter.overwrite = 1;\n \n \treturn parse_config(var, value, ctx, &parameter);\ndiff --git a/submodule.c b/submodule.c\nindex 0530e8cf24e..0821507ecaa 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -124,7 +124,7 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)\n \tif (is_gitmodules_unmerged(the_repository->index))\n \t\tdie(_(\"Cannot change unmerged .gitmodules, resolve merge conflicts first\"));\n \n-\tsubmodule = submodule_from_path(the_repository, null_oid(), oldpath);\n+\tsubmodule = submodule_from_path(the_repository, null_oid(the_hash_algo), oldpath);\n \tif (!submodule || !submodule->name) {\n \t\twarning(_(\"Could not find section in .gitmodules where path=%s\"), oldpath);\n \t\treturn -1;\n@@ -153,7 +153,7 @@ int remove_path_from_gitmodules(const char *path)\n \tif (is_gitmodules_unmerged(the_repository->index))\n \t\tdie(_(\"Cannot change unmerged .gitmodules, resolve merge conflicts first\"));\n \n-\tsubmodule = submodule_from_path(the_repository, null_oid(), path);\n+\tsubmodule = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \tif (!submodule || !submodule->name) {\n \t\twarning(_(\"Could not find section in .gitmodules where path=%s\"), path);\n \t\treturn -1;\n@@ -204,7 +204,7 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,\n \t\t\t\t\t     const char *path)\n {\n \tconst struct submodule *submodule = submodule_from_path(the_repository,\n-\t\t\t\t\t\t\t\tnull_oid(),\n+\t\t\t\t\t\t\t\tnull_oid(the_hash_algo),\n \t\t\t\t\t\t\t\tpath);\n \tif (submodule) {\n \t\tconst char *ignore;\n@@ -312,7 +312,7 @@ int is_tree_submodule_active(struct repository *repo,\n \n int is_submodule_active(struct repository *repo, const char *path)\n {\n-\treturn is_tree_submodule_active(repo, null_oid(), path);\n+\treturn is_tree_submodule_active(repo, null_oid(the_hash_algo), path);\n }\n \n int is_submodule_populated_gently(const char *path, int *return_error_code)\n@@ -778,7 +778,7 @@ const struct submodule *submodule_from_ce(const struct cache_entry *ce)\n \tif (!should_update_submodules())\n \t\treturn NULL;\n \n-\treturn submodule_from_path(the_repository, null_oid(), ce->name);\n+\treturn submodule_from_path(the_repository, null_oid(the_hash_algo), ce->name);\n }\n \n \n@@ -1062,7 +1062,7 @@ static int submodule_needs_pushing(struct repository *r,\n \t\t\t\t   const char *path,\n \t\t\t\t   struct oid_array *commits)\n {\n-\tif (!submodule_has_commits(r, path, null_oid(), commits))\n+\tif (!submodule_has_commits(r, path, null_oid(the_hash_algo), commits))\n \t\t/*\n \t\t * NOTE: We do consider it safe to return \"no\" here. The\n \t\t * correct answer would be \"We do not know\" instead of\n@@ -1126,7 +1126,7 @@ int find_unpushed_submodules(struct repository *r,\n \t\tconst struct submodule *submodule;\n \t\tconst char *path = NULL;\n \n-\t\tsubmodule = submodule_from_name(r, null_oid(), name->string);\n+\t\tsubmodule = submodule_from_name(r, null_oid(the_hash_algo), name->string);\n \t\tif (submodule)\n \t\t\tpath = submodule->path;\n \t\telse\n@@ -1351,7 +1351,7 @@ static void calculate_changed_submodule_paths(struct repository *r,\n \t\tconst struct submodule *submodule;\n \t\tconst char *path = NULL;\n \n-\t\tsubmodule = submodule_from_name(r, null_oid(), name->string);\n+\t\tsubmodule = submodule_from_name(r, null_oid(the_hash_algo), name->string);\n \t\tif (submodule)\n \t\t\tpath = submodule->path;\n \t\telse\n@@ -1360,7 +1360,7 @@ static void calculate_changed_submodule_paths(struct repository *r,\n \t\tif (!path)\n \t\t\tcontinue;\n \n-\t\tif (submodule_has_commits(r, path, null_oid(), &cs_data->new_commits)) {\n+\t\tif (submodule_has_commits(r, path, null_oid(the_hash_algo), &cs_data->new_commits)) {\n \t\t\tchanged_submodule_data_clear(cs_data);\n \t\t\t*name->string = '\\0';\n \t\t}\n@@ -1602,7 +1602,7 @@ get_fetch_task_from_index(struct submodule_parallel_fetch *spf,\n \t\tif (!S_ISGITLINK(ce->ce_mode))\n \t\t\tcontinue;\n \n-\t\ttask = fetch_task_create(spf, ce->name, null_oid());\n+\t\ttask = fetch_task_create(spf, ce->name, null_oid(the_hash_algo));\n \t\tif (!task)\n \t\t\tcontinue;\n \n@@ -2166,7 +2166,7 @@ int submodule_move_head(const char *path, const char *super_prefix,\n \tif (old_head && !is_submodule_populated_gently(path, error_code_ptr))\n \t\treturn 0;\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tBUG(\"could not get submodule information for '%s'\", path);\n@@ -2376,7 +2376,7 @@ static void relocate_single_git_dir_into_superproject(const char *path,\n \n \treal_old_git_dir = real_pathdup(old_git_dir, 1);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \tif (!sub)\n \t\tdie(_(\"could not lookup name for submodule '%s'\"), path);\n \n@@ -2462,7 +2462,7 @@ void absorb_git_dir_into_superproject(const char *path,\n \t\t* superproject did not rewrite the git file links yet,\n \t\t* fix it now.\n \t\t*/\n-\t\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\t\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \t\tif (!sub)\n \t\t\tdie(_(\"could not lookup name for submodule '%s'\"), path);\n \t\tsubmodule_name_to_gitdir(&sub_gitdir, the_repository, sub->name);\n@@ -2594,7 +2594,7 @@ int submodule_to_gitdir(struct repository *repo,\n \t\tstrbuf_addstr(buf, git_dir);\n \t}\n \tif (!is_git_directory(buf->buf)) {\n-\t\tsub = submodule_from_path(repo, null_oid(), submodule);\n+\t\tsub = submodule_from_path(repo, null_oid(the_hash_algo), submodule);\n \t\tif (!sub) {\n \t\t\tret = -1;\n \t\t\tgoto cleanup;\ndiff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c\nindex e00fce592b1..2ff67c067ac 100644\n--- a/t/helper/test-ref-store.c\n+++ b/t/helper/test-ref-store.c\n@@ -179,7 +179,7 @@ static int cmd_for_each_ref__exclude(struct ref_store *refs, const char **argv)\n \n static int cmd_resolve_ref(struct ref_store *refs, const char **argv)\n {\n-\tstruct object_id oid = *null_oid();\n+\tstruct object_id oid = *null_oid(the_hash_algo);\n \tconst char *refname = notnull(*argv++, \"refname\");\n \tint resolve_flags = arg_flags(*argv++, \"resolve-flags\", empty_flags);\n \tint flags;\ndiff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c\nindex 6dce9571531..2710341cd5d 100644\n--- a/t/helper/test-submodule-nested-repo-config.c\n+++ b/t/helper/test-submodule-nested-repo-config.c\n@@ -21,7 +21,7 @@ int cmd__submodule_nested_repo_config(int argc, const char **argv)\n \n \tsetup_git_directory();\n \n-\tif (repo_submodule_init(&subrepo, the_repository, argv[1], null_oid())) {\n+\tif (repo_submodule_init(&subrepo, the_repository, argv[1], null_oid(the_hash_algo))) {\n \t\tdie_usage(argv, \"Submodule not found.\");\n \t}\n \ndiff --git a/tree-diff.c b/tree-diff.c\nindex 60c558c2b56..e00fc2f450d 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -181,7 +181,7 @@ static void emit_path(struct combine_diff_path ***tail,\n \n \t\tstrbuf_add(base, path, pathlen);\n \t\tp = combine_diff_path_new(base->buf, base->len, mode,\n-\t\t\t\t\t  oid ? oid : null_oid(),\n+\t\t\t\t\t  oid ? oid : null_oid(the_hash_algo),\n \t\t\t\t\t  nparent);\n \t\tstrbuf_setlen(base, old_baselen);\n \n@@ -206,7 +206,7 @@ static void emit_path(struct combine_diff_path ***tail,\n \t\t\t\tmode_i = tp[i].entry.mode;\n \t\t\t}\n \t\t\telse {\n-\t\t\t\toid_i = null_oid();\n+\t\t\t\toid_i = null_oid(the_hash_algo);\n \t\t\t\tmode_i = 0;\n \t\t\t}\n \ndiff --git a/upload-pack.c b/upload-pack.c\nindex 7412d3c6ce8..0fa8fbdd6de 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -1446,7 +1446,7 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,\n \t\tfor_each_namespaced_ref_1(send_ref, &data);\n \t\tif (!data.sent_capabilities) {\n \t\t\tconst char *refname = \"capabilities^{}\";\n-\t\t\twrite_v0_ref(&data, refname, refname, null_oid());\n+\t\t\twrite_v0_ref(&data, refname, refname, null_oid(the_hash_algo));\n \t\t}\n \t\t/*\n \t\t * fflush stdout before calling advertise_shallow_grafts because send_ref\ndiff --git a/wt-status.c b/wt-status.c\nindex 1da5732f57b..454601afa15 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1824,10 +1824,10 @@ void wt_status_get_state(struct repository *r,\n \tif (!sequencer_get_last_command(r, &action)) {\n \t\tif (action == REPLAY_PICK && !state->cherry_pick_in_progress) {\n \t\t\tstate->cherry_pick_in_progress = 1;\n-\t\t\toidcpy(&state->cherry_pick_head_oid, null_oid());\n+\t\t\toidcpy(&state->cherry_pick_head_oid, null_oid(the_hash_algo));\n \t\t} else if (action == REPLAY_REVERT && !state->revert_in_progress) {\n \t\t\tstate->revert_in_progress = 1;\n-\t\t\toidcpy(&state->revert_head_oid, null_oid());\n+\t\t\toidcpy(&state->revert_head_oid, null_oid(the_hash_algo));\n \t\t}\n \t}\n \tif (get_detached_from)\ndiff --git a/xdiff-interface.c b/xdiff-interface.c\nindex 3bd61f26e90..77712811ff1 100644\n--- a/xdiff-interface.c\n+++ b/xdiff-interface.c\n@@ -181,7 +181,7 @@ void read_mmblob(mmfile_t *ptr, const struct object_id *oid)\n \tunsigned long size;\n \tenum object_type type;\n \n-\tif (oideq(oid, null_oid())) {\n+\tif (oideq(oid, null_oid(the_hash_algo))) {\n \t\tptr->ptr = xstrdup(\"\");\n \t\tptr->size = 0;\n \t\treturn;\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513782","messageId":"xmqqbjucg4tu.fsf@gitster.g","threadId":"63046","inReplyTo":"Z8q3nzhl3DHETZgf@pks.im","subject":"Re: [PATCH v2 12/12] hash: stop depending on `the_repository` in `null_oid()`","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-03-07T16:53:33Z","receivedAt":"2025-03-07T16:53:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> So in theory, I don't really think there is anything that keeps us from\n> mixing object formats, and I even think that this is a necessary feature\n> to have once people start to migrate their repositories to SHA256. There\n> are people out there who use submodules, and it may not be feasible for\n> them to wait until all of their submodules have been converted to SHA256\n> to migrate their own repositories.\n> ...\n> Anyway, that was a bit of a tangent to your initial question: which hash\n> should we be passing in the first place? As it turns out, we should be\n> passing the superproject's null OID indeed. The object ID we pass to\n> `repo_submodule_init()` does not describe any object in the submodule\n> itself, but rather indicates which tree-ish the submodule information\n> should be parsed from in the superproject. As such, it refers to an\n> object in the superproject itself and should thus use its object hash.\n\nGood reasoning.\n\nSo the null-object suitable for the superproject is what we want\nthere after all.  We've been using the_hash_algo, which is the\nalgorithm used in the_repository, which in turn *IS* the\nsuperproject in this code path, so we have been correct all the time\n;-)\n\n"},{"id":"513831","messageId":"CABPp-BG0AtKdUH2g8+_f0J0ViWs5xZKM9kCcbWYZ=uEu6bswdQ@mail.gmail.com","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-12-7bccf408731e@pks.im","subject":"Re: [PATCH v3 12/12] hash: stop depending on `the_repository` in `null_oid()`","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2025-03-08T16:05:09Z","receivedAt":"2025-03-08T16:05:21Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Mar 7, 2025 at 6:20 AM Patrick Steinhardt <ps@pks.im> wrote:\n>\n> The `null_oid()` function returns the object ID that only consists of\n> zeroes. Naturally, this ID also depends on the hash algorithm used, as\n> the number of zeroes is different between SHA1 and SHA256. Consequently,\n> the function returns the hash-algorithm-specific null object ID.\n>\n> This is currently done by depending on `the_hash_algo`, which implicitly\n> makes us depend on `the_repository`. Refactor the function to instead\n> pass in the hash algorithm for which we want to retrieve the null object\n> ID. Adapt callsites accordingly by passing in `the_repository`, thus\n> bubbling up the dependency on that global variable by one layer.\n>\n> There are a couple of trivial exceptions for subsystems that already got\n> rid of `the_repository`. These subsystems instead use the repository\n> that is available via the calling context:\n>\n>   - \"builtin/grep.c\"\n>   - \"grep.c\"\n>   - \"refs/debug.c\"\n>\n> There are also two non-trivial exceptions:\n>\n>   - \"diff-no-index.c\": Here we know that we may not have a repository\n>     initialized at all, so we cannot rely on `the_repository`. Instead,\n>     we adapt `diff_no_index()` to get a `struct git_hash_algo` as\n>     parameter. The only caller is located in \"builtin/diff.c\", where we\n>     know to call `repo_set_hash_algo()` in case we're running outside of\n>     a Git repository. Consequently, it is fine to continue passing\n>     `the_repository->hash_algo` even in this case.\n>\n>   - \"builtin/ls-files.c\": There is an in-flight patch series that drops\n>     `USE_THE_REPOSITORY_VARIABLE` in this file, which causes a semantic\n>     conflict because we use `null_oid()` in `show_submodule()`. The\n>     value is passed to `repo_submodule_init()`, which may use the object\n>     ID to resolve a tree-ish in the superproject from which we want to\n>     read the submodule config. As such, the object ID should refer to an\n>     object in the superproject, and consequently we need to use its hash\n>     algorithm.\n>\n> This means that we could in theory just not bother about this edge case\n> at all and just use `the_repository` in \"diff-no-index.c\". But doing so\n> would feel misdesigned.\n\nVery minor, but this was a bit jarring to me -- shouldn't this\nparagraph be indented over since it is a continuation of the second\nbullet above?\n\n> Remove the `USE_THE_REPOSITORY_VARIABLE` preprocessor define in\n> \"hash.c\".\n>\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n[...]\n> diff --git a/merge-ort.c b/merge-ort.c\n> index 46e78c3ffa6..eb3a834652a 100644\n> --- a/merge-ort.c\n> +++ b/merge-ort.c\n> @@ -1817,7 +1817,7 @@ static int merge_submodule(struct merge_options *opt,\n>                 BUG(\"submodule deleted on one side; this should be handled outside of merge_submodule()\");\n>\n>         if ((sub_not_initialized = repo_submodule_init(&subrepo,\n> -               opt->repo, path, null_oid()))) {\n> +               opt->repo, path, null_oid(the_hash_algo)))) {\n>                 path_msg(opt, CONFLICT_SUBMODULE_NOT_INITIALIZED, 0,\n>                          path, NULL, NULL, NULL,\n>                          _(\"Failed to merge submodule %s (not checked out)\"),\n> @@ -2199,7 +2199,7 @@ static int handle_content_merge(struct merge_options *opt,\n>                 two_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));\n>\n>                 merge_status = merge_3way(opt, path,\n> -                                         two_way ? null_oid() : &o->oid,\n> +                                         two_way ? null_oid(the_hash_algo) : &o->oid,\n>                                           &a->oid, &b->oid,\n>                                           pathnames, extra_marker_size,\n>                                           &result_buf);\n> @@ -2231,7 +2231,7 @@ static int handle_content_merge(struct merge_options *opt,\n>         } else if (S_ISGITLINK(a->mode)) {\n>                 int two_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));\n>                 clean = merge_submodule(opt, pathnames[0],\n> -                                       two_way ? null_oid() : &o->oid,\n> +                                       two_way ? null_oid(the_hash_algo) : &o->oid,\n>                                         &a->oid, &b->oid, &result->oid);\n>                 if (clean < 0)\n>                         return -1;\n> @@ -2739,7 +2739,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt,\n>                 assert(!new_ci->match_mask);\n>                 new_ci->dirmask = 0;\n>                 new_ci->stages[1].mode = 0;\n> -               oidcpy(&new_ci->stages[1].oid, null_oid());\n> +               oidcpy(&new_ci->stages[1].oid, null_oid(the_hash_algo));\n>\n>                 /*\n>                  * Now that we have the file information in new_ci, make sure\n> @@ -2752,7 +2752,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt,\n>                                 continue;\n>                         /* zero out any entries related to files */\n>                         ci->stages[i].mode = 0;\n> -                       oidcpy(&ci->stages[i].oid, null_oid());\n> +                       oidcpy(&ci->stages[i].oid, null_oid(the_hash_algo));\n>                 }\n>\n>                 /* Now we want to focus on new_ci, so reassign ci to it. */\n> @@ -3122,7 +3122,7 @@ static int process_renames(struct merge_options *opt,\n>                         if (type_changed) {\n>                                 /* rename vs. typechange */\n>                                 /* Mark the original as resolved by removal */\n> -                               memcpy(&oldinfo->stages[0].oid, null_oid(),\n> +                               memcpy(&oldinfo->stages[0].oid, null_oid(the_hash_algo),\n>                                        sizeof(oldinfo->stages[0].oid));\n>                                 oldinfo->stages[0].mode = 0;\n>                                 oldinfo->filemask &= 0x06;\n> @@ -3994,7 +3994,7 @@ static int process_entry(struct merge_options *opt,\n>                         if (ci->filemask & (1 << i))\n>                                 continue;\n>                         ci->stages[i].mode = 0;\n> -                       oidcpy(&ci->stages[i].oid, null_oid());\n> +                       oidcpy(&ci->stages[i].oid, null_oid(the_hash_algo));\n>                 }\n>         } else if (ci->df_conflict && ci->merged.result.mode != 0) {\n>                 /*\n> @@ -4041,7 +4041,7 @@ static int process_entry(struct merge_options *opt,\n>                                 continue;\n>                         /* zero out any entries related to directories */\n>                         new_ci->stages[i].mode = 0;\n> -                       oidcpy(&new_ci->stages[i].oid, null_oid());\n> +                       oidcpy(&new_ci->stages[i].oid, null_oid(the_hash_algo));\n>                 }\n>\n>                 /*\n> @@ -4163,11 +4163,11 @@ static int process_entry(struct merge_options *opt,\n>                         new_ci->merged.result.mode = ci->stages[2].mode;\n>                         oidcpy(&new_ci->merged.result.oid, &ci->stages[2].oid);\n>                         new_ci->stages[1].mode = 0;\n> -                       oidcpy(&new_ci->stages[1].oid, null_oid());\n> +                       oidcpy(&new_ci->stages[1].oid, null_oid(the_hash_algo));\n>                         new_ci->filemask = 5;\n>                         if ((S_IFMT & b_mode) != (S_IFMT & o_mode)) {\n>                                 new_ci->stages[0].mode = 0;\n> -                               oidcpy(&new_ci->stages[0].oid, null_oid());\n> +                               oidcpy(&new_ci->stages[0].oid, null_oid(the_hash_algo));\n>                                 new_ci->filemask = 4;\n>                         }\n>\n> @@ -4175,11 +4175,11 @@ static int process_entry(struct merge_options *opt,\n>                         ci->merged.result.mode = ci->stages[1].mode;\n>                         oidcpy(&ci->merged.result.oid, &ci->stages[1].oid);\n>                         ci->stages[2].mode = 0;\n> -                       oidcpy(&ci->stages[2].oid, null_oid());\n> +                       oidcpy(&ci->stages[2].oid, null_oid(the_hash_algo));\n>                         ci->filemask = 3;\n>                         if ((S_IFMT & a_mode) != (S_IFMT & o_mode)) {\n>                                 ci->stages[0].mode = 0;\n> -                               oidcpy(&ci->stages[0].oid, null_oid());\n> +                               oidcpy(&ci->stages[0].oid, null_oid(the_hash_algo));\n>                                 ci->filemask = 2;\n>                         }\n>\n> @@ -4304,7 +4304,7 @@ static int process_entry(struct merge_options *opt,\n>                 /* Deleted on both sides */\n>                 ci->merged.is_null = 1;\n>                 ci->merged.result.mode = 0;\n> -               oidcpy(&ci->merged.result.oid, null_oid());\n> +               oidcpy(&ci->merged.result.oid, null_oid(the_hash_algo));\n>                 assert(!ci->df_conflict);\n>                 ci->merged.clean = !ci->path_conflict;\n>         }\n\nWhat you have is an improvement since it's at least making things\nexplicit, but these should really be opt->repo->hash_algo.\n\n> diff --git a/merge-recursive.c b/merge-recursive.c\n> index 5dfaf32b2c1..d88e61b07a9 100644\n> --- a/merge-recursive.c\n> +++ b/merge-recursive.c\n> @@ -502,7 +502,7 @@ static int get_tree_entry_if_blob(struct repository *r,\n>\n>         ret = get_tree_entry(r, tree, path, &dfs->oid, &dfs->mode);\n>         if (S_ISDIR(dfs->mode)) {\n> -               oidcpy(&dfs->oid, null_oid());\n> +               oidcpy(&dfs->oid, null_oid(the_hash_algo));\n>                 dfs->mode = 0;\n>         }\n>         return ret;\n> @@ -1238,7 +1238,7 @@ static int merge_submodule(struct merge_options *opt,\n>         if (is_null_oid(b))\n>                 return 0;\n>\n> -       if (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) {\n> +       if (repo_submodule_init(&subrepo, opt->repo, path, null_oid(the_hash_algo))) {\n>                 output(opt, 1, _(\"Failed to merge submodule %s (not checked out)\"), path);\n>                 return 0;\n>         }\n> @@ -1698,7 +1698,7 @@ static int handle_file_collision(struct merge_options *opt,\n>\n>         /* Store things in diff_filespecs for functions that need it */\n>         null.path = (char *)collide_path;\n> -       oidcpy(&null.oid, null_oid());\n> +       oidcpy(&null.oid, null_oid(the_hash_algo));\n>         null.mode = 0;\n>\n>         if (merge_mode_and_contents(opt, &null, a, b, collide_path,\n> @@ -2898,14 +2898,14 @@ static int process_renames(struct merge_options *opt,\n>                         dst_other.mode = ren1->dst_entry->stages[other_stage].mode;\n>                         try_merge = 0;\n>\n> -                       if (oideq(&src_other.oid, null_oid()) &&\n> +                       if (oideq(&src_other.oid, null_oid(the_hash_algo)) &&\n>                             ren1->dir_rename_original_type == 'A') {\n>                                 setup_rename_conflict_info(RENAME_VIA_DIR,\n>                                                            opt, ren1, NULL);\n>                         } else if (renamed_to_self) {\n>                                 setup_rename_conflict_info(RENAME_NORMAL,\n>                                                            opt, ren1, NULL);\n> -                       } else if (oideq(&src_other.oid, null_oid())) {\n> +                       } else if (oideq(&src_other.oid, null_oid(the_hash_algo))) {\n>                                 setup_rename_conflict_info(RENAME_DELETE,\n>                                                            opt, ren1, NULL);\n>                         } else if ((dst_other.mode == ren1->pair->two->mode) &&\n> @@ -2924,7 +2924,7 @@ static int process_renames(struct merge_options *opt,\n>                                                       1, /* update_cache */\n>                                                       0  /* update_wd    */))\n>                                         clean_merge = -1;\n> -                       } else if (!oideq(&dst_other.oid, null_oid())) {\n> +                       } else if (!oideq(&dst_other.oid, null_oid(the_hash_algo))) {\n>                                 /*\n>                                  * Probably not a clean merge, but it's\n>                                  * premature to set clean_merge to 0 here,\n\nThis will textually conflict with my upcoming series to delete\nmerge-recursive.[ch].  Luckily, it'll be easy to resolve, since the\nchanges will just be irrelevant...  :-)\n\n[...]\n\nThe rest of the changes looked good to me.\n"},{"id":"513832","messageId":"CABPp-BEMy2w5O=azrvjXEcBb15uRXcTrFNPyy5hTVHgs_p4AKQ@mail.gmail.com","threadId":"63046","inReplyTo":"20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im","subject":"Re: [PATCH v3 00/12] Stop depending on `the_repository` in object-related subsystems","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2025-03-08T16:11:15Z","receivedAt":"2025-03-08T16:11:27Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Mar 7, 2025 at 6:19 AM Patrick Steinhardt <ps@pks.im> wrote:\n>\n> Hi,\n>\n> this patch series is another step to remove our dependency on the global\n> `the_repository` variable. The series focusses on subsystems related to\n> objects.\n>\n> The intent here is to work towards libification of the whole subsystem\n> so that we can start splitting out something like an object \"backend\".\n> It is thus part of a set of refactorings aimed at allowing pluggable\n> object databases eventually. I'm not discussing that bigger effort yet,\n> mostly because it's still taking shape. So these patch series contains\n> things that make sense standalone, even if pluggable ODBs never get to\n> be a thing.\n\nSounds like a good goal; and the series is helpful regardless of\nwhether we get there.\n\n> Note that this patch series stop short of dropping `the_repository` in\n> \"object-file.c\". This is a bigger undertaking, so I'm pushing that into\n> the next patch series.\n>\n> The series is built on top of cb0ae672aea (A bit more post -rc0,\n> 2025-02-27) with ps/path-sans-the-repository at 028f618658e (path:\n> adjust last remaining users of `the_repository`, 2025-02-07) merged into\n> it.\n>\n> Changes in v2:\n>   - Point out why t1050 had to be adapted.\n>   - Drop the rename of `get_max_object_index()` and\n>     `get_indexed_object()`.\n>   - Fix a couple of commit message typos.\n>   - Link to v1: https://lore.kernel.org/r/20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im\n>\n> Changes in v3:\n>   - Fix a semantic conflict with an in-flight patch series.\n>   - Link to v2: https://lore.kernel.org/r/20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im\n>\n> Thanks!\n>\n> Patrick\n>\n> ---\n> Patrick Steinhardt (12):\n>       csum-file: stop depending on `the_repository`\n>       object: stop depending on `the_repository`\n>       pack-write: stop depending on `the_repository` and `the_hash_algo`\n>       environment: move access to \"core.bigFileThreshold\" into repo settings\n>       pack-check: stop depending on `the_repository`\n>       pack-revindex: stop depending on `the_repository`\n>       pack-bitmap-write: stop depending on `the_repository`\n>       object-file-convert: stop depending on `the_repository`\n>       delta-islands: stop depending on `the_repository`\n>       object-file: split out logic regarding hash algorithms\n>       hash: fix \"-Wsign-compare\" warnings\n>       hash: stop depending on `the_repository` in `null_oid()`\n\nI read through the series.  I had a couple small comments on patch 12.\nOverall, I really like how you've divided things up; it makes it easy\nfor review, especially combined with --color-diff.\n"},{"id":"513871","messageId":"Z86Qh1yLUC7aIaG9@pks.im","threadId":"63046","inReplyTo":"CABPp-BG0AtKdUH2g8+_f0J0ViWs5xZKM9kCcbWYZ=uEu6bswdQ@mail.gmail.com","subject":"Re: [PATCH v3 12/12] hash: stop depending on `the_repository` in `null_oid()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:11:03Z","receivedAt":"2025-03-10T07:11:09Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Sat, Mar 08, 2025 at 08:05:09AM -0800, Elijah Newren wrote:\n> On Fri, Mar 7, 2025 at 6:20 AM Patrick Steinhardt <ps@pks.im> wrote:\n> >\n> > The `null_oid()` function returns the object ID that only consists of\n> > zeroes. Naturally, this ID also depends on the hash algorithm used, as\n> > the number of zeroes is different between SHA1 and SHA256. Consequently,\n> > the function returns the hash-algorithm-specific null object ID.\n> >\n> > This is currently done by depending on `the_hash_algo`, which implicitly\n> > makes us depend on `the_repository`. Refactor the function to instead\n> > pass in the hash algorithm for which we want to retrieve the null object\n> > ID. Adapt callsites accordingly by passing in `the_repository`, thus\n> > bubbling up the dependency on that global variable by one layer.\n> >\n> > There are a couple of trivial exceptions for subsystems that already got\n> > rid of `the_repository`. These subsystems instead use the repository\n> > that is available via the calling context:\n> >\n> >   - \"builtin/grep.c\"\n> >   - \"grep.c\"\n> >   - \"refs/debug.c\"\n> >\n> > There are also two non-trivial exceptions:\n> >\n> >   - \"diff-no-index.c\": Here we know that we may not have a repository\n> >     initialized at all, so we cannot rely on `the_repository`. Instead,\n> >     we adapt `diff_no_index()` to get a `struct git_hash_algo` as\n> >     parameter. The only caller is located in \"builtin/diff.c\", where we\n> >     know to call `repo_set_hash_algo()` in case we're running outside of\n> >     a Git repository. Consequently, it is fine to continue passing\n> >     `the_repository->hash_algo` even in this case.\n> >\n> >   - \"builtin/ls-files.c\": There is an in-flight patch series that drops\n> >     `USE_THE_REPOSITORY_VARIABLE` in this file, which causes a semantic\n> >     conflict because we use `null_oid()` in `show_submodule()`. The\n> >     value is passed to `repo_submodule_init()`, which may use the object\n> >     ID to resolve a tree-ish in the superproject from which we want to\n> >     read the submodule config. As such, the object ID should refer to an\n> >     object in the superproject, and consequently we need to use its hash\n> >     algorithm.\n> >\n> > This means that we could in theory just not bother about this edge case\n> > at all and just use `the_repository` in \"diff-no-index.c\". But doing so\n> > would feel misdesigned.\n> \n> Very minor, but this was a bit jarring to me -- shouldn't this\n> paragraph be indented over since it is a continuation of the second\n> bullet above?\n\nYes, you're right!\n\n> > @@ -4304,7 +4304,7 @@ static int process_entry(struct merge_options *opt,\n> >                 /* Deleted on both sides */\n> >                 ci->merged.is_null = 1;\n> >                 ci->merged.result.mode = 0;\n> > -               oidcpy(&ci->merged.result.oid, null_oid());\n> > +               oidcpy(&ci->merged.result.oid, null_oid(the_hash_algo));\n> >                 assert(!ci->df_conflict);\n> >                 ci->merged.clean = !ci->path_conflict;\n> >         }\n> \n> What you have is an improvement since it's at least making things\n> explicit, but these should really be opt->repo->hash_algo.\n\nOh, yeah, I suspect that we'll have a bunch of places where we can\nalready plug in a repository as available via the context. I typically\nrefrain from doing though unless really necessary (e.g. when the file at\nhand doesn't declare `USE_THE_REPOSITORY_VARIABLE` anymore). This is so\nthat neither I nor reviewers have to carefully vet every callsite, but\nto make this a mechanical change that is obviously correct because it is\nidentical to the old state. So I'm basically leaving it to the next\npatch series that gets rid of `USE_THE_REPOSITORY_VARIABLE` to think\nmore carefully about those callsites.\n\nThanks!\n\nPatrick\n"},{"id":"513872","messageId":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","threadId":"63046","inReplyTo":"20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im","subject":"[PATCH v4 00/12] Stop depending on `the_repository` in object-related subsystems","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:13:19Z","receivedAt":"2025-03-10T07:13:27Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis patch series is another step to remove our dependency on the global\n`the_repository` variable. The series focusses on subsystems related to\nobjects.\n\nThe intent here is to work towards libification of the whole subsystem\nso that we can start splitting out something like an object \"backend\".\nIt is thus part of a set of refactorings aimed at allowing pluggable\nobject databases eventually. I'm not discussing that bigger effort yet,\nmostly because it's still taking shape. So these patch series contains\nthings that make sense standalone, even if pluggable ODBs never get to\nbe a thing.\n\nNote that this patch series stop short of dropping `the_repository` in\n\"object-file.c\". This is a bigger undertaking, so I'm pushing that into\nthe next patch series.\n\nThe series is built on top of cb0ae672aea (A bit more post -rc0,\n2025-02-27) with ps/path-sans-the-repository at 028f618658e (path:\nadjust last remaining users of `the_repository`, 2025-02-07) merged into\nit.\n\nChanges in v2:\n  - Point out why t1050 had to be adapted.\n  - Drop the rename of `get_max_object_index()` and\n    `get_indexed_object()`.\n  - Fix a couple of commit message typos.\n  - Link to v1: https://lore.kernel.org/r/20250303-b4-pks-objects-without-the-repository-v1-0-c5dd43f2476e@pks.im\n\nChanges in v3:\n  - Fix a semantic conflict with an in-flight patch series.\n  - Link to v2: https://lore.kernel.org/r/20250306-b4-pks-objects-without-the-repository-v2-0-f3465327be69@pks.im\n\nChanges in v4:\n  - Fix indentation in one of the commit messages.\n  - Link to v3: https://lore.kernel.org/r/20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (12):\n      csum-file: stop depending on `the_repository`\n      object: stop depending on `the_repository`\n      pack-write: stop depending on `the_repository` and `the_hash_algo`\n      environment: move access to \"core.bigFileThreshold\" into repo settings\n      pack-check: stop depending on `the_repository`\n      pack-revindex: stop depending on `the_repository`\n      pack-bitmap-write: stop depending on `the_repository`\n      object-file-convert: stop depending on `the_repository`\n      delta-islands: stop depending on `the_repository`\n      object-file: split out logic regarding hash algorithms\n      hash: fix \"-Wsign-compare\" warnings\n      hash: stop depending on `the_repository` in `null_oid()`\n\n Makefile                                     |   1 +\n archive.c                                    |   4 +-\n blame.c                                      |   2 +-\n branch.c                                     |   2 +-\n builtin/checkout.c                           |   6 +-\n builtin/clone.c                              |   2 +-\n builtin/describe.c                           |   2 +-\n builtin/diff.c                               |   5 +-\n builtin/fast-export.c                        |  10 +-\n builtin/fast-import.c                        |   8 +-\n builtin/fsck.c                               |   6 +-\n builtin/grep.c                               |   4 +-\n builtin/index-pack.c                         |  16 +-\n builtin/log.c                                |   2 +-\n builtin/ls-files.c                           |   3 +-\n builtin/name-rev.c                           |   4 +-\n builtin/pack-objects.c                       |  17 +-\n builtin/prune.c                              |   2 +-\n builtin/rebase.c                             |   2 +-\n builtin/receive-pack.c                       |   2 +-\n builtin/submodule--helper.c                  |  36 ++--\n builtin/tag.c                                |   2 +-\n builtin/unpack-objects.c                     |   5 +-\n builtin/update-ref.c                         |   2 +-\n builtin/worktree.c                           |   2 +-\n bulk-checkin.c                               |   4 +-\n combine-diff.c                               |   2 +-\n commit-graph.c                               |   9 +-\n commit.c                                     |   2 +-\n config.c                                     |   5 -\n csum-file.c                                  |  28 +--\n csum-file.h                                  |  12 +-\n delta-islands.c                              |  14 +-\n delta-islands.h                              |   2 +-\n diff-lib.c                                   |  10 +-\n diff-no-index.c                              |  28 +--\n diff.c                                       |  14 +-\n diff.h                                       |   2 +-\n dir.c                                        |   2 +-\n environment.c                                |   1 -\n environment.h                                |   1 -\n grep.c                                       |   2 +-\n hash.c                                       | 277 +++++++++++++++++++++++++\n hash.h                                       |   4 +-\n log-tree.c                                   |   2 +-\n merge-ort.c                                  |  26 +--\n merge-recursive.c                            |  12 +-\n meson.build                                  |   1 +\n midx-write.c                                 |  12 +-\n midx.c                                       |   3 +-\n notes-merge.c                                |   2 +-\n notes.c                                      |   2 +-\n object-file-convert.c                        |  29 +--\n object-file-convert.h                        |   3 +-\n object-file.c                                | 292 +--------------------------\n object.c                                     |  21 +-\n object.h                                     |  10 +-\n pack-bitmap-write.c                          |  36 ++--\n pack-bitmap.c                                |  15 +-\n pack-bitmap.h                                |   1 +\n pack-check.c                                 |  12 +-\n pack-revindex.c                              |  35 ++--\n pack-write.c                                 |  55 +++--\n pack.h                                       |  11 +-\n parse-options-cb.c                           |   2 +-\n range-diff.c                                 |   2 +-\n reachable.c                                  |   6 +-\n read-cache.c                                 |   4 +-\n refs.c                                       |  12 +-\n refs/debug.c                                 |   2 +-\n refs/files-backend.c                         |   2 +-\n repo-settings.c                              |  20 ++\n repo-settings.h                              |   5 +\n reset.c                                      |   2 +-\n revision.c                                   |   3 +-\n sequencer.c                                  |  10 +-\n shallow.c                                    |  10 +-\n streaming.c                                  |   3 +-\n submodule-config.c                           |   2 +-\n submodule.c                                  |  28 +--\n t/helper/test-ref-store.c                    |   2 +-\n t/helper/test-submodule-nested-repo-config.c |   2 +-\n t/t1050-large.sh                             |   3 +-\n tree-diff.c                                  |   4 +-\n upload-pack.c                                |  14 +-\n wt-status.c                                  |   4 +-\n xdiff-interface.c                            |   2 +-\n 87 files changed, 677 insertions(+), 613 deletions(-)\n\nRange-diff versus v3:\n\n 1:  01b5b16c3a4 =  1:  9d65ce9a2f2 csum-file: stop depending on `the_repository`\n 2:  14e0349be2f =  2:  038c6e54308 object: stop depending on `the_repository`\n 3:  9c7b8a031cc =  3:  9abd1306d6a pack-write: stop depending on `the_repository` and `the_hash_algo`\n 4:  e0168b431e7 =  4:  605fb2a7176 environment: move access to \"core.bigFileThreshold\" into repo settings\n 5:  529f296a935 =  5:  dc88e5ca6b2 pack-check: stop depending on `the_repository`\n 6:  d4a2e9a7861 =  6:  fee92049913 pack-revindex: stop depending on `the_repository`\n 7:  15e4d4de519 =  7:  f8ff74c83cf pack-bitmap-write: stop depending on `the_repository`\n 8:  576d846495f =  8:  47547d3f566 object-file-convert: stop depending on `the_repository`\n 9:  faf0f90a005 =  9:  39da917072f delta-islands: stop depending on `the_repository`\n10:  b37879d101c = 10:  a509d63ee74 object-file: split out logic regarding hash algorithms\n11:  4a1a5c67792 = 11:  421f1e96595 hash: fix \"-Wsign-compare\" warnings\n12:  f45a7866d03 ! 12:  1b0b8f71125 hash: stop depending on `the_repository` in `null_oid()`\n    @@ Commit message\n             object in the superproject, and consequently we need to use its hash\n             algorithm.\n     \n    -    This means that we could in theory just not bother about this edge case\n    -    at all and just use `the_repository` in \"diff-no-index.c\". But doing so\n    -    would feel misdesigned.\n    +        This means that we could in theory just not bother about this edge\n    +        case at all and just use `the_repository` in \"diff-no-index.c\". But\n    +        doing so would feel misdesigned.\n     \n         Remove the `USE_THE_REPOSITORY_VARIABLE` preprocessor define in\n         \"hash.c\".\n\n---\nbase-commit: e2cb568e11f4ceb427ba4205e6b8a4426d26be12\nchange-id: 20250210-b4-pks-objects-without-the-repository-6ba8398f7cc0\n\n"},{"id":"513873","messageId":"20250310-b4-pks-objects-without-the-repository-v4-1-f201b8ec57ba@pks.im","threadId":"63046","inReplyTo":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","subject":"[PATCH v4 01/12] csum-file: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:13:20Z","receivedAt":"2025-03-10T07:13:29Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"csum-file.c\" where we use the global\n`the_repository` variable, either explicitly or implicitly by using\n`the_hash_algo`.\n\nRefactor the code to stop using `the_repository` by adapting functions\nto receive required data as parameters. Adapt callsites accordingly by\neither using `the_repository->hash_algo`, or by using a context-provided\nhash algorithm in case the subsystem already got rid of its dependency\non `the_repository`.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fast-import.c  |  2 +-\n builtin/index-pack.c   |  2 +-\n builtin/pack-objects.c |  3 ++-\n commit-graph.c         |  9 ++++++---\n csum-file.c            | 28 ++++++++++++++++------------\n csum-file.h            | 12 ++++++++----\n midx-write.c           |  6 ++++--\n midx.c                 |  3 ++-\n pack-bitmap-write.c    |  2 +-\n pack-bitmap.c          |  9 +++++----\n pack-check.c           |  2 +-\n pack-revindex.c        |  3 ++-\n pack-write.c           | 12 ++++++------\n read-cache.c           |  2 +-\n 14 files changed, 56 insertions(+), 39 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 397a6f46ad8..86e6e754816 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -770,7 +770,7 @@ static void start_packfile(void)\n \tp->pack_fd = pack_fd;\n \tp->do_not_close = 1;\n \tp->repo = the_repository;\n-\tpack_file = hashfd(pack_fd, p->pack_name);\n+\tpack_file = hashfd(the_repository->hash_algo, pack_fd, p->pack_name);\n \n \tpack_data = p;\n \tpack_size = write_pack_header(pack_file, 0);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 52cc97d52cb..3eb5af20950 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -1381,7 +1381,7 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha\n \t\tREALLOC_ARRAY(objects, nr_objects + nr_unresolved + 1);\n \t\tmemset(objects + nr_objects + 1, 0,\n \t\t       nr_unresolved * sizeof(*objects));\n-\t\tf = hashfd(output_fd, curr_pack);\n+\t\tf = hashfd(the_repository->hash_algo, output_fd, curr_pack);\n \t\tfix_unresolved_deltas(f);\n \t\tstrbuf_addf(&msg, Q_(\"completed with %d local object\",\n \t\t\t\t     \"completed with %d local objects\",\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 58a9b161262..8e282f2a980 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -1311,7 +1311,8 @@ static void write_pack_file(void)\n \t\tchar *pack_tmp_name = NULL;\n \n \t\tif (pack_to_stdout)\n-\t\t\tf = hashfd_throughput(1, \"<stdout>\", progress_state);\n+\t\t\tf = hashfd_throughput(the_repository->hash_algo, 1,\n+\t\t\t\t\t      \"<stdout>\", progress_state);\n \t\telse\n \t\t\tf = create_tmp_packfile(&pack_tmp_name);\n \ndiff --git a/commit-graph.c b/commit-graph.c\nindex 1021ccb983d..8286d5dda24 100644\n--- a/commit-graph.c\n+++ b/commit-graph.c\n@@ -2090,11 +2090,13 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)\n \t\t\treturn -1;\n \t\t}\n \n-\t\tf = hashfd(get_tempfile_fd(graph_layer), get_tempfile_path(graph_layer));\n+\t\tf = hashfd(the_repository->hash_algo,\n+\t\t\t   get_tempfile_fd(graph_layer), get_tempfile_path(graph_layer));\n \t} else {\n \t\thold_lock_file_for_update_mode(&lk, ctx->graph_name,\n \t\t\t\t\t       LOCK_DIE_ON_ERROR, 0444);\n-\t\tf = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk));\n+\t\tf = hashfd(the_repository->hash_algo,\n+\t\t\t   get_lock_file_fd(&lk), get_lock_file_path(&lk));\n \t}\n \n \tcf = init_chunkfile(f);\n@@ -2716,7 +2718,8 @@ static void graph_report(const char *fmt, ...)\n \n static int commit_graph_checksum_valid(struct commit_graph *g)\n {\n-\treturn hashfile_checksum_valid(g->data, g->data_len);\n+\treturn hashfile_checksum_valid(the_repository->hash_algo,\n+\t\t\t\t       g->data, g->data_len);\n }\n \n static int verify_one_commit_graph(struct repository *r,\ndiff --git a/csum-file.c b/csum-file.c\nindex b58c183a4f0..6e21e3cac8a 100644\n--- a/csum-file.c\n+++ b/csum-file.c\n@@ -8,8 +8,6 @@\n  * able to verify hasn't been messed with afterwards.\n  */\n \n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"csum-file.h\"\n #include \"git-zlib.h\"\n@@ -148,21 +146,23 @@ void hashwrite(struct hashfile *f, const void *buf, unsigned int count)\n \t}\n }\n \n-struct hashfile *hashfd_check(const char *name)\n+struct hashfile *hashfd_check(const struct git_hash_algo *algop,\n+\t\t\t      const char *name)\n {\n \tint sink, check;\n \tstruct hashfile *f;\n \n \tsink = xopen(\"/dev/null\", O_WRONLY);\n \tcheck = xopen(name, O_RDONLY);\n-\tf = hashfd(sink, name);\n+\tf = hashfd(algop, sink, name);\n \tf->check_fd = check;\n \tf->check_buffer = xmalloc(f->buffer_len);\n \n \treturn f;\n }\n \n-static struct hashfile *hashfd_internal(int fd, const char *name,\n+static struct hashfile *hashfd_internal(const struct git_hash_algo *algop,\n+\t\t\t\t\tint fd, const char *name,\n \t\t\t\t\tstruct progress *tp,\n \t\t\t\t\tsize_t buffer_len)\n {\n@@ -176,7 +176,7 @@ static struct hashfile *hashfd_internal(int fd, const char *name,\n \tf->do_crc = 0;\n \tf->skip_hash = 0;\n \n-\tf->algop = unsafe_hash_algo(the_hash_algo);\n+\tf->algop = unsafe_hash_algo(algop);\n \tf->algop->init_fn(&f->ctx);\n \n \tf->buffer_len = buffer_len;\n@@ -186,17 +186,19 @@ static struct hashfile *hashfd_internal(int fd, const char *name,\n \treturn f;\n }\n \n-struct hashfile *hashfd(int fd, const char *name)\n+struct hashfile *hashfd(const struct git_hash_algo *algop,\n+\t\t\tint fd, const char *name)\n {\n \t/*\n \t * Since we are not going to use a progress meter to\n \t * measure the rate of data passing through this hashfile,\n \t * use a larger buffer size to reduce fsync() calls.\n \t */\n-\treturn hashfd_internal(fd, name, NULL, 128 * 1024);\n+\treturn hashfd_internal(algop, fd, name, NULL, 128 * 1024);\n }\n \n-struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp)\n+struct hashfile *hashfd_throughput(const struct git_hash_algo *algop,\n+\t\t\t\t   int fd, const char *name, struct progress *tp)\n {\n \t/*\n \t * Since we are expecting to report progress of the\n@@ -204,7 +206,7 @@ struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp\n \t * size so the progress indicators arrive at a more\n \t * frequent rate.\n \t */\n-\treturn hashfd_internal(fd, name, tp, 8 * 1024);\n+\treturn hashfd_internal(algop, fd, name, tp, 8 * 1024);\n }\n \n void hashfile_checkpoint_init(struct hashfile *f,\n@@ -246,13 +248,15 @@ uint32_t crc32_end(struct hashfile *f)\n \treturn f->crc32;\n }\n \n-int hashfile_checksum_valid(const unsigned char *data, size_t total_len)\n+int hashfile_checksum_valid(const struct git_hash_algo *algop,\n+\t\t\t    const unsigned char *data, size_t total_len)\n {\n \tunsigned char got[GIT_MAX_RAWSZ];\n \tstruct git_hash_ctx ctx;\n-\tconst struct git_hash_algo *algop = unsafe_hash_algo(the_hash_algo);\n \tsize_t data_len = total_len - algop->rawsz;\n \n+\talgop = unsafe_hash_algo(algop);\n+\n \tif (total_len < algop->rawsz)\n \t\treturn 0; /* say \"too short\"? */\n \ndiff --git a/csum-file.h b/csum-file.h\nindex ffccbf09966..07ae11024af 100644\n--- a/csum-file.h\n+++ b/csum-file.h\n@@ -45,9 +45,12 @@ int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *);\n #define CSUM_FSYNC\t\t2\n #define CSUM_HASH_IN_STREAM\t4\n \n-struct hashfile *hashfd(int fd, const char *name);\n-struct hashfile *hashfd_check(const char *name);\n-struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp);\n+struct hashfile *hashfd(const struct git_hash_algo *algop,\n+\t\t\tint fd, const char *name);\n+struct hashfile *hashfd_check(const struct git_hash_algo *algop,\n+\t\t\t      const char *name);\n+struct hashfile *hashfd_throughput(const struct git_hash_algo *algop,\n+\t\t\t\t   int fd, const char *name, struct progress *tp);\n \n /*\n  * Free the hashfile without flushing its contents to disk. This only\n@@ -66,7 +69,8 @@ void crc32_begin(struct hashfile *);\n uint32_t crc32_end(struct hashfile *);\n \n /* Verify checksum validity while reading. Returns non-zero on success. */\n-int hashfile_checksum_valid(const unsigned char *data, size_t len);\n+int hashfile_checksum_valid(const struct git_hash_algo *algop,\n+\t\t\t    const unsigned char *data, size_t len);\n \n /*\n  * Returns the total number of bytes fed to the hashfile so far (including ones\ndiff --git a/midx-write.c b/midx-write.c\nindex 48d6558253e..26d9d8bb148 100644\n--- a/midx-write.c\n+++ b/midx-write.c\n@@ -1342,10 +1342,12 @@ static int write_midx_internal(struct repository *r, const char *object_dir,\n \t\t\treturn -1;\n \t\t}\n \n-\t\tf = hashfd(get_tempfile_fd(incr), get_tempfile_path(incr));\n+\t\tf = hashfd(r->hash_algo, get_tempfile_fd(incr),\n+\t\t\t   get_tempfile_path(incr));\n \t} else {\n \t\thold_lock_file_for_update(&lk, midx_name.buf, LOCK_DIE_ON_ERROR);\n-\t\tf = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk));\n+\t\tf = hashfd(r->hash_algo, get_lock_file_fd(&lk),\n+\t\t\t   get_lock_file_path(&lk));\n \t}\n \n \tcf = init_chunkfile(f);\ndiff --git a/midx.c b/midx.c\nindex d91088efb87..807fdf72f7b 100644\n--- a/midx.c\n+++ b/midx.c\n@@ -747,7 +747,8 @@ int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, i\n \n int midx_checksum_valid(struct multi_pack_index *m)\n {\n-\treturn hashfile_checksum_valid(m->data, m->data_len);\n+\treturn hashfile_checksum_valid(m->repo->hash_algo,\n+\t\t\t\t       m->data, m->data_len);\n }\n \n struct clear_midx_data {\ndiff --git a/pack-bitmap-write.c b/pack-bitmap-write.c\nindex 34e86d49947..50e5c491ccb 100644\n--- a/pack-bitmap-write.c\n+++ b/pack-bitmap-write.c\n@@ -1030,7 +1030,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,\n \tif (writer->pseudo_merges_nr)\n \t\toptions |= BITMAP_OPT_PSEUDO_MERGES;\n \n-\tf = hashfd(fd, tmp_file.buf);\n+\tf = hashfd(the_repository->hash_algo, fd, tmp_file.buf);\n \n \tmemcpy(header.magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE));\n \theader.version = htons(default_version);\ndiff --git a/pack-bitmap.c b/pack-bitmap.c\nindex 6406953d322..f0e2c000252 100644\n--- a/pack-bitmap.c\n+++ b/pack-bitmap.c\n@@ -3024,7 +3024,8 @@ int bitmap_is_preferred_refname(struct repository *r, const char *refname)\n \treturn 0;\n }\n \n-static int verify_bitmap_file(const char *name)\n+static int verify_bitmap_file(const struct git_hash_algo *algop,\n+\t\t\t      const char *name)\n {\n \tstruct stat st;\n \tunsigned char *data;\n@@ -3040,7 +3041,7 @@ static int verify_bitmap_file(const char *name)\n \n \tdata = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);\n \tclose(fd);\n-\tif (!hashfile_checksum_valid(data, st.st_size))\n+\tif (!hashfile_checksum_valid(algop, data, st.st_size))\n \t\tres = error(_(\"bitmap file '%s' has invalid checksum\"),\n \t\t\t    name);\n \n@@ -3055,14 +3056,14 @@ int verify_bitmap_files(struct repository *r)\n \tfor (struct multi_pack_index *m = get_multi_pack_index(r);\n \t     m; m = m->next) {\n \t\tchar *midx_bitmap_name = midx_bitmap_filename(m);\n-\t\tres |= verify_bitmap_file(midx_bitmap_name);\n+\t\tres |= verify_bitmap_file(r->hash_algo, midx_bitmap_name);\n \t\tfree(midx_bitmap_name);\n \t}\n \n \tfor (struct packed_git *p = get_all_packs(r);\n \t     p; p = p->next) {\n \t\tchar *pack_bitmap_name = pack_bitmap_filename(p);\n-\t\tres |= verify_bitmap_file(pack_bitmap_name);\n+\t\tres |= verify_bitmap_file(r->hash_algo, pack_bitmap_name);\n \t\tfree(pack_bitmap_name);\n \t}\n \ndiff --git a/pack-check.c b/pack-check.c\nindex d0aeb5ec412..6bcadc1e679 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -180,7 +180,7 @@ int verify_pack_index(struct packed_git *p)\n \t\treturn error(\"packfile %s index not opened\", p->pack_name);\n \n \t/* Verify SHA1 sum of the index file */\n-\tif (!hashfile_checksum_valid(p->index_data, p->index_size))\n+\tif (!hashfile_checksum_valid(the_repository->hash_algo, p->index_data, p->index_size))\n \t\terr = error(\"Packfile index for %s hash mismatch\",\n \t\t\t    p->pack_name);\n \treturn err;\ndiff --git a/pack-revindex.c b/pack-revindex.c\nindex d3832478d99..78139e3d7f5 100644\n--- a/pack-revindex.c\n+++ b/pack-revindex.c\n@@ -322,7 +322,8 @@ int verify_pack_revindex(struct packed_git *p)\n \tif (!p->revindex_map || !p->revindex_data)\n \t\treturn res;\n \n-\tif (!hashfile_checksum_valid((const unsigned char *)p->revindex_map, p->revindex_size)) {\n+\tif (!hashfile_checksum_valid(the_repository->hash_algo,\n+\t\t\t\t     (const unsigned char *)p->revindex_map, p->revindex_size)) {\n \t\terror(_(\"invalid checksum\"));\n \t\tres = -1;\n \t}\ndiff --git a/pack-write.c b/pack-write.c\nindex 823e40b42f2..5eb89f44cf4 100644\n--- a/pack-write.c\n+++ b/pack-write.c\n@@ -82,7 +82,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \n \tif (opts->flags & WRITE_IDX_VERIFY) {\n \t\tassert(index_name);\n-\t\tf = hashfd_check(index_name);\n+\t\tf = hashfd_check(the_repository->hash_algo, index_name);\n \t} else {\n \t\tif (!index_name) {\n \t\t\tstruct strbuf tmp_file = STRBUF_INIT;\n@@ -92,7 +92,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\t\tunlink(index_name);\n \t\t\tfd = xopen(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t}\n-\t\tf = hashfd(fd, index_name);\n+\t\tf = hashfd(the_repository->hash_algo, fd, index_name);\n \t}\n \n \t/* if last object's offset is >= 2^31 we should use index V2 */\n@@ -268,7 +268,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\tfd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t\tpath = xstrdup(rev_name);\n \t\t}\n-\t\tf = hashfd(fd, path);\n+\t\tf = hashfd(the_repository->hash_algo, fd, path);\n \t} else if (flags & WRITE_REV_VERIFY) {\n \t\tstruct stat statbuf;\n \t\tif (stat(rev_name, &statbuf)) {\n@@ -278,7 +278,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\t} else\n \t\t\t\tdie_errno(_(\"could not stat: %s\"), rev_name);\n \t\t}\n-\t\tf = hashfd_check(rev_name);\n+\t\tf = hashfd_check(the_repository->hash_algo, rev_name);\n \t\tpath = xstrdup(rev_name);\n \t} else {\n \t\treturn NULL;\n@@ -346,7 +346,7 @@ static char *write_mtimes_file(const struct git_hash_algo *hash_algo,\n \n \tfd = odb_mkstemp(&tmp_file, \"pack/tmp_mtimes_XXXXXX\");\n \tmtimes_name = strbuf_detach(&tmp_file, NULL);\n-\tf = hashfd(fd, mtimes_name);\n+\tf = hashfd(the_repository->hash_algo, fd, mtimes_name);\n \n \twrite_mtimes_header(hash_algo, f);\n \twrite_mtimes_objects(f, to_pack, objects, nr_objects);\n@@ -534,7 +534,7 @@ struct hashfile *create_tmp_packfile(char **pack_tmp_name)\n \n \tfd = odb_mkstemp(&tmpname, \"pack/tmp_pack_XXXXXX\");\n \t*pack_tmp_name = strbuf_detach(&tmpname, NULL);\n-\treturn hashfd(fd, *pack_tmp_name);\n+\treturn hashfd(the_repository->hash_algo, fd, *pack_tmp_name);\n }\n \n static void rename_tmp_packfile(struct strbuf *name_prefix, const char *source,\ndiff --git a/read-cache.c b/read-cache.c\nindex e678c13e8f1..a012cb22368 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -2848,7 +2848,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,\n \tstruct strbuf sb = STRBUF_INIT;\n \tint nr, nr_threads, ret;\n \n-\tf = hashfd(tempfile->fd, tempfile->filename.buf);\n+\tf = hashfd(the_repository->hash_algo, tempfile->fd, tempfile->filename.buf);\n \n \tprepare_repo_settings(r);\n \tf->skip_hash = r->settings.index_skip_hash;\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513874","messageId":"20250310-b4-pks-objects-without-the-repository-v4-2-f201b8ec57ba@pks.im","threadId":"63046","inReplyTo":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","subject":"[PATCH v4 02/12] object: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:13:21Z","receivedAt":"2025-03-10T07:13:30Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are a couple of functions exposed by \"object.c\" that implicitly\ndepend on `the_repository`. Remove this dependency by injecting the\nrepository via a parameter. Adapt callers accordingly by simply using\n`the_repository`, except in cases where the subsystem is already free of\nthe repository. In that case, we instead pass the repository provided by\nthe caller's context.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fsck.c         |  4 ++--\n builtin/grep.c         |  2 +-\n builtin/index-pack.c   |  4 ++--\n builtin/log.c          |  2 +-\n builtin/name-rev.c     |  4 ++--\n builtin/pack-objects.c |  2 +-\n builtin/prune.c        |  2 +-\n midx-write.c           |  4 ++--\n object.c               | 21 +++++++++++----------\n object.h               | 10 ++++++----\n pack-bitmap.c          |  6 +++---\n reachable.c            |  6 +++---\n revision.c             |  3 ++-\n shallow.c              | 10 +++++-----\n upload-pack.c          | 12 ++++++------\n 15 files changed, 48 insertions(+), 44 deletions(-)\n\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex eea1d43647f..62c7494bbda 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -399,12 +399,12 @@ static void check_connectivity(void)\n \t}\n \n \t/* Look up all the requirements, warn about missing objects.. */\n-\tmax = get_max_object_index();\n+\tmax = get_max_object_index(the_repository);\n \tif (verbose)\n \t\tfprintf_ln(stderr, _(\"Checking connectivity (%d objects)\"), max);\n \n \tfor (i = 0; i < max; i++) {\n-\t\tstruct object *obj = get_indexed_object(i);\n+\t\tstruct object *obj = get_indexed_object(the_repository, i);\n \n \t\tif (obj)\n \t\t\tcheck_object(obj);\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex d1427290f77..cbbf6f26439 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -1144,7 +1144,7 @@ int cmd_grep(int argc,\n \t\t\tbreak;\n \t\t}\n \n-\t\tobject = parse_object_or_die(&oid, arg);\n+\t\tobject = parse_object_or_die(the_repository, &oid, arg);\n \t\tif (!seen_dashdash)\n \t\t\tverify_non_filename(prefix, arg);\n \t\tadd_object_array_with_path(object, arg, &list, oc.mode, oc.path);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 3eb5af20950..1268032d769 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -279,14 +279,14 @@ static unsigned check_objects(void)\n {\n \tunsigned i, max, foreign_nr = 0;\n \n-\tmax = get_max_object_index();\n+\tmax = get_max_object_index(the_repository);\n \n \tif (verbose)\n \t\tprogress = start_delayed_progress(the_repository,\n \t\t\t\t\t\t  _(\"Checking objects\"), max);\n \n \tfor (i = 0; i < max; i++) {\n-\t\tforeign_nr += check_object(get_indexed_object(i));\n+\t\tforeign_nr += check_object(get_indexed_object(the_repository, i));\n \t\tdisplay_progress(progress, i + 1);\n \t}\n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 04a6ef97bc1..0d4c579dad7 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -2468,7 +2468,7 @@ int cmd_format_patch(int argc,\n \tbase = get_base_commit(&cfg, list, nr);\n \tif (base) {\n \t\treset_revision_walk();\n-\t\tclear_object_flags(UNINTERESTING);\n+\t\tclear_object_flags(the_repository, UNINTERESTING);\n \t\tprepare_bases(&bases, base, list, nr);\n \t}\n \ndiff --git a/builtin/name-rev.c b/builtin/name-rev.c\nindex beac166b5cb..2fe82c839ba 100644\n--- a/builtin/name-rev.c\n+++ b/builtin/name-rev.c\n@@ -667,9 +667,9 @@ int cmd_name_rev(int argc,\n \t} else if (all) {\n \t\tint i, max;\n \n-\t\tmax = get_max_object_index();\n+\t\tmax = get_max_object_index(the_repository);\n \t\tfor (i = 0; i < max; i++) {\n-\t\t\tstruct object *obj = get_indexed_object(i);\n+\t\t\tstruct object *obj = get_indexed_object(the_repository, i);\n \t\t\tif (!obj || obj->type != OBJ_COMMIT)\n \t\t\t\tcontinue;\n \t\t\tshow_name(obj, NULL,\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 8e282f2a980..c3adbc94504 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -4161,7 +4161,7 @@ static int mark_bitmap_preferred_tip(const char *refname,\n \tif (!peel_iterated_oid(the_repository, oid, &peeled))\n \t\toid = &peeled;\n \n-\tobject = parse_object_or_die(oid, refname);\n+\tobject = parse_object_or_die(the_repository, oid, refname);\n \tif (object->type == OBJ_COMMIT)\n \t\tobject->flags |= NEEDS_BITMAP;\n \ndiff --git a/builtin/prune.c b/builtin/prune.c\nindex 1c357fffd8c..8f52da8bd66 100644\n--- a/builtin/prune.c\n+++ b/builtin/prune.c\n@@ -185,7 +185,7 @@ int cmd_prune(int argc,\n \t\tconst char *name = *argv++;\n \n \t\tif (!repo_get_oid(the_repository, name, &oid)) {\n-\t\t\tstruct object *object = parse_object_or_die(&oid,\n+\t\t\tstruct object *object = parse_object_or_die(the_repository, &oid,\n \t\t\t\t\t\t\t\t    name);\n \t\t\tadd_pending_object(&revs, object, \"\");\n \t\t}\ndiff --git a/midx-write.c b/midx-write.c\nindex 26d9d8bb148..ac80a8298ed 100644\n--- a/midx-write.c\n+++ b/midx-write.c\n@@ -708,7 +708,7 @@ static int add_ref_to_pending(const char *refname, const char *referent UNUSED,\n \tif (!peel_iterated_oid(revs->repo, oid, &peeled))\n \t\toid = &peeled;\n \n-\tobject = parse_object_or_die(oid, refname);\n+\tobject = parse_object_or_die(revs->repo, oid, refname);\n \tif (object->type != OBJ_COMMIT)\n \t\treturn 0;\n \n@@ -768,7 +768,7 @@ static int read_refs_snapshot(const char *refs_snapshot,\n \t\tif (*end)\n \t\t\tdie(_(\"malformed line: %s\"), buf.buf);\n \n-\t\tobject = parse_object_or_die(&oid, NULL);\n+\t\tobject = parse_object_or_die(revs->repo, &oid, NULL);\n \t\tif (preferred)\n \t\t\tobject->flags |= NEEDS_BITMAP;\n \ndiff --git a/object.c b/object.c\nindex 100bf9b8d12..154525a4972 100644\n--- a/object.c\n+++ b/object.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -18,14 +17,15 @@\n #include \"commit-graph.h\"\n #include \"loose.h\"\n \n-unsigned int get_max_object_index(void)\n+unsigned int get_max_object_index(const struct repository *repo)\n {\n-\treturn the_repository->parsed_objects->obj_hash_size;\n+\treturn repo->parsed_objects->obj_hash_size;\n }\n \n-struct object *get_indexed_object(unsigned int idx)\n+struct object *get_indexed_object(const struct repository *repo,\n+\t\t\t\t       unsigned int idx)\n {\n-\treturn the_repository->parsed_objects->obj_hash[idx];\n+\treturn repo->parsed_objects->obj_hash[idx];\n }\n \n static const char *object_type_strings[] = {\n@@ -283,10 +283,11 @@ struct object *parse_object_buffer(struct repository *r, const struct object_id\n \treturn obj;\n }\n \n-struct object *parse_object_or_die(const struct object_id *oid,\n+struct object *parse_object_or_die(struct repository *repo,\n+\t\t\t\t   const struct object_id *oid,\n \t\t\t\t   const char *name)\n {\n-\tstruct object *o = parse_object(the_repository, oid);\n+\tstruct object *o = parse_object(repo, oid);\n \tif (o)\n \t\treturn o;\n \n@@ -524,12 +525,12 @@ void object_array_remove_duplicates(struct object_array *array)\n \t}\n }\n \n-void clear_object_flags(unsigned flags)\n+void clear_object_flags(struct repository *repo, unsigned flags)\n {\n \tint i;\n \n-\tfor (i=0; i < the_repository->parsed_objects->obj_hash_size; i++) {\n-\t\tstruct object *obj = the_repository->parsed_objects->obj_hash[i];\n+\tfor (i=0; i < repo->parsed_objects->obj_hash_size; i++) {\n+\t\tstruct object *obj = repo->parsed_objects->obj_hash[i];\n \t\tif (obj)\n \t\t\tobj->flags &= ~flags;\n \t}\ndiff --git a/object.h b/object.h\nindex 17f32f1103e..a3040939799 100644\n--- a/object.h\n+++ b/object.h\n@@ -169,12 +169,13 @@ int type_from_string_gently(const char *str, ssize_t, int gentle);\n /*\n  * Return the current number of buckets in the object hashmap.\n  */\n-unsigned int get_max_object_index(void);\n+unsigned int get_max_object_index(const struct repository *repo);\n \n /*\n  * Return the object from the specified bucket in the object hashmap.\n  */\n-struct object *get_indexed_object(unsigned int);\n+struct object *get_indexed_object(const struct repository *repo,\n+\t\t\t\t       unsigned int);\n \n /*\n  * This can be used to see if we have heard of the object before, but\n@@ -231,7 +232,8 @@ struct object *parse_object_with_flags(struct repository *r,\n  * \"name\" parameter is not NULL, it is included in the error message\n  * (otherwise, the hex object ID is given).\n  */\n-struct object *parse_object_or_die(const struct object_id *oid, const char *name);\n+struct object *parse_object_or_die(struct repository *repo, const struct object_id *oid,\n+\t\t\t\t   const char *name);\n \n /* Given the result of read_sha1_file(), returns the object after\n  * parsing it.  eaten_p indicates if the object has a borrowed copy\n@@ -336,7 +338,7 @@ void object_array_remove_duplicates(struct object_array *array);\n  */\n void object_array_clear(struct object_array *array);\n \n-void clear_object_flags(unsigned flags);\n+void clear_object_flags(struct repository *repo, unsigned flags);\n \n /*\n  * Clear the specified object flags from all in-core commit objects from\ndiff --git a/pack-bitmap.c b/pack-bitmap.c\nindex f0e2c000252..7fd78c634ef 100644\n--- a/pack-bitmap.c\n+++ b/pack-bitmap.c\n@@ -1301,7 +1301,7 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,\n \trevs->tag_objects = tmp_tags;\n \n \treset_revision_walk();\n-\tclear_object_flags(UNINTERESTING);\n+\tclear_object_flags(repo, UNINTERESTING);\n \n \t/*\n \t * Then add the boundary commit(s) as fill-in traversal tips.\n@@ -1935,7 +1935,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,\n \t\tstruct object *object = revs->pending.objects[i].item;\n \n \t\tif (object->type == OBJ_NONE)\n-\t\t\tparse_object_or_die(&object->oid, NULL);\n+\t\t\tparse_object_or_die(revs->repo, &object->oid, NULL);\n \n \t\twhile (object->type == OBJ_TAG) {\n \t\t\tstruct tag *tag = (struct tag *) object;\n@@ -1945,7 +1945,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,\n \t\t\telse\n \t\t\t\tobject_list_insert(object, &wants);\n \n-\t\t\tobject = parse_object_or_die(get_tagged_oid(tag), NULL);\n+\t\t\tobject = parse_object_or_die(revs->repo, get_tagged_oid(tag), NULL);\n \t\t\tobject->flags |= (tag->object.flags & UNINTERESTING);\n \t\t}\n \ndiff --git a/reachable.c b/reachable.c\nindex 9ee04c89ec6..1b26b9b1d76 100644\n--- a/reachable.c\n+++ b/reachable.c\n@@ -45,7 +45,7 @@ static void add_one_file(const char *path, struct rev_info *revs)\n \t}\n \tstrbuf_trim(&buf);\n \tif (!get_oid_hex(buf.buf, &oid)) {\n-\t\tobject = parse_object_or_die(&oid, buf.buf);\n+\t\tobject = parse_object_or_die(the_repository, &oid, buf.buf);\n \t\tadd_pending_object(revs, object, \"\");\n \t}\n \tstrbuf_release(&buf);\n@@ -94,7 +94,7 @@ static int add_one_ref(const char *path, const char *referent UNUSED, const stru\n \t\treturn 0;\n \t}\n \n-\tobject = parse_object_or_die(oid, path);\n+\tobject = parse_object_or_die(the_repository, oid, path);\n \tadd_pending_object(revs, object, \"\");\n \n \treturn 0;\n@@ -218,7 +218,7 @@ static void add_recent_object(const struct object_id *oid,\n \tswitch (type) {\n \tcase OBJ_TAG:\n \tcase OBJ_COMMIT:\n-\t\tobj = parse_object_or_die(oid, NULL);\n+\t\tobj = parse_object_or_die(the_repository, oid, NULL);\n \t\tbreak;\n \tcase OBJ_TREE:\n \t\tobj = (struct object *)lookup_tree(the_repository, oid);\ndiff --git a/revision.c b/revision.c\nindex c4390f0938c..b536c4a29ad 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -3612,7 +3612,8 @@ static void set_children(struct rev_info *revs)\n \n void reset_revision_walk(void)\n {\n-\tclear_object_flags(SEEN | ADDED | SHOWN | TOPO_WALK_EXPLORED | TOPO_WALK_INDEGREE);\n+\tclear_object_flags(the_repository,\n+\t\t\t   SEEN | ADDED | SHOWN | TOPO_WALK_EXPLORED | TOPO_WALK_INDEGREE);\n }\n \n static int mark_uninteresting(const struct object_id *oid,\ndiff --git a/shallow.c b/shallow.c\nindex 4bd9342c9a7..06c3266a3e0 100644\n--- a/shallow.c\n+++ b/shallow.c\n@@ -226,7 +226,7 @@ struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av,\n \t * SHALLOW (excluded) and NOT_SHALLOW (included) should not be\n \t * set at this point. But better be safe than sorry.\n \t */\n-\tclear_object_flags(both_flags);\n+\tclear_object_flags(the_repository, both_flags);\n \n \tis_repository_shallow(the_repository); /* make sure shallows are read */\n \n@@ -613,9 +613,9 @@ static void paint_down(struct paint_info *info, const struct object_id *oid,\n \t\t}\n \t}\n \n-\tnr = get_max_object_index();\n+\tnr = get_max_object_index(the_repository);\n \tfor (i = 0; i < nr; i++) {\n-\t\tstruct object *o = get_indexed_object(i);\n+\t\tstruct object *o = get_indexed_object(the_repository, i);\n \t\tif (o && o->type == OBJ_COMMIT)\n \t\t\to->flags &= ~SEEN;\n \t}\n@@ -675,9 +675,9 @@ void assign_shallow_commits_to_refs(struct shallow_info *info,\n \t * Prepare the commit graph to track what refs can reach what\n \t * (new) shallow commits.\n \t */\n-\tnr = get_max_object_index();\n+\tnr = get_max_object_index(the_repository);\n \tfor (i = 0; i < nr; i++) {\n-\t\tstruct object *o = get_indexed_object(i);\n+\t\tstruct object *o = get_indexed_object(the_repository, i);\n \t\tif (!o || o->type != OBJ_COMMIT)\n \t\t\tcontinue;\n \ndiff --git a/upload-pack.c b/upload-pack.c\nindex 728b2477fcc..7412d3c6ce8 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -662,8 +662,8 @@ static int do_reachable_revlist(struct child_process *cmd,\n \n \tcmd_in = xfdopen(cmd->in, \"w\");\n \n-\tfor (i = get_max_object_index(); 0 < i; ) {\n-\t\to = get_indexed_object(--i);\n+\tfor (i = get_max_object_index(the_repository); 0 < i; ) {\n+\t\to = get_indexed_object(the_repository, --i);\n \t\tif (!o)\n \t\t\tcontinue;\n \t\tif (reachable && o->type == OBJ_COMMIT)\n@@ -731,8 +731,8 @@ static int get_reachable_list(struct upload_pack_data *data,\n \t\t\to->flags &= ~TMP_MARK;\n \t\t}\n \t}\n-\tfor (i = get_max_object_index(); 0 < i; i--) {\n-\t\to = get_indexed_object(i - 1);\n+\tfor (i = get_max_object_index(the_repository); 0 < i; i--) {\n+\t\to = get_indexed_object(the_repository, i - 1);\n \t\tif (o && o->type == OBJ_COMMIT &&\n \t\t    (o->flags & TMP_MARK)) {\n \t\t\tadd_object_array(o, NULL, reachable);\n@@ -1554,7 +1554,7 @@ static int parse_want_ref(struct packet_writer *writer, const char *line,\n \t\t}\n \n \t\tif (!o)\n-\t\t\to = parse_object_or_die(&oid, refname_nons);\n+\t\t\to = parse_object_or_die(the_repository, &oid, refname_nons);\n \n \t\tif (!(o->flags & WANTED)) {\n \t\t\to->flags |= WANTED;\n@@ -1790,7 +1790,7 @@ int upload_pack_v2(struct repository *r, struct packet_reader *request)\n \tenum fetch_state state = FETCH_PROCESS_ARGS;\n \tstruct upload_pack_data data;\n \n-\tclear_object_flags(ALL_FLAGS);\n+\tclear_object_flags(the_repository, ALL_FLAGS);\n \n \tupload_pack_data_init(&data);\n \tdata.use_sideband = LARGE_PACKET_MAX;\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513875","messageId":"20250310-b4-pks-objects-without-the-repository-v4-3-f201b8ec57ba@pks.im","threadId":"63046","inReplyTo":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","subject":"[PATCH v4 03/12] pack-write: stop depending on `the_repository` and `the_hash_algo`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:13:22Z","receivedAt":"2025-03-10T07:13:31Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are a couple of functions in \"pack-write.c\" that implicitly depend\non `the_repository` or `the_hash_algo`. Remove this dependency by\ninjecting the repository via a parameter and adapt callers accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fast-import.c  |  2 +-\n builtin/index-pack.c   |  4 ++--\n builtin/pack-objects.c |  4 ++--\n bulk-checkin.c         |  4 ++--\n midx-write.c           |  2 +-\n pack-write.c           | 55 +++++++++++++++++++++++++-------------------------\n pack.h                 | 11 +++++-----\n 7 files changed, 41 insertions(+), 41 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 86e6e754816..e1758aa9514 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -798,7 +798,7 @@ static const char *create_index(void)\n \tif (c != last)\n \t\tdie(\"internal consistency error creating the index\");\n \n-\ttmpfile = write_idx_file(the_hash_algo, NULL, idx, object_count,\n+\ttmpfile = write_idx_file(the_repository, NULL, idx, object_count,\n \t\t\t\t &pack_idx_opts, pack_data->hash);\n \tfree(idx);\n \treturn tmpfile;\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 1268032d769..174e03afa61 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -2088,10 +2088,10 @@ int cmd_index_pack(int argc,\n \tALLOC_ARRAY(idx_objects, nr_objects);\n \tfor (i = 0; i < nr_objects; i++)\n \t\tidx_objects[i] = &objects[i].idx;\n-\tcurr_index = write_idx_file(the_hash_algo, index_name, idx_objects,\n+\tcurr_index = write_idx_file(the_repository, index_name, idx_objects,\n \t\t\t\t    nr_objects, &opts, pack_hash);\n \tif (rev_index)\n-\t\tcurr_rev_index = write_rev_file(the_hash_algo, rev_index_name,\n+\t\tcurr_rev_index = write_rev_file(the_repository, rev_index_name,\n \t\t\t\t\t\tidx_objects, nr_objects,\n \t\t\t\t\t\tpack_hash, opts.flags);\n \tfree(idx_objects);\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex c3adbc94504..e05dfc4021e 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -1314,7 +1314,7 @@ static void write_pack_file(void)\n \t\t\tf = hashfd_throughput(the_repository->hash_algo, 1,\n \t\t\t\t\t      \"<stdout>\", progress_state);\n \t\telse\n-\t\t\tf = create_tmp_packfile(&pack_tmp_name);\n+\t\t\tf = create_tmp_packfile(the_repository, &pack_tmp_name);\n \n \t\toffset = write_pack_header(f, nr_remaining);\n \n@@ -1407,7 +1407,7 @@ static void write_pack_file(void)\n \t\t\tif (cruft)\n \t\t\t\tpack_idx_opts.flags |= WRITE_MTIMES;\n \n-\t\t\tstage_tmp_packfiles(the_hash_algo, &tmpname,\n+\t\t\tstage_tmp_packfiles(the_repository, &tmpname,\n \t\t\t\t\t    pack_tmp_name, written_list,\n \t\t\t\t\t    nr_written, &to_pack,\n \t\t\t\t\t    &pack_idx_opts, hash,\ndiff --git a/bulk-checkin.c b/bulk-checkin.c\nindex 20f2da67b93..23ac00ea0a6 100644\n--- a/bulk-checkin.c\n+++ b/bulk-checkin.c\n@@ -44,7 +44,7 @@ static void finish_tmp_packfile(struct strbuf *basename,\n {\n \tchar *idx_tmp_name = NULL;\n \n-\tstage_tmp_packfiles(the_hash_algo, basename, pack_tmp_name,\n+\tstage_tmp_packfiles(the_repository, basename, pack_tmp_name,\n \t\t\t    written_list, nr_written, NULL, pack_idx_opts, hash,\n \t\t\t    &idx_tmp_name);\n \trename_tmp_packfile_idx(basename, &idx_tmp_name);\n@@ -244,7 +244,7 @@ static void prepare_to_stream(struct bulk_checkin_packfile *state,\n \tif (!(flags & HASH_WRITE_OBJECT) || state->f)\n \t\treturn;\n \n-\tstate->f = create_tmp_packfile(&state->pack_tmp_name);\n+\tstate->f = create_tmp_packfile(the_repository, &state->pack_tmp_name);\n \treset_pack_idx_option(&state->pack_idx_opts);\n \n \t/* Pretend we are going to write only one object */\ndiff --git a/midx-write.c b/midx-write.c\nindex ac80a8298ed..a628ac24dcb 100644\n--- a/midx-write.c\n+++ b/midx-write.c\n@@ -658,7 +658,7 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash,\n \tstrbuf_addf(&buf, \"%s-%s.rev\", midx_name, hash_to_hex_algop(midx_hash,\n \t\t\t\t\t\t\t\t    ctx->repo->hash_algo));\n \n-\ttmp_file = write_rev_file_order(ctx->repo->hash_algo, NULL, ctx->pack_order,\n+\ttmp_file = write_rev_file_order(ctx->repo, NULL, ctx->pack_order,\n \t\t\t\t\tctx->entries_nr, midx_hash, WRITE_REV);\n \n \tif (finalize_object_file(tmp_file, buf.buf))\ndiff --git a/pack-write.c b/pack-write.c\nindex 5eb89f44cf4..6b06315f80a 100644\n--- a/pack-write.c\n+++ b/pack-write.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"gettext.h\"\n@@ -56,7 +54,7 @@ static int need_large_offset(off_t offset, const struct pack_idx_option *opts)\n  * The *sha1 contains the pack content SHA1 hash.\n  * The objects array passed in will be sorted by SHA1 on exit.\n  */\n-const char *write_idx_file(const struct git_hash_algo *hash_algo,\n+const char *write_idx_file(struct repository *repo,\n \t\t\t   const char *index_name, struct pack_idx_entry **objects,\n \t\t\t   int nr_objects, const struct pack_idx_option *opts,\n \t\t\t   const unsigned char *sha1)\n@@ -82,7 +80,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \n \tif (opts->flags & WRITE_IDX_VERIFY) {\n \t\tassert(index_name);\n-\t\tf = hashfd_check(the_repository->hash_algo, index_name);\n+\t\tf = hashfd_check(repo->hash_algo, index_name);\n \t} else {\n \t\tif (!index_name) {\n \t\t\tstruct strbuf tmp_file = STRBUF_INIT;\n@@ -92,7 +90,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\t\tunlink(index_name);\n \t\t\tfd = xopen(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t}\n-\t\tf = hashfd(the_repository->hash_algo, fd, index_name);\n+\t\tf = hashfd(repo->hash_algo, fd, index_name);\n \t}\n \n \t/* if last object's offset is >= 2^31 we should use index V2 */\n@@ -131,7 +129,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\tstruct pack_idx_entry *obj = *list++;\n \t\tif (index_version < 2)\n \t\t\thashwrite_be32(f, obj->offset);\n-\t\thashwrite(f, obj->oid.hash, hash_algo->rawsz);\n+\t\thashwrite(f, obj->oid.hash, repo->hash_algo->rawsz);\n \t\tif ((opts->flags & WRITE_IDX_STRICT) &&\n \t\t    (i && oideq(&list[-2]->oid, &obj->oid)))\n \t\t\tdie(\"The same object %s appears twice in the pack\",\n@@ -173,7 +171,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo,\n \t\t}\n \t}\n \n-\thashwrite(f, sha1, hash_algo->rawsz);\n+\thashwrite(f, sha1, repo->hash_algo->rawsz);\n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n \t\t\t  CSUM_HASH_IN_STREAM | CSUM_CLOSE |\n \t\t\t  ((opts->flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC));\n@@ -217,7 +215,7 @@ static void write_rev_trailer(const struct git_hash_algo *hash_algo,\n \thashwrite(f, hash, hash_algo->rawsz);\n }\n \n-char *write_rev_file(const struct git_hash_algo *hash_algo,\n+char *write_rev_file(struct repository *repo,\n \t\t     const char *rev_name,\n \t\t     struct pack_idx_entry **objects,\n \t\t     uint32_t nr_objects,\n@@ -236,7 +234,7 @@ char *write_rev_file(const struct git_hash_algo *hash_algo,\n \t\tpack_order[i] = i;\n \tQSORT_S(pack_order, nr_objects, pack_order_cmp, objects);\n \n-\tret = write_rev_file_order(hash_algo, rev_name, pack_order, nr_objects,\n+\tret = write_rev_file_order(repo, rev_name, pack_order, nr_objects,\n \t\t\t\t   hash, flags);\n \n \tfree(pack_order);\n@@ -244,7 +242,7 @@ char *write_rev_file(const struct git_hash_algo *hash_algo,\n \treturn ret;\n }\n \n-char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n+char *write_rev_file_order(struct repository *repo,\n \t\t\t   const char *rev_name,\n \t\t\t   uint32_t *pack_order,\n \t\t\t   uint32_t nr_objects,\n@@ -268,7 +266,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\tfd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\t\tpath = xstrdup(rev_name);\n \t\t}\n-\t\tf = hashfd(the_repository->hash_algo, fd, path);\n+\t\tf = hashfd(repo->hash_algo, fd, path);\n \t} else if (flags & WRITE_REV_VERIFY) {\n \t\tstruct stat statbuf;\n \t\tif (stat(rev_name, &statbuf)) {\n@@ -278,18 +276,18 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n \t\t\t} else\n \t\t\t\tdie_errno(_(\"could not stat: %s\"), rev_name);\n \t\t}\n-\t\tf = hashfd_check(the_repository->hash_algo, rev_name);\n+\t\tf = hashfd_check(repo->hash_algo, rev_name);\n \t\tpath = xstrdup(rev_name);\n \t} else {\n \t\treturn NULL;\n \t}\n \n-\twrite_rev_header(hash_algo, f);\n+\twrite_rev_header(repo->hash_algo, f);\n \n \twrite_rev_index_positions(f, pack_order, nr_objects);\n-\twrite_rev_trailer(hash_algo, f, hash);\n+\twrite_rev_trailer(repo->hash_algo, f, hash);\n \n-\tif (adjust_shared_perm(the_repository, path) < 0)\n+\tif (adjust_shared_perm(repo, path) < 0)\n \t\tdie(_(\"failed to make %s readable\"), path);\n \n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n@@ -330,7 +328,7 @@ static void write_mtimes_trailer(const struct git_hash_algo *hash_algo,\n \thashwrite(f, hash, hash_algo->rawsz);\n }\n \n-static char *write_mtimes_file(const struct git_hash_algo *hash_algo,\n+static char *write_mtimes_file(struct repository *repo,\n \t\t\t       struct packing_data *to_pack,\n \t\t\t       struct pack_idx_entry **objects,\n \t\t\t       uint32_t nr_objects,\n@@ -346,13 +344,13 @@ static char *write_mtimes_file(const struct git_hash_algo *hash_algo,\n \n \tfd = odb_mkstemp(&tmp_file, \"pack/tmp_mtimes_XXXXXX\");\n \tmtimes_name = strbuf_detach(&tmp_file, NULL);\n-\tf = hashfd(the_repository->hash_algo, fd, mtimes_name);\n+\tf = hashfd(repo->hash_algo, fd, mtimes_name);\n \n-\twrite_mtimes_header(hash_algo, f);\n+\twrite_mtimes_header(repo->hash_algo, f);\n \twrite_mtimes_objects(f, to_pack, objects, nr_objects);\n-\twrite_mtimes_trailer(hash_algo, f, hash);\n+\twrite_mtimes_trailer(repo->hash_algo, f, hash);\n \n-\tif (adjust_shared_perm(the_repository, mtimes_name) < 0)\n+\tif (adjust_shared_perm(repo, mtimes_name) < 0)\n \t\tdie(_(\"failed to make %s readable\"), mtimes_name);\n \n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n@@ -527,14 +525,15 @@ int encode_in_pack_object_header(unsigned char *hdr, int hdr_len,\n \treturn n;\n }\n \n-struct hashfile *create_tmp_packfile(char **pack_tmp_name)\n+struct hashfile *create_tmp_packfile(struct repository *repo,\n+\t\t\t\t     char **pack_tmp_name)\n {\n \tstruct strbuf tmpname = STRBUF_INIT;\n \tint fd;\n \n \tfd = odb_mkstemp(&tmpname, \"pack/tmp_pack_XXXXXX\");\n \t*pack_tmp_name = strbuf_detach(&tmpname, NULL);\n-\treturn hashfd(the_repository->hash_algo, fd, *pack_tmp_name);\n+\treturn hashfd(repo->hash_algo, fd, *pack_tmp_name);\n }\n \n static void rename_tmp_packfile(struct strbuf *name_prefix, const char *source,\n@@ -555,7 +554,7 @@ void rename_tmp_packfile_idx(struct strbuf *name_buffer,\n \trename_tmp_packfile(name_buffer, *idx_tmp_name, \"idx\");\n }\n \n-void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,\n+void stage_tmp_packfiles(struct repository *repo,\n \t\t\t struct strbuf *name_buffer,\n \t\t\t const char *pack_tmp_name,\n \t\t\t struct pack_idx_entry **written_list,\n@@ -568,19 +567,19 @@ void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,\n \tchar *rev_tmp_name = NULL;\n \tchar *mtimes_tmp_name = NULL;\n \n-\tif (adjust_shared_perm(the_repository, pack_tmp_name))\n+\tif (adjust_shared_perm(repo, pack_tmp_name))\n \t\tdie_errno(\"unable to make temporary pack file readable\");\n \n-\t*idx_tmp_name = (char *)write_idx_file(hash_algo, NULL, written_list,\n+\t*idx_tmp_name = (char *)write_idx_file(repo, NULL, written_list,\n \t\t\t\t\t       nr_written, pack_idx_opts, hash);\n-\tif (adjust_shared_perm(the_repository, *idx_tmp_name))\n+\tif (adjust_shared_perm(repo, *idx_tmp_name))\n \t\tdie_errno(\"unable to make temporary index file readable\");\n \n-\trev_tmp_name = write_rev_file(hash_algo, NULL, written_list, nr_written,\n+\trev_tmp_name = write_rev_file(repo, NULL, written_list, nr_written,\n \t\t\t\t      hash, pack_idx_opts->flags);\n \n \tif (pack_idx_opts->flags & WRITE_MTIMES) {\n-\t\tmtimes_tmp_name = write_mtimes_file(hash_algo, to_pack,\n+\t\tmtimes_tmp_name = write_mtimes_file(repo, to_pack,\n \t\t\t\t\t\t    written_list, nr_written,\n \t\t\t\t\t\t    hash);\n \t}\ndiff --git a/pack.h b/pack.h\nindex 9f1194ac13d..5d4393eaffe 100644\n--- a/pack.h\n+++ b/pack.h\n@@ -87,7 +87,7 @@ struct progress;\n /* Note, the data argument could be NULL if object type is blob */\n typedef int (*verify_fn)(const struct object_id *, enum object_type, unsigned long, void*, int*);\n \n-const char *write_idx_file(const struct git_hash_algo *hash_algo,\n+const char *write_idx_file(struct repository *repo,\n \t\t\t   const char *index_name,\n \t\t\t   struct pack_idx_entry **objects,\n \t\t\t   int nr_objects,\n@@ -106,13 +106,13 @@ struct ref;\n \n void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought);\n \n-char *write_rev_file(const struct git_hash_algo *hash_algo,\n+char *write_rev_file(struct repository *repo,\n \t\t     const char *rev_name,\n \t\t     struct pack_idx_entry **objects,\n \t\t     uint32_t nr_objects,\n \t\t     const unsigned char *hash,\n \t\t     unsigned flags);\n-char *write_rev_file_order(const struct git_hash_algo *hash_algo,\n+char *write_rev_file_order(struct repository *repo,\n \t\t\t   const char *rev_name,\n \t\t\t   uint32_t *pack_order,\n \t\t\t   uint32_t nr_objects,\n@@ -134,8 +134,9 @@ int read_pack_header(int fd, struct pack_header *);\n \n struct packing_data;\n \n-struct hashfile *create_tmp_packfile(char **pack_tmp_name);\n-void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,\n+struct hashfile *create_tmp_packfile(struct repository *repo,\n+\t\t\t\t     char **pack_tmp_name);\n+void stage_tmp_packfiles(struct repository *repo,\n \t\t\t struct strbuf *name_buffer,\n \t\t\t const char *pack_tmp_name,\n \t\t\t struct pack_idx_entry **written_list,\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513876","messageId":"20250310-b4-pks-objects-without-the-repository-v4-4-f201b8ec57ba@pks.im","threadId":"63046","inReplyTo":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","subject":"[PATCH v4 04/12] environment: move access to \"core.bigFileThreshold\" into repo settings","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:13:23Z","receivedAt":"2025-03-10T07:13:33Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The \"core.bigFileThreshold\" setting is stored in a global variable and\npopulated via `git_default_core_config()`. This may cause issues in\nthe case where one is handling multiple different repositories in a\nsingle process with different values for that config key, as we may or\nmay not see the correct value in that case. Furthermore, global state\nblocks our path towards libification.\n\nRefactor the code so that we instead store the value in `struct\nrepo_settings`, where the value is computed as-needed and cached.\n\nNote that this change requires us to adapt one test in t1050 that\nverifies that we die when parsing an invalid \"core.bigFileThreshold\"\nvalue. The exercised Git command doesn't use the value at all, and thus\nit won't hit the new code path that parses the value. This is addressed\nby using git-hash-object(1) instead, which does read the value.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n archive.c                |  2 +-\n builtin/fast-import.c    |  4 ++--\n builtin/index-pack.c     |  6 ++++--\n builtin/pack-objects.c   |  6 ++++--\n builtin/unpack-objects.c |  3 ++-\n config.c                 |  5 -----\n diff.c                   |  6 ++++--\n environment.c            |  1 -\n environment.h            |  1 -\n object-file.c            |  6 ++++--\n pack-check.c             |  3 ++-\n repo-settings.c          | 20 ++++++++++++++++++++\n repo-settings.h          |  5 +++++\n streaming.c              |  3 ++-\n t/t1050-large.sh         |  3 ++-\n 15 files changed, 52 insertions(+), 22 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex 8be4e7ac8db..f4331aeb49e 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -216,7 +216,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,\n \t/* Stream it? */\n \tif (S_ISREG(mode) && !args->convert &&\n \t    oid_object_info(args->repo, oid, &size) == OBJ_BLOB &&\n-\t    size > big_file_threshold)\n+\t    size > repo_settings_get_big_file_threshold(the_repository))\n \t\treturn write_entry(args, oid, path.buf, path.len, mode, NULL, size);\n \n \tbuffer = object_file_to_archive(args, path.buf, oid, mode, &type, &size);\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex e1758aa9514..ce52f78579d 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -2021,7 +2021,7 @@ static void parse_and_store_blob(\n \tstatic struct strbuf buf = STRBUF_INIT;\n \tuintmax_t len;\n \n-\tif (parse_data(&buf, big_file_threshold, &len))\n+\tif (parse_data(&buf, repo_settings_get_big_file_threshold(the_repository), &len))\n \t\tstore_object(OBJ_BLOB, &buf, last, oidout, mark);\n \telse {\n \t\tif (last) {\n@@ -3402,7 +3402,7 @@ static int parse_one_option(const char *option)\n \t\tunsigned long v;\n \t\tif (!git_parse_ulong(option, &v))\n \t\t\treturn 0;\n-\t\tbig_file_threshold = v;\n+\t\trepo_settings_set_big_file_threshold(the_repository, v);\n \t} else if (skip_prefix(option, \"depth=\", &option)) {\n \t\toption_depth(option);\n \t} else if (skip_prefix(option, \"active-branches=\", &option)) {\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 174e03afa61..09c0a8adf63 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -485,7 +485,8 @@ static void *unpack_entry_data(off_t offset, unsigned long size,\n \t\tgit_hash_update(&c, hdr, hdrlen);\n \t} else\n \t\toid = NULL;\n-\tif (type == OBJ_BLOB && size > big_file_threshold)\n+\tif (type == OBJ_BLOB &&\n+\t    size > repo_settings_get_big_file_threshold(the_repository))\n \t\tbuf = fixed_buf;\n \telse\n \t\tbuf = xmallocz(size);\n@@ -799,7 +800,8 @@ static int check_collison(struct object_entry *entry)\n \tenum object_type type;\n \tunsigned long size;\n \n-\tif (entry->size <= big_file_threshold || entry->type != OBJ_BLOB)\n+\tif (entry->size <= repo_settings_get_big_file_threshold(the_repository) ||\n+\t    entry->type != OBJ_BLOB)\n \t\treturn -1;\n \n \tmemset(&data, 0, sizeof(data));\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex e05dfc4021e..eefc6c78096 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -499,7 +499,8 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent\n \n \tif (!usable_delta) {\n \t\tif (oe_type(entry) == OBJ_BLOB &&\n-\t\t    oe_size_greater_than(&to_pack, entry, big_file_threshold) &&\n+\t\t    oe_size_greater_than(&to_pack, entry,\n+\t\t\t\t\t repo_settings_get_big_file_threshold(the_repository)) &&\n \t\t    (st = open_istream(the_repository, &entry->idx.oid, &type,\n \t\t\t\t       &size, NULL)) != NULL)\n \t\t\tbuf = NULL;\n@@ -2454,7 +2455,8 @@ static void get_object_details(void)\n \t\tstruct object_entry *entry = sorted_by_offset[i];\n \t\tcheck_object(entry, i);\n \t\tif (entry->type_valid &&\n-\t\t    oe_size_greater_than(&to_pack, entry, big_file_threshold))\n+\t\t    oe_size_greater_than(&to_pack, entry,\n+\t\t\t\t\t repo_settings_get_big_file_threshold(the_repository)))\n \t\t\tentry->no_try_delta = 1;\n \t\tdisplay_progress(progress_state, i + 1);\n \t}\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex 8383bcf4049..e20c120913e 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -553,7 +553,8 @@ static void unpack_one(unsigned nr)\n \n \tswitch (type) {\n \tcase OBJ_BLOB:\n-\t\tif (!dry_run && size > big_file_threshold) {\n+\t\tif (!dry_run &&\n+\t\t    size > repo_settings_get_big_file_threshold(the_repository)) {\n \t\t\tstream_blob(size, nr);\n \t\t\treturn;\n \t\t}\ndiff --git a/config.c b/config.c\nindex dfd03b9421c..dc95608f749 100644\n--- a/config.c\n+++ b/config.c\n@@ -1490,11 +1490,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.bigfilethreshold\")) {\n-\t\tbig_file_threshold = git_config_ulong(var, value, ctx->kvi);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.autocrlf\")) {\n \t\tif (value && !strcasecmp(value, \"input\")) {\n \t\t\tauto_crlf = AUTO_CRLF_INPUT;\ndiff --git a/diff.c b/diff.c\nindex c89c15d98e0..4f802b4251c 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -4193,7 +4193,8 @@ int diff_populate_filespec(struct repository *r,\n \t\t * is probably fine.\n \t\t */\n \t\tif (check_binary &&\n-\t\t    s->size > big_file_threshold && s->is_binary == -1) {\n+\t\t    s->size > repo_settings_get_big_file_threshold(the_repository) &&\n+\t\t    s->is_binary == -1) {\n \t\t\ts->is_binary = 1;\n \t\t\treturn 0;\n \t\t}\n@@ -4243,7 +4244,8 @@ int diff_populate_filespec(struct repository *r,\n \t\tif (size_only || check_binary) {\n \t\t\tif (size_only)\n \t\t\t\treturn 0;\n-\t\t\tif (s->size > big_file_threshold && s->is_binary == -1) {\n+\t\t\tif (s->size > repo_settings_get_big_file_threshold(the_repository) &&\n+\t\t\t    s->is_binary == -1) {\n \t\t\t\ts->is_binary = 1;\n \t\t\t\treturn 0;\n \t\t\t}\ndiff --git a/environment.c b/environment.c\nindex 9e4c7781be0..3c32367c28c 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -49,7 +49,6 @@ int fsync_object_files = -1;\n int use_fsync = -1;\n enum fsync_method fsync_method = FSYNC_METHOD_DEFAULT;\n enum fsync_component fsync_components = FSYNC_COMPONENTS_DEFAULT;\n-unsigned long big_file_threshold = 512 * 1024 * 1024;\n char *editor_program;\n char *askpass_program;\n char *excludes_file;\ndiff --git a/environment.h b/environment.h\nindex 45e690f203f..91d854dcb08 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -154,7 +154,6 @@ extern int zlib_compression_level;\n extern int pack_compression_level;\n extern size_t packed_git_window_size;\n extern size_t packed_git_limit;\n-extern unsigned long big_file_threshold;\n extern unsigned long pack_size_limit_cfg;\n extern int max_allowed_tree_depth;\n \ndiff --git a/object-file.c b/object-file.c\nindex 726e41a0475..b3e0276b2a4 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2803,7 +2803,8 @@ int index_fd(struct index_state *istate, struct object_id *oid,\n \t\tret = index_stream_convert_blob(istate, oid, fd, path, flags);\n \telse if (!S_ISREG(st->st_mode))\n \t\tret = index_pipe(istate, oid, fd, type, path, flags);\n-\telse if (st->st_size <= big_file_threshold || type != OBJ_BLOB ||\n+\telse if (st->st_size <= repo_settings_get_big_file_threshold(the_repository) ||\n+\t\t type != OBJ_BLOB ||\n \t\t (path && would_convert_to_git(istate, path)))\n \t\tret = index_core(istate, oid, fd, xsize_t(st->st_size),\n \t\t\t\t type, path, flags);\n@@ -3137,7 +3138,8 @@ int read_loose_object(const char *path,\n \t\tgoto out;\n \t}\n \n-\tif (*oi->typep == OBJ_BLOB && *size > big_file_threshold) {\n+\tif (*oi->typep == OBJ_BLOB &&\n+\t    *size > repo_settings_get_big_file_threshold(the_repository)) {\n \t\tif (check_stream_oid(&stream, hdr, *size, path, expected_oid) < 0)\n \t\t\tgoto out;\n \t} else {\ndiff --git a/pack-check.c b/pack-check.c\nindex 6bcadc1e679..017dc740f7b 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -131,7 +131,8 @@ static int verify_packfile(struct repository *r,\n \t\ttype = unpack_object_header(p, w_curs, &curpos, &size);\n \t\tunuse_pack(w_curs);\n \n-\t\tif (type == OBJ_BLOB && big_file_threshold <= size) {\n+\t\tif (type == OBJ_BLOB &&\n+\t\t    repo_settings_get_big_file_threshold(the_repository) <= size) {\n \t\t\t/*\n \t\t\t * Let stream_object_signature() check it with\n \t\t\t * the streaming interface; no point slurping\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 67e9cfd2e63..4129f8fb2b4 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -20,6 +20,13 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest,\n \t\t*dest = def;\n }\n \n+static void repo_cfg_ulong(struct repository *r, const char *key, unsigned long *dest,\n+\t\t\t   unsigned long def)\n+{\n+\tif (repo_config_get_ulong(r, key, dest))\n+\t\t*dest = def;\n+}\n+\n void prepare_repo_settings(struct repository *r)\n {\n \tint experimental;\n@@ -151,6 +158,19 @@ void repo_settings_clear(struct repository *r)\n \tr->settings = empty;\n }\n \n+unsigned long repo_settings_get_big_file_threshold(struct repository *repo)\n+{\n+\tif (!repo->settings.big_file_threshold)\n+\t\trepo_cfg_ulong(repo, \"core.bigfilethreshold\",\n+\t\t\t       &repo->settings.big_file_threshold, 512 * 1024 * 1024);\n+\treturn repo->settings.big_file_threshold;\n+}\n+\n+void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value)\n+{\n+\trepo->settings.big_file_threshold = value;\n+}\n+\n enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo)\n {\n \tconst char *value;\ndiff --git a/repo-settings.h b/repo-settings.h\nindex ddc11967e01..2bf24b25973 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -64,6 +64,7 @@ struct repo_settings {\n \tsize_t delta_base_cache_limit;\n \tsize_t packed_git_window_size;\n \tsize_t packed_git_limit;\n+\tunsigned long big_file_threshold;\n \n \tchar *hooks_path;\n };\n@@ -88,6 +89,10 @@ int repo_settings_get_warn_ambiguous_refs(struct repository *repo);\n /* Read the value for \"core.hooksPath\". */\n const char *repo_settings_get_hooks_path(struct repository *repo);\n \n+/* Read and set the value for \"core.bigFileThreshold\". */\n+unsigned long repo_settings_get_big_file_threshold(struct repository *repo);\n+void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value);\n+\n /* Read, set or reset the value for \"core.sharedRepository\". */\n int repo_settings_get_shared_repository(struct repository *repo);\n void repo_settings_set_shared_repository(struct repository *repo, int value);\ndiff --git a/streaming.c b/streaming.c\nindex 38839511afc..018b794d252 100644\n--- a/streaming.c\n+++ b/streaming.c\n@@ -431,7 +431,8 @@ static int istream_source(struct git_istream *st,\n \t\tst->open = open_istream_loose;\n \t\treturn 0;\n \tcase OI_PACKED:\n-\t\tif (!oi.u.packed.is_delta && big_file_threshold < size) {\n+\t\tif (!oi.u.packed.is_delta &&\n+\t\t    repo_settings_get_big_file_threshold(the_repository) < size) {\n \t\t\tst->u.in_pack.pack = oi.u.packed.pack;\n \t\t\tst->u.in_pack.pos = oi.u.packed.offset;\n \t\t\tst->open = open_istream_pack_non_delta;\ndiff --git a/t/t1050-large.sh b/t/t1050-large.sh\nindex c71932b0242..5be273611ad 100755\n--- a/t/t1050-large.sh\n+++ b/t/t1050-large.sh\n@@ -6,7 +6,8 @@ test_description='adding and checking out large blobs'\n . ./test-lib.sh\n \n test_expect_success 'core.bigFileThreshold must be non-negative' '\n-\ttest_must_fail git -c core.bigFileThreshold=-1 rev-parse >out 2>err &&\n+\t: >input &&\n+\ttest_must_fail git -c core.bigFileThreshold=-1 hash-object input >out 2>err &&\n \tgrep \"bad numeric config value\" err &&\n \ttest_must_be_empty out\n '\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513877","messageId":"20250310-b4-pks-objects-without-the-repository-v4-5-f201b8ec57ba@pks.im","threadId":"63046","inReplyTo":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","subject":"[PATCH v4 05/12] pack-check: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:13:24Z","receivedAt":"2025-03-10T07:13:34Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"pack-check.c\" where we use the global\n`the_repository` variable, either explicitly or implicitly by using\n`the_hash_algo`. In all of those cases we already have a repository\navailable in the calling context though.\n\nRefactor the code to instead use the caller-provided repository and\nremove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n pack-check.c | 11 +++++------\n 1 file changed, 5 insertions(+), 6 deletions(-)\n\ndiff --git a/pack-check.c b/pack-check.c\nindex 017dc740f7b..95dcbbe9852 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -44,7 +43,7 @@ int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,\n \t} while (len);\n \n \tindex_crc = p->index_data;\n-\tindex_crc += 2 + 256 + (size_t)p->num_objects * (the_hash_algo->rawsz/4) + nr;\n+\tindex_crc += 2 + 256 + (size_t)p->num_objects * (p->repo->hash_algo->rawsz/4) + nr;\n \n \treturn data_crc != ntohl(*index_crc);\n }\n@@ -81,11 +80,11 @@ static int verify_packfile(struct repository *r,\n \t} while (offset < pack_sig_ofs);\n \tgit_hash_final(hash, &ctx);\n \tpack_sig = use_pack(p, w_curs, pack_sig_ofs, NULL);\n-\tif (!hasheq(hash, pack_sig, the_repository->hash_algo))\n+\tif (!hasheq(hash, pack_sig, r->hash_algo))\n \t\terr = error(\"%s pack checksum mismatch\",\n \t\t\t    p->pack_name);\n \tif (!hasheq(index_base + index_size - r->hash_algo->hexsz, pack_sig,\n-\t\t    the_repository->hash_algo))\n+\t\t    r->hash_algo))\n \t\terr = error(\"%s pack checksum does not match its index\",\n \t\t\t    p->pack_name);\n \tunuse_pack(w_curs);\n@@ -132,7 +131,7 @@ static int verify_packfile(struct repository *r,\n \t\tunuse_pack(w_curs);\n \n \t\tif (type == OBJ_BLOB &&\n-\t\t    repo_settings_get_big_file_threshold(the_repository) <= size) {\n+\t\t    repo_settings_get_big_file_threshold(r) <= size) {\n \t\t\t/*\n \t\t\t * Let stream_object_signature() check it with\n \t\t\t * the streaming interface; no point slurping\n@@ -181,7 +180,7 @@ int verify_pack_index(struct packed_git *p)\n \t\treturn error(\"packfile %s index not opened\", p->pack_name);\n \n \t/* Verify SHA1 sum of the index file */\n-\tif (!hashfile_checksum_valid(the_repository->hash_algo, p->index_data, p->index_size))\n+\tif (!hashfile_checksum_valid(p->repo->hash_algo, p->index_data, p->index_size))\n \t\terr = error(\"Packfile index for %s hash mismatch\",\n \t\t\t    p->pack_name);\n \treturn err;\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513878","messageId":"20250310-b4-pks-objects-without-the-repository-v4-6-f201b8ec57ba@pks.im","threadId":"63046","inReplyTo":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","subject":"[PATCH v4 06/12] pack-revindex: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:13:25Z","receivedAt":"2025-03-10T07:13:36Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"pack-revindex.c\" where we use the global\n`the_repository` variable, either explicitly or implicitly by using\n`the_hash_algo`. In all of those cases we already have a repository\navailable in the calling context though.\n\nRefactor the code to instead use the caller-provided repository and\nremove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n pack-revindex.c | 34 ++++++++++++++++++++--------------\n 1 file changed, 20 insertions(+), 14 deletions(-)\n\ndiff --git a/pack-revindex.c b/pack-revindex.c\nindex 78139e3d7f5..038e0c96b1c 100644\n--- a/pack-revindex.c\n+++ b/pack-revindex.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"gettext.h\"\n #include \"pack-revindex.h\"\n@@ -9,6 +7,7 @@\n #include \"strbuf.h\"\n #include \"trace2.h\"\n #include \"parse.h\"\n+#include \"repository.h\"\n #include \"midx.h\"\n #include \"csum-file.h\"\n \n@@ -137,7 +136,7 @@ static void create_pack_revindex(struct packed_git *p)\n \tconst unsigned num_ent = p->num_objects;\n \tunsigned i;\n \tconst char *index = p->index_data;\n-\tconst unsigned hashsz = the_hash_algo->rawsz;\n+\tconst unsigned hashsz = p->repo->hash_algo->rawsz;\n \n \tALLOC_ARRAY(p->revindex, num_ent + 1);\n \tindex += 4 * 256;\n@@ -193,7 +192,11 @@ static char *pack_revindex_filename(struct packed_git *p)\n }\n \n #define RIDX_HEADER_SIZE (12)\n-#define RIDX_MIN_SIZE (RIDX_HEADER_SIZE + (2 * the_hash_algo->rawsz))\n+\n+static size_t ridx_min_size(const struct git_hash_algo *algo)\n+{\n+\treturn RIDX_HEADER_SIZE + (2 * algo->rawsz);\n+}\n \n struct revindex_header {\n \tuint32_t signature;\n@@ -201,7 +204,8 @@ struct revindex_header {\n \tuint32_t hash_id;\n };\n \n-static int load_revindex_from_disk(char *revindex_name,\n+static int load_revindex_from_disk(const struct git_hash_algo *algo,\n+\t\t\t\t   char *revindex_name,\n \t\t\t\t   uint32_t num_objects,\n \t\t\t\t   const uint32_t **data_p, size_t *len_p)\n {\n@@ -228,12 +232,12 @@ static int load_revindex_from_disk(char *revindex_name,\n \n \trevindex_size = xsize_t(st.st_size);\n \n-\tif (revindex_size < RIDX_MIN_SIZE) {\n+\tif (revindex_size < ridx_min_size(algo)) {\n \t\tret = error(_(\"reverse-index file %s is too small\"), revindex_name);\n \t\tgoto cleanup;\n \t}\n \n-\tif (revindex_size - RIDX_MIN_SIZE != st_mult(sizeof(uint32_t), num_objects)) {\n+\tif (revindex_size - ridx_min_size(algo) != st_mult(sizeof(uint32_t), num_objects)) {\n \t\tret = error(_(\"reverse-index file %s is corrupt\"), revindex_name);\n \t\tgoto cleanup;\n \t}\n@@ -279,7 +283,8 @@ int load_pack_revindex_from_disk(struct packed_git *p)\n \n \trevindex_name = pack_revindex_filename(p);\n \n-\tret = load_revindex_from_disk(revindex_name,\n+\tret = load_revindex_from_disk(p->repo->hash_algo,\n+\t\t\t\t      revindex_name,\n \t\t\t\t      p->num_objects,\n \t\t\t\t      &p->revindex_map,\n \t\t\t\t      &p->revindex_size);\n@@ -322,7 +327,7 @@ int verify_pack_revindex(struct packed_git *p)\n \tif (!p->revindex_map || !p->revindex_data)\n \t\treturn res;\n \n-\tif (!hashfile_checksum_valid(the_repository->hash_algo,\n+\tif (!hashfile_checksum_valid(p->repo->hash_algo,\n \t\t\t\t     (const unsigned char *)p->revindex_map, p->revindex_size)) {\n \t\terror(_(\"invalid checksum\"));\n \t\tres = -1;\n@@ -375,19 +380,20 @@ int load_midx_revindex(struct multi_pack_index *m)\n \t\t * not want to accidentally call munmap() in the middle of the\n \t\t * MIDX.\n \t\t */\n-\t\ttrace2_data_string(\"load_midx_revindex\", the_repository,\n+\t\ttrace2_data_string(\"load_midx_revindex\", m->repo,\n \t\t\t\t   \"source\", \"midx\");\n \t\tm->revindex_data = (const uint32_t *)m->chunk_revindex;\n \t\treturn 0;\n \t}\n \n-\ttrace2_data_string(\"load_midx_revindex\", the_repository,\n+\ttrace2_data_string(\"load_midx_revindex\", m->repo,\n \t\t\t   \"source\", \"rev\");\n \n \tget_midx_filename_ext(m->repo->hash_algo, &revindex_name, m->object_dir,\n \t\t\t      get_midx_checksum(m), MIDX_EXT_REV);\n \n-\tret = load_revindex_from_disk(revindex_name.buf,\n+\tret = load_revindex_from_disk(m->repo->hash_algo,\n+\t\t\t\t      revindex_name.buf,\n \t\t\t\t      m->num_objects,\n \t\t\t\t      &m->revindex_map,\n \t\t\t\t      &m->revindex_len);\n@@ -419,7 +425,7 @@ int offset_to_pack_pos(struct packed_git *p, off_t ofs, uint32_t *pos)\n {\n \tunsigned lo, hi;\n \n-\tif (load_pack_revindex(the_repository, p) < 0)\n+\tif (load_pack_revindex(p->repo, p) < 0)\n \t\treturn -1;\n \n \tlo = 0;\n@@ -465,7 +471,7 @@ off_t pack_pos_to_offset(struct packed_git *p, uint32_t pos)\n \tif (p->revindex)\n \t\treturn p->revindex[pos].offset;\n \telse if (pos == p->num_objects)\n-\t\treturn p->pack_size - the_hash_algo->rawsz;\n+\t\treturn p->pack_size - p->repo->hash_algo->rawsz;\n \telse\n \t\treturn nth_packed_object_offset(p, pack_pos_to_index(p, pos));\n }\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513879","messageId":"20250310-b4-pks-objects-without-the-repository-v4-7-f201b8ec57ba@pks.im","threadId":"63046","inReplyTo":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","subject":"[PATCH v4 07/12] pack-bitmap-write: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:13:26Z","receivedAt":"2025-03-10T07:13:37Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"pack-bitmap-write.c\" where we use the\nglobal `the_repository` variable, either explicitly or implicitly by\nusing `the_hash_algo`.\n\nRefactor the code so that the `struct bitmap_writer` stores the\nrepository it is getting initialized with. Like this, we can adapt\ncallsites that use `the_repository` to instead use the repository\nprovided by the writer.\n\nRemove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n pack-bitmap-write.c | 36 ++++++++++++++++++------------------\n pack-bitmap.h       |  1 +\n 2 files changed, 19 insertions(+), 18 deletions(-)\n\ndiff --git a/pack-bitmap-write.c b/pack-bitmap-write.c\nindex 50e5c491ccb..6a97b52b36d 100644\n--- a/pack-bitmap-write.c\n+++ b/pack-bitmap-write.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -48,6 +47,7 @@ void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r,\n \tmemset(writer, 0, sizeof(struct bitmap_writer));\n \tif (writer->bitmaps)\n \t\tBUG(\"bitmap writer already initialized\");\n+\twriter->repo = r;\n \twriter->bitmaps = kh_init_oid_map();\n \twriter->pseudo_merge_commits = kh_init_oid_map();\n \twriter->to_pack = pdata;\n@@ -415,9 +415,9 @@ static void bitmap_builder_init(struct bitmap_builder *bb,\n \t\tbb->commits[bb->commits_nr++] = r->item;\n \t}\n \n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"num_selected_commits\", writer->selected_nr);\n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"num_maximal_commits\", num_maximal);\n \n \trelease_revisions(&revs);\n@@ -460,7 +460,7 @@ static int fill_bitmap_tree(struct bitmap_writer *writer,\n \t\tswitch (object_type(entry.mode)) {\n \t\tcase OBJ_TREE:\n \t\t\tif (fill_bitmap_tree(writer, bitmap,\n-\t\t\t\t\t     lookup_tree(the_repository, &entry.oid)) < 0)\n+\t\t\t\t\t     lookup_tree(writer->repo, &entry.oid)) < 0)\n \t\t\t\treturn -1;\n \t\t\tbreak;\n \t\tcase OBJ_BLOB:\n@@ -536,7 +536,7 @@ static int fill_bitmap_commit(struct bitmap_writer *writer,\n \t\t\t\treturn -1;\n \t\t\tbitmap_set(ent->bitmap, pos);\n \t\t\tprio_queue_put(tree_queue,\n-\t\t\t\t       repo_get_commit_tree(the_repository, c));\n+\t\t\t\t       repo_get_commit_tree(writer->repo, c));\n \t\t}\n \n \t\tfor (p = c->parents; p; p = p->next) {\n@@ -590,11 +590,11 @@ int bitmap_writer_build(struct bitmap_writer *writer)\n \tint closed = 1; /* until proven otherwise */\n \n \tif (writer->show_progress)\n-\t\twriter->progress = start_progress(the_repository,\n+\t\twriter->progress = start_progress(writer->repo,\n \t\t\t\t\t\t  \"Building bitmaps\",\n \t\t\t\t\t\t  writer->selected_nr);\n \ttrace2_region_enter(\"pack-bitmap-write\", \"building_bitmaps_total\",\n-\t\t\t    the_repository);\n+\t\t\t    writer->repo);\n \n \told_bitmap = prepare_bitmap_git(writer->to_pack->repo);\n \tif (old_bitmap)\n@@ -645,10 +645,10 @@ int bitmap_writer_build(struct bitmap_writer *writer)\n \tfree(mapping);\n \n \ttrace2_region_leave(\"pack-bitmap-write\", \"building_bitmaps_total\",\n-\t\t\t    the_repository);\n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\t\t\t    writer->repo);\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"building_bitmaps_reused\", reused_bitmaps_nr);\n-\ttrace2_data_intmax(\"pack-bitmap-write\", the_repository,\n+\ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n \t\t\t   \"building_bitmaps_pseudo_merge_reused\",\n \t\t\t   reused_pseudo_merge_bitmaps_nr);\n \n@@ -711,7 +711,7 @@ void bitmap_writer_select_commits(struct bitmap_writer *writer,\n \t}\n \n \tif (writer->show_progress)\n-\t\twriter->progress = start_progress(the_repository,\n+\t\twriter->progress = start_progress(writer->repo,\n \t\t\t\t\t\t  \"Selecting bitmap commits\", 0);\n \n \tfor (;;) {\n@@ -960,7 +960,7 @@ static void write_lookup_table(struct bitmap_writer *writer, struct hashfile *f,\n \tfor (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++)\n \t\ttable_inv[table[i]] = i;\n \n-\ttrace2_region_enter(\"pack-bitmap-write\", \"writing_lookup_table\", the_repository);\n+\ttrace2_region_enter(\"pack-bitmap-write\", \"writing_lookup_table\", writer->repo);\n \tfor (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) {\n \t\tstruct bitmapped_commit *selected = &writer->selected[table[i]];\n \t\tuint32_t xor_offset = selected->xor_offset;\n@@ -987,7 +987,7 @@ static void write_lookup_table(struct bitmap_writer *writer, struct hashfile *f,\n \t\thashwrite_be64(f, (uint64_t)offsets[table[i]]);\n \t\thashwrite_be32(f, xor_row);\n \t}\n-\ttrace2_region_leave(\"pack-bitmap-write\", \"writing_lookup_table\", the_repository);\n+\ttrace2_region_leave(\"pack-bitmap-write\", \"writing_lookup_table\", writer->repo);\n \n \tfree(table);\n \tfree(table_inv);\n@@ -1008,7 +1008,7 @@ static void write_hash_cache(struct hashfile *f,\n void bitmap_writer_set_checksum(struct bitmap_writer *writer,\n \t\t\t\tconst unsigned char *sha1)\n {\n-\thashcpy(writer->pack_checksum, sha1, the_repository->hash_algo);\n+\thashcpy(writer->pack_checksum, sha1, writer->repo->hash_algo);\n }\n \n void bitmap_writer_finish(struct bitmap_writer *writer,\n@@ -1030,15 +1030,15 @@ void bitmap_writer_finish(struct bitmap_writer *writer,\n \tif (writer->pseudo_merges_nr)\n \t\toptions |= BITMAP_OPT_PSEUDO_MERGES;\n \n-\tf = hashfd(the_repository->hash_algo, fd, tmp_file.buf);\n+\tf = hashfd(writer->repo->hash_algo, fd, tmp_file.buf);\n \n \tmemcpy(header.magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE));\n \theader.version = htons(default_version);\n \theader.options = htons(flags | options);\n \theader.entry_count = htonl(bitmap_writer_nr_selected_commits(writer));\n-\thashcpy(header.checksum, writer->pack_checksum, the_repository->hash_algo);\n+\thashcpy(header.checksum, writer->pack_checksum, writer->repo->hash_algo);\n \n-\thashwrite(f, &header, sizeof(header) - GIT_MAX_RAWSZ + the_hash_algo->rawsz);\n+\thashwrite(f, &header, sizeof(header) - GIT_MAX_RAWSZ + writer->repo->hash_algo->rawsz);\n \tdump_bitmap(f, writer->commits);\n \tdump_bitmap(f, writer->trees);\n \tdump_bitmap(f, writer->blobs);\n@@ -1072,7 +1072,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,\n \tfinalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,\n \t\t\t  CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE);\n \n-\tif (adjust_shared_perm(the_repository, tmp_file.buf))\n+\tif (adjust_shared_perm(writer->repo, tmp_file.buf))\n \t\tdie_errno(\"unable to make temporary bitmap file readable\");\n \n \tif (rename(tmp_file.buf, filename))\ndiff --git a/pack-bitmap.h b/pack-bitmap.h\nindex d7f4b8b8e95..53cd42772f3 100644\n--- a/pack-bitmap.h\n+++ b/pack-bitmap.h\n@@ -104,6 +104,7 @@ int bitmap_has_oid_in_uninteresting(struct bitmap_index *, const struct object_i\n off_t get_disk_usage_from_bitmap(struct bitmap_index *, struct rev_info *);\n \n struct bitmap_writer {\n+\tstruct repository *repo;\n \tstruct ewah_bitmap *commits;\n \tstruct ewah_bitmap *trees;\n \tstruct ewah_bitmap *blobs;\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513880","messageId":"20250310-b4-pks-objects-without-the-repository-v4-8-f201b8ec57ba@pks.im","threadId":"63046","inReplyTo":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","subject":"[PATCH v4 08/12] object-file-convert: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:13:27Z","receivedAt":"2025-03-10T07:13:38Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"object-file-convert.c\" where we use the\nglobal `the_repository` variable, either explicitly or implicitly by\nusing `the_hash_algo`. All of these callsites are transitively called\nfrom `convert_object_file()`, which indeed has no repo as input.\n\nRefactor the function so that it receives a repository as a parameter\nand pass it through to all internal functions to get rid of the\ndependency. Remove the `USE_THE_REPOSITORY_VARIABLE` define.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/tag.c         |  2 +-\n commit.c              |  2 +-\n object-file-convert.c | 29 ++++++++++++++++-------------\n object-file-convert.h |  3 ++-\n object-file.c         |  7 ++++---\n 5 files changed, 24 insertions(+), 19 deletions(-)\n\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex d3e0943b734..7c173535cb3 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -172,7 +172,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,\n \tif (compat) {\n \t\tconst struct git_hash_algo *algo = the_repository->hash_algo;\n \n-\t\tif (convert_object_file(&compat_buf, algo, compat,\n+\t\tif (convert_object_file(the_repository ,&compat_buf, algo, compat,\n \t\t\t\t\tbuffer->buf, buffer->len, OBJ_TAG, 1))\n \t\t\tgoto out;\n \t\tif (sign_buffer(&compat_buf, &compat_sig, keyid))\ndiff --git a/commit.c b/commit.c\nindex 6efdb03997d..48aeefaad31 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1380,7 +1380,7 @@ static int convert_commit_extra_headers(const struct commit_extra_header *orig,\n \t\tstruct commit_extra_header *new;\n \t\tCALLOC_ARRAY(new, 1);\n \t\tif (!strcmp(orig->key, \"mergetag\")) {\n-\t\t\tif (convert_object_file(&out, algo, compat,\n+\t\t\tif (convert_object_file(the_repository, &out, algo, compat,\n \t\t\t\t\t\torig->value, orig->len,\n \t\t\t\t\t\tOBJ_TAG, 1)) {\n \t\t\t\tfree(new);\ndiff --git a/object-file-convert.c b/object-file-convert.c\nindex eba71955cf7..7ab875afe6c 100644\n--- a/object-file-convert.c\n+++ b/object-file-convert.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -63,7 +62,8 @@ static int decode_tree_entry_raw(struct object_id *oid, const char **path,\n \treturn 0;\n }\n \n-static int convert_tree_object(struct strbuf *out,\n+static int convert_tree_object(struct repository *repo,\n+\t\t\t       struct strbuf *out,\n \t\t\t       const struct git_hash_algo *from,\n \t\t\t       const struct git_hash_algo *to,\n \t\t\t       const char *buffer, size_t size)\n@@ -78,7 +78,7 @@ static int convert_tree_object(struct strbuf *out,\n \t\tif (decode_tree_entry_raw(&entry_oid, &path, &pathlen, from, p,\n \t\t\t\t\t  end - p))\n \t\t\treturn error(_(\"failed to decode tree entry\"));\n-\t\tif (repo_oid_to_algop(the_repository, &entry_oid, to, &mapped_oid))\n+\t\tif (repo_oid_to_algop(repo, &entry_oid, to, &mapped_oid))\n \t\t\treturn error(_(\"failed to map tree entry for %s\"), oid_to_hex(&entry_oid));\n \t\tstrbuf_add(out, p, path - p);\n \t\tstrbuf_add(out, path, pathlen);\n@@ -88,7 +88,8 @@ static int convert_tree_object(struct strbuf *out,\n \treturn 0;\n }\n \n-static int convert_tag_object(struct strbuf *out,\n+static int convert_tag_object(struct repository *repo,\n+\t\t\t      struct strbuf *out,\n \t\t\t      const struct git_hash_algo *from,\n \t\t\t      const struct git_hash_algo *to,\n \t\t\t      const char *buffer, size_t size)\n@@ -105,7 +106,7 @@ static int convert_tag_object(struct strbuf *out,\n \t\treturn error(\"bogus tag object\");\n \tif (parse_oid_hex_algop(buffer + 7, &oid, &p, from) < 0)\n \t\treturn error(\"bad tag object ID\");\n-\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n+\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n \t\treturn error(\"unable to map tree %s in tag object\",\n \t\t\t     oid_to_hex(&oid));\n \tsize -= ((p + 1) - buffer);\n@@ -139,7 +140,8 @@ static int convert_tag_object(struct strbuf *out,\n \treturn 0;\n }\n \n-static int convert_commit_object(struct strbuf *out,\n+static int convert_commit_object(struct repository *repo,\n+\t\t\t\t struct strbuf *out,\n \t\t\t\t const struct git_hash_algo *from,\n \t\t\t\t const struct git_hash_algo *to,\n \t\t\t\t const char *buffer, size_t size)\n@@ -165,7 +167,7 @@ static int convert_commit_object(struct strbuf *out,\n \t\t\t    (p != eol))\n \t\t\t\treturn error(_(\"bad %s in commit\"), \"tree\");\n \n-\t\t\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n+\t\t\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n \t\t\t\treturn error(_(\"unable to map %s %s in commit object\"),\n \t\t\t\t\t     \"tree\", oid_to_hex(&oid));\n \t\t\tstrbuf_addf(out, \"tree %s\\n\", oid_to_hex(&mapped_oid));\n@@ -177,7 +179,7 @@ static int convert_commit_object(struct strbuf *out,\n \t\t\t    (p != eol))\n \t\t\t\treturn error(_(\"bad %s in commit\"), \"parent\");\n \n-\t\t\tif (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))\n+\t\t\tif (repo_oid_to_algop(repo, &oid, to, &mapped_oid))\n \t\t\t\treturn error(_(\"unable to map %s %s in commit object\"),\n \t\t\t\t\t     \"parent\", oid_to_hex(&oid));\n \n@@ -202,7 +204,7 @@ static int convert_commit_object(struct strbuf *out,\n \t\t\t}\n \n \t\t\t/* Compute the new tag object */\n-\t\t\tif (convert_tag_object(&new_tag, from, to, tag.buf, tag.len)) {\n+\t\t\tif (convert_tag_object(repo, &new_tag, from, to, tag.buf, tag.len)) {\n \t\t\t\tstrbuf_release(&tag);\n \t\t\t\tstrbuf_release(&new_tag);\n \t\t\t\treturn -1;\n@@ -241,7 +243,8 @@ static int convert_commit_object(struct strbuf *out,\n \treturn 0;\n }\n \n-int convert_object_file(struct strbuf *outbuf,\n+int convert_object_file(struct repository *repo,\n+\t\t\tstruct strbuf *outbuf,\n \t\t\tconst struct git_hash_algo *from,\n \t\t\tconst struct git_hash_algo *to,\n \t\t\tconst void *buf, size_t len,\n@@ -256,13 +259,13 @@ int convert_object_file(struct strbuf *outbuf,\n \n \tswitch (type) {\n \tcase OBJ_COMMIT:\n-\t\tret = convert_commit_object(outbuf, from, to, buf, len);\n+\t\tret = convert_commit_object(repo, outbuf, from, to, buf, len);\n \t\tbreak;\n \tcase OBJ_TREE:\n-\t\tret = convert_tree_object(outbuf, from, to, buf, len);\n+\t\tret = convert_tree_object(repo, outbuf, from, to, buf, len);\n \t\tbreak;\n \tcase OBJ_TAG:\n-\t\tret = convert_tag_object(outbuf, from, to, buf, len);\n+\t\tret = convert_tag_object(repo, outbuf, from, to, buf, len);\n \t\tbreak;\n \tdefault:\n \t\t/* Not implemented yet, so fail. */\ndiff --git a/object-file-convert.h b/object-file-convert.h\nindex a4f802aa8ee..9b3cc5e533d 100644\n--- a/object-file-convert.h\n+++ b/object-file-convert.h\n@@ -14,7 +14,8 @@ int repo_oid_to_algop(struct repository *repo, const struct object_id *src,\n  * Convert an object file from one hash algorithm to another algorithm.\n  * Return -1 on failure, 0 on success.\n  */\n-int convert_object_file(struct strbuf *outbuf,\n+int convert_object_file(struct repository *repo,\n+\t\t\tstruct strbuf *outbuf,\n \t\t\tconst struct git_hash_algo *from,\n \t\t\tconst struct git_hash_algo *to,\n \t\t\tconst void *buf, size_t len,\ndiff --git a/object-file.c b/object-file.c\nindex b3e0276b2a4..b0e237a2acc 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1793,7 +1793,7 @@ static int oid_object_info_convert(struct repository *r,\n \t\tif (type == -1)\n \t\t\treturn -1;\n \t\tif (type != OBJ_BLOB) {\n-\t\t\tret = convert_object_file(&outbuf,\n+\t\t\tret = convert_object_file(the_repository, &outbuf,\n \t\t\t\t\t\t  the_hash_algo, input_algo,\n \t\t\t\t\t\t  content, size, type, !do_die);\n \t\t\tfree(content);\n@@ -2510,7 +2510,7 @@ int write_object_file_flags(const void *buf, unsigned long len,\n \t\t\thash_object_file(compat, buf, len, type, &compat_oid);\n \t\telse {\n \t\t\tstruct strbuf converted = STRBUF_INIT;\n-\t\t\tconvert_object_file(&converted, algo, compat,\n+\t\t\tconvert_object_file(the_repository, &converted, algo, compat,\n \t\t\t\t\t    buf, len, type, 0);\n \t\t\thash_object_file(compat, converted.buf, converted.len,\n \t\t\t\t\t type, &compat_oid);\n@@ -2550,7 +2550,8 @@ int write_object_file_literally(const void *buf, unsigned long len,\n \t\t\t\t\t &compat_oid);\n \t\telse if (compat_type != -1) {\n \t\t\tstruct strbuf converted = STRBUF_INIT;\n-\t\t\tconvert_object_file(&converted, algo, compat,\n+\t\t\tconvert_object_file(the_repository,\n+\t\t\t\t\t    &converted, algo, compat,\n \t\t\t\t\t    buf, len, compat_type, 0);\n \t\t\thash_object_file(compat, converted.buf, converted.len,\n \t\t\t\t\t compat_type, &compat_oid);\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513881","messageId":"20250310-b4-pks-objects-without-the-repository-v4-9-f201b8ec57ba@pks.im","threadId":"63046","inReplyTo":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","subject":"[PATCH v4 09/12] delta-islands: stop depending on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:13:28Z","receivedAt":"2025-03-10T07:13:39Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are multiple sites in \"delta-islands.c\" where we use the\nglobal `the_repository` variable, either explicitly or implicitly by\nusing `the_hash_algo`.\n\nRefactor the code to stop using `the_repository`. In most cases this is\ntrivial because we already had a repository available in the calling\ncontext, with the only exception being `propagate_island_marks()`. Adapt\nit so that the repository gets passed in via a parameter.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/pack-objects.c |  2 +-\n delta-islands.c        | 14 ++++++--------\n delta-islands.h        |  2 +-\n 3 files changed, 8 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex eefc6c78096..fba5db74656 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -3847,7 +3847,7 @@ static void show_commit(struct commit *commit, void *data UNUSED)\n \t\tindex_commit_for_bitmap(commit);\n \n \tif (use_delta_islands)\n-\t\tpropagate_island_marks(commit);\n+\t\tpropagate_island_marks(the_repository, commit);\n }\n \n static void show_object(struct object *obj, const char *name,\ndiff --git a/delta-islands.c b/delta-islands.c\nindex 3aec43fada3..36c94799d69 100644\n--- a/delta-islands.c\n+++ b/delta-islands.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -267,8 +266,7 @@ void resolve_tree_islands(struct repository *r,\n \tQSORT(todo, nr, tree_depth_compare);\n \n \tif (progress)\n-\t\tprogress_state = start_progress(the_repository,\n-\t\t\t\t\t\t_(\"Propagating island marks\"), nr);\n+\t\tprogress_state = start_progress(r, _(\"Propagating island marks\"), nr);\n \n \tfor (i = 0; i < nr; i++) {\n \t\tstruct object_entry *ent = todo[i].entry;\n@@ -490,9 +488,9 @@ void load_delta_islands(struct repository *r, int progress)\n \n \tisland_marks = kh_init_oid_map();\n \n-\tgit_config(island_config_callback, &ild);\n+\trepo_config(r, island_config_callback, &ild);\n \tild.remote_islands = kh_init_str();\n-\trefs_for_each_ref(get_main_ref_store(the_repository),\n+\trefs_for_each_ref(get_main_ref_store(r),\n \t\t\t  find_island_for_ref, &ild);\n \tfree_config_regexes(&ild);\n \tdeduplicate_islands(ild.remote_islands, r);\n@@ -502,7 +500,7 @@ void load_delta_islands(struct repository *r, int progress)\n \t\tfprintf(stderr, _(\"Marked %d islands, done.\\n\"), island_counter);\n }\n \n-void propagate_island_marks(struct commit *commit)\n+void propagate_island_marks(struct repository *r, struct commit *commit)\n {\n \tkhiter_t pos = kh_get_oid_map(island_marks, commit->object.oid);\n \n@@ -510,8 +508,8 @@ void propagate_island_marks(struct commit *commit)\n \t\tstruct commit_list *p;\n \t\tstruct island_bitmap *root_marks = kh_value(island_marks, pos);\n \n-\t\trepo_parse_commit(the_repository, commit);\n-\t\tset_island_marks(&repo_get_commit_tree(the_repository, commit)->object,\n+\t\trepo_parse_commit(r, commit);\n+\t\tset_island_marks(&repo_get_commit_tree(r, commit)->object,\n \t\t\t\t root_marks);\n \t\tfor (p = commit->parents; p; p = p->next)\n \t\t\tset_island_marks(&p->item->object, root_marks);\ndiff --git a/delta-islands.h b/delta-islands.h\nindex 8d1591ae28b..6107660306b 100644\n--- a/delta-islands.h\n+++ b/delta-islands.h\n@@ -12,7 +12,7 @@ void resolve_tree_islands(struct repository *r,\n \t\t\t  int progress,\n \t\t\t  struct packing_data *to_pack);\n void load_delta_islands(struct repository *r, int progress);\n-void propagate_island_marks(struct commit *commit);\n+void propagate_island_marks(struct repository *r, struct commit *commit);\n int compute_pack_layers(struct packing_data *to_pack);\n void free_island_marks(void);\n \n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513882","messageId":"20250310-b4-pks-objects-without-the-repository-v4-11-f201b8ec57ba@pks.im","threadId":"63046","inReplyTo":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","subject":"[PATCH v4 11/12] hash: fix \"-Wsign-compare\" warnings","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:13:30Z","receivedAt":"2025-03-10T07:13:40Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"There are a couple of trivial \"-Wsign-compare\" warnings in \"hash.c\". Fix\nthem.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n hash.c | 12 ++++--------\n hash.h |  2 +-\n 2 files changed, 5 insertions(+), 9 deletions(-)\n\ndiff --git a/hash.c b/hash.c\nindex dd5ac9d0eb2..4d9f98f72c2 100644\n--- a/hash.c\n+++ b/hash.c\n@@ -1,5 +1,4 @@\n #define USE_THE_REPOSITORY_VARIABLE\n-#define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n #include \"hash.h\"\n@@ -246,10 +245,9 @@ const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\n \n int hash_algo_by_name(const char *name)\n {\n-\tint i;\n \tif (!name)\n \t\treturn GIT_HASH_UNKNOWN;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\tfor (size_t i = 1; i < GIT_HASH_NALGOS; i++)\n \t\tif (!strcmp(name, hash_algos[i].name))\n \t\t\treturn i;\n \treturn GIT_HASH_UNKNOWN;\n@@ -257,17 +255,15 @@ int hash_algo_by_name(const char *name)\n \n int hash_algo_by_id(uint32_t format_id)\n {\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\tfor (size_t i = 1; i < GIT_HASH_NALGOS; i++)\n \t\tif (format_id == hash_algos[i].format_id)\n \t\t\treturn i;\n \treturn GIT_HASH_UNKNOWN;\n }\n \n-int hash_algo_by_length(int len)\n+int hash_algo_by_length(size_t len)\n {\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\tfor (size_t i = 1; i < GIT_HASH_NALGOS; i++)\n \t\tif (len == hash_algos[i].rawsz)\n \t\t\treturn i;\n \treturn GIT_HASH_UNKNOWN;\ndiff --git a/hash.h b/hash.h\nindex 4367acfec50..55d67ed83f3 100644\n--- a/hash.h\n+++ b/hash.h\n@@ -325,7 +325,7 @@ int hash_algo_by_name(const char *name);\n /* Identical, except based on the format ID. */\n int hash_algo_by_id(uint32_t format_id);\n /* Identical, except based on the length. */\n-int hash_algo_by_length(int len);\n+int hash_algo_by_length(size_t len);\n /* Identical, except for a pointer to struct git_hash_algo. */\n static inline int hash_algo_by_ptr(const struct git_hash_algo *p)\n {\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513883","messageId":"20250310-b4-pks-objects-without-the-repository-v4-10-f201b8ec57ba@pks.im","threadId":"63046","inReplyTo":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","subject":"[PATCH v4 10/12] object-file: split out logic regarding hash algorithms","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:13:29Z","receivedAt":"2025-03-10T07:13:40Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"While we have a \"hash.h\" header, the actual implementation of the\nsubsystem is hosted by \"object-file.c\". This makes it harder than\nnecessary to find the actual implementation of the hash subsystem and\nintermingles the different concerns with one another.\n\nSplit out the implementation of hash algorithms into a new, separate\n\"hash.c\" file.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile      |   1 +\n hash.c        | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n meson.build   |   1 +\n object-file.c | 277 --------------------------------------------------------\n 4 files changed, 285 insertions(+), 277 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 6d45093089d..6dfe88322dd 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1041,6 +1041,7 @@ LIB_OBJS += gpg-interface.o\n LIB_OBJS += graph.o\n LIB_OBJS += grep.o\n LIB_OBJS += hash-lookup.o\n+LIB_OBJS += hash.o\n LIB_OBJS += hashmap.o\n LIB_OBJS += help.o\n LIB_OBJS += hex.o\ndiff --git a/hash.c b/hash.c\nnew file mode 100644\nindex 00000000000..dd5ac9d0eb2\n--- /dev/null\n+++ b/hash.c\n@@ -0,0 +1,283 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+#define DISABLE_SIGN_COMPARE_WARNINGS\n+\n+#include \"git-compat-util.h\"\n+#include \"hash.h\"\n+#include \"hex.h\"\n+\n+static const struct object_id empty_tree_oid = {\n+\t.hash = {\n+\t\t0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,\n+\t\t0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04\n+\t},\n+\t.algo = GIT_HASH_SHA1,\n+};\n+static const struct object_id empty_blob_oid = {\n+\t.hash = {\n+\t\t0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,\n+\t\t0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91\n+\t},\n+\t.algo = GIT_HASH_SHA1,\n+};\n+static const struct object_id null_oid_sha1 = {\n+\t.hash = {0},\n+\t.algo = GIT_HASH_SHA1,\n+};\n+static const struct object_id empty_tree_oid_sha256 = {\n+\t.hash = {\n+\t\t0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1,\n+\t\t0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5,\n+\t\t0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc,\n+\t\t0x53, 0x21\n+\t},\n+\t.algo = GIT_HASH_SHA256,\n+};\n+static const struct object_id empty_blob_oid_sha256 = {\n+\t.hash = {\n+\t\t0x47, 0x3a, 0x0f, 0x4c, 0x3b, 0xe8, 0xa9, 0x36, 0x81, 0xa2,\n+\t\t0x67, 0xe3, 0xb1, 0xe9, 0xa7, 0xdc, 0xda, 0x11, 0x85, 0x43,\n+\t\t0x6f, 0xe1, 0x41, 0xf7, 0x74, 0x91, 0x20, 0xa3, 0x03, 0x72,\n+\t\t0x18, 0x13\n+\t},\n+\t.algo = GIT_HASH_SHA256,\n+};\n+static const struct object_id null_oid_sha256 = {\n+\t.hash = {0},\n+\t.algo = GIT_HASH_SHA256,\n+};\n+\n+static void git_hash_sha1_init(struct git_hash_ctx *ctx)\n+{\n+\tctx->algop = &hash_algos[GIT_HASH_SHA1];\n+\tgit_SHA1_Init(&ctx->state.sha1);\n+}\n+\n+static void git_hash_sha1_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n+{\n+\tdst->algop = src->algop;\n+\tgit_SHA1_Clone(&dst->state.sha1, &src->state.sha1);\n+}\n+\n+static void git_hash_sha1_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n+{\n+\tgit_SHA1_Update(&ctx->state.sha1, data, len);\n+}\n+\n+static void git_hash_sha1_final(unsigned char *hash, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final(hash, &ctx->state.sha1);\n+}\n+\n+static void git_hash_sha1_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final(oid->hash, &ctx->state.sha1);\n+\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n+\toid->algo = GIT_HASH_SHA1;\n+}\n+\n+static void git_hash_sha1_init_unsafe(struct git_hash_ctx *ctx)\n+{\n+\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA1]);\n+\tgit_SHA1_Init_unsafe(&ctx->state.sha1_unsafe);\n+}\n+\n+static void git_hash_sha1_clone_unsafe(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n+{\n+\tdst->algop = src->algop;\n+\tgit_SHA1_Clone_unsafe(&dst->state.sha1_unsafe, &src->state.sha1_unsafe);\n+}\n+\n+static void git_hash_sha1_update_unsafe(struct git_hash_ctx *ctx, const void *data,\n+\t\t\t\t      size_t len)\n+{\n+\tgit_SHA1_Update_unsafe(&ctx->state.sha1_unsafe, data, len);\n+}\n+\n+static void git_hash_sha1_final_unsafe(unsigned char *hash, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final_unsafe(hash, &ctx->state.sha1_unsafe);\n+}\n+\n+static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA1_Final_unsafe(oid->hash, &ctx->state.sha1_unsafe);\n+\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n+\toid->algo = GIT_HASH_SHA1;\n+}\n+\n+static void git_hash_sha256_init(struct git_hash_ctx *ctx)\n+{\n+\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA256]);\n+\tgit_SHA256_Init(&ctx->state.sha256);\n+}\n+\n+static void git_hash_sha256_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n+{\n+\tdst->algop = src->algop;\n+\tgit_SHA256_Clone(&dst->state.sha256, &src->state.sha256);\n+}\n+\n+static void git_hash_sha256_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n+{\n+\tgit_SHA256_Update(&ctx->state.sha256, data, len);\n+}\n+\n+static void git_hash_sha256_final(unsigned char *hash, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA256_Final(hash, &ctx->state.sha256);\n+}\n+\n+static void git_hash_sha256_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n+{\n+\tgit_SHA256_Final(oid->hash, &ctx->state.sha256);\n+\t/*\n+\t * This currently does nothing, so the compiler should optimize it out,\n+\t * but keep it in case we extend the hash size again.\n+\t */\n+\tmemset(oid->hash + GIT_SHA256_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA256_RAWSZ);\n+\toid->algo = GIT_HASH_SHA256;\n+}\n+\n+static void git_hash_unknown_init(struct git_hash_ctx *ctx UNUSED)\n+{\n+\tBUG(\"trying to init unknown hash\");\n+}\n+\n+static void git_hash_unknown_clone(struct git_hash_ctx *dst UNUSED,\n+\t\t\t\t   const struct git_hash_ctx *src UNUSED)\n+{\n+\tBUG(\"trying to clone unknown hash\");\n+}\n+\n+static void git_hash_unknown_update(struct git_hash_ctx *ctx UNUSED,\n+\t\t\t\t    const void *data UNUSED,\n+\t\t\t\t    size_t len UNUSED)\n+{\n+\tBUG(\"trying to update unknown hash\");\n+}\n+\n+static void git_hash_unknown_final(unsigned char *hash UNUSED,\n+\t\t\t\t   struct git_hash_ctx *ctx UNUSED)\n+{\n+\tBUG(\"trying to finalize unknown hash\");\n+}\n+\n+static void git_hash_unknown_final_oid(struct object_id *oid UNUSED,\n+\t\t\t\t       struct git_hash_ctx *ctx UNUSED)\n+{\n+\tBUG(\"trying to finalize unknown hash\");\n+}\n+\n+static const struct git_hash_algo sha1_unsafe_algo = {\n+\t.name = \"sha1\",\n+\t.format_id = GIT_SHA1_FORMAT_ID,\n+\t.rawsz = GIT_SHA1_RAWSZ,\n+\t.hexsz = GIT_SHA1_HEXSZ,\n+\t.blksz = GIT_SHA1_BLKSZ,\n+\t.init_fn = git_hash_sha1_init_unsafe,\n+\t.clone_fn = git_hash_sha1_clone_unsafe,\n+\t.update_fn = git_hash_sha1_update_unsafe,\n+\t.final_fn = git_hash_sha1_final_unsafe,\n+\t.final_oid_fn = git_hash_sha1_final_oid_unsafe,\n+\t.empty_tree = &empty_tree_oid,\n+\t.empty_blob = &empty_blob_oid,\n+\t.null_oid = &null_oid_sha1,\n+};\n+\n+const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n+\t{\n+\t\t.name = NULL,\n+\t\t.format_id = 0x00000000,\n+\t\t.rawsz = 0,\n+\t\t.hexsz = 0,\n+\t\t.blksz = 0,\n+\t\t.init_fn = git_hash_unknown_init,\n+\t\t.clone_fn = git_hash_unknown_clone,\n+\t\t.update_fn = git_hash_unknown_update,\n+\t\t.final_fn = git_hash_unknown_final,\n+\t\t.final_oid_fn = git_hash_unknown_final_oid,\n+\t\t.empty_tree = NULL,\n+\t\t.empty_blob = NULL,\n+\t\t.null_oid = NULL,\n+\t},\n+\t{\n+\t\t.name = \"sha1\",\n+\t\t.format_id = GIT_SHA1_FORMAT_ID,\n+\t\t.rawsz = GIT_SHA1_RAWSZ,\n+\t\t.hexsz = GIT_SHA1_HEXSZ,\n+\t\t.blksz = GIT_SHA1_BLKSZ,\n+\t\t.init_fn = git_hash_sha1_init,\n+\t\t.clone_fn = git_hash_sha1_clone,\n+\t\t.update_fn = git_hash_sha1_update,\n+\t\t.final_fn = git_hash_sha1_final,\n+\t\t.final_oid_fn = git_hash_sha1_final_oid,\n+\t\t.unsafe = &sha1_unsafe_algo,\n+\t\t.empty_tree = &empty_tree_oid,\n+\t\t.empty_blob = &empty_blob_oid,\n+\t\t.null_oid = &null_oid_sha1,\n+\t},\n+\t{\n+\t\t.name = \"sha256\",\n+\t\t.format_id = GIT_SHA256_FORMAT_ID,\n+\t\t.rawsz = GIT_SHA256_RAWSZ,\n+\t\t.hexsz = GIT_SHA256_HEXSZ,\n+\t\t.blksz = GIT_SHA256_BLKSZ,\n+\t\t.init_fn = git_hash_sha256_init,\n+\t\t.clone_fn = git_hash_sha256_clone,\n+\t\t.update_fn = git_hash_sha256_update,\n+\t\t.final_fn = git_hash_sha256_final,\n+\t\t.final_oid_fn = git_hash_sha256_final_oid,\n+\t\t.empty_tree = &empty_tree_oid_sha256,\n+\t\t.empty_blob = &empty_blob_oid_sha256,\n+\t\t.null_oid = &null_oid_sha256,\n+\t}\n+};\n+\n+const struct object_id *null_oid(void)\n+{\n+\treturn the_hash_algo->null_oid;\n+}\n+\n+const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\n+{\n+\tstatic char buf[GIT_MAX_HEXSZ + 1];\n+\treturn oid_to_hex_r(buf, algop->empty_tree);\n+}\n+\n+int hash_algo_by_name(const char *name)\n+{\n+\tint i;\n+\tif (!name)\n+\t\treturn GIT_HASH_UNKNOWN;\n+\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\t\tif (!strcmp(name, hash_algos[i].name))\n+\t\t\treturn i;\n+\treturn GIT_HASH_UNKNOWN;\n+}\n+\n+int hash_algo_by_id(uint32_t format_id)\n+{\n+\tint i;\n+\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\t\tif (format_id == hash_algos[i].format_id)\n+\t\t\treturn i;\n+\treturn GIT_HASH_UNKNOWN;\n+}\n+\n+int hash_algo_by_length(int len)\n+{\n+\tint i;\n+\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n+\t\tif (len == hash_algos[i].rawsz)\n+\t\t\treturn i;\n+\treturn GIT_HASH_UNKNOWN;\n+}\n+\n+const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop)\n+{\n+\t/* If we have a faster \"unsafe\" implementation, use that. */\n+\tif (algop->unsafe)\n+\t\treturn algop->unsafe;\n+\t/* Otherwise use the default one. */\n+\treturn algop;\n+}\ndiff --git a/meson.build b/meson.build\nindex 021a182135f..38568344953 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -311,6 +311,7 @@ libgit_sources = [\n   'graph.c',\n   'grep.c',\n   'hash-lookup.c',\n+  'hash.c',\n   'hashmap.c',\n   'help.c',\n   'hex.c',\ndiff --git a/object-file.c b/object-file.c\nindex b0e237a2acc..de603e2ca8c 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -45,283 +45,6 @@\n /* The maximum size for an object header. */\n #define MAX_HEADER_LEN 32\n \n-static const struct object_id empty_tree_oid = {\n-\t.hash = {\n-\t\t0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,\n-\t\t0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04\n-\t},\n-\t.algo = GIT_HASH_SHA1,\n-};\n-static const struct object_id empty_blob_oid = {\n-\t.hash = {\n-\t\t0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,\n-\t\t0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91\n-\t},\n-\t.algo = GIT_HASH_SHA1,\n-};\n-static const struct object_id null_oid_sha1 = {\n-\t.hash = {0},\n-\t.algo = GIT_HASH_SHA1,\n-};\n-static const struct object_id empty_tree_oid_sha256 = {\n-\t.hash = {\n-\t\t0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1,\n-\t\t0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5,\n-\t\t0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc,\n-\t\t0x53, 0x21\n-\t},\n-\t.algo = GIT_HASH_SHA256,\n-};\n-static const struct object_id empty_blob_oid_sha256 = {\n-\t.hash = {\n-\t\t0x47, 0x3a, 0x0f, 0x4c, 0x3b, 0xe8, 0xa9, 0x36, 0x81, 0xa2,\n-\t\t0x67, 0xe3, 0xb1, 0xe9, 0xa7, 0xdc, 0xda, 0x11, 0x85, 0x43,\n-\t\t0x6f, 0xe1, 0x41, 0xf7, 0x74, 0x91, 0x20, 0xa3, 0x03, 0x72,\n-\t\t0x18, 0x13\n-\t},\n-\t.algo = GIT_HASH_SHA256,\n-};\n-static const struct object_id null_oid_sha256 = {\n-\t.hash = {0},\n-\t.algo = GIT_HASH_SHA256,\n-};\n-\n-static void git_hash_sha1_init(struct git_hash_ctx *ctx)\n-{\n-\tctx->algop = &hash_algos[GIT_HASH_SHA1];\n-\tgit_SHA1_Init(&ctx->state.sha1);\n-}\n-\n-static void git_hash_sha1_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n-{\n-\tdst->algop = src->algop;\n-\tgit_SHA1_Clone(&dst->state.sha1, &src->state.sha1);\n-}\n-\n-static void git_hash_sha1_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n-{\n-\tgit_SHA1_Update(&ctx->state.sha1, data, len);\n-}\n-\n-static void git_hash_sha1_final(unsigned char *hash, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final(hash, &ctx->state.sha1);\n-}\n-\n-static void git_hash_sha1_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final(oid->hash, &ctx->state.sha1);\n-\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n-\toid->algo = GIT_HASH_SHA1;\n-}\n-\n-static void git_hash_sha1_init_unsafe(struct git_hash_ctx *ctx)\n-{\n-\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA1]);\n-\tgit_SHA1_Init_unsafe(&ctx->state.sha1_unsafe);\n-}\n-\n-static void git_hash_sha1_clone_unsafe(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n-{\n-\tdst->algop = src->algop;\n-\tgit_SHA1_Clone_unsafe(&dst->state.sha1_unsafe, &src->state.sha1_unsafe);\n-}\n-\n-static void git_hash_sha1_update_unsafe(struct git_hash_ctx *ctx, const void *data,\n-\t\t\t\t      size_t len)\n-{\n-\tgit_SHA1_Update_unsafe(&ctx->state.sha1_unsafe, data, len);\n-}\n-\n-static void git_hash_sha1_final_unsafe(unsigned char *hash, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final_unsafe(hash, &ctx->state.sha1_unsafe);\n-}\n-\n-static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA1_Final_unsafe(oid->hash, &ctx->state.sha1_unsafe);\n-\tmemset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);\n-\toid->algo = GIT_HASH_SHA1;\n-}\n-\n-static void git_hash_sha256_init(struct git_hash_ctx *ctx)\n-{\n-\tctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA256]);\n-\tgit_SHA256_Init(&ctx->state.sha256);\n-}\n-\n-static void git_hash_sha256_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)\n-{\n-\tdst->algop = src->algop;\n-\tgit_SHA256_Clone(&dst->state.sha256, &src->state.sha256);\n-}\n-\n-static void git_hash_sha256_update(struct git_hash_ctx *ctx, const void *data, size_t len)\n-{\n-\tgit_SHA256_Update(&ctx->state.sha256, data, len);\n-}\n-\n-static void git_hash_sha256_final(unsigned char *hash, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA256_Final(hash, &ctx->state.sha256);\n-}\n-\n-static void git_hash_sha256_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)\n-{\n-\tgit_SHA256_Final(oid->hash, &ctx->state.sha256);\n-\t/*\n-\t * This currently does nothing, so the compiler should optimize it out,\n-\t * but keep it in case we extend the hash size again.\n-\t */\n-\tmemset(oid->hash + GIT_SHA256_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA256_RAWSZ);\n-\toid->algo = GIT_HASH_SHA256;\n-}\n-\n-static void git_hash_unknown_init(struct git_hash_ctx *ctx UNUSED)\n-{\n-\tBUG(\"trying to init unknown hash\");\n-}\n-\n-static void git_hash_unknown_clone(struct git_hash_ctx *dst UNUSED,\n-\t\t\t\t   const struct git_hash_ctx *src UNUSED)\n-{\n-\tBUG(\"trying to clone unknown hash\");\n-}\n-\n-static void git_hash_unknown_update(struct git_hash_ctx *ctx UNUSED,\n-\t\t\t\t    const void *data UNUSED,\n-\t\t\t\t    size_t len UNUSED)\n-{\n-\tBUG(\"trying to update unknown hash\");\n-}\n-\n-static void git_hash_unknown_final(unsigned char *hash UNUSED,\n-\t\t\t\t   struct git_hash_ctx *ctx UNUSED)\n-{\n-\tBUG(\"trying to finalize unknown hash\");\n-}\n-\n-static void git_hash_unknown_final_oid(struct object_id *oid UNUSED,\n-\t\t\t\t       struct git_hash_ctx *ctx UNUSED)\n-{\n-\tBUG(\"trying to finalize unknown hash\");\n-}\n-\n-static const struct git_hash_algo sha1_unsafe_algo = {\n-\t.name = \"sha1\",\n-\t.format_id = GIT_SHA1_FORMAT_ID,\n-\t.rawsz = GIT_SHA1_RAWSZ,\n-\t.hexsz = GIT_SHA1_HEXSZ,\n-\t.blksz = GIT_SHA1_BLKSZ,\n-\t.init_fn = git_hash_sha1_init_unsafe,\n-\t.clone_fn = git_hash_sha1_clone_unsafe,\n-\t.update_fn = git_hash_sha1_update_unsafe,\n-\t.final_fn = git_hash_sha1_final_unsafe,\n-\t.final_oid_fn = git_hash_sha1_final_oid_unsafe,\n-\t.empty_tree = &empty_tree_oid,\n-\t.empty_blob = &empty_blob_oid,\n-\t.null_oid = &null_oid_sha1,\n-};\n-\n-const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n-\t{\n-\t\t.name = NULL,\n-\t\t.format_id = 0x00000000,\n-\t\t.rawsz = 0,\n-\t\t.hexsz = 0,\n-\t\t.blksz = 0,\n-\t\t.init_fn = git_hash_unknown_init,\n-\t\t.clone_fn = git_hash_unknown_clone,\n-\t\t.update_fn = git_hash_unknown_update,\n-\t\t.final_fn = git_hash_unknown_final,\n-\t\t.final_oid_fn = git_hash_unknown_final_oid,\n-\t\t.empty_tree = NULL,\n-\t\t.empty_blob = NULL,\n-\t\t.null_oid = NULL,\n-\t},\n-\t{\n-\t\t.name = \"sha1\",\n-\t\t.format_id = GIT_SHA1_FORMAT_ID,\n-\t\t.rawsz = GIT_SHA1_RAWSZ,\n-\t\t.hexsz = GIT_SHA1_HEXSZ,\n-\t\t.blksz = GIT_SHA1_BLKSZ,\n-\t\t.init_fn = git_hash_sha1_init,\n-\t\t.clone_fn = git_hash_sha1_clone,\n-\t\t.update_fn = git_hash_sha1_update,\n-\t\t.final_fn = git_hash_sha1_final,\n-\t\t.final_oid_fn = git_hash_sha1_final_oid,\n-\t\t.unsafe = &sha1_unsafe_algo,\n-\t\t.empty_tree = &empty_tree_oid,\n-\t\t.empty_blob = &empty_blob_oid,\n-\t\t.null_oid = &null_oid_sha1,\n-\t},\n-\t{\n-\t\t.name = \"sha256\",\n-\t\t.format_id = GIT_SHA256_FORMAT_ID,\n-\t\t.rawsz = GIT_SHA256_RAWSZ,\n-\t\t.hexsz = GIT_SHA256_HEXSZ,\n-\t\t.blksz = GIT_SHA256_BLKSZ,\n-\t\t.init_fn = git_hash_sha256_init,\n-\t\t.clone_fn = git_hash_sha256_clone,\n-\t\t.update_fn = git_hash_sha256_update,\n-\t\t.final_fn = git_hash_sha256_final,\n-\t\t.final_oid_fn = git_hash_sha256_final_oid,\n-\t\t.empty_tree = &empty_tree_oid_sha256,\n-\t\t.empty_blob = &empty_blob_oid_sha256,\n-\t\t.null_oid = &null_oid_sha256,\n-\t}\n-};\n-\n-const struct object_id *null_oid(void)\n-{\n-\treturn the_hash_algo->null_oid;\n-}\n-\n-const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\n-{\n-\tstatic char buf[GIT_MAX_HEXSZ + 1];\n-\treturn oid_to_hex_r(buf, algop->empty_tree);\n-}\n-\n-int hash_algo_by_name(const char *name)\n-{\n-\tint i;\n-\tif (!name)\n-\t\treturn GIT_HASH_UNKNOWN;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n-\t\tif (!strcmp(name, hash_algos[i].name))\n-\t\t\treturn i;\n-\treturn GIT_HASH_UNKNOWN;\n-}\n-\n-int hash_algo_by_id(uint32_t format_id)\n-{\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n-\t\tif (format_id == hash_algos[i].format_id)\n-\t\t\treturn i;\n-\treturn GIT_HASH_UNKNOWN;\n-}\n-\n-int hash_algo_by_length(int len)\n-{\n-\tint i;\n-\tfor (i = 1; i < GIT_HASH_NALGOS; i++)\n-\t\tif (len == hash_algos[i].rawsz)\n-\t\t\treturn i;\n-\treturn GIT_HASH_UNKNOWN;\n-}\n-\n-const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop)\n-{\n-\t/* If we have a faster \"unsafe\" implementation, use that. */\n-\tif (algop->unsafe)\n-\t\treturn algop->unsafe;\n-\t/* Otherwise use the default one. */\n-\treturn algop;\n-}\n-\n /*\n  * This is meant to hold a *small* number of objects that you would\n  * want repo_read_object_file() to be able to return, but yet you do not want\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513884","messageId":"20250310-b4-pks-objects-without-the-repository-v4-12-f201b8ec57ba@pks.im","threadId":"63046","inReplyTo":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","subject":"[PATCH v4 12/12] hash: stop depending on `the_repository` in `null_oid()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-03-10T07:13:31Z","receivedAt":"2025-03-10T07:13:41Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `null_oid()` function returns the object ID that only consists of\nzeroes. Naturally, this ID also depends on the hash algorithm used, as\nthe number of zeroes is different between SHA1 and SHA256. Consequently,\nthe function returns the hash-algorithm-specific null object ID.\n\nThis is currently done by depending on `the_hash_algo`, which implicitly\nmakes us depend on `the_repository`. Refactor the function to instead\npass in the hash algorithm for which we want to retrieve the null object\nID. Adapt callsites accordingly by passing in `the_repository`, thus\nbubbling up the dependency on that global variable by one layer.\n\nThere are a couple of trivial exceptions for subsystems that already got\nrid of `the_repository`. These subsystems instead use the repository\nthat is available via the calling context:\n\n  - \"builtin/grep.c\"\n  - \"grep.c\"\n  - \"refs/debug.c\"\n\nThere are also two non-trivial exceptions:\n\n  - \"diff-no-index.c\": Here we know that we may not have a repository\n    initialized at all, so we cannot rely on `the_repository`. Instead,\n    we adapt `diff_no_index()` to get a `struct git_hash_algo` as\n    parameter. The only caller is located in \"builtin/diff.c\", where we\n    know to call `repo_set_hash_algo()` in case we're running outside of\n    a Git repository. Consequently, it is fine to continue passing\n    `the_repository->hash_algo` even in this case.\n\n  - \"builtin/ls-files.c\": There is an in-flight patch series that drops\n    `USE_THE_REPOSITORY_VARIABLE` in this file, which causes a semantic\n    conflict because we use `null_oid()` in `show_submodule()`. The\n    value is passed to `repo_submodule_init()`, which may use the object\n    ID to resolve a tree-ish in the superproject from which we want to\n    read the submodule config. As such, the object ID should refer to an\n    object in the superproject, and consequently we need to use its hash\n    algorithm.\n\n    This means that we could in theory just not bother about this edge\n    case at all and just use `the_repository` in \"diff-no-index.c\". But\n    doing so would feel misdesigned.\n\nRemove the `USE_THE_REPOSITORY_VARIABLE` preprocessor define in\n\"hash.c\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n archive.c                                    |  2 +-\n blame.c                                      |  2 +-\n branch.c                                     |  2 +-\n builtin/checkout.c                           |  6 ++---\n builtin/clone.c                              |  2 +-\n builtin/describe.c                           |  2 +-\n builtin/diff.c                               |  5 ++--\n builtin/fast-export.c                        | 10 ++++----\n builtin/fsck.c                               |  2 +-\n builtin/grep.c                               |  2 +-\n builtin/ls-files.c                           |  3 ++-\n builtin/rebase.c                             |  2 +-\n builtin/receive-pack.c                       |  2 +-\n builtin/submodule--helper.c                  | 36 ++++++++++++++--------------\n builtin/unpack-objects.c                     |  2 +-\n builtin/update-ref.c                         |  2 +-\n builtin/worktree.c                           |  2 +-\n combine-diff.c                               |  2 +-\n diff-lib.c                                   | 10 ++++----\n diff-no-index.c                              | 28 +++++++++++-----------\n diff.c                                       |  8 +++----\n diff.h                                       |  2 +-\n dir.c                                        |  2 +-\n grep.c                                       |  2 +-\n hash.c                                       |  6 ++---\n hash.h                                       |  2 +-\n log-tree.c                                   |  2 +-\n merge-ort.c                                  | 26 ++++++++++----------\n merge-recursive.c                            | 12 +++++-----\n notes-merge.c                                |  2 +-\n notes.c                                      |  2 +-\n object-file.c                                |  2 +-\n parse-options-cb.c                           |  2 +-\n range-diff.c                                 |  2 +-\n read-cache.c                                 |  2 +-\n refs.c                                       | 12 +++++-----\n refs/debug.c                                 |  2 +-\n refs/files-backend.c                         |  2 +-\n reset.c                                      |  2 +-\n sequencer.c                                  | 10 ++++----\n submodule-config.c                           |  2 +-\n submodule.c                                  | 28 +++++++++++-----------\n t/helper/test-ref-store.c                    |  2 +-\n t/helper/test-submodule-nested-repo-config.c |  2 +-\n tree-diff.c                                  |  4 ++--\n upload-pack.c                                |  2 +-\n wt-status.c                                  |  4 ++--\n xdiff-interface.c                            |  2 +-\n 48 files changed, 136 insertions(+), 136 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex f4331aeb49e..c95e3981524 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -312,7 +312,7 @@ int write_archive_entries(struct archiver_args *args,\n \tstruct object_id fake_oid;\n \tint i;\n \n-\toidcpy(&fake_oid, null_oid());\n+\toidcpy(&fake_oid, null_oid(the_hash_algo));\n \n \tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n \t\tsize_t len = args->baselen;\ndiff --git a/blame.c b/blame.c\nindex a15ddf93335..703dab43e78 100644\n--- a/blame.c\n+++ b/blame.c\n@@ -255,7 +255,7 @@ static struct commit *fake_working_tree_commit(struct repository *r,\n \t\tswitch (st.st_mode & S_IFMT) {\n \t\tcase S_IFREG:\n \t\t\tif (opt->flags.allow_textconv &&\n-\t\t\t    textconv_object(r, read_from, mode, null_oid(), 0, &buf_ptr, &buf_len))\n+\t\t\t    textconv_object(r, read_from, mode, null_oid(the_hash_algo), 0, &buf_ptr, &buf_len))\n \t\t\t\tstrbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1);\n \t\t\telse if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)\n \t\t\t\tdie_errno(\"cannot open or read '%s'\", read_from);\ndiff --git a/branch.c b/branch.c\nindex 91297d55ac9..6d01d7d6bdb 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -633,7 +633,7 @@ void create_branch(struct repository *r,\n \t\t\t\t\t\t  0, &err);\n \tif (!transaction ||\n \t\tref_transaction_update(transaction, ref.buf,\n-\t\t\t\t\t&oid, forcing ? NULL : null_oid(),\n+\t\t\t\t\t&oid, forcing ? NULL : null_oid(the_hash_algo),\n \t\t\t\t\tNULL, NULL, flags, msg, &err) ||\n \t\tref_transaction_commit(transaction, &err))\n \t\tdie(\"%s\", err.buf);\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 01ea9ff8b28..2e7486cf658 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -130,8 +130,8 @@ static int post_checkout_hook(struct commit *old_commit, struct commit *new_comm\n \t\t\t      int changed)\n {\n \treturn run_hooks_l(the_repository, \"post-checkout\",\n-\t\t\t   oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()),\n-\t\t\t   oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()),\n+\t\t\t   oid_to_hex(old_commit ? &old_commit->object.oid : null_oid(the_hash_algo)),\n+\t\t\t   oid_to_hex(new_commit ? &new_commit->object.oid : null_oid(the_hash_algo)),\n \t\t\t   changed ? \"1\" : \"0\", NULL);\n \t/* \"new_commit\" can be NULL when checking out from the index before\n \t   a commit exists. */\n@@ -710,7 +710,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,\n \topts.src_index = the_repository->index;\n \topts.dst_index = the_repository->index;\n \tinit_checkout_metadata(&opts.meta, info->refname,\n-\t\t\t       info->commit ? &info->commit->object.oid : null_oid(),\n+\t\t\t       info->commit ? &info->commit->object.oid : null_oid(the_hash_algo),\n \t\t\t       NULL);\n \tif (parse_tree(tree) < 0)\n \t\treturn 128;\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex f14229abf45..36aba65e06c 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -690,7 +690,7 @@ static int checkout(int submodule_progress, int filter_submodules,\n \tif (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))\n \t\tdie(_(\"unable to write new index file\"));\n \n-\terr |= run_hooks_l(the_repository, \"post-checkout\", oid_to_hex(null_oid()),\n+\terr |= run_hooks_l(the_repository, \"post-checkout\", oid_to_hex(null_oid(the_hash_algo)),\n \t\t\t   oid_to_hex(&oid), \"1\", NULL);\n \n \tif (!err && (option_recurse_submodules.nr > 0)) {\ndiff --git a/builtin/describe.c b/builtin/describe.c\nindex e2e73f3d757..23df333fd04 100644\n--- a/builtin/describe.c\n+++ b/builtin/describe.c\n@@ -518,7 +518,7 @@ static void describe_blob(struct object_id oid, struct strbuf *dst)\n {\n \tstruct rev_info revs;\n \tstruct strvec args = STRVEC_INIT;\n-\tstruct process_commit_data pcd = { *null_oid(), oid, dst, &revs};\n+\tstruct process_commit_data pcd = { *null_oid(the_hash_algo), oid, dst, &revs};\n \n \tstrvec_pushl(&args, \"internal: The first arg is not parsed\",\n \t\t     \"--objects\", \"--in-commit-order\", \"--reverse\", \"HEAD\",\ndiff --git a/builtin/diff.c b/builtin/diff.c\nindex a4fffee42c6..fa963808c31 100644\n--- a/builtin/diff.c\n+++ b/builtin/diff.c\n@@ -104,7 +104,7 @@ static void builtin_diff_b_f(struct rev_info *revs,\n \n \tstuff_change(&revs->diffopt,\n \t\t     blob[0]->mode, canon_mode(st.st_mode),\n-\t\t     &blob[0]->item->oid, null_oid(),\n+\t\t     &blob[0]->item->oid, null_oid(the_hash_algo),\n \t\t     1, 0,\n \t\t     blob[0]->path ? blob[0]->path : path,\n \t\t     path);\n@@ -498,7 +498,8 @@ int cmd_diff(int argc,\n \n \t/* If this is a no-index diff, just run it and exit there. */\n \tif (no_index)\n-\t\texit(diff_no_index(&rev, no_index == DIFF_NO_INDEX_IMPLICIT,\n+\t\texit(diff_no_index(&rev, the_repository->hash_algo,\n+\t\t\t\t   no_index == DIFF_NO_INDEX_IMPLICIT,\n \t\t\t\t   argc, argv));\n \n \ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex a5c82eef1de..7a5c2925cd2 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -869,7 +869,7 @@ static void handle_tag(const char *name, struct tag *tag)\n \t\t\t\tp = rewrite_commit((struct commit *)tagged);\n \t\t\t\tif (!p) {\n \t\t\t\t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\t\t       name, oid_to_hex(null_oid()));\n+\t\t\t\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t\t\t\t\tfree(buf);\n \t\t\t\t\treturn;\n \t\t\t\t}\n@@ -883,7 +883,7 @@ static void handle_tag(const char *name, struct tag *tag)\n \n \tif (tagged->type == OBJ_TAG) {\n \t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t       name, oid_to_hex(null_oid()));\n+\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t}\n \tskip_prefix(name, \"refs/tags/\", &name);\n \tprintf(\"tag %s\\n\", name);\n@@ -1023,7 +1023,7 @@ static void handle_tags_and_duplicates(struct string_list *extras)\n \t\t\t\t * it.\n \t\t\t\t */\n \t\t\t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\t       name, oid_to_hex(null_oid()));\n+\t\t\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t\t\t\tcontinue;\n \t\t\t}\n \n@@ -1042,7 +1042,7 @@ static void handle_tags_and_duplicates(struct string_list *extras)\n \t\t\t\tif (!reference_excluded_commits) {\n \t\t\t\t\t/* delete the ref */\n \t\t\t\t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\t\t       name, oid_to_hex(null_oid()));\n+\t\t\t\t\t       name, oid_to_hex(null_oid(the_hash_algo)));\n \t\t\t\t\tcontinue;\n \t\t\t\t}\n \t\t\t\t/* set ref to commit using oid, not mark */\n@@ -1153,7 +1153,7 @@ static void handle_deletes(void)\n \t\t\tcontinue;\n \n \t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n-\t\t\t\trefspec->dst, oid_to_hex(null_oid()));\n+\t\t\t\trefspec->dst, oid_to_hex(null_oid(the_hash_algo)));\n \t}\n }\n \ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex 62c7494bbda..f86ecd8eaa5 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -625,7 +625,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)\n \tvoid *contents = NULL;\n \tint eaten;\n \tstruct object_info oi = OBJECT_INFO_INIT;\n-\tstruct object_id real_oid = *null_oid();\n+\tstruct object_id real_oid = *null_oid(the_hash_algo);\n \tint err = 0;\n \n \tstrbuf_reset(&cb_data->obj_type);\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex cbbf6f26439..283d64cab80 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -453,7 +453,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t\treturn 0;\n \n \tsubrepo = xmalloc(sizeof(*subrepo));\n-\tif (repo_submodule_init(subrepo, superproject, path, null_oid())) {\n+\tif (repo_submodule_init(subrepo, superproject, path, null_oid(opt->repo->hash_algo))) {\n \t\tfree(subrepo);\n \t\treturn 0;\n \t}\ndiff --git a/builtin/ls-files.c b/builtin/ls-files.c\nindex a4431429b7d..7bc418be5d4 100644\n--- a/builtin/ls-files.c\n+++ b/builtin/ls-files.c\n@@ -234,7 +234,8 @@ static void show_submodule(struct repository *superproject,\n {\n \tstruct repository subrepo;\n \n-\tif (repo_submodule_init(&subrepo, superproject, path, null_oid()))\n+\tif (repo_submodule_init(&subrepo, superproject, path,\n+\t\t\t\tnull_oid(superproject->hash_algo)))\n \t\treturn;\n \n \tif (repo_read_index(&subrepo) < 0)\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex d4715ed35d7..1cd802dd92a 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -925,7 +925,7 @@ static void fill_branch_base(struct rebase_options *options,\n \t\t\t\t options->orig_head, &merge_bases) < 0)\n \t\texit(128);\n \tif (!merge_bases || merge_bases->next)\n-\t\toidcpy(branch_base, null_oid());\n+\t\toidcpy(branch_base, null_oid(the_hash_algo));\n \telse\n \t\toidcpy(branch_base, &merge_bases->item->object.oid);\n \ndiff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\nindex 7b28fc9df6e..b3e2a9d0c60 100644\n--- a/builtin/receive-pack.c\n+++ b/builtin/receive-pack.c\n@@ -363,7 +363,7 @@ static void write_head_info(void)\n \tstrvec_clear(&excludes_vector);\n \n \tif (!sent_capabilities)\n-\t\tshow_ref(\"capabilities^{}\", null_oid());\n+\t\tshow_ref(\"capabilities^{}\", null_oid(the_hash_algo));\n \n \tadvertise_shallow_grafts(1);\n \ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex c1a8029714b..570226ea166 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -78,7 +78,7 @@ static int get_default_remote_submodule(const char *module_path, char **default_\n \tint ret;\n \n \tif (repo_submodule_init(&subrepo, the_repository, module_path,\n-\t\t\t\tnull_oid()) < 0)\n+\t\t\t\tnull_oid(the_hash_algo)) < 0)\n \t\treturn die_message(_(\"could not get a repository handle for submodule '%s'\"),\n \t\t\t\t   module_path);\n \tret = repo_get_default_remote(&subrepo, default_remote);\n@@ -308,7 +308,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,\n \tdisplaypath = get_submodule_displaypath(path, info->prefix,\n \t\t\t\t\t\tinfo->super_prefix);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n@@ -468,7 +468,7 @@ static void init_submodule(const char *path, const char *prefix,\n \n \tdisplaypath = get_submodule_displaypath(path, prefix, super_prefix);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n@@ -645,14 +645,14 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,\n \tif (validate_submodule_path(path) < 0)\n \t\texit(128);\n \n-\tif (!submodule_from_path(the_repository, null_oid(), path))\n+\tif (!submodule_from_path(the_repository, null_oid(the_hash_algo), path))\n \t\tdie(_(\"no submodule mapping found in .gitmodules for path '%s'\"),\n \t\t      path);\n \n \tdisplaypath = get_submodule_displaypath(path, prefix, super_prefix);\n \n \tif ((CE_STAGEMASK & ce_flags) >> CE_STAGESHIFT) {\n-\t\tprint_status(flags, 'U', path, null_oid(), displaypath);\n+\t\tprint_status(flags, 'U', path, null_oid(the_hash_algo), displaypath);\n \t\tgoto cleanup;\n \t}\n \n@@ -912,7 +912,7 @@ static void generate_submodule_summary(struct summary_cb *info,\n \tstruct strbuf errmsg = STRBUF_INIT;\n \tint total_commits = -1;\n \n-\tif (!info->cached && oideq(&p->oid_dst, null_oid())) {\n+\tif (!info->cached && oideq(&p->oid_dst, null_oid(the_hash_algo))) {\n \t\tif (S_ISGITLINK(p->mod_dst)) {\n \t\t\tstruct ref_store *refs = repo_get_submodule_ref_store(the_repository,\n \t\t\t\t\t\t\t\t\t      p->sm_path);\n@@ -1051,7 +1051,7 @@ static void prepare_submodule_summary(struct summary_cb *info,\n \n \t\tif (info->for_status && p->status != 'A' &&\n \t\t    (sub = submodule_from_path(the_repository,\n-\t\t\t\t\t       null_oid(), p->sm_path))) {\n+\t\t\t\t\t       null_oid(the_hash_algo), p->sm_path))) {\n \t\t\tchar *config_key = NULL;\n \t\t\tconst char *value;\n \t\t\tint ignore_all = 0;\n@@ -1259,7 +1259,7 @@ static void sync_submodule(const char *path, const char *prefix,\n \tif (validate_submodule_path(path) < 0)\n \t\texit(128);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (sub && sub->url) {\n \t\tif (starts_with_dot_dot_slash(sub->url) ||\n@@ -1404,7 +1404,7 @@ static void deinit_submodule(const char *path, const char *prefix,\n \tif (validate_submodule_path(path) < 0)\n \t\texit(128);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub || !sub->name)\n \t\tgoto cleanup;\n@@ -1929,7 +1929,7 @@ static int determine_submodule_update_strategy(struct repository *r,\n \t\t\t\t\t       enum submodule_update_type update,\n \t\t\t\t\t       struct submodule_update_strategy *out)\n {\n-\tconst struct submodule *sub = submodule_from_path(r, null_oid(), path);\n+\tconst struct submodule *sub = submodule_from_path(r, null_oid(the_hash_algo), path);\n \tchar *key;\n \tconst char *val;\n \tint ret;\n@@ -2089,7 +2089,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\tgoto cleanup;\n \t}\n \n-\tsub = submodule_from_path(the_repository, null_oid(), ce->name);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), ce->name);\n \n \tif (!sub) {\n \t\tnext_submodule_warn_missing(suc, out, displaypath);\n@@ -2485,7 +2485,7 @@ static int remote_submodule_branch(const char *path, const char **branch)\n \tchar *key;\n \t*branch = NULL;\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \tif (!sub)\n \t\treturn die_message(_(\"could not initialize submodule at path '%s'\"),\n \t\t\t\t   path);\n@@ -2531,7 +2531,7 @@ static int ensure_core_worktree(const char *path)\n \tconst char *cw;\n \tstruct repository subrepo;\n \n-\tif (repo_submodule_init(&subrepo, the_repository, path, null_oid()))\n+\tif (repo_submodule_init(&subrepo, the_repository, path, null_oid(the_hash_algo)))\n \t\treturn die_message(_(\"could not get a repository handle for submodule '%s'\"),\n \t\t\t\t   path);\n \n@@ -2644,7 +2644,7 @@ static int update_submodule(struct update_data *update_data)\n \t\treturn ret;\n \n \tif (update_data->just_cloned)\n-\t\toidcpy(&update_data->suboid, null_oid());\n+\t\toidcpy(&update_data->suboid, null_oid(the_hash_algo));\n \telse if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path,\n \t\t\t\t\t  \"HEAD\", &update_data->suboid))\n \t\treturn die_message(_(\"Unable to find current revision in submodule path '%s'\"),\n@@ -2697,8 +2697,8 @@ static int update_submodule(struct update_data *update_data)\n \t\tstruct update_data next = *update_data;\n \n \t\tnext.prefix = NULL;\n-\t\toidcpy(&next.oid, null_oid());\n-\t\toidcpy(&next.suboid, null_oid());\n+\t\toidcpy(&next.oid, null_oid(the_hash_algo));\n+\t\toidcpy(&next.suboid, null_oid(the_hash_algo));\n \n \t\tcp.dir = update_data->sm_path;\n \t\tcp.git_cmd = 1;\n@@ -3057,7 +3057,7 @@ static int module_set_url(int argc, const char **argv, const char *prefix,\n \tif (argc != 2 || !(path = argv[0]) || !(newurl = argv[1]))\n \t\tusage_with_options(usage, options);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"no submodule mapping found in .gitmodules for path '%s'\"),\n@@ -3113,7 +3113,7 @@ static int module_set_branch(int argc, const char **argv, const char *prefix,\n \tif (argc != 1 || !(path = argv[0]))\n \t\tusage_with_options(usage, options);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tdie(_(\"no submodule mapping found in .gitmodules for path '%s'\"),\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex e20c120913e..73d431a0dde 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -505,7 +505,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,\n \t\t\t * has not been resolved yet.\n \t\t\t */\n \t\t\toidclr(&obj_list[nr].oid, the_repository->hash_algo);\n-\t\t\tadd_delta_to_list(nr, null_oid(), base_offset,\n+\t\t\tadd_delta_to_list(nr, null_oid(the_hash_algo), base_offset,\n \t\t\t\t\t  delta_data, delta_size);\n \t\t\treturn;\n \t\t}\ndiff --git a/builtin/update-ref.c b/builtin/update-ref.c\nindex 4d35bdc4b4b..3796b9844d1 100644\n--- a/builtin/update-ref.c\n+++ b/builtin/update-ref.c\n@@ -500,7 +500,7 @@ static void parse_cmd_symref_verify(struct ref_transaction *transaction,\n \t */\n \told_target = parse_next_refname(&next);\n \tif (!old_target)\n-\t\toidcpy(&old_oid, null_oid());\n+\t\toidcpy(&old_oid, null_oid(the_hash_algo));\n \n \tif (*next != line_termination)\n \t\tdie(\"symref-verify %s: extra input: %s\", refname, next);\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 48448a83550..87ccd47794c 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -578,7 +578,7 @@ static int add_worktree(const char *path, const char *refname,\n \n \t\tstrvec_pushl(&opt.env, \"GIT_DIR\", \"GIT_WORK_TREE\", NULL);\n \t\tstrvec_pushl(&opt.args,\n-\t\t\t     oid_to_hex(null_oid()),\n+\t\t\t     oid_to_hex(null_oid(the_hash_algo)),\n \t\t\t     oid_to_hex(&commit->object.oid),\n \t\t\t     \"1\",\n \t\t\t     NULL);\ndiff --git a/combine-diff.c b/combine-diff.c\nindex 9527f3160d8..553bf59fed6 100644\n--- a/combine-diff.c\n+++ b/combine-diff.c\n@@ -1066,7 +1066,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,\n \t\t\t\t\t\t   &result_size, NULL, NULL);\n \t\t} else if (textconv) {\n \t\t\tstruct diff_filespec *df = alloc_filespec(elem->path);\n-\t\t\tfill_filespec(df, null_oid(), 0, st.st_mode);\n+\t\t\tfill_filespec(df, null_oid(the_hash_algo), 0, st.st_mode);\n \t\t\tresult_size = fill_textconv(opt->repo, textconv, df, &result);\n \t\t\tfree_filespec(df);\n \t\t} else if (0 <= (fd = open(elem->path, O_RDONLY))) {\ndiff --git a/diff-lib.c b/diff-lib.c\nindex 353b473ed52..244468dd1a2 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -172,7 +172,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t\t * these from (stage - 2).\n \t\t\t */\n \t\t\tdpath = combine_diff_path_new(ce->name, ce_namelen(ce),\n-\t\t\t\t\t\t      wt_mode, null_oid(), 2);\n+\t\t\t\t\t\t      wt_mode, null_oid(the_hash_algo), 2);\n \n \t\t\twhile (i < entries) {\n \t\t\t\tstruct cache_entry *nce = istate->cache[i];\n@@ -257,7 +257,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t\t\t   ce_intent_to_add(ce)) {\n \t\t\t\tnewmode = ce_mode_from_stat(ce, st.st_mode);\n \t\t\t\tdiff_addremove(&revs->diffopt, '+', newmode,\n-\t\t\t\t\t       null_oid(), 0, ce->name, 0);\n+\t\t\t\t\t       null_oid(the_hash_algo), 0, ce->name, 0);\n \t\t\t\tcontinue;\n \t\t\t}\n \n@@ -274,7 +274,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t}\n \t\toldmode = ce->ce_mode;\n \t\told_oid = &ce->oid;\n-\t\tnew_oid = changed ? null_oid() : &ce->oid;\n+\t\tnew_oid = changed ? null_oid(the_hash_algo) : &ce->oid;\n \t\tdiff_change(&revs->diffopt, oldmode, newmode,\n \t\t\t    old_oid, new_oid,\n \t\t\t    !is_null_oid(old_oid),\n@@ -330,7 +330,7 @@ static int get_stat_data(const struct cache_entry *ce,\n \t\t\t\t\t\t    0, dirty_submodule);\n \t\tif (changed) {\n \t\t\tmode = ce_mode_from_stat(ce, st.st_mode);\n-\t\t\toid = null_oid();\n+\t\t\toid = null_oid(the_hash_algo);\n \t\t}\n \t}\n \n@@ -402,7 +402,7 @@ static int show_modified(struct rev_info *revs,\n \n \t\tp = combine_diff_path_new(new_entry->name,\n \t\t\t\t\t  ce_namelen(new_entry),\n-\t\t\t\t\t  mode, null_oid(), 2);\n+\t\t\t\t\t  mode, null_oid(the_hash_algo), 2);\n \t\tp->parent[0].status = DIFF_STATUS_MODIFIED;\n \t\tp->parent[0].mode = new_entry->ce_mode;\n \t\toidcpy(&p->parent[0].oid, &new_entry->oid);\ndiff --git a/diff-no-index.c b/diff-no-index.c\nindex 6f277892d3a..9739b2b268b 100644\n--- a/diff-no-index.c\n+++ b/diff-no-index.c\n@@ -113,7 +113,8 @@ static void populate_from_stdin(struct diff_filespec *s)\n \tpopulate_common(s, &buf);\n }\n \n-static struct diff_filespec *noindex_filespec(const char *name, int mode,\n+static struct diff_filespec *noindex_filespec(const struct git_hash_algo *algop,\n+\t\t\t\t\t      const char *name, int mode,\n \t\t\t\t\t      enum special special)\n {\n \tstruct diff_filespec *s;\n@@ -121,7 +122,7 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode,\n \tif (!name)\n \t\tname = \"/dev/null\";\n \ts = alloc_filespec(name);\n-\tfill_filespec(s, null_oid(), 0, mode);\n+\tfill_filespec(s, null_oid(algop), 0, mode);\n \tif (special == SPECIAL_STDIN)\n \t\tpopulate_from_stdin(s);\n \telse if (special == SPECIAL_PIPE)\n@@ -129,7 +130,7 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode,\n \treturn s;\n }\n \n-static int queue_diff(struct diff_options *o,\n+static int queue_diff(struct diff_options *o, const struct git_hash_algo *algop,\n \t\t      const char *name1, const char *name2, int recursing)\n {\n \tint mode1 = 0, mode2 = 0;\n@@ -145,14 +146,14 @@ static int queue_diff(struct diff_options *o,\n \n \t\tif (S_ISDIR(mode1)) {\n \t\t\t/* 2 is file that is created */\n-\t\t\td1 = noindex_filespec(NULL, 0, SPECIAL_NONE);\n-\t\t\td2 = noindex_filespec(name2, mode2, special2);\n+\t\t\td1 = noindex_filespec(algop, NULL, 0, SPECIAL_NONE);\n+\t\t\td2 = noindex_filespec(algop, name2, mode2, special2);\n \t\t\tname2 = NULL;\n \t\t\tmode2 = 0;\n \t\t} else {\n \t\t\t/* 1 is file that is deleted */\n-\t\t\td1 = noindex_filespec(name1, mode1, special1);\n-\t\t\td2 = noindex_filespec(NULL, 0, SPECIAL_NONE);\n+\t\t\td1 = noindex_filespec(algop, name1, mode1, special1);\n+\t\t\td2 = noindex_filespec(algop, NULL, 0, SPECIAL_NONE);\n \t\t\tname1 = NULL;\n \t\t\tmode1 = 0;\n \t\t}\n@@ -217,7 +218,7 @@ static int queue_diff(struct diff_options *o,\n \t\t\t\tn2 = buffer2.buf;\n \t\t\t}\n \n-\t\t\tret = queue_diff(o, n1, n2, 1);\n+\t\t\tret = queue_diff(o, algop, n1, n2, 1);\n \t\t}\n \t\tstring_list_clear(&p1, 0);\n \t\tstring_list_clear(&p2, 0);\n@@ -234,8 +235,8 @@ static int queue_diff(struct diff_options *o,\n \t\t\tSWAP(special1, special2);\n \t\t}\n \n-\t\td1 = noindex_filespec(name1, mode1, special1);\n-\t\td2 = noindex_filespec(name2, mode2, special2);\n+\t\td1 = noindex_filespec(algop, name1, mode1, special1);\n+\t\td2 = noindex_filespec(algop, name2, mode2, special2);\n \t\tdiff_queue(&diff_queued_diff, d1, d2);\n \t\treturn 0;\n \t}\n@@ -297,9 +298,8 @@ static const char * const diff_no_index_usage[] = {\n \tNULL\n };\n \n-int diff_no_index(struct rev_info *revs,\n-\t\t  int implicit_no_index,\n-\t\t  int argc, const char **argv)\n+int diff_no_index(struct rev_info *revs, const struct git_hash_algo *algop,\n+\t\t  int implicit_no_index, int argc, const char **argv)\n {\n \tint i, no_index;\n \tint ret = 1;\n@@ -354,7 +354,7 @@ int diff_no_index(struct rev_info *revs,\n \tsetup_diff_pager(&revs->diffopt);\n \trevs->diffopt.flags.exit_with_status = 1;\n \n-\tif (queue_diff(&revs->diffopt, paths[0], paths[1], 0))\n+\tif (queue_diff(&revs->diffopt, algop, paths[0], paths[1], 0))\n \t\tgoto out;\n \tdiff_set_mnemonic_prefix(&revs->diffopt, \"1/\", \"2/\");\n \tdiffcore_std(&revs->diffopt);\ndiff --git a/diff.c b/diff.c\nindex 4f802b4251c..4ce5933a442 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -4346,7 +4346,7 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r,\n \t\t\t\tdie_errno(\"readlink(%s)\", one->path);\n \t\t\tprep_temp_blob(r->index, one->path, temp, sb.buf, sb.len,\n \t\t\t\t       (one->oid_valid ?\n-\t\t\t\t\t&one->oid : null_oid()),\n+\t\t\t\t\t&one->oid : null_oid(the_hash_algo)),\n \t\t\t\t       (one->oid_valid ?\n \t\t\t\t\tone->mode : S_IFLNK));\n \t\t\tstrbuf_release(&sb);\n@@ -4355,7 +4355,7 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r,\n \t\t\t/* we can borrow from the file in the work tree */\n \t\t\ttemp->name = one->path;\n \t\t\tif (!one->oid_valid)\n-\t\t\t\toid_to_hex_r(temp->hex, null_oid());\n+\t\t\t\toid_to_hex_r(temp->hex, null_oid(the_hash_algo));\n \t\t\telse\n \t\t\t\toid_to_hex_r(temp->hex, &one->oid);\n \t\t\t/* Even though we may sometimes borrow the\n@@ -6649,8 +6649,8 @@ static void create_filepairs_for_header_only_notifications(struct diff_options *\n \n \t\t\tone = alloc_filespec(e->key);\n \t\t\ttwo = alloc_filespec(e->key);\n-\t\t\tfill_filespec(one, null_oid(), 0, 0);\n-\t\t\tfill_filespec(two, null_oid(), 0, 0);\n+\t\t\tfill_filespec(one, null_oid(the_hash_algo), 0, 0);\n+\t\t\tfill_filespec(two, null_oid(the_hash_algo), 0, 0);\n \t\t\tp = diff_queue(q, one, two);\n \t\t\tp->status = DIFF_STATUS_MODIFIED;\n \t\t}\ndiff --git a/diff.h b/diff.h\nindex 0a566f5531a..0822111c62a 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -656,7 +656,7 @@ void flush_one_hunk(struct object_id *result, struct git_hash_ctx *ctx);\n \n int diff_result_code(struct rev_info *);\n \n-int diff_no_index(struct rev_info *,\n+int diff_no_index(struct rev_info *, const struct git_hash_algo *algop,\n \t\t  int implicit_no_index, int, const char **);\n \n int index_differs_from(struct repository *r, const char *def,\ndiff --git a/dir.c b/dir.c\nindex cbd82be6c91..28b0e03feb4 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -4035,7 +4035,7 @@ static void connect_wt_gitdir_in_nested(const char *sub_worktree,\n \t\t\t */\n \t\t\ti++;\n \n-\t\tsub = submodule_from_path(&subrepo, null_oid(), ce->name);\n+\t\tsub = submodule_from_path(&subrepo, null_oid(the_hash_algo), ce->name);\n \t\tif (!sub || !is_submodule_active(&subrepo, ce->name))\n \t\t\t/* .gitmodules broken or inactive sub */\n \t\t\tcontinue;\ndiff --git a/grep.c b/grep.c\nindex 4e155ee9e66..9284b5741f5 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -1517,7 +1517,7 @@ static int fill_textconv_grep(struct repository *r,\n \t\tfill_filespec(df, gs->identifier, 1, 0100644);\n \t\tbreak;\n \tcase GREP_SOURCE_FILE:\n-\t\tfill_filespec(df, null_oid(), 0, 0100644);\n+\t\tfill_filespec(df, null_oid(r->hash_algo), 0, 0100644);\n \t\tbreak;\n \tdefault:\n \t\tBUG(\"attempt to textconv something without a path?\");\ndiff --git a/hash.c b/hash.c\nindex 4d9f98f72c2..4a04ecb50e8 100644\n--- a/hash.c\n+++ b/hash.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"hash.h\"\n #include \"hex.h\"\n@@ -232,9 +230,9 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n \t}\n };\n \n-const struct object_id *null_oid(void)\n+const struct object_id *null_oid(const struct git_hash_algo *algop)\n {\n-\treturn the_hash_algo->null_oid;\n+\treturn algop->null_oid;\n }\n \n const char *empty_tree_oid_hex(const struct git_hash_algo *algop)\ndiff --git a/hash.h b/hash.h\nindex 55d67ed83f3..a9ef76fc8e7 100644\n--- a/hash.h\n+++ b/hash.h\n@@ -340,7 +340,7 @@ static inline int hash_algo_by_ptr(const struct git_hash_algo *p)\n \n const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop);\n \n-const struct object_id *null_oid(void);\n+const struct object_id *null_oid(const struct git_hash_algo *algop);\n \n static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)\n {\ndiff --git a/log-tree.c b/log-tree.c\nindex 8b184d67763..5dd1b63076f 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -499,7 +499,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,\n {\n \tstruct strbuf headers = STRBUF_INIT;\n \tconst char *name = oid_to_hex(opt->zero_commit ?\n-\t\t\t\t      null_oid() : &commit->object.oid);\n+\t\t\t\t      null_oid(the_hash_algo) : &commit->object.oid);\n \n \t*need_8bit_cte_p = 0; /* unknown */\n \ndiff --git a/merge-ort.c b/merge-ort.c\nindex 46e78c3ffa6..eb3a834652a 100644\n--- a/merge-ort.c\n+++ b/merge-ort.c\n@@ -1817,7 +1817,7 @@ static int merge_submodule(struct merge_options *opt,\n \t\tBUG(\"submodule deleted on one side; this should be handled outside of merge_submodule()\");\n \n \tif ((sub_not_initialized = repo_submodule_init(&subrepo,\n-\t\topt->repo, path, null_oid()))) {\n+\t\topt->repo, path, null_oid(the_hash_algo)))) {\n \t\tpath_msg(opt, CONFLICT_SUBMODULE_NOT_INITIALIZED, 0,\n \t\t\t path, NULL, NULL, NULL,\n \t\t\t _(\"Failed to merge submodule %s (not checked out)\"),\n@@ -2199,7 +2199,7 @@ static int handle_content_merge(struct merge_options *opt,\n \t\ttwo_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));\n \n \t\tmerge_status = merge_3way(opt, path,\n-\t\t\t\t\t  two_way ? null_oid() : &o->oid,\n+\t\t\t\t\t  two_way ? null_oid(the_hash_algo) : &o->oid,\n \t\t\t\t\t  &a->oid, &b->oid,\n \t\t\t\t\t  pathnames, extra_marker_size,\n \t\t\t\t\t  &result_buf);\n@@ -2231,7 +2231,7 @@ static int handle_content_merge(struct merge_options *opt,\n \t} else if (S_ISGITLINK(a->mode)) {\n \t\tint two_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));\n \t\tclean = merge_submodule(opt, pathnames[0],\n-\t\t\t\t\ttwo_way ? null_oid() : &o->oid,\n+\t\t\t\t\ttwo_way ? null_oid(the_hash_algo) : &o->oid,\n \t\t\t\t\t&a->oid, &b->oid, &result->oid);\n \t\tif (clean < 0)\n \t\t\treturn -1;\n@@ -2739,7 +2739,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt,\n \t\tassert(!new_ci->match_mask);\n \t\tnew_ci->dirmask = 0;\n \t\tnew_ci->stages[1].mode = 0;\n-\t\toidcpy(&new_ci->stages[1].oid, null_oid());\n+\t\toidcpy(&new_ci->stages[1].oid, null_oid(the_hash_algo));\n \n \t\t/*\n \t\t * Now that we have the file information in new_ci, make sure\n@@ -2752,7 +2752,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt,\n \t\t\t\tcontinue;\n \t\t\t/* zero out any entries related to files */\n \t\t\tci->stages[i].mode = 0;\n-\t\t\toidcpy(&ci->stages[i].oid, null_oid());\n+\t\t\toidcpy(&ci->stages[i].oid, null_oid(the_hash_algo));\n \t\t}\n \n \t\t/* Now we want to focus on new_ci, so reassign ci to it. */\n@@ -3122,7 +3122,7 @@ static int process_renames(struct merge_options *opt,\n \t\t\tif (type_changed) {\n \t\t\t\t/* rename vs. typechange */\n \t\t\t\t/* Mark the original as resolved by removal */\n-\t\t\t\tmemcpy(&oldinfo->stages[0].oid, null_oid(),\n+\t\t\t\tmemcpy(&oldinfo->stages[0].oid, null_oid(the_hash_algo),\n \t\t\t\t       sizeof(oldinfo->stages[0].oid));\n \t\t\t\toldinfo->stages[0].mode = 0;\n \t\t\t\toldinfo->filemask &= 0x06;\n@@ -3994,7 +3994,7 @@ static int process_entry(struct merge_options *opt,\n \t\t\tif (ci->filemask & (1 << i))\n \t\t\t\tcontinue;\n \t\t\tci->stages[i].mode = 0;\n-\t\t\toidcpy(&ci->stages[i].oid, null_oid());\n+\t\t\toidcpy(&ci->stages[i].oid, null_oid(the_hash_algo));\n \t\t}\n \t} else if (ci->df_conflict && ci->merged.result.mode != 0) {\n \t\t/*\n@@ -4041,7 +4041,7 @@ static int process_entry(struct merge_options *opt,\n \t\t\t\tcontinue;\n \t\t\t/* zero out any entries related to directories */\n \t\t\tnew_ci->stages[i].mode = 0;\n-\t\t\toidcpy(&new_ci->stages[i].oid, null_oid());\n+\t\t\toidcpy(&new_ci->stages[i].oid, null_oid(the_hash_algo));\n \t\t}\n \n \t\t/*\n@@ -4163,11 +4163,11 @@ static int process_entry(struct merge_options *opt,\n \t\t\tnew_ci->merged.result.mode = ci->stages[2].mode;\n \t\t\toidcpy(&new_ci->merged.result.oid, &ci->stages[2].oid);\n \t\t\tnew_ci->stages[1].mode = 0;\n-\t\t\toidcpy(&new_ci->stages[1].oid, null_oid());\n+\t\t\toidcpy(&new_ci->stages[1].oid, null_oid(the_hash_algo));\n \t\t\tnew_ci->filemask = 5;\n \t\t\tif ((S_IFMT & b_mode) != (S_IFMT & o_mode)) {\n \t\t\t\tnew_ci->stages[0].mode = 0;\n-\t\t\t\toidcpy(&new_ci->stages[0].oid, null_oid());\n+\t\t\t\toidcpy(&new_ci->stages[0].oid, null_oid(the_hash_algo));\n \t\t\t\tnew_ci->filemask = 4;\n \t\t\t}\n \n@@ -4175,11 +4175,11 @@ static int process_entry(struct merge_options *opt,\n \t\t\tci->merged.result.mode = ci->stages[1].mode;\n \t\t\toidcpy(&ci->merged.result.oid, &ci->stages[1].oid);\n \t\t\tci->stages[2].mode = 0;\n-\t\t\toidcpy(&ci->stages[2].oid, null_oid());\n+\t\t\toidcpy(&ci->stages[2].oid, null_oid(the_hash_algo));\n \t\t\tci->filemask = 3;\n \t\t\tif ((S_IFMT & a_mode) != (S_IFMT & o_mode)) {\n \t\t\t\tci->stages[0].mode = 0;\n-\t\t\t\toidcpy(&ci->stages[0].oid, null_oid());\n+\t\t\t\toidcpy(&ci->stages[0].oid, null_oid(the_hash_algo));\n \t\t\t\tci->filemask = 2;\n \t\t\t}\n \n@@ -4304,7 +4304,7 @@ static int process_entry(struct merge_options *opt,\n \t\t/* Deleted on both sides */\n \t\tci->merged.is_null = 1;\n \t\tci->merged.result.mode = 0;\n-\t\toidcpy(&ci->merged.result.oid, null_oid());\n+\t\toidcpy(&ci->merged.result.oid, null_oid(the_hash_algo));\n \t\tassert(!ci->df_conflict);\n \t\tci->merged.clean = !ci->path_conflict;\n \t}\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 5dfaf32b2c1..d88e61b07a9 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -502,7 +502,7 @@ static int get_tree_entry_if_blob(struct repository *r,\n \n \tret = get_tree_entry(r, tree, path, &dfs->oid, &dfs->mode);\n \tif (S_ISDIR(dfs->mode)) {\n-\t\toidcpy(&dfs->oid, null_oid());\n+\t\toidcpy(&dfs->oid, null_oid(the_hash_algo));\n \t\tdfs->mode = 0;\n \t}\n \treturn ret;\n@@ -1238,7 +1238,7 @@ static int merge_submodule(struct merge_options *opt,\n \tif (is_null_oid(b))\n \t\treturn 0;\n \n-\tif (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) {\n+\tif (repo_submodule_init(&subrepo, opt->repo, path, null_oid(the_hash_algo))) {\n \t\toutput(opt, 1, _(\"Failed to merge submodule %s (not checked out)\"), path);\n \t\treturn 0;\n \t}\n@@ -1698,7 +1698,7 @@ static int handle_file_collision(struct merge_options *opt,\n \n \t/* Store things in diff_filespecs for functions that need it */\n \tnull.path = (char *)collide_path;\n-\toidcpy(&null.oid, null_oid());\n+\toidcpy(&null.oid, null_oid(the_hash_algo));\n \tnull.mode = 0;\n \n \tif (merge_mode_and_contents(opt, &null, a, b, collide_path,\n@@ -2898,14 +2898,14 @@ static int process_renames(struct merge_options *opt,\n \t\t\tdst_other.mode = ren1->dst_entry->stages[other_stage].mode;\n \t\t\ttry_merge = 0;\n \n-\t\t\tif (oideq(&src_other.oid, null_oid()) &&\n+\t\t\tif (oideq(&src_other.oid, null_oid(the_hash_algo)) &&\n \t\t\t    ren1->dir_rename_original_type == 'A') {\n \t\t\t\tsetup_rename_conflict_info(RENAME_VIA_DIR,\n \t\t\t\t\t\t\t   opt, ren1, NULL);\n \t\t\t} else if (renamed_to_self) {\n \t\t\t\tsetup_rename_conflict_info(RENAME_NORMAL,\n \t\t\t\t\t\t\t   opt, ren1, NULL);\n-\t\t\t} else if (oideq(&src_other.oid, null_oid())) {\n+\t\t\t} else if (oideq(&src_other.oid, null_oid(the_hash_algo))) {\n \t\t\t\tsetup_rename_conflict_info(RENAME_DELETE,\n \t\t\t\t\t\t\t   opt, ren1, NULL);\n \t\t\t} else if ((dst_other.mode == ren1->pair->two->mode) &&\n@@ -2924,7 +2924,7 @@ static int process_renames(struct merge_options *opt,\n \t\t\t\t\t\t      1, /* update_cache */\n \t\t\t\t\t\t      0  /* update_wd    */))\n \t\t\t\t\tclean_merge = -1;\n-\t\t\t} else if (!oideq(&dst_other.oid, null_oid())) {\n+\t\t\t} else if (!oideq(&dst_other.oid, null_oid(the_hash_algo))) {\n \t\t\t\t/*\n \t\t\t\t * Probably not a clean merge, but it's\n \t\t\t\t * premature to set clean_merge to 0 here,\ndiff --git a/notes-merge.c b/notes-merge.c\nindex 67a472020de..5008faef450 100644\n--- a/notes-merge.c\n+++ b/notes-merge.c\n@@ -617,7 +617,7 @@ int notes_merge(struct notes_merge_options *o,\n \tif (repo_get_merge_bases(the_repository, local, remote, &bases) < 0)\n \t\texit(128);\n \tif (!bases) {\n-\t\tbase_oid = null_oid();\n+\t\tbase_oid = null_oid(the_hash_algo);\n \t\tbase_tree_oid = the_hash_algo->empty_tree;\n \t\tif (o->verbosity >= 4)\n \t\t\tprintf(\"No merge base found; doing history-less merge\\n\");\ndiff --git a/notes.c b/notes.c\nindex f5344230505..ce5a1006a83 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -1353,7 +1353,7 @@ int copy_note(struct notes_tree *t,\n \tif (note)\n \t\treturn add_note(t, to_obj, note, combine_notes);\n \telse if (existing_note)\n-\t\treturn add_note(t, to_obj, null_oid(), combine_notes);\n+\t\treturn add_note(t, to_obj, null_oid(the_hash_algo), combine_notes);\n \n \treturn 0;\n }\ndiff --git a/object-file.c b/object-file.c\nindex de603e2ca8c..772c311f188 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2405,7 +2405,7 @@ static int index_mem(struct index_state *istate,\n \n \t\topts.strict = 1;\n \t\topts.error_func = hash_format_check_report;\n-\t\tif (fsck_buffer(null_oid(), type, buf, size, &opts))\n+\t\tif (fsck_buffer(null_oid(the_hash_algo), type, buf, size, &opts))\n \t\t\tdie(_(\"refusing to create malformed object\"));\n \t\tfsck_finish(&opts);\n \t}\ndiff --git a/parse-options-cb.c b/parse-options-cb.c\nindex 166d35e0ebd..50c8afe4121 100644\n--- a/parse-options-cb.c\n+++ b/parse-options-cb.c\n@@ -145,7 +145,7 @@ int parse_opt_object_id(const struct option *opt, const char *arg, int unset)\n \tstruct object_id *target = opt->value;\n \n \tif (unset) {\n-\t\toidcpy(target, null_oid());\n+\t\toidcpy(target, null_oid(the_hash_algo));\n \t\treturn 0;\n \t}\n \tif (!arg)\ndiff --git a/range-diff.c b/range-diff.c\nindex 9501c358a84..8a2dcbee322 100644\n--- a/range-diff.c\n+++ b/range-diff.c\n@@ -467,7 +467,7 @@ static struct diff_filespec *get_filespec(const char *name, const char *p)\n {\n \tstruct diff_filespec *spec = alloc_filespec(name);\n \n-\tfill_filespec(spec, null_oid(), 0, 0100644);\n+\tfill_filespec(spec, null_oid(the_hash_algo), 0, 0100644);\n \tspec->data = (char *)p;\n \tspec->size = strlen(p);\n \tspec->should_munmap = 0;\ndiff --git a/read-cache.c b/read-cache.c\nindex a012cb22368..2f9e21c897d 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1735,7 +1735,7 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)\n \tend = (unsigned char *)hdr + size;\n \tstart = end - the_hash_algo->rawsz;\n \toidread(&oid, start, the_repository->hash_algo);\n-\tif (oideq(&oid, null_oid()))\n+\tif (oideq(&oid, null_oid(the_hash_algo)))\n \t\treturn 0;\n \n \tthe_hash_algo->init_fn(&c);\ndiff --git a/refs.c b/refs.c\nindex 118465271d7..215294115b4 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1377,7 +1377,7 @@ int ref_transaction_create(struct ref_transaction *transaction,\n \t\treturn 1;\n \t}\n \treturn ref_transaction_update(transaction, refname, new_oid,\n-\t\t\t\t      null_oid(), new_target, NULL, flags,\n+\t\t\t\t      null_oid(the_hash_algo), new_target, NULL, flags,\n \t\t\t\t      msg, err);\n }\n \n@@ -1396,7 +1396,7 @@ int ref_transaction_delete(struct ref_transaction *transaction,\n \tif (old_target && !(flags & REF_NO_DEREF))\n \t\tBUG(\"delete cannot operate on symrefs with deref mode\");\n \treturn ref_transaction_update(transaction, refname,\n-\t\t\t\t      null_oid(), old_oid,\n+\t\t\t\t      null_oid(the_hash_algo), old_oid,\n \t\t\t\t      NULL, old_target, flags,\n \t\t\t\t      msg, err);\n }\n@@ -2160,7 +2160,7 @@ struct ref_store *repo_get_submodule_ref_store(struct repository *repo,\n \tsubrepo = xmalloc(sizeof(*subrepo));\n \n \tif (repo_submodule_init(subrepo, repo, submodule,\n-\t\t\t\tnull_oid())) {\n+\t\t\t\tnull_oid(the_hash_algo))) {\n \t\tfree(subrepo);\n \t\tgoto done;\n \t}\n@@ -2345,14 +2345,14 @@ static int run_transaction_hook(struct ref_transaction *transaction,\n \t\tstrbuf_reset(&buf);\n \n \t\tif (!(update->flags & REF_HAVE_OLD))\n-\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid()));\n+\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid(the_hash_algo)));\n \t\telse if (update->old_target)\n \t\t\tstrbuf_addf(&buf, \"ref:%s \", update->old_target);\n \t\telse\n \t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(&update->old_oid));\n \n \t\tif (!(update->flags & REF_HAVE_NEW))\n-\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid()));\n+\t\t\tstrbuf_addf(&buf, \"%s \", oid_to_hex(null_oid(the_hash_algo)));\n \t\telse if (update->new_target)\n \t\t\tstrbuf_addf(&buf, \"ref:%s \", update->new_target);\n \t\telse\n@@ -2794,7 +2794,7 @@ static int migrate_one_ref(const char *refname, const char *referent UNUSED, con\n \t\tif (ret < 0)\n \t\t\tgoto done;\n \n-\t\tret = ref_transaction_update(data->transaction, refname, NULL, null_oid(),\n+\t\tret = ref_transaction_update(data->transaction, refname, NULL, null_oid(the_hash_algo),\n \t\t\t\t\t     symref_target.buf, NULL,\n \t\t\t\t\t     REF_SKIP_CREATE_REFLOG | REF_NO_DEREF, NULL, data->errbuf);\n \t\tif (ret < 0)\ndiff --git a/refs/debug.c b/refs/debug.c\nindex fbc4df08b43..7c61b775e4e 100644\n--- a/refs/debug.c\n+++ b/refs/debug.c\n@@ -217,7 +217,7 @@ static int debug_read_raw_ref(struct ref_store *ref_store, const char *refname,\n \tstruct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;\n \tint res = 0;\n \n-\toidcpy(oid, null_oid());\n+\toidcpy(oid, null_oid(ref_store->repo->hash_algo));\n \tres = drefs->refs->be->read_raw_ref(drefs->refs, refname, oid, referent,\n \t\t\t\t\t    type, failure_errno);\n \ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 6c6e67dc1c4..ba31cfdb93f 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1270,7 +1270,7 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r)\n \tref_transaction_add_update(\n \t\t\ttransaction, r->name,\n \t\t\tREF_NO_DEREF | REF_HAVE_NEW | REF_HAVE_OLD | REF_IS_PRUNING,\n-\t\t\tnull_oid(), &r->oid, NULL, NULL, NULL, NULL);\n+\t\t\tnull_oid(the_hash_algo), &r->oid, NULL, NULL, NULL, NULL);\n \tif (ref_transaction_commit(transaction, &err))\n \t\tgoto cleanup;\n \ndiff --git a/reset.c b/reset.c\nindex b22b1be792d..bb590271811 100644\n--- a/reset.c\n+++ b/reset.c\n@@ -80,7 +80,7 @@ static int update_refs(const struct reset_head_opts *opts,\n \t}\n \tif (!ret && run_hook)\n \t\trun_hooks_l(the_repository, \"post-checkout\",\n-\t\t\t    oid_to_hex(head ? head : null_oid()),\n+\t\t\t    oid_to_hex(head ? head : null_oid(the_hash_algo)),\n \t\t\t    oid_to_hex(oid), \"1\", NULL);\n \tstrbuf_release(&msg);\n \treturn ret;\ndiff --git a/sequencer.c b/sequencer.c\nindex ad0ab75c8d4..c112d2e1c43 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -265,8 +265,8 @@ static struct update_ref_record *init_update_ref_record(const char *ref)\n \n \tCALLOC_ARRAY(rec, 1);\n \n-\toidcpy(&rec->before, null_oid());\n-\toidcpy(&rec->after, null_oid());\n+\toidcpy(&rec->before, null_oid(the_hash_algo));\n+\toidcpy(&rec->after, null_oid(the_hash_algo));\n \n \t/* This may fail, but that's fine, we will keep the null OID. */\n \trefs_read_ref(get_main_ref_store(the_repository), ref, &rec->before);\n@@ -667,7 +667,7 @@ static int fast_forward_to(struct repository *r,\n \tif (!transaction ||\n \t    ref_transaction_update(transaction, \"HEAD\",\n \t\t\t\t   to, unborn && !is_rebase_i(opts) ?\n-\t\t\t\t   null_oid() : from, NULL, NULL,\n+\t\t\t\t   null_oid(the_hash_algo) : from, NULL, NULL,\n \t\t\t\t   0, sb.buf, &err) ||\n \t    ref_transaction_commit(transaction, &err)) {\n \t\tref_transaction_free(transaction);\n@@ -1301,7 +1301,7 @@ int update_head_with_reflog(const struct commit *old_head,\n \t\t\t\t\t\t  0, err);\n \tif (!transaction ||\n \t    ref_transaction_update(transaction, \"HEAD\", new_head,\n-\t\t\t\t   old_head ? &old_head->object.oid : null_oid(),\n+\t\t\t\t   old_head ? &old_head->object.oid : null_oid(the_hash_algo),\n \t\t\t\t   NULL, NULL, 0, sb.buf, err) ||\n \t    ref_transaction_commit(transaction, err)) {\n \t\tret = -1;\n@@ -4683,7 +4683,7 @@ static void create_autostash_internal(struct repository *r,\n \t\t\twrite_file(path, \"%s\", oid_to_hex(&oid));\n \t\t} else {\n \t\t\trefs_update_ref(get_main_ref_store(r), \"\", refname,\n-\t\t\t\t\t&oid, null_oid(), 0, UPDATE_REFS_DIE_ON_ERR);\n+\t\t\t\t\t&oid, null_oid(the_hash_algo), 0, UPDATE_REFS_DIE_ON_ERR);\n \t\t}\n \n \t\tprintf(_(\"Created autostash: %s\\n\"), buf.buf);\ndiff --git a/submodule-config.c b/submodule-config.c\nindex a25059ed7f8..d82b404b73e 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -831,7 +831,7 @@ static int gitmodules_cb(const char *var, const char *value,\n \n \tparameter.cache = repo->submodule_cache;\n \tparameter.treeish_name = NULL;\n-\tparameter.gitmodules_oid = null_oid();\n+\tparameter.gitmodules_oid = null_oid(the_hash_algo);\n \tparameter.overwrite = 1;\n \n \treturn parse_config(var, value, ctx, &parameter);\ndiff --git a/submodule.c b/submodule.c\nindex 0530e8cf24e..0821507ecaa 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -124,7 +124,7 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)\n \tif (is_gitmodules_unmerged(the_repository->index))\n \t\tdie(_(\"Cannot change unmerged .gitmodules, resolve merge conflicts first\"));\n \n-\tsubmodule = submodule_from_path(the_repository, null_oid(), oldpath);\n+\tsubmodule = submodule_from_path(the_repository, null_oid(the_hash_algo), oldpath);\n \tif (!submodule || !submodule->name) {\n \t\twarning(_(\"Could not find section in .gitmodules where path=%s\"), oldpath);\n \t\treturn -1;\n@@ -153,7 +153,7 @@ int remove_path_from_gitmodules(const char *path)\n \tif (is_gitmodules_unmerged(the_repository->index))\n \t\tdie(_(\"Cannot change unmerged .gitmodules, resolve merge conflicts first\"));\n \n-\tsubmodule = submodule_from_path(the_repository, null_oid(), path);\n+\tsubmodule = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \tif (!submodule || !submodule->name) {\n \t\twarning(_(\"Could not find section in .gitmodules where path=%s\"), path);\n \t\treturn -1;\n@@ -204,7 +204,7 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,\n \t\t\t\t\t     const char *path)\n {\n \tconst struct submodule *submodule = submodule_from_path(the_repository,\n-\t\t\t\t\t\t\t\tnull_oid(),\n+\t\t\t\t\t\t\t\tnull_oid(the_hash_algo),\n \t\t\t\t\t\t\t\tpath);\n \tif (submodule) {\n \t\tconst char *ignore;\n@@ -312,7 +312,7 @@ int is_tree_submodule_active(struct repository *repo,\n \n int is_submodule_active(struct repository *repo, const char *path)\n {\n-\treturn is_tree_submodule_active(repo, null_oid(), path);\n+\treturn is_tree_submodule_active(repo, null_oid(the_hash_algo), path);\n }\n \n int is_submodule_populated_gently(const char *path, int *return_error_code)\n@@ -778,7 +778,7 @@ const struct submodule *submodule_from_ce(const struct cache_entry *ce)\n \tif (!should_update_submodules())\n \t\treturn NULL;\n \n-\treturn submodule_from_path(the_repository, null_oid(), ce->name);\n+\treturn submodule_from_path(the_repository, null_oid(the_hash_algo), ce->name);\n }\n \n \n@@ -1062,7 +1062,7 @@ static int submodule_needs_pushing(struct repository *r,\n \t\t\t\t   const char *path,\n \t\t\t\t   struct oid_array *commits)\n {\n-\tif (!submodule_has_commits(r, path, null_oid(), commits))\n+\tif (!submodule_has_commits(r, path, null_oid(the_hash_algo), commits))\n \t\t/*\n \t\t * NOTE: We do consider it safe to return \"no\" here. The\n \t\t * correct answer would be \"We do not know\" instead of\n@@ -1126,7 +1126,7 @@ int find_unpushed_submodules(struct repository *r,\n \t\tconst struct submodule *submodule;\n \t\tconst char *path = NULL;\n \n-\t\tsubmodule = submodule_from_name(r, null_oid(), name->string);\n+\t\tsubmodule = submodule_from_name(r, null_oid(the_hash_algo), name->string);\n \t\tif (submodule)\n \t\t\tpath = submodule->path;\n \t\telse\n@@ -1351,7 +1351,7 @@ static void calculate_changed_submodule_paths(struct repository *r,\n \t\tconst struct submodule *submodule;\n \t\tconst char *path = NULL;\n \n-\t\tsubmodule = submodule_from_name(r, null_oid(), name->string);\n+\t\tsubmodule = submodule_from_name(r, null_oid(the_hash_algo), name->string);\n \t\tif (submodule)\n \t\t\tpath = submodule->path;\n \t\telse\n@@ -1360,7 +1360,7 @@ static void calculate_changed_submodule_paths(struct repository *r,\n \t\tif (!path)\n \t\t\tcontinue;\n \n-\t\tif (submodule_has_commits(r, path, null_oid(), &cs_data->new_commits)) {\n+\t\tif (submodule_has_commits(r, path, null_oid(the_hash_algo), &cs_data->new_commits)) {\n \t\t\tchanged_submodule_data_clear(cs_data);\n \t\t\t*name->string = '\\0';\n \t\t}\n@@ -1602,7 +1602,7 @@ get_fetch_task_from_index(struct submodule_parallel_fetch *spf,\n \t\tif (!S_ISGITLINK(ce->ce_mode))\n \t\t\tcontinue;\n \n-\t\ttask = fetch_task_create(spf, ce->name, null_oid());\n+\t\ttask = fetch_task_create(spf, ce->name, null_oid(the_hash_algo));\n \t\tif (!task)\n \t\t\tcontinue;\n \n@@ -2166,7 +2166,7 @@ int submodule_move_head(const char *path, const char *super_prefix,\n \tif (old_head && !is_submodule_populated_gently(path, error_code_ptr))\n \t\treturn 0;\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \n \tif (!sub)\n \t\tBUG(\"could not get submodule information for '%s'\", path);\n@@ -2376,7 +2376,7 @@ static void relocate_single_git_dir_into_superproject(const char *path,\n \n \treal_old_git_dir = real_pathdup(old_git_dir, 1);\n \n-\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \tif (!sub)\n \t\tdie(_(\"could not lookup name for submodule '%s'\"), path);\n \n@@ -2462,7 +2462,7 @@ void absorb_git_dir_into_superproject(const char *path,\n \t\t* superproject did not rewrite the git file links yet,\n \t\t* fix it now.\n \t\t*/\n-\t\tsub = submodule_from_path(the_repository, null_oid(), path);\n+\t\tsub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);\n \t\tif (!sub)\n \t\t\tdie(_(\"could not lookup name for submodule '%s'\"), path);\n \t\tsubmodule_name_to_gitdir(&sub_gitdir, the_repository, sub->name);\n@@ -2594,7 +2594,7 @@ int submodule_to_gitdir(struct repository *repo,\n \t\tstrbuf_addstr(buf, git_dir);\n \t}\n \tif (!is_git_directory(buf->buf)) {\n-\t\tsub = submodule_from_path(repo, null_oid(), submodule);\n+\t\tsub = submodule_from_path(repo, null_oid(the_hash_algo), submodule);\n \t\tif (!sub) {\n \t\t\tret = -1;\n \t\t\tgoto cleanup;\ndiff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c\nindex e00fce592b1..2ff67c067ac 100644\n--- a/t/helper/test-ref-store.c\n+++ b/t/helper/test-ref-store.c\n@@ -179,7 +179,7 @@ static int cmd_for_each_ref__exclude(struct ref_store *refs, const char **argv)\n \n static int cmd_resolve_ref(struct ref_store *refs, const char **argv)\n {\n-\tstruct object_id oid = *null_oid();\n+\tstruct object_id oid = *null_oid(the_hash_algo);\n \tconst char *refname = notnull(*argv++, \"refname\");\n \tint resolve_flags = arg_flags(*argv++, \"resolve-flags\", empty_flags);\n \tint flags;\ndiff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c\nindex 6dce9571531..2710341cd5d 100644\n--- a/t/helper/test-submodule-nested-repo-config.c\n+++ b/t/helper/test-submodule-nested-repo-config.c\n@@ -21,7 +21,7 @@ int cmd__submodule_nested_repo_config(int argc, const char **argv)\n \n \tsetup_git_directory();\n \n-\tif (repo_submodule_init(&subrepo, the_repository, argv[1], null_oid())) {\n+\tif (repo_submodule_init(&subrepo, the_repository, argv[1], null_oid(the_hash_algo))) {\n \t\tdie_usage(argv, \"Submodule not found.\");\n \t}\n \ndiff --git a/tree-diff.c b/tree-diff.c\nindex 60c558c2b56..e00fc2f450d 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -181,7 +181,7 @@ static void emit_path(struct combine_diff_path ***tail,\n \n \t\tstrbuf_add(base, path, pathlen);\n \t\tp = combine_diff_path_new(base->buf, base->len, mode,\n-\t\t\t\t\t  oid ? oid : null_oid(),\n+\t\t\t\t\t  oid ? oid : null_oid(the_hash_algo),\n \t\t\t\t\t  nparent);\n \t\tstrbuf_setlen(base, old_baselen);\n \n@@ -206,7 +206,7 @@ static void emit_path(struct combine_diff_path ***tail,\n \t\t\t\tmode_i = tp[i].entry.mode;\n \t\t\t}\n \t\t\telse {\n-\t\t\t\toid_i = null_oid();\n+\t\t\t\toid_i = null_oid(the_hash_algo);\n \t\t\t\tmode_i = 0;\n \t\t\t}\n \ndiff --git a/upload-pack.c b/upload-pack.c\nindex 7412d3c6ce8..0fa8fbdd6de 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -1446,7 +1446,7 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,\n \t\tfor_each_namespaced_ref_1(send_ref, &data);\n \t\tif (!data.sent_capabilities) {\n \t\t\tconst char *refname = \"capabilities^{}\";\n-\t\t\twrite_v0_ref(&data, refname, refname, null_oid());\n+\t\t\twrite_v0_ref(&data, refname, refname, null_oid(the_hash_algo));\n \t\t}\n \t\t/*\n \t\t * fflush stdout before calling advertise_shallow_grafts because send_ref\ndiff --git a/wt-status.c b/wt-status.c\nindex 1da5732f57b..454601afa15 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1824,10 +1824,10 @@ void wt_status_get_state(struct repository *r,\n \tif (!sequencer_get_last_command(r, &action)) {\n \t\tif (action == REPLAY_PICK && !state->cherry_pick_in_progress) {\n \t\t\tstate->cherry_pick_in_progress = 1;\n-\t\t\toidcpy(&state->cherry_pick_head_oid, null_oid());\n+\t\t\toidcpy(&state->cherry_pick_head_oid, null_oid(the_hash_algo));\n \t\t} else if (action == REPLAY_REVERT && !state->revert_in_progress) {\n \t\t\tstate->revert_in_progress = 1;\n-\t\t\toidcpy(&state->revert_head_oid, null_oid());\n+\t\t\toidcpy(&state->revert_head_oid, null_oid(the_hash_algo));\n \t\t}\n \t}\n \tif (get_detached_from)\ndiff --git a/xdiff-interface.c b/xdiff-interface.c\nindex 3bd61f26e90..77712811ff1 100644\n--- a/xdiff-interface.c\n+++ b/xdiff-interface.c\n@@ -181,7 +181,7 @@ void read_mmblob(mmfile_t *ptr, const struct object_id *oid)\n \tunsigned long size;\n \tenum object_type type;\n \n-\tif (oideq(oid, null_oid())) {\n+\tif (oideq(oid, null_oid(the_hash_algo))) {\n \t\tptr->ptr = xstrdup(\"\");\n \t\tptr->size = 0;\n \t\treturn;\n\n-- \n2.49.0.rc1.455.g4cd33545ba.dirty\n\n"},{"id":"513903","messageId":"xmqqjz8waoax.fsf@gitster.g","threadId":"63046","inReplyTo":"CABPp-BG0AtKdUH2g8+_f0J0ViWs5xZKM9kCcbWYZ=uEu6bswdQ@mail.gmail.com","subject":"Re: [PATCH v3 12/12] hash: stop depending on `the_repository` in `null_oid()`","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-03-10T15:38:30Z","receivedAt":"2025-03-10T15:38:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Elijah Newren <newren@gmail.com> writes:\n\n>> @@ -4304,7 +4304,7 @@ static int process_entry(struct merge_options *opt,\n>>                 /* Deleted on both sides */\n>>                 ci->merged.is_null = 1;\n>>                 ci->merged.result.mode = 0;\n>> -               oidcpy(&ci->merged.result.oid, null_oid());\n>> +               oidcpy(&ci->merged.result.oid, null_oid(the_hash_algo));\n>>                 assert(!ci->df_conflict);\n>>                 ci->merged.clean = !ci->path_conflict;\n>>         }\n>\n> What you have is an improvement since it's at least making things\n> explicit, but these should really be opt->repo->hash_algo.\n\nI think this is following the typical pattern in recent topics of\nthis sort, i.e. first make things explicit and use \"the\" singleton\ninstance, with the plan to find if there are instances more\nappropriate in the context.  When we passed a repo instance through\nthe call chain, the caller at the root may have passed the_repository\ndown the call chain, to make sure everybody down below will be\nbug-to-bug compatible (because they either used the_repository or\nused a helper that implicitly always used the_repository).  This is\ndoing the same, and your \"but these should really be\" belongs to the\n\"with the plan to find\" phase, which may come later but outside the\nscope of this series.\n\nIncidentally, that is the reason why the use of superproject\nrepository instead of the_repository was singled out in the proposed\ncommit log message.  It should have been mechanical replacement to\nmake this step mechanical and easier to audit, but with another\ntopic in flight that semantically conflicts the changes in ths\npatch, it took an exception.\n\n"},{"id":"513950","messageId":"CABPp-BGXJ38txpr=B_xi7V4+uVhLiDX2n=czZjoX3f+-9E6ZRQ@mail.gmail.com","threadId":"63046","inReplyTo":"Z86Qh1yLUC7aIaG9@pks.im","subject":"Re: [PATCH v3 12/12] hash: stop depending on `the_repository` in `null_oid()`","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2025-03-10T22:37:00Z","receivedAt":"2025-03-10T22:37:12Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Mon, Mar 10, 2025 at 12:11 AM Patrick Steinhardt <ps@pks.im> wrote:\n>\n> On Sat, Mar 08, 2025 at 08:05:09AM -0800, Elijah Newren wrote:\n\n> > What you have is an improvement since it's at least making things\n> > explicit, but these should really be opt->repo->hash_algo.\n>\n> Oh, yeah, I suspect that we'll have a bunch of places where we can\n> already plug in a repository as available via the context. I typically\n> refrain from doing though unless really necessary (e.g. when the file at\n> hand doesn't declare `USE_THE_REPOSITORY_VARIABLE` anymore). This is so\n> that neither I nor reviewers have to carefully vet every callsite, but\n> to make this a mechanical change that is obviously correct because it is\n> identical to the old state. So I'm basically leaving it to the next\n> patch series that gets rid of `USE_THE_REPOSITORY_VARIABLE` to think\n> more carefully about those callsites.\n\nAh, ok, that makes sense.  Thanks for the context.\n"},{"id":"513952","messageId":"CABPp-BFrjqf=dMNwxzyMj3EQrAXTYkH7rDTi7X7xoWnoW_A4eA@mail.gmail.com","threadId":"63046","inReplyTo":"20250310-b4-pks-objects-without-the-repository-v4-0-f201b8ec57ba@pks.im","subject":"Re: [PATCH v4 00/12] Stop depending on `the_repository` in object-related subsystems","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2025-03-10T22:39:01Z","receivedAt":"2025-03-10T22:39:13Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Mon, Mar 10, 2025 at 12:13 AM Patrick Steinhardt <ps@pks.im> wrote:\n>\n> Hi,\n>\n> this patch series is another step to remove our dependency on the global\n> `the_repository` variable. The series focusses on subsystems related to\n> objects.\n>\n[...]\n> Changes in v4:\n>   - Fix indentation in one of the commit messages.\n>   - Link to v3: https://lore.kernel.org/r/20250307-b4-pks-objects-without-the-repository-v3-0-7bccf408731e@pks.im\n\nThanks, v4 looks good to me.\n\n>\n> Thanks!\n>\n> Patrick\n>\n> ---\n> Patrick Steinhardt (12):\n>       csum-file: stop depending on `the_repository`\n>       object: stop depending on `the_repository`\n>       pack-write: stop depending on `the_repository` and `the_hash_algo`\n>       environment: move access to \"core.bigFileThreshold\" into repo settings\n>       pack-check: stop depending on `the_repository`\n>       pack-revindex: stop depending on `the_repository`\n>       pack-bitmap-write: stop depending on `the_repository`\n>       object-file-convert: stop depending on `the_repository`\n>       delta-islands: stop depending on `the_repository`\n>       object-file: split out logic regarding hash algorithms\n>       hash: fix \"-Wsign-compare\" warnings\n>       hash: stop depending on `the_repository` in `null_oid()`\n>\n>  Makefile                                     |   1 +\n>  archive.c                                    |   4 +-\n>  blame.c                                      |   2 +-\n>  branch.c                                     |   2 +-\n>  builtin/checkout.c                           |   6 +-\n>  builtin/clone.c                              |   2 +-\n>  builtin/describe.c                           |   2 +-\n>  builtin/diff.c                               |   5 +-\n>  builtin/fast-export.c                        |  10 +-\n>  builtin/fast-import.c                        |   8 +-\n>  builtin/fsck.c                               |   6 +-\n>  builtin/grep.c                               |   4 +-\n>  builtin/index-pack.c                         |  16 +-\n>  builtin/log.c                                |   2 +-\n>  builtin/ls-files.c                           |   3 +-\n>  builtin/name-rev.c                           |   4 +-\n>  builtin/pack-objects.c                       |  17 +-\n>  builtin/prune.c                              |   2 +-\n>  builtin/rebase.c                             |   2 +-\n>  builtin/receive-pack.c                       |   2 +-\n>  builtin/submodule--helper.c                  |  36 ++--\n>  builtin/tag.c                                |   2 +-\n>  builtin/unpack-objects.c                     |   5 +-\n>  builtin/update-ref.c                         |   2 +-\n>  builtin/worktree.c                           |   2 +-\n>  bulk-checkin.c                               |   4 +-\n>  combine-diff.c                               |   2 +-\n>  commit-graph.c                               |   9 +-\n>  commit.c                                     |   2 +-\n>  config.c                                     |   5 -\n>  csum-file.c                                  |  28 +--\n>  csum-file.h                                  |  12 +-\n>  delta-islands.c                              |  14 +-\n>  delta-islands.h                              |   2 +-\n>  diff-lib.c                                   |  10 +-\n>  diff-no-index.c                              |  28 +--\n>  diff.c                                       |  14 +-\n>  diff.h                                       |   2 +-\n>  dir.c                                        |   2 +-\n>  environment.c                                |   1 -\n>  environment.h                                |   1 -\n>  grep.c                                       |   2 +-\n>  hash.c                                       | 277 +++++++++++++++++++++++++\n>  hash.h                                       |   4 +-\n>  log-tree.c                                   |   2 +-\n>  merge-ort.c                                  |  26 +--\n>  merge-recursive.c                            |  12 +-\n>  meson.build                                  |   1 +\n>  midx-write.c                                 |  12 +-\n>  midx.c                                       |   3 +-\n>  notes-merge.c                                |   2 +-\n>  notes.c                                      |   2 +-\n>  object-file-convert.c                        |  29 +--\n>  object-file-convert.h                        |   3 +-\n>  object-file.c                                | 292 +--------------------------\n>  object.c                                     |  21 +-\n>  object.h                                     |  10 +-\n>  pack-bitmap-write.c                          |  36 ++--\n>  pack-bitmap.c                                |  15 +-\n>  pack-bitmap.h                                |   1 +\n>  pack-check.c                                 |  12 +-\n>  pack-revindex.c                              |  35 ++--\n>  pack-write.c                                 |  55 +++--\n>  pack.h                                       |  11 +-\n>  parse-options-cb.c                           |   2 +-\n>  range-diff.c                                 |   2 +-\n>  reachable.c                                  |   6 +-\n>  read-cache.c                                 |   4 +-\n>  refs.c                                       |  12 +-\n>  refs/debug.c                                 |   2 +-\n>  refs/files-backend.c                         |   2 +-\n>  repo-settings.c                              |  20 ++\n>  repo-settings.h                              |   5 +\n>  reset.c                                      |   2 +-\n>  revision.c                                   |   3 +-\n>  sequencer.c                                  |  10 +-\n>  shallow.c                                    |  10 +-\n>  streaming.c                                  |   3 +-\n>  submodule-config.c                           |   2 +-\n>  submodule.c                                  |  28 +--\n>  t/helper/test-ref-store.c                    |   2 +-\n>  t/helper/test-submodule-nested-repo-config.c |   2 +-\n>  t/t1050-large.sh                             |   3 +-\n>  tree-diff.c                                  |   4 +-\n>  upload-pack.c                                |  14 +-\n>  wt-status.c                                  |   4 +-\n>  xdiff-interface.c                            |   2 +-\n>  87 files changed, 677 insertions(+), 613 deletions(-)\n>\n> Range-diff versus v3:\n>\n>  1:  01b5b16c3a4 =  1:  9d65ce9a2f2 csum-file: stop depending on `the_repository`\n>  2:  14e0349be2f =  2:  038c6e54308 object: stop depending on `the_repository`\n>  3:  9c7b8a031cc =  3:  9abd1306d6a pack-write: stop depending on `the_repository` and `the_hash_algo`\n>  4:  e0168b431e7 =  4:  605fb2a7176 environment: move access to \"core.bigFileThreshold\" into repo settings\n>  5:  529f296a935 =  5:  dc88e5ca6b2 pack-check: stop depending on `the_repository`\n>  6:  d4a2e9a7861 =  6:  fee92049913 pack-revindex: stop depending on `the_repository`\n>  7:  15e4d4de519 =  7:  f8ff74c83cf pack-bitmap-write: stop depending on `the_repository`\n>  8:  576d846495f =  8:  47547d3f566 object-file-convert: stop depending on `the_repository`\n>  9:  faf0f90a005 =  9:  39da917072f delta-islands: stop depending on `the_repository`\n> 10:  b37879d101c = 10:  a509d63ee74 object-file: split out logic regarding hash algorithms\n> 11:  4a1a5c67792 = 11:  421f1e96595 hash: fix \"-Wsign-compare\" warnings\n> 12:  f45a7866d03 ! 12:  1b0b8f71125 hash: stop depending on `the_repository` in `null_oid()`\n>     @@ Commit message\n>              object in the superproject, and consequently we need to use its hash\n>              algorithm.\n>\n>     -    This means that we could in theory just not bother about this edge case\n>     -    at all and just use `the_repository` in \"diff-no-index.c\". But doing so\n>     -    would feel misdesigned.\n>     +        This means that we could in theory just not bother about this edge\n>     +        case at all and just use `the_repository` in \"diff-no-index.c\". But\n>     +        doing so would feel misdesigned.\n>\n>          Remove the `USE_THE_REPOSITORY_VARIABLE` preprocessor define in\n>          \"hash.c\".\n>\n> ---\n> base-commit: e2cb568e11f4ceb427ba4205e6b8a4426d26be12\n> change-id: 20250210-b4-pks-objects-without-the-repository-6ba8398f7cc0\n>\n"}]}