git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 1/8] submodule: lazily add submodule ODBs as alternates

From
JTJonathan Tan <jonathantanmy@google.com>
Date
Aug 16, 2021, 21:09 UTC
Message-ID
<5994a517e8afc345e8f649b2368756e22b0e9ebe.1629148153.git.jonathantanmy@google.com>
In-Reply-To
<cover.1629148153.git.jonathantanmy@google.com>

Teach Git to add submodule ODBs as alternates to the object store of the_repository only upon the first access of an object not in the_repository, and not when add_submodule_odb() is called.

This provides a means of gradually migrating from accessing a submodule's object through alternates to accessing a submodule's object by explicitly passing its repository object. Any Git command can declare that it might access submodule objects by calling add_submodule_odb() (as they do now), but the submodule ODBs themselves will not be added until needed, so individual commands and/or combinations of arguments can be migrated one by one.

[The advantage of explicit repository-object passing is code clarity (it is clear which repository an object read is from), performance (there is no need to linearly search through all submodule ODBs whenever an object is accessed from any repository, whether superproject or submodule), and the possibility of future features like partial clone submodules (which right now is not possible because if an object is missing, we do not know which repository to lazy-fetch into).]

This commit also introduces an environment variable that a test may set to make the actual registration of alternates fatal, in order to demonstrate that its codepaths do not need this registration.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
 object-file.c |  5 +++++
 submodule.c   | 20 +++++++++++++++++++-
 submodule.h   |  7 +++++++
 t/README      | 10 ++++++++++
 4 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/object-file.c b/object-file.c
index 3d27dc8dea..621b121bcb 100644
--- a/object-file.c
+++ b/object-file.c
@@ -32,6 +32,7 @@
 #include "packfile.h"
 #include "object-store.h"
 #include "promisor-remote.h"
+#include "submodule.h"
 
 /* The maximum size for an object header. */
 #define MAX_HEADER_LEN 32
@@ -1592,6 +1593,10 @@ static int do_oid_object_info_extended(struct repository *r,
 				break;
 		}
 
+		if (register_all_submodule_odb_as_alternates())
+			/* We added some alternates; retry */
+			continue;
+
 		/* Check if it is a missing object */
 		if (fetch_if_missing && repo_has_promisor_remote(r) &&
 		    !already_retried &&
diff --git a/submodule.c b/submodule.c
index 8e611fe1db..8fde90e906 100644
--- a/submodule.c
+++ b/submodule.c
@@ -165,6 +165,8 @@ void stage_updated_gitmodules(struct index_state *istate)
 		die(_("staging updated .gitmodules failed"));
 }
 
+static struct string_list added_submodule_odb_paths = STRING_LIST_INIT_NODUP;
+
 /* TODO: remove this function, use repo_submodule_init instead. */
 int add_submodule_odb(const char *path)
 {
@@ -178,12 +180,28 @@ int add_submodule_odb(const char *path)
 		ret = -1;
 		goto done;
 	}
-	add_to_alternates_memory(objects_directory.buf);
+	string_list_insert(&added_submodule_odb_paths,
+			   strbuf_detach(&objects_directory, NULL));
 done:
 	strbuf_release(&objects_directory);
 	return ret;
 }
 
+int register_all_submodule_odb_as_alternates(void)
+{
+	int i;
+	int ret = added_submodule_odb_paths.nr;
+
+	for (i = 0; i < added_submodule_odb_paths.nr; i++)
+		add_to_alternates_memory(added_submodule_odb_paths.items[i].string);
+	if (ret) {
+		string_list_clear(&added_submodule_odb_paths, 0);
+		if (git_env_bool("GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB", 0))
+			BUG("register_all_submodule_odb_as_alternates() called");
+	}
+	return ret;
+}
+
 void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
 					     const char *path)
 {
diff --git a/submodule.h b/submodule.h
index 84640c49c1..c252784bc2 100644
--- a/submodule.h
+++ b/submodule.h
@@ -97,7 +97,14 @@ int submodule_uses_gitfile(const char *path);
 #define SUBMODULE_REMOVAL_IGNORE_IGNORED_UNTRACKED (1<<2)
 int bad_to_remove_submodule(const char *path, unsigned flags);
 
+/*
+ * Call add_submodule_odb() to add the submodule at the given path to a list.
+ * When register_all_submodule_odb_as_alternates() is called, the object stores
+ * of all submodules in that list will be added as alternates in
+ * the_repository.
+ */
 int add_submodule_odb(const char *path);
+int register_all_submodule_odb_as_alternates(void);
 
 /*
  * Checks if there are submodule changes in a..b. If a is the null OID,
diff --git a/t/README b/t/README
index 9e70122302..8b67b4f00b 100644
--- a/t/README
+++ b/t/README
@@ -448,6 +448,16 @@ GIT_TEST_CHECKOUT_WORKERS=<n> overrides the 'checkout.workers' setting
 to <n> and 'checkout.thresholdForParallelism' to 0, forcing the
 execution of the parallel-checkout code.
 
+GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=<boolean>, when true, makes
+registering submodule ODBs as alternates a fatal action. Support for
+this environment variable can be removed once the migration to
+explicitly providing repositories when accessing submodule objects is
+complete (in which case we might want to replace this with a trace2
+call so that users can make it visible if accessing submodule objects
+without an explicit repository still happens) or needs to be abandoned
+for whatever reason (in which case the migrated codepaths still retain
+their performance benefits).
+
 Naming Tests
 ------------
 
-- 
2.33.0.rc1.237.g0d66db33f3-goog
Previous: Jonathan TanNext: Jonathan Tan
Message 57 of 71 in “In grep, no adding submodule ODB as alternates”
  1. 0/7 In grep, no adding submodule ODB as alternatesJonathan Tan, Aug 10, 2021
  2. 4/7 grep: read submodule entry with explicit repoJonathan Tan, Aug 10, 2021
  3. Emily ShafferAug 11, 2021
  4. Jonathan TanAug 13, 2021
  5. 3/7 grep: typesafe versions of grep_source_initJonathan Tan, Aug 10, 2021
  6. Junio C HamanoAug 10, 2021
  7. Emily ShafferAug 11, 2021
  8. Ramsay JonesAug 11, 2021
  9. Jonathan TanAug 13, 2021
  10. Matheus Tavares BernardinoAug 11, 2021
  11. Junio C HamanoAug 12, 2021
  12. Jonathan TanAug 13, 2021
  13. 2/7 grep: use submodule-ODB-as-alternate lazy-additionJonathan Tan, Aug 10, 2021
  14. Emily ShafferAug 11, 2021
  15. Jonathan TanAug 13, 2021
  16. 1/7 submodule: lazily add submodule ODBs as alternatesJonathan Tan, Aug 10, 2021
  17. Junio C HamanoAug 10, 2021
  18. Jonathan TanAug 13, 2021
  19. Emily ShafferAug 11, 2021
  20. Jonathan TanAug 13, 2021
  21. 5/7 grep: allocate subrepos on heapJonathan Tan, Aug 10, 2021
  22. Emily ShafferAug 11, 2021
  23. Jonathan TanAug 13, 2021
  24. 6/7 grep: add repository to OID grep sourcesJonathan Tan, Aug 10, 2021
  25. Emily ShafferAug 11, 2021
  26. Jonathan TanAug 13, 2021
  27. Matheus Tavares BernardinoAug 11, 2021
  28. Jonathan TanAug 13, 2021
  29. 7/7 t7814: show lack of alternate ODB-addingJonathan Tan, Aug 10, 2021
  30. Emily ShafferAug 11, 2021
  31. Matheus Tavares BernardinoAug 11, 2021
  32. Jonathan TanAug 13, 2021
  33. Emily ShafferAug 11, 2021
  34. Josh SteadmonAug 11, 2021
  35. 0/8 In grep, no adding submodule ODB as alternatesJonathan Tan, Aug 13, 2021
  36. 2/8 grep: use submodule-ODB-as-alternate lazy-additionJonathan Tan, Aug 13, 2021
  37. 1/8 submodule: lazily add submodule ODBs as alternatesJonathan Tan, Aug 13, 2021
  38. 3/8 grep: typesafe versions of grep_source_initJonathan Tan, Aug 13, 2021
  39. Matheus Tavares BernardinoAug 16, 2021
  40. 4/8 grep: read submodule entry with explicit repoJonathan Tan, Aug 13, 2021
  41. 5/8 grep: allocate subrepos on heapJonathan Tan, Aug 13, 2021
  42. Junio C HamanoAug 13, 2021
  43. Jonathan TanAug 16, 2021
  44. 6/8 grep: add repository to OID grep sourcesJonathan Tan, Aug 13, 2021
  45. Matheus Tavares BernardinoAug 16, 2021
  46. Jonathan TanAug 16, 2021
  47. 7/8 submodule-config: pass repo upon blob config readJonathan Tan, Aug 13, 2021
  48. Matheus Tavares BernardinoAug 16, 2021
  49. Matheus Tavares BernardinoAug 16, 2021
  50. Jonathan TanAug 16, 2021
  51. Matheus Tavares BernardinoAug 16, 2021
  52. Jonathan TanAug 16, 2021
  53. Jonathan TanAug 16, 2021
  54. 8/8 t7814: show lack of alternate ODB-addingJonathan Tan, Aug 13, 2021
  55. Matheus Tavares BernardinoAug 16, 2021
  56. 0/8 In grep, no adding submodule ODB as alternatesJonathan Tan, Aug 16, 2021
  57. 1/8 submodule: lazily add submodule ODBs as alternatesJonathan Tan, Aug 16, 2021
  58. 2/8 grep: use submodule-ODB-as-alternate lazy-additionJonathan Tan, Aug 16, 2021
  59. 3/8 grep: typesafe versions of grep_source_initJonathan Tan, Aug 16, 2021
  60. 4/8 grep: read submodule entry with explicit repoJonathan Tan, Aug 16, 2021
  61. 5/8 grep: allocate subrepos on heapJonathan Tan, Aug 16, 2021
  62. 6/8 grep: add repository to OID grep sourcesJonathan Tan, Aug 16, 2021
  63. Ævar Arnfjörð BjarmasonSep 27, 2021
  64. Matheus TavaresSep 27, 2021
  65. Ævar Arnfjörð BjarmasonSep 27, 2021
  66. 7/8 submodule-config: pass repo upon blob config readJonathan Tan, Aug 16, 2021
  67. 8/8 t7814: show lack of alternate ODB-addingJonathan Tan, Aug 16, 2021
  68. Matheus Tavares BernardinoAug 17, 2021
  69. Junio C HamanoSep 8, 2021
  70. Matheus Tavares BernardinoSep 8, 2021
  71. Junio C HamanoSep 8, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.