Git fork

odb: get rid of `the_repository` when handling submodule sources

The "--recursive" flag for git-grep(1) allows users to grep for a string
across submodule boundaries. To make this work we add each submodule's
object sources to our own object database so that the objects can be
accessed directly.

The infrastructure for this depends on a global string list of submodule
paths. The caller is expected to call `add_submodule_odb_by_path()` for
each source and the object database will then eventually register all
submodule sources via `do_oid_object_info_extended()` in case it isn't
able to look up a specific object.

This reliance on global state is of course suboptimal with regards to
our libification efforts.

Refactor the logic so that the list of submodule sources is instead
tracked in the object database itself. This allows us to lose the
condition of `r == the_repository` before registering submodule sources
as we only ever add submodule sources to `the_repository` anyway. As
such, behaviour before and after this refactoring should always be the
same.

Rename the functions accordingly.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Patrick Steinhardt and committed by
Junio C Hamano
fc28a8a8 7eafd447

+50 -43
+2 -1
builtin/grep.c
··· 505 * lazily registered as alternates when needed (and except in an 506 * unexpected code interaction, it won't be needed). 507 */ 508 - add_submodule_odb_by_path(subrepo->objects->sources->path); 509 obj_read_unlock(); 510 511 memcpy(&subopt, opt, sizeof(subopt));
··· 505 * lazily registered as alternates when needed (and except in an 506 * unexpected code interaction, it won't be needed). 507 */ 508 + odb_add_submodule_source_by_path(the_repository->objects, 509 + subrepo->objects->sources->path); 510 obj_read_unlock(); 511 512 memcpy(&subopt, opt, sizeof(subopt));
+31 -6
odb.c
··· 24 #include "strbuf.h" 25 #include "strvec.h" 26 #include "submodule.h" 27 #include "write-or-die.h" 28 29 KHASH_INIT(odb_path_map, const char * /* key: odb_path */, ··· 469 return source; 470 } 471 472 static void fill_alternate_refs_command(struct child_process *cmd, 473 const char *repo_path) 474 { ··· 623 624 int fetch_if_missing = 1; 625 626 static int do_oid_object_info_extended(struct repository *r, 627 const struct object_id *oid, 628 struct object_info *oi, unsigned flags) ··· 676 } 677 678 /* 679 - * If r is the_repository, this might be an attempt at 680 - * accessing a submodule object as if it were in the_repository 681 - * (having called add_submodule_odb() on that submodule's ODB). 682 - * If any such ODBs exist, register them and try again. 683 */ 684 - if (r == the_repository && 685 - register_all_submodule_odb_as_alternates()) 686 /* We added some alternates; retry */ 687 continue; 688 ··· 968 INIT_LIST_HEAD(&o->packed_git_mru); 969 hashmap_init(&o->pack_map, pack_map_entry_cmp, NULL, 0); 970 pthread_mutex_init(&o->replace_mutex, NULL); 971 return o; 972 } 973 ··· 1017 o->packed_git = NULL; 1018 1019 hashmap_clear(&o->pack_map); 1020 }
··· 24 #include "strbuf.h" 25 #include "strvec.h" 26 #include "submodule.h" 27 + #include "trace2.h" 28 #include "write-or-die.h" 29 30 KHASH_INIT(odb_path_map, const char * /* key: odb_path */, ··· 470 return source; 471 } 472 473 + void odb_add_submodule_source_by_path(struct object_database *odb, 474 + const char *path) 475 + { 476 + string_list_insert(&odb->submodule_source_paths, path); 477 + } 478 + 479 static void fill_alternate_refs_command(struct child_process *cmd, 480 const char *repo_path) 481 { ··· 630 631 int fetch_if_missing = 1; 632 633 + static int register_all_submodule_sources(struct object_database *odb) 634 + { 635 + int ret = odb->submodule_source_paths.nr; 636 + 637 + for (size_t i = 0; i < odb->submodule_source_paths.nr; i++) 638 + odb_add_to_alternates_memory(odb, 639 + odb->submodule_source_paths.items[i].string); 640 + if (ret) { 641 + string_list_clear(&odb->submodule_source_paths, 0); 642 + trace2_data_intmax("submodule", odb->repo, 643 + "register_all_submodule_sources/registered", ret); 644 + if (git_env_bool("GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB", 0)) 645 + BUG("register_all_submodule_sources() called"); 646 + } 647 + return ret; 648 + } 649 + 650 static int do_oid_object_info_extended(struct repository *r, 651 const struct object_id *oid, 652 struct object_info *oi, unsigned flags) ··· 700 } 701 702 /* 703 + * This might be an attempt at accessing a submodule object as 704 + * if it were in main object store (having called 705 + * `odb_add_submodule_source_by_path()` on that submodule's 706 + * ODB). If any such ODBs exist, register them and try again. 707 */ 708 + if (register_all_submodule_sources(r->objects)) 709 /* We added some alternates; retry */ 710 continue; 711 ··· 991 INIT_LIST_HEAD(&o->packed_git_mru); 992 hashmap_init(&o->pack_map, pack_map_entry_cmp, NULL, 0); 993 pthread_mutex_init(&o->replace_mutex, NULL); 994 + string_list_init_dup(&o->submodule_source_paths); 995 return o; 996 } 997 ··· 1041 o->packed_git = NULL; 1042 1043 hashmap_clear(&o->pack_map); 1044 + string_list_clear(&o->submodule_source_paths, 0); 1045 }
+15
odb.h
··· 6 #include "list.h" 7 #include "oidset.h" 8 #include "oidmap.h" 9 #include "thread-utils.h" 10 11 struct oidmap; ··· 165 * packs. 166 */ 167 unsigned packed_git_initialized : 1; 168 }; 169 170 struct object_database *odb_new(struct repository *repo); ··· 190 void odb_restore_primary_source(struct object_database *odb, 191 struct odb_source *restore_source, 192 const char *old_path); 193 194 /* 195 * Iterate through all alternates of the database and execute the provided
··· 6 #include "list.h" 7 #include "oidset.h" 8 #include "oidmap.h" 9 + #include "string-list.h" 10 #include "thread-utils.h" 11 12 struct oidmap; ··· 166 * packs. 167 */ 168 unsigned packed_git_initialized : 1; 169 + 170 + /* 171 + * Submodule source paths that will be added as additional sources to 172 + * allow lookup of submodule objects via the main object database. 173 + */ 174 + struct string_list submodule_source_paths; 175 }; 176 177 struct object_database *odb_new(struct repository *repo); ··· 197 void odb_restore_primary_source(struct object_database *odb, 198 struct odb_source *restore_source, 199 const char *old_path); 200 + 201 + /* 202 + * Call odb_add_submodule_source_by_path() to add the submodule at the given 203 + * path to a list. The object stores of all submodules in that list will be 204 + * added as additional sources in the object store when looking up objects. 205 + */ 206 + void odb_add_submodule_source_by_path(struct object_database *odb, 207 + const char *path); 208 209 /* 210 * Iterate through all alternates of the database and execute the provided
+2 -1
submodule-config.c
··· 810 repo_get_oid(repo, GITMODULES_HEAD, &oid) >= 0) { 811 config_source.blob = oidstr = xstrdup(oid_to_hex(&oid)); 812 if (repo != the_repository) 813 - add_submodule_odb_by_path(repo->objects->sources->path); 814 } else { 815 goto out; 816 }
··· 810 repo_get_oid(repo, GITMODULES_HEAD, &oid) >= 0) { 811 config_source.blob = oidstr = xstrdup(oid_to_hex(&oid)); 812 if (repo != the_repository) 813 + odb_add_submodule_source_by_path(the_repository->objects, 814 + repo->objects->sources->path); 815 } else { 816 goto out; 817 }
-26
submodule.c
··· 31 #include "commit-reach.h" 32 #include "read-cache-ll.h" 33 #include "setup.h" 34 - #include "trace2.h" 35 36 static int config_update_recurse_submodules = RECURSE_SUBMODULES_OFF; 37 static int initialized_fetch_ref_tips; ··· 174 { 175 if (add_file_to_index(istate, GITMODULES_FILE, 0)) 176 die(_("staging updated .gitmodules failed")); 177 - } 178 - 179 - static struct string_list added_submodule_odb_paths = STRING_LIST_INIT_DUP; 180 - 181 - void add_submodule_odb_by_path(const char *path) 182 - { 183 - string_list_insert(&added_submodule_odb_paths, path); 184 - } 185 - 186 - int register_all_submodule_odb_as_alternates(void) 187 - { 188 - int i; 189 - int ret = added_submodule_odb_paths.nr; 190 - 191 - for (i = 0; i < added_submodule_odb_paths.nr; i++) 192 - odb_add_to_alternates_memory(the_repository->objects, 193 - added_submodule_odb_paths.items[i].string); 194 - if (ret) { 195 - string_list_clear(&added_submodule_odb_paths, 0); 196 - trace2_data_intmax("submodule", the_repository, 197 - "register_all_submodule_odb_as_alternates/registered", ret); 198 - if (git_env_bool("GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB", 0)) 199 - BUG("register_all_submodule_odb_as_alternates() called"); 200 - } 201 - return ret; 202 } 203 204 void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
··· 31 #include "commit-reach.h" 32 #include "read-cache-ll.h" 33 #include "setup.h" 34 35 static int config_update_recurse_submodules = RECURSE_SUBMODULES_OFF; 36 static int initialized_fetch_ref_tips; ··· 173 { 174 if (add_file_to_index(istate, GITMODULES_FILE, 0)) 175 die(_("staging updated .gitmodules failed")); 176 } 177 178 void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
-9
submodule.h
··· 105 int bad_to_remove_submodule(const char *path, unsigned flags); 106 107 /* 108 - * Call add_submodule_odb_by_path() to add the submodule at the given 109 - * path to a list. When register_all_submodule_odb_as_alternates() is 110 - * called, the object stores of all submodules in that list will be 111 - * added as alternates in the_repository. 112 - */ 113 - void add_submodule_odb_by_path(const char *path); 114 - int register_all_submodule_odb_as_alternates(void); 115 - 116 - /* 117 * Checks if there are submodule changes in a..b. If a is the null OID, 118 * checks b and all its ancestors instead. 119 */
··· 105 int bad_to_remove_submodule(const char *path, unsigned flags); 106 107 /* 108 * Checks if there are submodule changes in a..b. If a is the null OID, 109 * checks b and all its ancestors instead. 110 */