From: Stefan Sperling Subject: reject Git repositories using multi-pack-index (MIDX) files To: gameoftrees@openbsd.org Date: Wed, 20 May 2026 15:30:18 +0200 The test failures with Git 2.54 are related to the multi-pack-index feature which gets enabled as part of their new default repository maintenance strategy. Until we add support for MIDX files advise users to turn this feature off in Git's configuration if they want to run Game of Trees on a repository touched by recent versions of Git which default to MIDX. ok? M include/got_repository.h | 1+ 0- M lib/got_lib_privsep.h | 3+ 0- M lib/got_lib_repository.h | 5+ 3- M lib/privsep.c | 11+ 0- M lib/read_gitconfig.c | 5+ 0- M lib/read_gitconfig_privsep.c | 10+ 0- M lib/repository.c | 33+ 2- M libexec/got-read-gitconfig/got-read-gitconfig.c | 4+ 0- M regress/cmdline/dump.sh | 2+ 0- 9 files changed, 74 insertions(+), 5 deletions(-) commit - 7e43a084bda36bdcd07318dea19722707b078d1f commit + 5212bdba0fee69a0e2ef3a5e52c9470d1f4dab77 blob - 89dabf01804eecca3d8273fcc04ca27c031c0f5e blob + fb07336ee1045644befc1dbe0b49ce6f4263317e --- include/got_repository.h +++ include/got_repository.h @@ -117,6 +117,7 @@ const struct got_gotconfig *got_repo_get_gotconfig(str */ char *got_repo_get_path_objects(struct got_repository *); char *got_repo_get_path_objects_pack(struct got_repository *); +char *got_repo_get_path_objects_pack_midx(struct got_repository *); char *got_repo_get_path_refs(struct got_repository *); char *got_repo_get_path_packed_refs(struct got_repository *); char *got_repo_get_path_gitconfig(struct got_repository *); blob - 5d45acef7f774410e32a0b1a920e76ff356930e8 blob + 9a3049542daebbd6dee4252d5f15c71f54a0ba7a --- lib/got_lib_privsep.h +++ lib/got_lib_privsep.h @@ -156,6 +156,7 @@ enum got_imsg_type { GOT_IMSG_GITCONFIG_PARSE_REQUEST, GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST, GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST, + GOT_IMSG_GITCONFIG_MULTI_PACK_INDEX_REQUEST, GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST, GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST, GOT_IMSG_GITCONFIG_REMOTES_REQUEST, @@ -773,6 +774,8 @@ const struct got_error *got_privsep_send_gitconfig_par int); const struct got_error * got_privsep_send_gitconfig_repository_format_version_req(struct imsgbuf *); +const struct got_error *got_privsep_send_gitconfig_multi_pack_index_req( + struct imsgbuf *); const struct got_error *got_privsep_send_gitconfig_repository_extensions_req( struct imsgbuf *); const struct got_error *got_privsep_send_gitconfig_author_name_req( blob - 825c284a4e4d1d2d2a5c1a4d62d6ba968820390a blob + 0c8759bc78f4e9122aac645917ce7b2e1a18f4d4 --- lib/got_lib_repository.h +++ lib/got_lib_repository.h @@ -27,6 +27,7 @@ #define GOT_ORIG_HEAD_FILE "ORIG_HEAD" #define GOT_OBJECTS_PACK_DIR "objects/pack" #define GOT_PACKED_REFS_FILE "packed-refs" +#define GOT_MIDX_FILE "multi-pack-index" #define GOT_PACK_CACHE_SIZE 32 @@ -121,6 +122,7 @@ struct got_repository { /* Settings read from Git configuration files. */ int gitconfig_repository_format_version; + int gitconfig_midx_enabled; char *gitconfig_author_name; char *gitconfig_author_email; char *global_gitconfig_author_name; @@ -177,9 +179,9 @@ const struct got_error *got_repo_pin_pack(struct got_r struct got_pack *got_repo_get_pinned_pack(struct got_repository *); void got_repo_unpin_pack(struct got_repository *); -const struct got_error *got_repo_read_gitconfig(int *, char **, char **, - struct got_remote_repo **, int *, char **, char ***, char ***, int *, - const char *); +const struct got_error *got_repo_read_gitconfig(int *, int *, char **, + char **, struct got_remote_repo **, int *, char **, char ***, char ***, + int *, const char *); const struct got_error *got_repo_temp_fds_get(int *, int *, struct got_repository *); blob - ef88b5607ee86b311e7fe35357fa3aa76758968f blob + 2034d65b0d08b0a113e2327a73c89fe49bbb3ba9 --- lib/privsep.c +++ lib/privsep.c @@ -2081,7 +2081,18 @@ got_privsep_send_gitconfig_repository_extensions_req(s return flush_imsg(ibuf); } +const struct got_error * +got_privsep_send_gitconfig_multi_pack_index_req(struct imsgbuf *ibuf) +{ + if (imsg_compose(ibuf, + GOT_IMSG_GITCONFIG_MULTI_PACK_INDEX_REQUEST, 0, 0, -1, + NULL, 0) == -1) + return got_error_from_errno("imsg_compose " + "GITCONFIG_MULTI_PACK_INDEX_REQUEST"); + return flush_imsg(ibuf); +} + const struct got_error * got_privsep_send_gitconfig_author_name_req(struct imsgbuf *ibuf) { blob - 9f370db70d268838b93dbe6d96b498def97df472 blob + a7c62c024213f21e2d037b836d2757d579bc94ad --- lib/read_gitconfig.c +++ lib/read_gitconfig.c @@ -66,6 +66,7 @@ skip_node(struct got_gitconfig *gitconfig, const struct got_error * got_repo_read_gitconfig(int *gitconfig_repository_format_version, + int *gitconfig_midx_enabled, char **gitconfig_author_name, char **gitconfig_author_email, struct got_remote_repo **remotes, int *nremotes, char **gitconfig_owner, char ***extnames, char ***extvals, @@ -79,6 +80,7 @@ got_repo_read_gitconfig(int *gitconfig_repository_form const char *author, *email, *owner; *gitconfig_repository_format_version = 0; + *gitconfig_midx_enabled = 0; if (extnames) *extnames = NULL; if (extvals) @@ -108,6 +110,9 @@ got_repo_read_gitconfig(int *gitconfig_repository_form *gitconfig_repository_format_version = got_gitconfig_get_num(gitconfig, "core", "repositoryformatversion", 0); + *gitconfig_midx_enabled = got_gitconfig_get_num(gitconfig, + "core", "multiPackIndex", 1); + tags = got_gitconfig_get_tag_list(gitconfig, "extensions"); if (extnames && extvals && nextensions && tags) { size_t numext = 0; blob - 888590ed15c13705cc6d56675504992831a23950 blob + 9cc0ab3903f7327e92238ab81f0f01ee5deb515d --- lib/read_gitconfig_privsep.c +++ lib/read_gitconfig_privsep.c @@ -48,6 +48,7 @@ const struct got_error * got_repo_read_gitconfig(int *gitconfig_repository_format_version, + int *gitconfig_midx_enabled, char **gitconfig_author_name, char **gitconfig_author_email, struct got_remote_repo **remotes, int *nremotes, char **gitconfig_owner, char ***extnames, char ***extvals, @@ -62,6 +63,7 @@ got_repo_read_gitconfig(int *gitconfig_repository_form memset(&ibuf, 0, sizeof(ibuf)); *gitconfig_repository_format_version = 0; + *gitconfig_midx_enabled = 1; if (extnames) *extnames = NULL; if (extvals) @@ -124,6 +126,14 @@ got_repo_read_gitconfig(int *gitconfig_repository_form if (err) goto wait; + err = got_privsep_send_gitconfig_multi_pack_index_req(&ibuf); + if (err) + goto wait; + + err = got_privsep_recv_gitconfig_int(gitconfig_midx_enabled, &ibuf); + if (err) + goto wait; + if (extnames && extvals && nextensions) { err = got_privsep_send_gitconfig_repository_extensions_req( &ibuf); blob - 14731673ee55811e65071b506239d1af5c93077a blob + 122592a88e32ff6cebb90cf77075f7fe9c124b6b --- lib/repository.c +++ lib/repository.c @@ -195,6 +195,12 @@ got_repo_get_path_objects_pack(struct got_repository * } char * +got_repo_get_path_objects_pack_midx(struct got_repository *repo) +{ + return get_path_git_child(repo, GOT_OBJECTS_PACK_DIR "/" GOT_MIDX_FILE); +} + +char * got_repo_get_path_refs(struct got_repository *repo) { return get_path_git_child(repo, GOT_REFS_DIR); @@ -625,8 +631,9 @@ read_gitconfig(struct got_repository *repo, const char if (global_gitconfig_path) { /* Read settings from ~/.gitconfig. */ - int dummy_repo_version; - err = got_repo_read_gitconfig(&dummy_repo_version, + int dummy_repo_version, dummy_midx; + + err = got_repo_read_gitconfig(&dummy_repo_version, &dummy_midx, &repo->global_gitconfig_author_name, &repo->global_gitconfig_author_email, NULL, NULL, NULL, NULL, NULL, NULL, @@ -642,6 +649,7 @@ read_gitconfig(struct got_repository *repo, const char err = got_repo_read_gitconfig( &repo->gitconfig_repository_format_version, + &repo->gitconfig_midx_enabled, &repo->gitconfig_author_name, &repo->gitconfig_author_email, &repo->gitconfig_remotes, &repo->ngitconfig_remotes, &repo->gitconfig_owner, &repo->extnames, &repo->extvals, @@ -706,6 +714,8 @@ got_repo_open(struct got_repository **repop, const cha const struct got_error *err = NULL; char *repo_path = NULL; size_t i, j = 0; + char *midxpath = NULL; + struct stat sb; *repop = NULL; @@ -834,6 +844,26 @@ got_repo_open(struct got_repository **repop, const cha } } + midxpath = got_repo_get_path_objects_pack_midx(repo); + if (midxpath == NULL) { + err = got_error_from_errno("asprintf"); + goto done; + } + + if (stat(midxpath, &sb) == -1) { + if (errno != ENOENT) { + err = got_error_from_errno2("stat", midxpath); + goto done; + } + } else if (repo->gitconfig_midx_enabled) { + err = got_error_fmt(GOT_ERR_GIT_REPO_FORMAT, + "repository '%s' is using the multi-pack-index feature; " + "Run 'git config set core.multiPackIndex false' and " + "'git repack -a' to restore compatibility with " + "Game of Trees", got_repo_get_path(repo)); + goto done; + } + err = got_repo_list_packidx(&repo->packidx_paths, repo); done: if (err) @@ -841,6 +871,7 @@ done: else *repop = repo; free(repo_path); + free(midxpath); return err; } blob - f74cfb26aa0cb92c1256643e3df545102860a05e blob + 0ca13b75325d6daa1a7ffd47545c3a1cb5ac08e0 --- libexec/got-read-gitconfig/got-read-gitconfig.c +++ libexec/got-read-gitconfig/got-read-gitconfig.c @@ -407,6 +407,10 @@ main(int argc, char *argv[]) err = gitconfig_num_request(&ibuf, gitconfig, "core", "repositoryformatversion", 0); break; + case GOT_IMSG_GITCONFIG_MULTI_PACK_INDEX_REQUEST: + err = gitconfig_num_request(&ibuf, gitconfig, "core", + "multiPackIndex", 1); + break; case GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST: err = gitconfig_extensions_request(&ibuf, gitconfig); break; blob - 4f75fc02d6a40ac31f5851218e869d2b5526e031 blob + d27d32621b92a9b3ebeeb2d4a0a97d60603060a8 --- regress/cmdline/dump.sh +++ regress/cmdline/dump.sh @@ -38,6 +38,8 @@ test_dump_bundle() { return 1 fi + git -C "$testroot"/r config set core.multiPackIndex false + if ! (cd "$testroot/r" && got log -p >$testroot/r.log); then echo "got log failed unexpectedly" >&2 test_done "$testroot" 1