Skip to contentSkip to conversation

Teach fetch and pull the on-demand mode for submodules

PATCH New Jens Lehmann 1 participant 1 message Jun 15, 2016

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Teach fetch and pull the on-demand mode for submodules

To be able to recursively checkout submodules it is sufficient to only then fetch a submodule recursively when the new commits fetched in the superproject record new commits for it.

Before a new or changed ref from upstream is updated in update_local_ref() "git rev-list <new-sha1> --not --branches --remotes" is used to determine all newly fetched commits. These are then walked and diffed against their parent(s) to see if a submodule has been changed. If that is the case, its path is stored to fetch it after the superproject fetch is completed. This is the new default behavior for fetch and pull.

Using the "--recurse-submodules" or the "--no-recurse-submodules" option disables the examination of the fetched refs because the result will be ignored anyway.

Because of the currently lacking infrastructure for storing deleted and new submodules in the .git directory of the superproject fetch and pull can currently only fetch submodules that are already checked out.

---

So here is the first usable iteration of on-demand fetching for submodules for people to test and comment on.

Still missing:

1) A new "on-demand" (other suggestions are welcome) value for the recurse[-]submodules command line and config options.

2) Tests. This patch currently breaks 5 tests and needs some of its own.

3) Optimizations:

a) Check if the submodule commit is already present locally and don't add it to the to-be-fetched-list then.

b) It hurts me to do the same computations again locally that the remote side already did to decide what commits to send. But not being very familiar with revision walking and transport I couldn't come up with a better solution for now. Ideas welcome.

And when we start implementing deletion and creation of submodules where the .git directories have to live in the superprojects .git this code can be extended to fetch into those directories when the submodule isn't even checked out.

This patch applies to next.

 builtin/fetch.c |   11 ++++++++-
 submodule.c     |   66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 submodule.h     |    1 +
 3 files changed, 76 insertions(+), 2 deletions(-)
builtin/fetch.c +10 -1
index 357f3cd..417fe77 100644
@@ -284,6 +284,9 @@ static int update_local_ref(struct ref *ref,
 		else {
 			msg = "storing head";
 			what = "[new branch]";
+			if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
+			    (recurse_submodules != RECURSE_SUBMODULES_ON))
+				check_for_new_submodule_commits(ref->new_sha1);
 		}
 
 		r = s_update_ref(msg, ref, 0);
@@ -299,6 +302,9 @@ static int update_local_ref(struct ref *ref,
 		strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
 		strcat(quickref, "..");
 		strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
+		if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
+		    (recurse_submodules != RECURSE_SUBMODULES_ON))
+			check_for_new_submodule_commits(ref->new_sha1);
 		r = s_update_ref("fast-forward", ref, 1);
 		sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : ' ',
 			TRANSPORT_SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
@@ -310,6 +316,9 @@ static int update_local_ref(struct ref *ref,
 		strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
 		strcat(quickref, "...");
 		strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
+		if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
+		    (recurse_submodules != RECURSE_SUBMODULES_ON))
+			check_for_new_submodule_commits(ref->new_sha1);
 		r = s_update_ref("forced-update", ref, 1);
 		sprintf(display, "%c %-*s %-*s -> %s  (%s)", r ? '!' : '+',
 			TRANSPORT_SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
@@ -951,7 +960,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 		int num_options = 0;
 		/* Set recursion as default when we already are recursing */
 		if (submodule_prefix[0])
-			set_config_fetch_recurse_submodules(1);
+			set_config_fetch_recurse_submodules(recurse_submodules == RECURSE_SUBMODULES_ON ? 1 : -1);
 		gitmodules_config();
 		git_config(submodule_config, NULL);
 		add_options_to_argv(&num_options, options);
submodule.c +65 -1

84 lines not on this page · raw message

submodule.h +1 -0
index 4729023..a574f11 100644
@@ -14,6 +14,7 @@ void show_submodule_summary(FILE *f, const char *path,
 		unsigned dirty_submodule,
 		const char *del, const char *add, const char *reset);
 void set_config_fetch_recurse_submodules(int value);
+void check_for_new_submodule_commits(unsigned char new_sha1[20]);
 int fetch_populated_submodules(int num_options, const char **options,
 			       const char *prefix, int ignore_config,
 			       int quiet);
Signature · 1 line
1.7.3.3.711.g95750