{"thread":{"id":"64765","subject":"[PATCH 00/10] tree: stop using the_repository","startedAt":"2026-01-09T21:30:23Z","lastAt":"2026-01-16T17:28:37Z","messageCount":25,"participants":["René Scharfe","Patrick Steinhardt","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":10},"messages":[{"id":"533437","messageId":"20260109213021.2546-1-l.s.r@web.de","threadId":"64765","inReplyTo":null,"subject":"[PATCH 00/10] tree: stop using the_repository","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-09T21:30:11Z","receivedAt":"2026-01-09T21:30:23Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"The tree parsing functions use the_repository internally.  Add variants\nthat allow using arbitrary repositories.  Fix callers one by one for\nwhich had USE_THE_REPOSITORY_VARIABLE removed despite this implicit\nusage and convert the rest mechanically.\n\n  environment: move access to core.maxTreeDepth into repo settings\n  tree: add repo_parse_tree*()\n  add-interactive: use repo_parse_tree_indirect()\n  bloom: use repo_parse_tree()\n  delta-islands: use repo_parse_tree()\n  pack-bitmap-write: use repo_parse_tree()\n  path-walk: use repo_parse_tree_gently()\n  tree: use repo_parse_tree()\n  tree: stop using the_repository\n  cocci: convert parse_tree functions to repo_ variants\n\n add-interactive.c                       |  2 +-\n archive.c                               |  2 +-\n bloom.c                                 |  2 +-\n builtin/am.c                            | 10 ++++-----\n builtin/checkout.c                      | 12 +++++-----\n builtin/clone.c                         |  4 ++--\n builtin/commit.c                        |  5 +++--\n builtin/diff-tree.c                     |  2 +-\n builtin/ls-tree.c                       |  2 +-\n builtin/merge-tree.c                    |  9 +++++---\n builtin/merge.c                         |  8 +++----\n builtin/read-tree.c                     |  4 ++--\n builtin/reset.c                         |  4 ++--\n builtin/stash.c                         |  8 +++----\n cache-tree.c                            |  2 +-\n contrib/coccinelle/the_repository.cocci | 10 +++++++++\n delta-islands.c                         |  2 +-\n diff-lib.c                              |  2 +-\n environment.c                           | 29 -------------------------\n environment.h                           |  1 -\n fsck.c                                  |  2 +-\n git-compat-util.h                       | 24 ++++++++++++++++++++\n http-push.c                             |  2 +-\n list-objects.c                          |  4 ++--\n merge-ort.c                             | 13 ++++++-----\n merge.c                                 |  6 ++---\n pack-bitmap-write.c                     |  2 +-\n path-walk.c                             |  2 +-\n read-cache.c                            |  2 +-\n repo-settings.c                         |  3 +++\n repo-settings.h                         |  3 +++\n reset.c                                 |  2 +-\n revision.c                              |  4 ++--\n sequencer.c                             |  4 ++--\n t/helper/test-cache-tree.c              |  2 +-\n t/helper/test-match-trees.c             |  4 ++--\n tree-diff.c                             |  2 +-\n tree-walk.c                             |  4 +++-\n tree.c                                  | 16 ++++++--------\n tree.h                                  | 13 +++++++----\n walker.c                                |  2 +-\n 41 files changed, 129 insertions(+), 107 deletions(-)\n\n-- \n2.52.0\n\n"},{"id":"533438","messageId":"20260109213021.2546-4-l.s.r@web.de","threadId":"64765","inReplyTo":"20260109213021.2546-1-l.s.r@web.de","subject":"[PATCH 03/10] add-interactive: use repo_parse_tree_indirect()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-09T21:30:14Z","receivedAt":"2026-01-09T21:30:24Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"1b374ad71f (add-interactive: stop using `the_repository`, 2024-12-17)\nreplaced explicit uses of the_repository.  parse_tree_indirect() uses it\ninternally, though, so call repo_parse_tree_indirect() instead and hand\nit the correct repository.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n add-interactive.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/add-interactive.c b/add-interactive.c\nindex 68fc09547dd..95ec5a89f8c 100644\n--- a/add-interactive.c\n+++ b/add-interactive.c\n@@ -840,7 +840,7 @@ static int run_revert(struct add_i_state *s, const struct pathspec *ps,\n \tif (is_initial)\n \t\toidcpy(&oid, s->r->hash_algo->empty_tree);\n \telse {\n-\t\ttree = parse_tree_indirect(&oid);\n+\t\ttree = repo_parse_tree_indirect(s->r, &oid);\n \t\tif (!tree) {\n \t\t\tres = error(_(\"Could not parse HEAD^{tree}\"));\n \t\t\tgoto finish_revert;\n-- \n2.52.0\n\n"},{"id":"533439","messageId":"20260109213021.2546-5-l.s.r@web.de","threadId":"64765","inReplyTo":"20260109213021.2546-1-l.s.r@web.de","subject":"[PATCH 04/10] bloom: use repo_parse_tree()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-09T21:30:15Z","receivedAt":"2026-01-09T21:30:24Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Use the passed in repository instead of the implicit the_repository when\nparsing the tree.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n bloom.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/bloom.c b/bloom.c\nindex 2d7b951e5bf..77a6fddf720 100644\n--- a/bloom.c\n+++ b/bloom.c\n@@ -354,7 +354,7 @@ static void init_truncated_large_filter(struct bloom_filter *filter,\n \n static int has_entries_with_high_bit(struct repository *r, struct tree *t)\n {\n-\tif (parse_tree(t))\n+\tif (repo_parse_tree(r, t))\n \t\treturn 1;\n \n \tif (!(t->object.flags & VISITED)) {\n-- \n2.52.0\n\n"},{"id":"533440","messageId":"20260109213021.2546-9-l.s.r@web.de","threadId":"64765","inReplyTo":"20260109213021.2546-1-l.s.r@web.de","subject":"[PATCH 08/10] tree: use repo_parse_tree()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-09T21:30:19Z","receivedAt":"2026-01-09T21:30:24Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"e092073d64 (tree.c: make read_tree*() take 'struct repository *',\n2018-11-18) replaced explicit uses of the_repository.  parse_tree() uses\nit internally, though, so call repo_parse_tree() instead and hand it the\ncorrect repository.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n tree.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/tree.c b/tree.c\nindex 036f56ca29b..edcf6a284cb 100644\n--- a/tree.c\n+++ b/tree.c\n@@ -28,7 +28,7 @@ int read_tree_at(struct repository *r,\n \tif (depth > r->settings.max_allowed_tree_depth)\n \t\treturn error(\"exceeded maximum allowed tree depth\");\n \n-\tif (parse_tree(tree))\n+\tif (repo_parse_tree(r, tree))\n \t\treturn -1;\n \n \tinit_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);\n-- \n2.52.0\n\n"},{"id":"533441","messageId":"20260109213021.2546-10-l.s.r@web.de","threadId":"64765","inReplyTo":"20260109213021.2546-1-l.s.r@web.de","subject":"[PATCH 09/10] tree: stop using the_repository","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-09T21:30:20Z","receivedAt":"2026-01-09T21:30:25Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Push the use of the_repository to the remaining callers by turning the\ncompatibility wrappers into macros, whose use still requires\nUSE_THE_REPOSITORY_VARIABLE to be defined.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n tree.c | 12 ------------\n tree.h |  9 +++------\n 2 files changed, 3 insertions(+), 18 deletions(-)\n\ndiff --git a/tree.c b/tree.c\nindex edcf6a284cb..d703ab97c83 100644\n--- a/tree.c\n+++ b/tree.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"hex.h\"\n #include \"tree.h\"\n@@ -185,11 +183,6 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)\n \treturn 0;\n }\n \n-int parse_tree_gently(struct tree *item, int quiet_on_missing)\n-{\n-\treturn repo_parse_tree_gently(the_repository, item, quiet_on_missing);\n-}\n-\n int repo_parse_tree_gently(struct repository *r, struct tree *item,\n \t\t\t   int quiet_on_missing)\n {\n@@ -219,11 +212,6 @@ void free_tree_buffer(struct tree *tree)\n \ttree->object.parsed = 0;\n }\n \n-struct tree *parse_tree_indirect(const struct object_id *oid)\n-{\n-\treturn repo_parse_tree_indirect(the_repository, oid);\n-}\n-\n struct tree *repo_parse_tree_indirect(struct repository *r,\n \t\t\t\t      const struct object_id *oid)\n {\ndiff --git a/tree.h b/tree.h\nindex 9037891d30f..677382eed86 100644\n--- a/tree.h\n+++ b/tree.h\n@@ -19,13 +19,10 @@ struct tree *lookup_tree(struct repository *r, const struct object_id *oid);\n \n int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size);\n \n-int parse_tree_gently(struct tree *tree, int quiet_on_missing);\n+#define parse_tree_gently(t, q) repo_parse_tree_gently(the_repository, t, q)\n int repo_parse_tree_gently(struct repository *r, struct tree *item,\n \t\t\t   int quiet_on_missing);\n-static inline int parse_tree(struct tree *tree)\n-{\n-\treturn parse_tree_gently(tree, 0);\n-}\n+#define parse_tree(t) repo_parse_tree(the_repository, t)\n static inline int repo_parse_tree(struct repository *r, struct tree *item)\n {\n \treturn repo_parse_tree_gently(r, item, 0);\n@@ -33,7 +30,7 @@ static inline int repo_parse_tree(struct repository *r, struct tree *item)\n void free_tree_buffer(struct tree *tree);\n \n /* Parses and returns the tree in the given ent, chasing tags and commits. */\n-struct tree *parse_tree_indirect(const struct object_id *oid);\n+#define parse_tree_indirect(o) repo_parse_tree_indirect(the_repository, o)\n struct tree *repo_parse_tree_indirect(struct repository *r,\n \t\t\t\t      const struct object_id *oid);\n \n-- \n2.52.0\n\n"},{"id":"533442","messageId":"20260109213021.2546-11-l.s.r@web.de","threadId":"64765","inReplyTo":"20260109213021.2546-1-l.s.r@web.de","subject":"[PATCH 10/10] cocci: convert parse_tree functions to repo_ variants","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-09T21:30:21Z","receivedAt":"2026-01-09T21:30:25Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Add and apply a semantic patch to convert calls to parse_tree() and\nfriends to the corresponding variant that takes a repository argument,\nto allow the functions that implicitly use the_repository to be retired\nonce all potential in-flight topics are settled and converted as well.\n\nThe changes in .c files were generated by Coccinelle, but I fixed a\nwhitespace bug it would have introduced to builtin/commit.c.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n archive.c                               |  2 +-\n builtin/am.c                            | 10 +++++-----\n builtin/checkout.c                      | 12 +++++++-----\n builtin/clone.c                         |  4 ++--\n builtin/commit.c                        |  5 +++--\n builtin/diff-tree.c                     |  2 +-\n builtin/ls-tree.c                       |  2 +-\n builtin/merge-tree.c                    |  9 ++++++---\n builtin/merge.c                         |  8 ++++----\n builtin/read-tree.c                     |  4 ++--\n builtin/reset.c                         |  4 ++--\n builtin/stash.c                         |  8 ++++----\n cache-tree.c                            |  2 +-\n contrib/coccinelle/the_repository.cocci | 10 ++++++++++\n diff-lib.c                              |  2 +-\n fsck.c                                  |  2 +-\n http-push.c                             |  2 +-\n list-objects.c                          |  2 +-\n merge-ort.c                             | 13 +++++++------\n merge.c                                 |  6 +++---\n read-cache.c                            |  2 +-\n reset.c                                 |  2 +-\n revision.c                              |  4 ++--\n sequencer.c                             |  4 ++--\n t/helper/test-cache-tree.c              |  2 +-\n t/helper/test-match-trees.c             |  4 ++--\n walker.c                                |  2 +-\n 27 files changed, 73 insertions(+), 56 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex 310672b479a..fcd474c682f 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -519,7 +519,7 @@ static void parse_treeish_arg(const char **argv,\n \tif (ar_args->mtime_option)\n \t\tarchive_time = approxidate(ar_args->mtime_option);\n \n-\ttree = parse_tree_indirect(&oid);\n+\ttree = repo_parse_tree_indirect(the_repository, &oid);\n \tif (!tree)\n \t\tdie(_(\"not a tree object: %s\"), oid_to_hex(&oid));\n \ndiff --git a/builtin/am.c b/builtin/am.c\nindex 277c2e7937d..b66a33d8a88 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1998,7 +1998,7 @@ static int fast_forward_to(struct tree *head, struct tree *remote, int reset)\n \tstruct unpack_trees_options opts;\n \tstruct tree_desc t[2];\n \n-\tif (parse_tree(head) || parse_tree(remote))\n+\tif (repo_parse_tree(the_repository, head) || repo_parse_tree(the_repository, remote))\n \t\treturn -1;\n \n \trepo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);\n@@ -2038,7 +2038,7 @@ static int merge_tree(struct tree *tree)\n \tstruct unpack_trees_options opts;\n \tstruct tree_desc t[1];\n \n-\tif (parse_tree(tree))\n+\tif (repo_parse_tree(the_repository, tree))\n \t\treturn -1;\n \n \trepo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);\n@@ -2071,11 +2071,11 @@ static int clean_index(const struct object_id *head, const struct object_id *rem\n \tstruct tree *head_tree, *remote_tree, *index_tree;\n \tstruct object_id index;\n \n-\thead_tree = parse_tree_indirect(head);\n+\thead_tree = repo_parse_tree_indirect(the_repository, head);\n \tif (!head_tree)\n \t\treturn error(_(\"Could not parse object '%s'.\"), oid_to_hex(head));\n \n-\tremote_tree = parse_tree_indirect(remote);\n+\tremote_tree = repo_parse_tree_indirect(the_repository, remote);\n \tif (!remote_tree)\n \t\treturn error(_(\"Could not parse object '%s'.\"), oid_to_hex(remote));\n \n@@ -2089,7 +2089,7 @@ static int clean_index(const struct object_id *head, const struct object_id *rem\n \t\t\t\t0, NULL))\n \t\treturn -1;\n \n-\tindex_tree = parse_tree_indirect(&index);\n+\tindex_tree = repo_parse_tree_indirect(the_repository, &index);\n \tif (!index_tree)\n \t\treturn error(_(\"Could not parse object '%s'.\"), oid_to_hex(&index));\n \ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 261699e2f5f..0ba4f03f2ee 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -724,7 +724,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,\n \tinit_checkout_metadata(&opts.meta, info->refname,\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+\tif (repo_parse_tree(the_repository, tree) < 0)\n \t\treturn 128;\n \tinit_tree_desc(&tree_desc, &tree->object.oid, tree->buffer, tree->size);\n \tswitch (unpack_trees(1, &tree_desc, &opts)) {\n@@ -803,7 +803,8 @@ static int merge_working_tree(const struct checkout_opts *opts,\n \tif (opts->new_orphan_branch && opts->orphan_from_empty_tree) {\n \t\tif (new_branch_info->commit)\n \t\t\tBUG(\"'switch --orphan' should never accept a commit as starting point\");\n-\t\tnew_tree = parse_tree_indirect(the_hash_algo->empty_tree);\n+\t\tnew_tree = repo_parse_tree_indirect(the_repository,\n+\t\t\t\t\t\t    the_hash_algo->empty_tree);\n \t\tif (!new_tree)\n \t\t\tBUG(\"unable to read empty tree\");\n \t} else {\n@@ -841,14 +842,15 @@ static int merge_working_tree(const struct checkout_opts *opts,\n \t\told_commit_oid = old_branch_info->commit ?\n \t\t\t&old_branch_info->commit->object.oid :\n \t\t\tthe_hash_algo->empty_tree;\n-\t\ttree = parse_tree_indirect(old_commit_oid);\n+\t\ttree = repo_parse_tree_indirect(the_repository,\n+\t\t\t\t\t\told_commit_oid);\n \t\tif (!tree)\n \t\t\tdie(_(\"unable to parse commit %s\"),\n \t\t\t\toid_to_hex(old_commit_oid));\n \n \t\tinit_tree_desc(&trees[0], &tree->object.oid,\n \t\t\t       tree->buffer, tree->size);\n-\t\tif (parse_tree(new_tree) < 0)\n+\t\tif (repo_parse_tree(the_repository, new_tree) < 0)\n \t\t\tdie(NULL);\n \t\ttree = new_tree;\n \t\tinit_tree_desc(&trees[1], &tree->object.oid,\n@@ -1278,7 +1280,7 @@ static void setup_new_branch_info_and_source_tree(\n \tnew_branch_info->commit = lookup_commit_reference_gently(the_repository, rev, 1);\n \tif (!new_branch_info->commit) {\n \t\t/* not a commit */\n-\t\t*source_tree = parse_tree_indirect(rev);\n+\t\t*source_tree = repo_parse_tree_indirect(the_repository, rev);\n \t\tif (!*source_tree)\n \t\t\tdie(_(\"unable to read tree (%s)\"), oid_to_hex(rev));\n \t} else {\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex b19b302b065..b40cee59680 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -680,10 +680,10 @@ static int checkout(int submodule_progress, int filter_submodules,\n \topts.dst_index = the_repository->index;\n \tinit_checkout_metadata(&opts.meta, head, &oid, NULL);\n \n-\ttree = parse_tree_indirect(&oid);\n+\ttree = repo_parse_tree_indirect(the_repository, &oid);\n \tif (!tree)\n \t\tdie(_(\"unable to parse commit %s\"), oid_to_hex(&oid));\n-\tif (parse_tree(tree) < 0)\n+\tif (repo_parse_tree(the_repository, tree) < 0)\n \t\texit(128);\n \tinit_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size);\n \tif (unpack_trees(1, &t, &opts) < 0)\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 0243f17d53c..8e901fe8db7 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -327,10 +327,11 @@ static void create_base_index(const struct commit *current_head)\n \topts.dst_index = the_repository->index;\n \n \topts.fn = oneway_merge;\n-\ttree = parse_tree_indirect(&current_head->object.oid);\n+\ttree = repo_parse_tree_indirect(the_repository,\n+\t\t\t\t\t&current_head->object.oid);\n \tif (!tree)\n \t\tdie(_(\"failed to unpack HEAD tree object\"));\n-\tif (parse_tree(tree) < 0)\n+\tif (repo_parse_tree(the_repository, tree) < 0)\n \t\texit(128);\n \tinit_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size);\n \tif (unpack_trees(1, &t, &opts))\ndiff --git a/builtin/diff-tree.c b/builtin/diff-tree.c\nindex 49dd4d00ebf..740d9a791c9 100644\n--- a/builtin/diff-tree.c\n+++ b/builtin/diff-tree.c\n@@ -52,7 +52,7 @@ static int stdin_diff_trees(struct tree *tree1, const char *p)\n \tif (!isspace(*p++) || parse_oid_hex(p, &oid, &p) || *p)\n \t\treturn error(\"Need exactly two trees, separated by a space\");\n \ttree2 = lookup_tree(the_repository, &oid);\n-\tif (!tree2 || parse_tree(tree2))\n+\tif (!tree2 || repo_parse_tree(the_repository, tree2))\n \t\treturn -1;\n \tprintf(\"%s %s\\n\", oid_to_hex(&tree1->object.oid),\n \t\t\t  oid_to_hex(&tree2->object.oid));\ndiff --git a/builtin/ls-tree.c b/builtin/ls-tree.c\nindex ec6940fc7c4..113e4a960dc 100644\n--- a/builtin/ls-tree.c\n+++ b/builtin/ls-tree.c\n@@ -421,7 +421,7 @@ int cmd_ls_tree(int argc,\n \tfor (i = 0; i < options.pathspec.nr; i++)\n \t\toptions.pathspec.items[i].nowildcard_len = options.pathspec.items[i].len;\n \toptions.pathspec.has_wildcard = 0;\n-\ttree = parse_tree_indirect(&oid);\n+\ttree = repo_parse_tree_indirect(the_repository, &oid);\n \tif (!tree)\n \t\tdie(\"not a tree object\");\n \t/*\ndiff --git a/builtin/merge-tree.c b/builtin/merge-tree.c\nindex 1c063d9a41a..a6e6d5b555f 100644\n--- a/builtin/merge-tree.c\n+++ b/builtin/merge-tree.c\n@@ -447,17 +447,20 @@ static int real_merge(struct merge_tree_options *o,\n \n \t\tif (repo_get_oid_treeish(the_repository, merge_base, &base_oid))\n \t\t\tdie(_(\"could not parse as tree '%s'\"), merge_base);\n-\t\tbase_tree = parse_tree_indirect(&base_oid);\n+\t\tbase_tree = repo_parse_tree_indirect(the_repository,\n+\t\t\t\t\t\t     &base_oid);\n \t\tif (!base_tree)\n \t\t\tdie(_(\"unable to read tree (%s)\"), oid_to_hex(&base_oid));\n \t\tif (repo_get_oid_treeish(the_repository, branch1, &head_oid))\n \t\t\tdie(_(\"could not parse as tree '%s'\"), branch1);\n-\t\tparent1_tree = parse_tree_indirect(&head_oid);\n+\t\tparent1_tree = repo_parse_tree_indirect(the_repository,\n+\t\t\t\t\t\t\t&head_oid);\n \t\tif (!parent1_tree)\n \t\t\tdie(_(\"unable to read tree (%s)\"), oid_to_hex(&head_oid));\n \t\tif (repo_get_oid_treeish(the_repository, branch2, &merge_oid))\n \t\t\tdie(_(\"could not parse as tree '%s'\"), branch2);\n-\t\tparent2_tree = parse_tree_indirect(&merge_oid);\n+\t\tparent2_tree = repo_parse_tree_indirect(the_repository,\n+\t\t\t\t\t\t\t&merge_oid);\n \t\tif (!parent2_tree)\n \t\t\tdie(_(\"unable to read tree (%s)\"), oid_to_hex(&merge_oid));\n \ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex c421a11b0b6..50001b4c59f 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -756,19 +756,19 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head,\n \topts.trivial_merges_only = 1;\n \topts.merge = 1;\n \topts.preserve_ignored = 0; /* FIXME: !overwrite_ignore */\n-\ttrees[nr_trees] = parse_tree_indirect(common);\n+\ttrees[nr_trees] = repo_parse_tree_indirect(the_repository, common);\n \tif (!trees[nr_trees++])\n \t\treturn -1;\n-\ttrees[nr_trees] = parse_tree_indirect(head);\n+\ttrees[nr_trees] = repo_parse_tree_indirect(the_repository, head);\n \tif (!trees[nr_trees++])\n \t\treturn -1;\n-\ttrees[nr_trees] = parse_tree_indirect(one);\n+\ttrees[nr_trees] = repo_parse_tree_indirect(the_repository, one);\n \tif (!trees[nr_trees++])\n \t\treturn -1;\n \topts.fn = threeway_merge;\n \tcache_tree_free(&the_repository->index->cache_tree);\n \tfor (i = 0; i < nr_trees; i++) {\n-\t\tparse_tree(trees[i]);\n+\t\trepo_parse_tree(the_repository, trees[i]);\n \t\tinit_tree_desc(t+i, &trees[i]->object.oid,\n \t\t\t       trees[i]->buffer, trees[i]->size);\n \t}\ndiff --git a/builtin/read-tree.c b/builtin/read-tree.c\nindex 34f7a59f38e..460b21e40ac 100644\n--- a/builtin/read-tree.c\n+++ b/builtin/read-tree.c\n@@ -32,7 +32,7 @@ static int list_tree(struct object_id *oid)\n \n \tif (nr_trees >= MAX_UNPACK_TREES)\n \t\tdie(\"I cannot read more than %d trees\", MAX_UNPACK_TREES);\n-\ttree = parse_tree_indirect(oid);\n+\ttree = repo_parse_tree_indirect(the_repository, oid);\n \tif (!tree)\n \t\treturn -1;\n \ttrees[nr_trees++] = tree;\n@@ -268,7 +268,7 @@ int cmd_read_tree(int argc,\n \tcache_tree_free(&the_repository->index->cache_tree);\n \tfor (i = 0; i < nr_trees; i++) {\n \t\tstruct tree *tree = trees[i];\n-\t\tif (parse_tree(tree) < 0)\n+\t\tif (repo_parse_tree(the_repository, tree) < 0)\n \t\t\treturn 128;\n \t\tinit_tree_desc(t+i, &tree->object.oid, tree->buffer, tree->size);\n \t}\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex ed35802af15..c48d9845f84 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -118,7 +118,7 @@ static int reset_index(const char *ref, const struct object_id *oid, int reset_t\n \t\tgoto out;\n \n \tif (reset_type == MIXED || reset_type == HARD) {\n-\t\ttree = parse_tree_indirect(oid);\n+\t\ttree = repo_parse_tree_indirect(the_repository, oid);\n \t\tif (!tree) {\n \t\t\terror(_(\"unable to read tree (%s)\"), oid_to_hex(oid));\n \t\t\tgoto out;\n@@ -417,7 +417,7 @@ int cmd_reset(int argc,\n \t\tstruct tree *tree;\n \t\tif (repo_get_oid_treeish(the_repository, rev, &oid))\n \t\t\tdie(_(\"Failed to resolve '%s' as a valid tree.\"), rev);\n-\t\ttree = parse_tree_indirect(&oid);\n+\t\ttree = repo_parse_tree_indirect(the_repository, &oid);\n \t\tif (!tree)\n \t\t\tdie(_(\"Could not parse object '%s'.\"), rev);\n \t\toidcpy(&oid, &tree->object.oid);\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex 948eba06fbc..193e3ea47a1 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -347,8 +347,8 @@ static int reset_tree(struct object_id *i_tree, int update, int reset)\n \n \tmemset(&opts, 0, sizeof(opts));\n \n-\ttree = parse_tree_indirect(i_tree);\n-\tif (parse_tree(tree))\n+\ttree = repo_parse_tree_indirect(the_repository, i_tree);\n+\tif (repo_parse_tree(the_repository, tree))\n \t\treturn -1;\n \n \tinit_tree_desc(t, &tree->object.oid, tree->buffer, tree->size);\n@@ -940,8 +940,8 @@ static void diff_include_untracked(const struct stash_info *info, struct diff_op\n \tstruct unpack_trees_options unpack_tree_opt = { 0 };\n \n \tfor (size_t i = 0; i < ARRAY_SIZE(oid); i++) {\n-\t\ttree[i] = parse_tree_indirect(oid[i]);\n-\t\tif (parse_tree(tree[i]) < 0)\n+\t\ttree[i] = repo_parse_tree_indirect(the_repository, oid[i]);\n+\t\tif (repo_parse_tree(the_repository, tree[i]) < 0)\n \t\t\tdie(_(\"failed to parse tree\"));\n \t\tinit_tree_desc(&tree_desc[i], &tree[i]->object.oid,\n \t\t\t       tree[i]->buffer, tree[i]->size);\ndiff --git a/cache-tree.c b/cache-tree.c\nindex 2d8947b5187..16c3a36b482 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -813,7 +813,7 @@ static void prime_cache_tree_rec(struct repository *r,\n \t\t\tstruct cache_tree_sub *sub;\n \t\t\tstruct tree *subtree = lookup_tree(r, &entry.oid);\n \n-\t\t\tif (parse_tree(subtree) < 0)\n+\t\t\tif (repo_parse_tree(the_repository, subtree) < 0)\n \t\t\t\texit(128);\n \t\t\tsub = cache_tree_sub(it, entry.path);\n \t\t\tsub->cache_tree = cache_tree();\ndiff --git a/contrib/coccinelle/the_repository.cocci b/contrib/coccinelle/the_repository.cocci\nindex ea7fe1c8db7..a1f6f5ac06c 100644\n--- a/contrib/coccinelle/the_repository.cocci\n+++ b/contrib/coccinelle/the_repository.cocci\n@@ -117,6 +117,16 @@\n |\n - init_revisions\n + repo_init_revisions\n+// tree.h\n+|\n+- parse_tree\n++ repo_parse_tree\n+|\n+- parse_tree_gently\n++ repo_parse_tree_gently\n+|\n+- parse_tree_indirect\n++ repo_parse_tree_indirect\n )\n   (\n + the_repository,\ndiff --git a/diff-lib.c b/diff-lib.c\nindex 5307390ff3d..506000761d4 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -552,7 +552,7 @@ static int diff_cache(struct rev_info *revs,\n \tstruct tree_desc t;\n \tstruct unpack_trees_options opts;\n \n-\ttree = parse_tree_indirect(tree_oid);\n+\ttree = repo_parse_tree_indirect(the_repository, tree_oid);\n \tif (!tree)\n \t\treturn error(\"bad tree object %s\",\n \t\t\t     tree_name ? tree_name : oid_to_hex(tree_oid));\ndiff --git a/fsck.c b/fsck.c\nindex fae18d8561e..5532f5ae9f9 100644\n--- a/fsck.c\n+++ b/fsck.c\n@@ -360,7 +360,7 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op\n \tint res = 0;\n \tconst char *name;\n \n-\tif (parse_tree(tree))\n+\tif (repo_parse_tree(the_repository, tree))\n \t\treturn -1;\n \n \tname = fsck_get_object_name(options, &tree->object.oid);\ndiff --git a/http-push.c b/http-push.c\nindex 60a9b756209..cc0f8093461 100644\n--- a/http-push.c\n+++ b/http-push.c\n@@ -1311,7 +1311,7 @@ static struct object_list **process_tree(struct tree *tree,\n \n \tif (obj->flags & (UNINTERESTING | SEEN))\n \t\treturn p;\n-\tif (parse_tree(tree) < 0)\n+\tif (repo_parse_tree(the_repository, tree) < 0)\n \t\tdie(\"bad tree object %s\", oid_to_hex(&obj->oid));\n \n \tobj->flags |= SEEN;\ndiff --git a/list-objects.c b/list-objects.c\nindex 1279676ddca..91b23e22f71 100644\n--- a/list-objects.c\n+++ b/list-objects.c\n@@ -170,7 +170,7 @@ static void process_tree(struct traversal_context *ctx,\n \tif (ctx->depth > revs->repo->settings.max_allowed_tree_depth)\n \t\tdie(\"exceeded maximum allowed tree depth\");\n \n-\tfailed_parse = parse_tree_gently(tree, 1);\n+\tfailed_parse = repo_parse_tree_gently(the_repository, tree, 1);\n \tif (failed_parse) {\n \t\tif (revs->ignore_missing_links)\n \t\t\treturn;\ndiff --git a/merge-ort.c b/merge-ort.c\nindex 2b837a58c3a..e80e4f735a6 100644\n--- a/merge-ort.c\n+++ b/merge-ort.c\n@@ -1732,9 +1732,9 @@ static int collect_merge_info(struct merge_options *opt,\n \tinfo.data = opt;\n \tinfo.show_all_errors = 1;\n \n-\tif (parse_tree(merge_base) < 0 ||\n-\t    parse_tree(side1) < 0 ||\n-\t    parse_tree(side2) < 0)\n+\tif (repo_parse_tree(the_repository, merge_base) < 0 ||\n+\t    repo_parse_tree(the_repository, side1) < 0 ||\n+\t    repo_parse_tree(the_repository, side2) < 0)\n \t\treturn -1;\n \tinit_tree_desc(t + 0, &merge_base->object.oid,\n \t\t       merge_base->buffer, merge_base->size);\n@@ -4619,10 +4619,10 @@ static int checkout(struct merge_options *opt,\n \tunpack_opts.verbose_update = (opt->verbosity > 2);\n \tunpack_opts.fn = twoway_merge;\n \tunpack_opts.preserve_ignored = 0; /* FIXME: !opts->overwrite_ignore */\n-\tif (parse_tree(prev) < 0)\n+\tif (repo_parse_tree(the_repository, prev) < 0)\n \t\treturn -1;\n \tinit_tree_desc(&trees[0], &prev->object.oid, prev->buffer, prev->size);\n-\tif (parse_tree(next) < 0)\n+\tif (repo_parse_tree(the_repository, next) < 0)\n \t\treturn -1;\n \tinit_tree_desc(&trees[1], &next->object.oid, next->buffer, next->size);\n \n@@ -5280,7 +5280,8 @@ static void merge_ort_nonrecursive_internal(struct merge_options *opt,\n \n \tif (result->clean >= 0) {\n \t\tif (!opt->mergeability_only) {\n-\t\t\tresult->tree = parse_tree_indirect(&working_tree_oid);\n+\t\t\tresult->tree = repo_parse_tree_indirect(the_repository,\n+\t\t\t\t\t\t\t\t&working_tree_oid);\n \t\t\tif (!result->tree)\n \t\t\t\tdie(_(\"unable to read tree (%s)\"),\n \t\t\t\t    oid_to_hex(&working_tree_oid));\ndiff --git a/merge.c b/merge.c\nindex 5ecaf508e4c..0f5e823e63e 100644\n--- a/merge.c\n+++ b/merge.c\n@@ -68,18 +68,18 @@ int checkout_fast_forward(struct repository *r,\n \tmemset(&trees, 0, sizeof(trees));\n \tmemset(&t, 0, sizeof(t));\n \n-\ttrees[nr_trees] = parse_tree_indirect(head);\n+\ttrees[nr_trees] = repo_parse_tree_indirect(the_repository, head);\n \tif (!trees[nr_trees++]) {\n \t\trollback_lock_file(&lock_file);\n \t\treturn -1;\n \t}\n-\ttrees[nr_trees] = parse_tree_indirect(remote);\n+\ttrees[nr_trees] = repo_parse_tree_indirect(the_repository, remote);\n \tif (!trees[nr_trees++]) {\n \t\trollback_lock_file(&lock_file);\n \t\treturn -1;\n \t}\n \tfor (i = 0; i < nr_trees; i++) {\n-\t\tif (parse_tree(trees[i]) < 0) {\n+\t\tif (repo_parse_tree(the_repository, trees[i]) < 0) {\n \t\t\trollback_lock_file(&lock_file);\n \t\t\treturn -1;\n \t\t}\ndiff --git a/read-cache.c b/read-cache.c\nindex 990d4ead0d8..e9c1b23e484 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -3807,7 +3807,7 @@ void overlay_tree_on_index(struct index_state *istate,\n \n \tif (repo_get_oid(the_repository, tree_name, &oid))\n \t\tdie(\"tree-ish %s not found.\", tree_name);\n-\ttree = parse_tree_indirect(&oid);\n+\ttree = repo_parse_tree_indirect(the_repository, &oid);\n \tif (!tree)\n \t\tdie(\"bad tree-ish %s\", tree_name);\n \ndiff --git a/reset.c b/reset.c\nindex bb590271811..46e30e63945 100644\n--- a/reset.c\n+++ b/reset.c\n@@ -163,7 +163,7 @@ int reset_head(struct repository *r, const struct reset_head_opts *opts)\n \t\tgoto leave_reset_head;\n \t}\n \n-\ttree = parse_tree_indirect(oid);\n+\ttree = repo_parse_tree_indirect(the_repository, oid);\n \tif (!tree) {\n \t\tret = error(_(\"unable to read tree (%s)\"), oid_to_hex(oid));\n \t\tgoto leave_reset_head;\ndiff --git a/revision.c b/revision.c\nindex 5f0850ae5c9..426d19a2c6c 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -72,7 +72,7 @@ static void mark_tree_contents_uninteresting(struct repository *r,\n \tstruct tree_desc desc;\n \tstruct name_entry entry;\n \n-\tif (parse_tree_gently(tree, 1) < 0)\n+\tif (repo_parse_tree_gently(the_repository, tree, 1) < 0)\n \t\treturn;\n \n \tinit_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);\n@@ -179,7 +179,7 @@ static void add_children_by_path(struct repository *r,\n \tif (!tree)\n \t\treturn;\n \n-\tif (parse_tree_gently(tree, 1) < 0)\n+\tif (repo_parse_tree_gently(the_repository, tree, 1) < 0)\n \t\treturn;\n \n \tinit_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);\ndiff --git a/sequencer.c b/sequencer.c\nindex 71ed31c7740..cccde58bee9 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -767,7 +767,7 @@ static int do_recursive_merge(struct repository *r,\n \t\to.buffer_output = 2;\n \to.show_rename_progress = 1;\n \n-\thead_tree = parse_tree_indirect(head);\n+\thead_tree = repo_parse_tree_indirect(the_repository, head);\n \tif (!head_tree)\n \t\treturn error(_(\"unable to read tree (%s)\"), oid_to_hex(head));\n \tnext_tree = next ? repo_get_commit_tree(r, next) : empty_tree(r);\n@@ -4052,7 +4052,7 @@ static int do_reset(struct repository *r,\n \t\tgoto cleanup;\n \t}\n \n-\ttree = parse_tree_indirect(&oid);\n+\ttree = repo_parse_tree_indirect(the_repository, &oid);\n \tif (!tree)\n \t\treturn error(_(\"unable to read tree (%s)\"), oid_to_hex(&oid));\n \tprime_cache_tree(r, r->index, tree);\ndiff --git a/t/helper/test-cache-tree.c b/t/helper/test-cache-tree.c\nindex 3ae45cec3be..ff61d0ca7e2 100644\n--- a/t/helper/test-cache-tree.c\n+++ b/t/helper/test-cache-tree.c\n@@ -41,7 +41,7 @@ int cmd__cache_tree(int argc, const char **argv)\n \t\tdie(_(\"unable to read index file\"));\n \n \toidcpy(&oid, &the_repository->index->cache_tree->oid);\n-\ttree = parse_tree_indirect(&oid);\n+\ttree = repo_parse_tree_indirect(the_repository, &oid);\n \tif (!tree)\n \t\tdie(_(\"not a tree object: %s\"), oid_to_hex(&oid));\n \ndiff --git a/t/helper/test-match-trees.c b/t/helper/test-match-trees.c\nindex e0e2048320d..2ed064b9716 100644\n--- a/t/helper/test-match-trees.c\n+++ b/t/helper/test-match-trees.c\n@@ -19,10 +19,10 @@ int cmd__match_trees(int ac UNUSED, const char **av)\n \t\tdie(\"cannot parse %s as an object name\", av[1]);\n \tif (repo_get_oid(the_repository, av[2], &hash2))\n \t\tdie(\"cannot parse %s as an object name\", av[2]);\n-\tone = parse_tree_indirect(&hash1);\n+\tone = repo_parse_tree_indirect(the_repository, &hash1);\n \tif (!one)\n \t\tdie(\"not a tree-ish %s\", av[1]);\n-\ttwo = parse_tree_indirect(&hash2);\n+\ttwo = repo_parse_tree_indirect(the_repository, &hash2);\n \tif (!two)\n \t\tdie(\"not a tree-ish %s\", av[2]);\n \ndiff --git a/walker.c b/walker.c\nindex 2891563b036..91332539d3a 100644\n--- a/walker.c\n+++ b/walker.c\n@@ -45,7 +45,7 @@ static int process_tree(struct walker *walker, struct tree *tree)\n \tstruct tree_desc desc;\n \tstruct name_entry entry;\n \n-\tif (parse_tree(tree))\n+\tif (repo_parse_tree(the_repository, tree))\n \t\treturn -1;\n \n \tinit_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);\n-- \n2.52.0\n\n"},{"id":"533444","messageId":"20260109213021.2546-3-l.s.r@web.de","threadId":"64765","inReplyTo":"20260109213021.2546-1-l.s.r@web.de","subject":"[PATCH 02/10] tree: add repo_parse_tree*()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-09T21:30:13Z","receivedAt":"2026-01-09T21:30:29Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Add variants of parse_tree(), parse_tree_gently() and\nparse_tree_indirect() that allow using an arbitrary repository.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n tree.c | 16 +++++++++++++---\n tree.h |  8 ++++++++\n 2 files changed, 21 insertions(+), 3 deletions(-)\n\ndiff --git a/tree.c b/tree.c\nindex 2a677234d60..036f56ca29b 100644\n--- a/tree.c\n+++ b/tree.c\n@@ -186,6 +186,12 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)\n }\n \n int parse_tree_gently(struct tree *item, int quiet_on_missing)\n+{\n+\treturn repo_parse_tree_gently(the_repository, item, quiet_on_missing);\n+}\n+\n+int repo_parse_tree_gently(struct repository *r, struct tree *item,\n+\t\t\t   int quiet_on_missing)\n {\n \t enum object_type type;\n \t void *buffer;\n@@ -193,8 +199,7 @@ int parse_tree_gently(struct tree *item, int quiet_on_missing)\n \n \tif (item->object.parsed)\n \t\treturn 0;\n-\tbuffer = odb_read_object(the_repository->objects, &item->object.oid,\n-\t\t\t\t &type, &size);\n+\tbuffer = odb_read_object(r->objects, &item->object.oid, &type, &size);\n \tif (!buffer)\n \t\treturn quiet_on_missing ? -1 :\n \t\t\terror(\"Could not read %s\",\n@@ -216,7 +221,12 @@ void free_tree_buffer(struct tree *tree)\n \n struct tree *parse_tree_indirect(const struct object_id *oid)\n {\n-\tstruct repository *r = the_repository;\n+\treturn repo_parse_tree_indirect(the_repository, oid);\n+}\n+\n+struct tree *repo_parse_tree_indirect(struct repository *r,\n+\t\t\t\t      const struct object_id *oid)\n+{\n \tstruct object *obj = parse_object(r, oid);\n \treturn (struct tree *)repo_peel_to_type(r, NULL, 0, obj, OBJ_TREE);\n }\ndiff --git a/tree.h b/tree.h\nindex cc6ddf51b32..9037891d30f 100644\n--- a/tree.h\n+++ b/tree.h\n@@ -20,14 +20,22 @@ struct tree *lookup_tree(struct repository *r, const struct object_id *oid);\n int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size);\n \n int parse_tree_gently(struct tree *tree, int quiet_on_missing);\n+int repo_parse_tree_gently(struct repository *r, struct tree *item,\n+\t\t\t   int quiet_on_missing);\n static inline int parse_tree(struct tree *tree)\n {\n \treturn parse_tree_gently(tree, 0);\n }\n+static inline int repo_parse_tree(struct repository *r, struct tree *item)\n+{\n+\treturn repo_parse_tree_gently(r, item, 0);\n+}\n void free_tree_buffer(struct tree *tree);\n \n /* Parses and returns the tree in the given ent, chasing tags and commits. */\n struct tree *parse_tree_indirect(const struct object_id *oid);\n+struct tree *repo_parse_tree_indirect(struct repository *r,\n+\t\t\t\t      const struct object_id *oid);\n \n /*\n  * Functions for comparing pathnames\n-- \n2.52.0\n\n"},{"id":"533445","messageId":"20260109213021.2546-2-l.s.r@web.de","threadId":"64765","inReplyTo":"20260109213021.2546-1-l.s.r@web.de","subject":"[PATCH 01/10] environment: move access to core.maxTreeDepth into repo settings","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-09T21:30:12Z","receivedAt":"2026-01-09T21:30:29Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"The config setting core.maxTreeDepth is stored in a global variable and\npopulated by the function git_default_core_config.  This won't work if\nwe need to access multiple repositories with different values of that\nsetting in the same process.  Store the setting in struct repo_settings\ninstead and track it separately for each repository.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n environment.c     | 29 -----------------------------\n environment.h     |  1 -\n git-compat-util.h | 24 ++++++++++++++++++++++++\n list-objects.c    |  2 +-\n repo-settings.c   |  3 +++\n repo-settings.h   |  3 +++\n tree-diff.c       |  2 +-\n tree-walk.c       |  4 +++-\n tree.c            |  2 +-\n 9 files changed, 36 insertions(+), 34 deletions(-)\n\ndiff --git a/environment.c b/environment.c\nindex a770b5921d9..c6e5b65abac 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -80,30 +80,6 @@ int core_sparse_checkout_cone;\n int sparse_expect_files_outside_of_patterns;\n int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */\n unsigned long pack_size_limit_cfg;\n-int max_allowed_tree_depth =\n-#ifdef _MSC_VER\n-\t/*\n-\t * When traversing into too-deep trees, Visual C-compiled Git seems to\n-\t * run into some internal stack overflow detection in the\n-\t * `RtlpAllocateHeap()` function that is called from within\n-\t * `git_inflate_init()`'s call tree. The following value seems to be\n-\t * low enough to avoid that by letting Git exit with an error before\n-\t * the stack overflow can occur.\n-\t */\n-\t512;\n-#elif defined(GIT_WINDOWS_NATIVE) && defined(__clang__) && defined(__aarch64__)\n-\t/*\n-\t * Similar to Visual C, it seems that on Windows/ARM64 the clang-based\n-\t * builds have a smaller stack space available. When running out of\n-\t * that stack space, a `STATUS_STACK_OVERFLOW` is produced. When the\n-\t * Git command was run from an MSYS2 Bash, this unfortunately results\n-\t * in an exit code 127. Let's prevent that by lowering the maximal\n-\t * tree depth; This value seems to be low enough.\n-\t */\n-\t1280;\n-#else\n-\t2048;\n-#endif\n \n #ifndef PROTECT_HFS_DEFAULT\n #define PROTECT_HFS_DEFAULT 0\n@@ -569,11 +545,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.maxtreedepth\")) {\n-\t\tmax_allowed_tree_depth = git_config_int(var, value, ctx->kvi);\n-\t\treturn 0;\n-\t}\n-\n \t/* Add other config variables here and to Documentation/config.adoc. */\n \treturn platform_core_config(var, value, ctx, cb);\n }\ndiff --git a/environment.h b/environment.h\nindex 51898c99cd1..9efe0b30fb3 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -156,7 +156,6 @@ extern char *git_attributes_file;\n extern int zlib_compression_level;\n extern int pack_compression_level;\n extern unsigned long pack_size_limit_cfg;\n-extern int max_allowed_tree_depth;\n \n extern int precomposed_unicode;\n extern int protect_hfs;\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex b0673d1a450..bebcf9f698c 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -578,6 +578,30 @@ static inline bool strip_suffix(const char *str, const char *suffix,\n #define DEFAULT_PACKED_GIT_LIMIT \\\n \t((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? (32 * 1024L * 1024L) : 256))\n \n+#ifdef _MSC_VER\n+  /*\n+   * When traversing into too-deep trees, Visual C-compiled Git seems to\n+   * run into some internal stack overflow detection in the\n+   * `RtlpAllocateHeap()` function that is called from within\n+   * `git_inflate_init()`'s call tree. The following value seems to be\n+   * low enough to avoid that by letting Git exit with an error before\n+   * the stack overflow can occur.\n+   */\n+#define DEFAULT_MAX_ALLOWED_TREE_DEPTH 512\n+#elif defined(GIT_WINDOWS_NATIVE) && defined(__clang__) && defined(__aarch64__)\n+  /*\n+   * Similar to Visual C, it seems that on Windows/ARM64 the clang-based\n+   * builds have a smaller stack space available. When running out of\n+   * that stack space, a `STATUS_STACK_OVERFLOW` is produced. When the\n+   * Git command was run from an MSYS2 Bash, this unfortunately results\n+   * in an exit code 127. Let's prevent that by lowering the maximal\n+   * tree depth; This value seems to be low enough.\n+   */\n+#define DEFAULT_MAX_ALLOWED_TREE_DEPTH 1280\n+#else\n+#define DEFAULT_MAX_ALLOWED_TREE_DEPTH 2048\n+#endif\n+\n int git_open_cloexec(const char *name, int flags);\n #define git_open(name) git_open_cloexec(name, O_RDONLY)\n \ndiff --git a/list-objects.c b/list-objects.c\nindex 42c17d95739..1279676ddca 100644\n--- a/list-objects.c\n+++ b/list-objects.c\n@@ -167,7 +167,7 @@ static void process_tree(struct traversal_context *ctx,\n \t    !revs->include_check_obj(&tree->object, revs->include_check_data))\n \t\treturn;\n \n-\tif (ctx->depth > max_allowed_tree_depth)\n+\tif (ctx->depth > revs->repo->settings.max_allowed_tree_depth)\n \t\tdie(\"exceeded maximum allowed tree depth\");\n \n \tfailed_parse = parse_tree_gently(tree, 1);\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 195c24e9c07..208e09ff17f 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -100,6 +100,9 @@ void prepare_repo_settings(struct repository *r)\n \t */\n \tif (!repo_config_get_int(r, \"index.version\", &value))\n \t\tr->settings.index_version = value;\n+\trepo_cfg_int(r, \"core.maxtreedepth\",\n+\t\t     &r->settings.max_allowed_tree_depth,\n+\t\t     DEFAULT_MAX_ALLOWED_TREE_DEPTH);\n \n \tif (!repo_config_get_string_tmp(r, \"core.untrackedcache\", &strval)) {\n \t\tint v = git_parse_maybe_bool(strval);\ndiff --git a/repo-settings.h b/repo-settings.h\nindex d4778855614..cad9c3f0cc1 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -67,6 +67,8 @@ struct repo_settings {\n \tsize_t packed_git_limit;\n \tunsigned long big_file_threshold;\n \n+\tint max_allowed_tree_depth;\n+\n \tchar *hooks_path;\n };\n #define REPO_SETTINGS_INIT { \\\n@@ -78,6 +80,7 @@ struct repo_settings {\n \t.delta_base_cache_limit = DEFAULT_DELTA_BASE_CACHE_LIMIT, \\\n \t.packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE, \\\n \t.packed_git_limit = DEFAULT_PACKED_GIT_LIMIT, \\\n+\t.max_allowed_tree_depth = DEFAULT_MAX_ALLOWED_TREE_DEPTH, \\\n }\n \n void prepare_repo_settings(struct repository *r);\ndiff --git a/tree-diff.c b/tree-diff.c\nindex 5988148b602..631ea868124 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -439,7 +439,7 @@ static void ll_diff_tree_paths(\n \tvoid *ttree, **tptree;\n \tint i;\n \n-\tif (depth > max_allowed_tree_depth)\n+\tif (depth > opt->repo->settings.max_allowed_tree_depth)\n \t\tdie(\"exceeded maximum allowed tree depth\");\n \n \tFAST_ARRAY_ALLOC(tp, nparent);\ndiff --git a/tree-walk.c b/tree-walk.c\nindex e449a1320e5..7e1b956f278 100644\n--- a/tree-walk.c\n+++ b/tree-walk.c\n@@ -12,6 +12,7 @@\n #include \"pathspec.h\"\n #include \"json-writer.h\"\n #include \"environment.h\"\n+#include \"read-cache-ll.h\"\n \n static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned long size, struct strbuf *err)\n {\n@@ -441,8 +442,9 @@ int traverse_trees(struct index_state *istate,\n \tstruct strbuf base = STRBUF_INIT;\n \tint interesting = 1;\n \tchar *traverse_path;\n+\tstruct repository *r = istate ? istate->repo : the_repository;\n \n-\tif (traverse_trees_cur_depth > max_allowed_tree_depth)\n+\tif (traverse_trees_cur_depth > r->settings.max_allowed_tree_depth)\n \t\treturn error(\"exceeded maximum allowed tree depth\");\n \n \ttraverse_trees_count++;\ndiff --git a/tree.c b/tree.c\nindex 1ef743d90f4..2a677234d60 100644\n--- a/tree.c\n+++ b/tree.c\n@@ -25,7 +25,7 @@ int read_tree_at(struct repository *r,\n \tint len, oldlen = base->len;\n \tenum interesting retval = entry_not_interesting;\n \n-\tif (depth > max_allowed_tree_depth)\n+\tif (depth > r->settings.max_allowed_tree_depth)\n \t\treturn error(\"exceeded maximum allowed tree depth\");\n \n \tif (parse_tree(tree))\n-- \n2.52.0\n\n"},{"id":"533443","messageId":"20260109213021.2546-8-l.s.r@web.de","threadId":"64765","inReplyTo":"20260109213021.2546-1-l.s.r@web.de","subject":"[PATCH 07/10] path-walk: use repo_parse_tree_gently()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-09T21:30:18Z","receivedAt":"2026-01-09T21:30:30Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Use the passed in repository instead of the implicit the_repository when\nparsing the tree.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n path-walk.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/path-walk.c b/path-walk.c\nindex f1ceed99e94..364e4cfa19b 100644\n--- a/path-walk.c\n+++ b/path-walk.c\n@@ -137,7 +137,7 @@ static int add_tree_entries(struct path_walk_context *ctx,\n \t\terror(_(\"failed to walk children of tree %s: not found\"),\n \t\t      oid_to_hex(oid));\n \t\treturn -1;\n-\t} else if (parse_tree_gently(tree, 1)) {\n+\t} else if (repo_parse_tree_gently(ctx->repo, tree, 1)) {\n \t\terror(\"bad tree object %s\", oid_to_hex(oid));\n \t\treturn -1;\n \t}\n-- \n2.52.0\n\n"},{"id":"533446","messageId":"20260109213021.2546-6-l.s.r@web.de","threadId":"64765","inReplyTo":"20260109213021.2546-1-l.s.r@web.de","subject":"[PATCH 05/10] delta-islands: use repo_parse_tree()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-09T21:30:16Z","receivedAt":"2026-01-09T21:30:30Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"19be71db9c (delta-islands: stop depending on `the_repository`,\n2025-03-10) replaced explicit uses of the_repository.  parse_tree() uses\nit internally, though, so call repo_parse_tree() instead and hand it the\ncorrect repository.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n delta-islands.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/delta-islands.c b/delta-islands.c\nindex 7cfebc4162b..f4d2468790c 100644\n--- a/delta-islands.c\n+++ b/delta-islands.c\n@@ -283,7 +283,7 @@ void resolve_tree_islands(struct repository *r,\n \t\troot_marks = kh_value(island_marks, pos);\n \n \t\ttree = lookup_tree(r, &ent->idx.oid);\n-\t\tif (!tree || parse_tree(tree) < 0)\n+\t\tif (!tree || repo_parse_tree(r, tree) < 0)\n \t\t\tdie(_(\"bad tree object %s\"), oid_to_hex(&ent->idx.oid));\n \n \t\tinit_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);\n-- \n2.52.0\n\n"},{"id":"533447","messageId":"20260109213021.2546-7-l.s.r@web.de","threadId":"64765","inReplyTo":"20260109213021.2546-1-l.s.r@web.de","subject":"[PATCH 06/10] pack-bitmap-write: use repo_parse_tree()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-09T21:30:17Z","receivedAt":"2026-01-09T21:30:30Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"1a6768d1dd (pack-bitmap-write: stop depending on `the_repository`,\n2025-03-10) replaced explicit uses of the_repository.  parse_tree() uses\nit internally, though, so call repo_parse_tree() instead and hand it the\ncorrect repository.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n pack-bitmap-write.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/pack-bitmap-write.c b/pack-bitmap-write.c\nindex 4404921521c..d38de772c6c 100644\n--- a/pack-bitmap-write.c\n+++ b/pack-bitmap-write.c\n@@ -478,7 +478,7 @@ static int fill_bitmap_tree(struct bitmap_writer *writer,\n \t\treturn 0;\n \tbitmap_set(bitmap, pos);\n \n-\tif (parse_tree(tree) < 0)\n+\tif (repo_parse_tree(writer->repo, tree) < 0)\n \t\tdie(\"unable to load tree object %s\",\n \t\t    oid_to_hex(&tree->object.oid));\n \tinit_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);\n-- \n2.52.0\n\n"},{"id":"533596","messageId":"aWS9JLb3UyxOwg9Z@pks.im","threadId":"64765","inReplyTo":"20260109213021.2546-2-l.s.r@web.de","subject":"Re: [PATCH 01/10] environment: move access to core.maxTreeDepth into repo settings","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-01-12T09:21:40Z","receivedAt":"2026-01-12T09:21:46Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Jan 09, 2026 at 10:30:12PM +0100, René Scharfe wrote:\n> diff --git a/git-compat-util.h b/git-compat-util.h\n> index b0673d1a450..bebcf9f698c 100644\n> --- a/git-compat-util.h\n> +++ b/git-compat-util.h\n> @@ -578,6 +578,30 @@ static inline bool strip_suffix(const char *str, const char *suffix,\n>  #define DEFAULT_PACKED_GIT_LIMIT \\\n>  \t((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? (32 * 1024L * 1024L) : 256))\n>  \n> +#ifdef _MSC_VER\n> +  /*\n> +   * When traversing into too-deep trees, Visual C-compiled Git seems to\n> +   * run into some internal stack overflow detection in the\n> +   * `RtlpAllocateHeap()` function that is called from within\n> +   * `git_inflate_init()`'s call tree. The following value seems to be\n> +   * low enough to avoid that by letting Git exit with an error before\n> +   * the stack overflow can occur.\n> +   */\n> +#define DEFAULT_MAX_ALLOWED_TREE_DEPTH 512\n> +#elif defined(GIT_WINDOWS_NATIVE) && defined(__clang__) && defined(__aarch64__)\n> +  /*\n> +   * Similar to Visual C, it seems that on Windows/ARM64 the clang-based\n> +   * builds have a smaller stack space available. When running out of\n> +   * that stack space, a `STATUS_STACK_OVERFLOW` is produced. When the\n> +   * Git command was run from an MSYS2 Bash, this unfortunately results\n> +   * in an exit code 127. Let's prevent that by lowering the maximal\n> +   * tree depth; This value seems to be low enough.\n> +   */\n> +#define DEFAULT_MAX_ALLOWED_TREE_DEPTH 1280\n> +#else\n> +#define DEFAULT_MAX_ALLOWED_TREE_DEPTH 2048\n> +#endif\n> +\n>  int git_open_cloexec(const char *name, int flags);\n>  #define git_open(name) git_open_cloexec(name, O_RDONLY)\n>  \n\nWhy is this new constant defined in \"git-compat-util.h\"? That feels way\ntoo global for my taste for a value that should ultimately only be\nrequired by \"repo-settings.c\". Is there a reason why it's not declared\nin \"repo-settings.h\"?\n\nI think we could even get away with declaring it in \"repo-settings.c\".\nThe expectation is that the settings need to be prepared anyway, so we\ncan simply set up the default when parsing the config.\n\nPatrick\n"},{"id":"533597","messageId":"aWS9KUQDrHj7J6zX@pks.im","threadId":"64765","inReplyTo":"20260109213021.2546-9-l.s.r@web.de","subject":"Re: [PATCH 08/10] tree: use repo_parse_tree()","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-01-12T09:21:45Z","receivedAt":"2026-01-12T09:21:50Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Jan 09, 2026 at 10:30:19PM +0100, René Scharfe wrote:\n> e092073d64 (tree.c: make read_tree*() take 'struct repository *',\n> 2018-11-18) replaced explicit uses of the_repository.  parse_tree() uses\n> it internally, though, so call repo_parse_tree() instead and hand it the\n> correct repository.\n\nAll of the conversions in preceding commits were trivial, so I feel like\nthey could've just been squashed together. Please feel free to ignore\nthis suggestion though.\n\nPatrick\n"},{"id":"533598","messageId":"aWS9Ll8CQ3eILx3z@pks.im","threadId":"64765","inReplyTo":"20260109213021.2546-10-l.s.r@web.de","subject":"Re: [PATCH 09/10] tree: stop using the_repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-01-12T09:21:50Z","receivedAt":"2026-01-12T09:21:55Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Jan 09, 2026 at 10:30:20PM +0100, René Scharfe wrote:\n> Push the use of the_repository to the remaining callers by turning the\n> compatibility wrappers into macros, whose use still requires\n> USE_THE_REPOSITORY_VARIABLE to be defined.\n\nCan't we make this step a bit more explicit by adapting all callers to\nparse `repo_parse_tree()` with `the_repository`? That makes it way more\nobvious that we rely on the global repository.\n\nEdit: I see that you _do_ edit all callsites in the next commit, nice.\n\nIn any case, I'd propose to move the compatibility macros into a section\nthat says something like:\n\n    /* Deprecated wrappers that will be removed once Git 2.53 is released. */\n\nWe can then have a follow-up patch in a couple weeks to convert any new\ncallsites that were added meanwhile and then purge the compatibility\nwrappers.\n\nThanks!\n\nPatrick\n"},{"id":"533632","messageId":"xmqqh5sqoqr0.fsf@gitster.g","threadId":"64765","inReplyTo":"aWS9Ll8CQ3eILx3z@pks.im","subject":"Re: [PATCH 09/10] tree: stop using the_repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-01-12T14:22:11Z","receivedAt":"2026-01-12T14:22:13Z","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> On Fri, Jan 09, 2026 at 10:30:20PM +0100, René Scharfe wrote:\n>> Push the use of the_repository to the remaining callers by turning the\n>> compatibility wrappers into macros, whose use still requires\n>> USE_THE_REPOSITORY_VARIABLE to be defined.\n>\n> Can't we make this step a bit more explicit by adapting all callers to\n> parse `repo_parse_tree()` with `the_repository`? That makes it way more\n> obvious that we rely on the global repository.\n>\n> Edit: I see that you _do_ edit all callsites in the next commit, nice.\n>\n> In any case, I'd propose to move the compatibility macros into a section\n> that says something like:\n>\n>     /* Deprecated wrappers that will be removed once Git 2.53 is released. */\n\nPlease do not take release schedule hostage to one particular fix-up\nseries of patches.  Thanks.\n\n>\n> We can then have a follow-up patch in a couple weeks to convert any new\n> callsites that were added meanwhile and then purge the compatibility\n> wrappers.\n>\n> Thanks!\n>\n> Patrick\n"},{"id":"533640","messageId":"aWUMn6G0C1cHA4qY@pks.im","threadId":"64765","inReplyTo":"xmqqh5sqoqr0.fsf@gitster.g","subject":"Re: [PATCH 09/10] tree: stop using the_repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-01-12T15:00:47Z","receivedAt":"2026-01-12T15:00:57Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Jan 12, 2026 at 06:22:11AM -0800, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> > On Fri, Jan 09, 2026 at 10:30:20PM +0100, René Scharfe wrote:\n> >> Push the use of the_repository to the remaining callers by turning the\n> >> compatibility wrappers into macros, whose use still requires\n> >> USE_THE_REPOSITORY_VARIABLE to be defined.\n> >\n> > Can't we make this step a bit more explicit by adapting all callers to\n> > parse `repo_parse_tree()` with `the_repository`? That makes it way more\n> > obvious that we rely on the global repository.\n> >\n> > Edit: I see that you _do_ edit all callsites in the next commit, nice.\n> >\n> > In any case, I'd propose to move the compatibility macros into a section\n> > that says something like:\n> >\n> >     /* Deprecated wrappers that will be removed once Git 2.53 is released. */\n> \n> Please do not take release schedule hostage to one particular fix-up\n> series of patches.  Thanks.\n\nThe intent isn't really to take anything hostage. It's rather intended\nas a hint that once a specific event has happened, we should take\nanother look at removing these wrappers.\n\nWe regularly have the case that we add compatibility wrappers to not\nbreak in-flight patch series. We then have to wait a bit before we can\nremove those wrappers, which makes it likely that we forget doing so. By\nhaving the above marker we basically crowdsource their removal as\neveryone passing by the comment will now wonder \"Wait, we already have\nGit 2.67, why do these wrappers still exist?\".\n\nPatrick\n"},{"id":"533645","messageId":"xmqqqzrun9lu.fsf@gitster.g","threadId":"64765","inReplyTo":"aWUMn6G0C1cHA4qY@pks.im","subject":"Re: [PATCH 09/10] tree: stop using the_repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-01-12T15:17:49Z","receivedAt":"2026-01-12T15:17:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":""},{"id":"533646","messageId":"xmqqms2in9hb.fsf@gitster.g","threadId":"64765","inReplyTo":"aWUMn6G0C1cHA4qY@pks.im","subject":"Re: [PATCH 09/10] tree: stop using the_repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-01-12T15:20:32Z","receivedAt":"2026-01-12T15:20:34Z","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>> > In any case, I'd propose to move the compatibility macros into a section\n>> > that says something like:\n>> >\n>> >     /* Deprecated wrappers that will be removed once Git 2.53 is released. */\n>> \n>> Please do not take release schedule hostage to one particular fix-up\n>> series of patches.  Thanks.\n>\n> The intent isn't really to take anything hostage. It's rather intended\n> as a hint that once a specific event has happened, we should take\n> another look at removing these wrappers.\n\nI am OK with a comment that records the intent, e.g., \"let's work\ntowards reducing the use of these wrappers\", with the plan for the\nnext step, e.g., \"and once we have done so, remove these.\"\n\nBut the comment you wrote is forcing people to make sure we remove\nthe code that uses these wrappers and unless we finish it we cannot\nrelease 2.53, no?\n"},{"id":"533648","messageId":"aWUTNU7WGTwHt6Ks@pks.im","threadId":"64765","inReplyTo":"xmqqms2in9hb.fsf@gitster.g","subject":"Re: [PATCH 09/10] tree: stop using the_repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-01-12T15:28:53Z","receivedAt":"2026-01-12T15:28:59Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Jan 12, 2026 at 07:20:32AM -0800, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> >> > In any case, I'd propose to move the compatibility macros into a section\n> >> > that says something like:\n> >> >\n> >> >     /* Deprecated wrappers that will be removed once Git 2.53 is released. */\n> >> \n> >> Please do not take release schedule hostage to one particular fix-up\n> >> series of patches.  Thanks.\n> >\n> > The intent isn't really to take anything hostage. It's rather intended\n> > as a hint that once a specific event has happened, we should take\n> > another look at removing these wrappers.\n> \n> I am OK with a comment that records the intent, e.g., \"let's work\n> towards reducing the use of these wrappers\", with the plan for the\n> next step, e.g., \"and once we have done so, remove these.\"\n> \n> But the comment you wrote is forcing people to make sure we remove\n> the code that uses these wrappers and unless we finish it we cannot\n> release 2.53, no?\n\nThat's definitely not my intent. It's really only intended as a hint\nwhen those should be removed at the earliest. Maybe something like the\nfollowing instead?\n\n    /*\n     * These wrappers can be removed once Git 2.53 is released. If you\n     * see this comment and that release has been published then chances\n     * are high that we forgot to remove them.\n     */\n\nPatrick\n"},{"id":"533675","messageId":"cf8330f2-e624-4d58-9250-57f0dbe7a0d2@web.de","threadId":"64765","inReplyTo":"aWS9JLb3UyxOwg9Z@pks.im","subject":"Re: [PATCH 01/10] environment: move access to core.maxTreeDepth into repo settings","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-12T19:37:02Z","receivedAt":"2026-01-12T19:37:03Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"On 1/12/26 10:21 AM, Patrick Steinhardt wrote:\n> On Fri, Jan 09, 2026 at 10:30:12PM +0100, René Scharfe wrote:\n>> diff --git a/git-compat-util.h b/git-compat-util.h\n>> index b0673d1a450..bebcf9f698c 100644\n>> --- a/git-compat-util.h\n>> +++ b/git-compat-util.h\n>> @@ -578,6 +578,30 @@ static inline bool strip_suffix(const char *str, const char *suffix,\n>>  #define DEFAULT_PACKED_GIT_LIMIT \\\n>>  \t((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? (32 * 1024L * 1024L) : 256))\n>>  \n>> +#ifdef _MSC_VER\n>> +  /*\n>> +   * When traversing into too-deep trees, Visual C-compiled Git seems to\n>> +   * run into some internal stack overflow detection in the\n>> +   * `RtlpAllocateHeap()` function that is called from within\n>> +   * `git_inflate_init()`'s call tree. The following value seems to be\n>> +   * low enough to avoid that by letting Git exit with an error before\n>> +   * the stack overflow can occur.\n>> +   */\n>> +#define DEFAULT_MAX_ALLOWED_TREE_DEPTH 512\n>> +#elif defined(GIT_WINDOWS_NATIVE) && defined(__clang__) && defined(__aarch64__)\n>> +  /*\n>> +   * Similar to Visual C, it seems that on Windows/ARM64 the clang-based\n>> +   * builds have a smaller stack space available. When running out of\n>> +   * that stack space, a `STATUS_STACK_OVERFLOW` is produced. When the\n>> +   * Git command was run from an MSYS2 Bash, this unfortunately results\n>> +   * in an exit code 127. Let's prevent that by lowering the maximal\n>> +   * tree depth; This value seems to be low enough.\n>> +   */\n>> +#define DEFAULT_MAX_ALLOWED_TREE_DEPTH 1280\n>> +#else\n>> +#define DEFAULT_MAX_ALLOWED_TREE_DEPTH 2048\n>> +#endif\n>> +\n>>  int git_open_cloexec(const char *name, int flags);\n>>  #define git_open(name) git_open_cloexec(name, O_RDONLY)\n>>  \n> \n> Why is this new constant defined in \"git-compat-util.h\"?\n\nNo particular reason, I just put it next to the existing similar macros\nDEFAULT_PACKED_GIT_WINDOW_SIZE and DEFAULT_PACKED_GIT_LIMIT.\n\n> That feels way\n> too global for my taste for a value that should ultimately only be\n> required by \"repo-settings.c\". Is there a reason why it's not declared\n> in \"repo-settings.h\"?\n\nNo.  The same goes for the above two, I guess.  Or they could go to\npackfile.h and DEFAULT_MAX_ALLOWED_TREE_DEPTH to tree.h.\n> I think we could even get away with declaring it in \"repo-settings.c\".\n> The expectation is that the settings need to be prepared anyway, so we\n> can simply set up the default when parsing the config.\n\nTrue, REPO_SETTINGS_INIT is the only user of \nDEFAULT_MAX_ALLOWED_TREE_DEPTH outside of repo-settings.c and is itself\nonly referenced there, so we could make it private, or even inline it to\nits only user, repo_settings_clear().\n\nRené\n\n"},{"id":"533676","messageId":"89e23323-7e0f-42b6-9a89-dd8a682644dd@web.de","threadId":"64765","inReplyTo":"aWUTNU7WGTwHt6Ks@pks.im","subject":"Re: [PATCH 09/10] tree: stop using the_repository","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-12T19:37:03Z","receivedAt":"2026-01-12T19:37:07Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"On 1/12/26 4:28 PM, Patrick Steinhardt wrote:\n> On Mon, Jan 12, 2026 at 07:20:32AM -0800, Junio C Hamano wrote:\n>> Patrick Steinhardt <ps@pks.im> writes:\n>>\n>>>>> In any case, I'd propose to move the compatibility macros into a section\n>>>>> that says something like:\n>>>>>\n>>>>>     /* Deprecated wrappers that will be removed once Git 2.53 is released. */\n>>>>\n>>>> Please do not take release schedule hostage to one particular fix-up\n>>>> series of patches.  Thanks.\n>>>\n>>> The intent isn't really to take anything hostage. It's rather intended\n>>> as a hint that once a specific event has happened, we should take\n>>> another look at removing these wrappers.\n>>\n>> I am OK with a comment that records the intent, e.g., \"let's work\n>> towards reducing the use of these wrappers\", with the plan for the\n>> next step, e.g., \"and once we have done so, remove these.\"\n>>\n>> But the comment you wrote is forcing people to make sure we remove\n>> the code that uses these wrappers and unless we finish it we cannot\n>> release 2.53, no?\n> \n> That's definitely not my intent. It's really only intended as a hint\n> when those should be removed at the earliest. Maybe something like the\n> following instead?\n> \n>     /*\n>      * These wrappers can be removed once Git 2.53 is released. If you\n>      * see this comment and that release has been published then chances\n>      * are high that we forgot to remove them.\n>      */\n\nForgetting to remove the three macro definitions is very cheap.\nForgetting to remove their Coccinelle rules is a bit more expensive.\nCan add a reminder.\n\nRené\n\n"},{"id":"533703","messageId":"aWXihQ3ETjQfO6dz@pks.im","threadId":"64765","inReplyTo":"89e23323-7e0f-42b6-9a89-dd8a682644dd@web.de","subject":"Re: [PATCH 09/10] tree: stop using the_repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-01-13T06:13:25Z","receivedAt":"2026-01-13T06:13:30Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Jan 12, 2026 at 08:37:03PM +0100, René Scharfe wrote:\n> On 1/12/26 4:28 PM, Patrick Steinhardt wrote:\n> > On Mon, Jan 12, 2026 at 07:20:32AM -0800, Junio C Hamano wrote:\n> >> Patrick Steinhardt <ps@pks.im> writes:\n> >>\n> >>>>> In any case, I'd propose to move the compatibility macros into a section\n> >>>>> that says something like:\n> >>>>>\n> >>>>>     /* Deprecated wrappers that will be removed once Git 2.53 is released. */\n> >>>>\n> >>>> Please do not take release schedule hostage to one particular fix-up\n> >>>> series of patches.  Thanks.\n> >>>\n> >>> The intent isn't really to take anything hostage. It's rather intended\n> >>> as a hint that once a specific event has happened, we should take\n> >>> another look at removing these wrappers.\n> >>\n> >> I am OK with a comment that records the intent, e.g., \"let's work\n> >> towards reducing the use of these wrappers\", with the plan for the\n> >> next step, e.g., \"and once we have done so, remove these.\"\n> >>\n> >> But the comment you wrote is forcing people to make sure we remove\n> >> the code that uses these wrappers and unless we finish it we cannot\n> >> release 2.53, no?\n> > \n> > That's definitely not my intent. It's really only intended as a hint\n> > when those should be removed at the earliest. Maybe something like the\n> > following instead?\n> > \n> >     /*\n> >      * These wrappers can be removed once Git 2.53 is released. If you\n> >      * see this comment and that release has been published then chances\n> >      * are high that we forgot to remove them.\n> >      */\n> \n> Forgetting to remove the three macro definitions is very cheap.\n> Forgetting to remove their Coccinelle rules is a bit more expensive.\n> Can add a reminder.\n\nTrue indeed. We have a bunch of Coccinelle rules that are not needed\nanymore. We should probably do a spring cleanup of those.\n\nPatrick\n"},{"id":"533996","messageId":"cd6e8f5a-baaa-4c4d-9d2d-576d4b6a9a5e@web.de","threadId":"64765","inReplyTo":"20260109213021.2546-1-l.s.r@web.de","subject":"[PATCH 11/10] cocci: remove obsolete the_repository rules","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-01-15T22:01:25Z","receivedAt":"2026-01-15T22:01:33Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"035c7de9e9e (cocci: apply the \"revision.h\" part of\n\"the_repository.pending\", 2023-03-28) removed the last of the repo-less\nfunctions and macros mentioned in the_repository.cocci at the time.  No\nstragglers appeared since then.  Remove the applied rules now that they\nhave outlived their usefulness.\n\nAlso add a reminder to eventually remove the just added rules for\ntree.h.\n\nSuggested-by: Patrick Steinhardt <ps@pks.im>\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n contrib/coccinelle/the_repository.cocci | 119 +-----------------------\n 1 file changed, 2 insertions(+), 117 deletions(-)\n\ndiff --git a/contrib/coccinelle/the_repository.cocci b/contrib/coccinelle/the_repository.cocci\nindex a1f6f5ac06c..f1129f79859 100644\n--- a/contrib/coccinelle/the_repository.cocci\n+++ b/contrib/coccinelle/the_repository.cocci\n@@ -2,123 +2,8 @@\n @@\n @@\n (\n-// cache.h\n-- get_oid\n-+ repo_get_oid\n-|\n-- get_oid_commit\n-+ repo_get_oid_commit\n-|\n-- get_oid_committish\n-+ repo_get_oid_committish\n-|\n-- get_oid_tree\n-+ repo_get_oid_tree\n-|\n-- get_oid_treeish\n-+ repo_get_oid_treeish\n-|\n-- get_oid_blob\n-+ repo_get_oid_blob\n-|\n-- get_oid_mb\n-+ repo_get_oid_mb\n-|\n-- find_unique_abbrev\n-+ repo_find_unique_abbrev\n-|\n-- find_unique_abbrev_r\n-+ repo_find_unique_abbrev_r\n-|\n-- for_each_abbrev\n-+ repo_for_each_abbrev\n-|\n-- interpret_branch_name\n-+ repo_interpret_branch_name\n-|\n-- peel_to_type\n-+ repo_peel_to_type\n-// commit-reach.h\n-|\n-- get_merge_bases\n-+ repo_get_merge_bases\n-|\n-- get_merge_bases_many\n-+ repo_get_merge_bases_many\n-|\n-- get_merge_bases_many_dirty\n-+ repo_get_merge_bases_many_dirty\n-|\n-- in_merge_bases\n-+ repo_in_merge_bases\n-|\n-- in_merge_bases_many\n-+ repo_in_merge_bases_many\n-// commit.h\n-|\n-- parse_commit_internal\n-+ repo_parse_commit_internal\n-|\n-- parse_commit\n-+ repo_parse_commit\n-|\n-- get_commit_buffer\n-+ repo_get_commit_buffer\n-|\n-- unuse_commit_buffer\n-+ repo_unuse_commit_buffer\n-|\n-- logmsg_reencode\n-+ repo_logmsg_reencode\n-|\n-- get_commit_tree\n-+ repo_get_commit_tree\n-// diff.h\n-|\n-- diff_setup\n-+ repo_diff_setup\n-// odb.h\n-|\n-- read_object_file\n-+ repo_read_object_file\n-|\n-- has_object_file\n-+ repo_has_object_file\n-|\n-- has_object_file_with_flags\n-+ repo_has_object_file_with_flags\n-// pretty.h\n-|\n-- format_commit_message\n-+ repo_format_commit_message\n-// packfile.h\n-|\n-- approximate_object_count\n-+ repo_approximate_object_count\n-// promisor-remote.h\n-|\n-- promisor_remote_reinit\n-+ repo_promisor_remote_reinit\n-|\n-- promisor_remote_find\n-+ repo_promisor_remote_find\n-|\n-- has_promisor_remote\n-+ repo_has_promisor_remote\n-// refs.h\n-|\n-- dwim_ref\n-+ repo_dwim_ref\n-// rerere.h\n-|\n-- rerere\n-+ repo_rerere\n-// revision.h\n-|\n-- init_revisions\n-+ repo_init_revisions\n-// tree.h\n-|\n+// TODO: remove the rules below and the macros from tree.h after the\n+// next Git release.\n - parse_tree\n + repo_parse_tree\n |\n-- \n2.52.0\n"},{"id":"534024","messageId":"aWoMqfTmrOU8UMhm@pks.im","threadId":"64765","inReplyTo":"cd6e8f5a-baaa-4c4d-9d2d-576d4b6a9a5e@web.de","subject":"Re: [PATCH 11/10] cocci: remove obsolete the_repository rules","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-01-16T10:02:17Z","receivedAt":"2026-01-16T10:02:24Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Jan 15, 2026 at 11:01:25PM +0100, René Scharfe wrote:\n> 035c7de9e9e (cocci: apply the \"revision.h\" part of\n> \"the_repository.pending\", 2023-03-28) removed the last of the repo-less\n> functions and macros mentioned in the_repository.cocci at the time.  No\n> stragglers appeared since then.  Remove the applied rules now that they\n> have outlived their usefulness.\n> \n> Also add a reminder to eventually remove the just added rules for\n> tree.h.\n\nAll of the removals look good to me, and I verified that we indeed don't\nhave these functions anymore. Thanks!\n\nPatrick\n"},{"id":"534062","messageId":"xmqqtswl8o1o.fsf@gitster.g","threadId":"64765","inReplyTo":"aWoMqfTmrOU8UMhm@pks.im","subject":"Re: [PATCH 11/10] cocci: remove obsolete the_repository rules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-01-16T17:28:35Z","receivedAt":"2026-01-16T17:28: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> On Thu, Jan 15, 2026 at 11:01:25PM +0100, René Scharfe wrote:\n>> 035c7de9e9e (cocci: apply the \"revision.h\" part of\n>> \"the_repository.pending\", 2023-03-28) removed the last of the repo-less\n>> functions and macros mentioned in the_repository.cocci at the time.  No\n>> stragglers appeared since then.  Remove the applied rules now that they\n>> have outlived their usefulness.\n>> \n>> Also add a reminder to eventually remove the just added rules for\n>> tree.h.\n>\n> All of the removals look good to me, and I verified that we indeed don't\n> have these functions anymore. Thanks!\n>\n> Patrick\n\nThanks, both.  These look good to me, too.\n"}]}