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

[RFC PATCHv2 09/17] update submodules: add scheduling to update submodules

From
Stefan Beller <sbeller@google.com>
Date
Dec 3, 2016, 00:30 UTC
Message-ID
<20161203003022.29797-10-sbeller@google.com>
In-Reply-To
<20161203003022.29797-1-sbeller@google.com>

The walker of a tree is only expected to call `schedule_submodule_for_update` and once done, to run `update_submodules`. This avoids directory/file conflicts and later we can parallelize all submodule actions if needed.

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 submodule.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 submodule.h |   5 +++
 2 files changed, 137 insertions(+)
diff --git a/submodule.c b/submodule.c
index 7bb64d6c69..02c28ef56b 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1348,3 +1348,135 @@ int parallel_submodules(void)
 {
 	return parallel_jobs;
 }
+
+static struct scheduled_submodules_update_type {
+	const char *path;
+	const struct object_id *oid;
+	/*
+	 * Do we need to perform a complete checkout or just incremental
+	 * update?
+	 */
+	unsigned is_new:1;
+} *scheduled_submodules;
+#define SCHEDULED_SUBMODULES_INIT {NULL, NULL, 0}
+
+static int scheduled_submodules_nr, scheduled_submodules_alloc;
+
+void schedule_submodule_for_update(const struct cache_entry *ce, int is_new)
+{
+	struct scheduled_submodules_update_type *ssu;
+	ALLOC_GROW(scheduled_submodules,
+		   scheduled_submodules_nr + 1,
+		   scheduled_submodules_alloc);
+	ssu = &scheduled_submodules[scheduled_submodules_nr++];
+	ssu->path = ce->name;
+	ssu->oid = &ce->oid;
+	ssu->is_new = !!is_new;
+}
+
+static int update_submodule(const char *path, const struct object_id *oid,
+			    int force, int is_new)
+{
+	const char *git_dir;
+	struct child_process cp = CHILD_PROCESS_INIT;
+	const struct submodule *sub = submodule_from_path(null_sha1, path);
+
+	if (!sub || !sub->name)
+		return -1;
+
+	git_dir = resolve_gitdir(git_common_path("modules/%s", sub->name));
+
+	if (!git_dir)
+		return -1;
+
+	if (is_new)
+		connect_work_tree_and_git_dir(path, git_dir);
+
+	/* update index via `read-tree --reset sha1` */
+	argv_array_pushl(&cp.args, "read-tree",
+				   force ? "--reset" : "-m",
+				   "-u", sha1_to_hex(oid->hash), NULL);
+	prepare_submodule_repo_env(&cp.env_array);
+	cp.git_cmd = 1;
+	cp.no_stdin = 1;
+	cp.dir = path;
+	if (run_command(&cp)) {
+		warning(_("reading the index in submodule '%s' failed"), path);
+		child_process_clear(&cp);
+		return -1;
+	}
+
+	/* write index to working dir */
+	child_process_clear(&cp);
+	child_process_init(&cp);
+	argv_array_pushl(&cp.args, "checkout-index", "-a", NULL);
+	cp.git_cmd = 1;
+	cp.no_stdin = 1;
+	cp.dir = path;
+	if (force)
+		argv_array_push(&cp.args, "-f");
+
+	if (run_command(&cp)) {
+		warning(_("populating the working directory in submodule '%s' failed"), path);
+		child_process_clear(&cp);
+		return -1;
+	}
+
+	/* get the HEAD right */
+	child_process_clear(&cp);
+	child_process_init(&cp);
+	argv_array_pushl(&cp.args, "checkout", "--recurse-submodules", NULL);
+	cp.git_cmd = 1;
+	cp.no_stdin = 1;
+	cp.dir = path;
+	if (force)
+		argv_array_push(&cp.args, "-f");
+	argv_array_push(&cp.args, sha1_to_hex(oid->hash));
+
+	if (run_command(&cp)) {
+		warning(_("setting the HEAD in submodule '%s' failed"), path);
+		child_process_clear(&cp);
+		return -1;
+	}
+
+	child_process_clear(&cp);
+	return 0;
+}
+
+int update_submodules(int force)
+{
+	int i;
+	gitmodules_config();
+
+	/*
+	 * NEEDSWORK: As submodule updates can potentially take some
+	 * time each and they do not overlap (i.e. no d/f conflicts;
+	 * this can be parallelized using the run_commands.h API.
+	 */
+	for (i = 0; i < scheduled_submodules_nr; i++) {
+		struct submodule *sub;
+		struct scheduled_submodules_update_type *ssu =
+			&scheduled_submodules[i];
+
+		if (!submodule_is_interesting(ssu->path))
+			continue;
+
+		sub = submodule_from_path(null_sha1, ssu->path);
+
+		switch (sub->update_strategy) {
+		case SM_UPDATE_UNSPECIFIED: /* fall thru */
+		case SM_UPDATE_CHECKOUT:
+			update_submodule(ssu->path, ssu->oid,
+					 force, ssu->is_new);
+			break;
+		case SM_UPDATE_REBASE:
+		case SM_UPDATE_MERGE:
+		case SM_UPDATE_NONE:
+		case SM_UPDATE_COMMAND:
+			warning("update strategy for submodule '%s' not supported", ssu->path);
+		}
+	}
+
+	scheduled_submodules_nr = 0;
+	return 0;
+}
diff --git a/submodule.h b/submodule.h
index d8bb1d4baf..74df8b93d5 100644
--- a/submodule.h
+++ b/submodule.h
@@ -90,4 +90,9 @@ extern int parallel_submodules(void);
  * retaining any config in the environment.
  */
 extern void prepare_submodule_repo_env(struct argv_array *out);
+
+extern void schedule_submodule_for_update(const struct cache_entry *ce,
+					  int new);
+extern int update_submodules(int force);
+
 #endif
-- 
2.11.0.rc2.28.g2673dad
Previous: Stefan BellerNext: David Turner
Message 4 of 30 in “[RFC PATCHv2 00/17] Checkout aware of Submodules!”
  1. Stefan BellerDec 3, 2016
  2. 02/17 submodule: modernize ok_to_remove_submodule to use argv_arrayStefan Beller, Dec 3, 2016
  3. 12/17 unpack-trees: remove submodule contents if interestingStefan Beller, Dec 3, 2016
  4. 09/17 update submodules: add scheduling to update submodulesStefan Beller, Dec 3, 2016
  5. David TurnerDec 5, 2016
  6. Stefan BellerDec 5, 2016
  7. 07/17 update submodules: introduce submodule_is_interestingStefan Beller, Dec 3, 2016
  8. 08/17 update submodules: add depopulate_submoduleStefan Beller, Dec 3, 2016
  9. David TurnerDec 5, 2016
  10. Stefan BellerDec 6, 2016
  11. 04/17 update submodules: add is_submodule_populatedStefan Beller, Dec 3, 2016
  12. 10/17 update submodules: is_submodule_checkout_safeStefan Beller, Dec 3, 2016
  13. 05/17 update submodules: add submodule config parsingStefan Beller, Dec 3, 2016
  14. 15/17 checkout: recurse into submodules if asked toStefan Beller, Dec 3, 2016
  15. Brandon WilliamsDec 5, 2016
  16. Stefan BellerDec 5, 2016
  17. Brandon WilliamsDec 5, 2016
  18. David TurnerDec 5, 2016
  19. 03/17 update submodules: move up prepare_submodule_repo_envStefan Beller, Dec 3, 2016
  20. 16/17 completion: add '--recurse-submodules' to checkoutStefan Beller, Dec 3, 2016
  21. 01/17 submodule.h: add extern keyword to functionsStefan Beller, Dec 3, 2016
  22. 14/17 submodule: teach unpack_trees() to update submodulesStefan Beller, Dec 3, 2016
  23. David TurnerDec 5, 2016
  24. 06/17 update submodules: add a config option to determine if submodules are updatedStefan Beller, Dec 3, 2016
  25. 13/17 entry: write_entry to write populate submodulesStefan Beller, Dec 3, 2016
  26. 11/17 unpack-trees: teach verify_clean_submodule to inspect submodulesStefan Beller, Dec 3, 2016
  27. 17/17 checkout: add config option to recurse into submodules by defaultStefan Beller, Dec 3, 2016
  28. Brandon WilliamsDec 5, 2016
  29. Stefan BellerDec 5, 2016
  30. Brandon WilliamsDec 5, 2016

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.