From 88a21979c5717e3f37b9691e90b6dbf2b94c751a Mon Sep 17 00:00:00 2001 From: Jens Lehmann Date: Sun, 6 Mar 2011 23:10:46 +0100 Subject: fetch/pull: recurse into submodules when necessary To be able to access all commits of populated submodules referenced by the superproject it is sufficient to only then let "git fetch" recurse into a submodule when the new commits fetched in the superproject record new commits for it. Having these commits present is extremely useful when using the "--submodule" option to "git diff" (which is what "git gui" and "gitk" do since 1.6.6), as all submodule commits needed for creating a descriptive output can be accessed. Also merging submodule commits (added in 1.7.3) depends on the submodule commits in question being present to work. Last but not least this enables disconnected operation when using submodules, as all commits necessary for a successful "git submodule update -N" will have been fetched automatically. So we choose this mode as the default for fetch and pull. Before a new or changed ref from upstream is updated in update_local_ref() "git rev-list --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 be fetched after the superproject fetch is completed. Using the "--recurse-submodules" or the "--no-recurse-submodules" option disables the examination of the fetched refs because the result will be ignored anyway. There is currently no infrastructure for storing deleted and new submodules in the .git directory of the superproject. That's why fetch and pull for now only fetch submodules that are already checked out and are not renamed. In t7403 the "--no-recurse-submodules" argument had to be added to "git pull" to avoid failure because of the moved upstream submodule repo. Thanks-to: Jonathan Nieder Thanks-to: Heiko Voigt Signed-off-by: Jens Lehmann Signed-off-by: Junio C Hamano --- builtin/fetch.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'builtin') diff --git a/builtin/fetch.c b/builtin/fetch.c index 357f3cdbb..23c249dbf 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -28,12 +28,6 @@ enum { TAGS_SET = 2 }; -enum { - RECURSE_SUBMODULES_OFF = 0, - RECURSE_SUBMODULES_DEFAULT = 1, - RECURSE_SUBMODULES_ON = 2 -}; - static int all, append, dry_run, force, keep, multiple, prune, update_head_ok, verbosity; static int progress, recurse_submodules = RECURSE_SUBMODULES_DEFAULT; static int tags = TAGS_DEFAULT; @@ -42,6 +36,7 @@ static const char *upload_pack; static struct strbuf default_rla = STRBUF_INIT; static struct transport *transport; static const char *submodule_prefix = ""; +static const char *recurse_submodules_default; static struct option builtin_fetch_options[] = { OPT__VERBOSITY(&verbosity), @@ -73,6 +68,9 @@ static struct option builtin_fetch_options[] = { "deepen history of shallow clone"), { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, "DIR", "prepend this to submodule path output", PARSE_OPT_HIDDEN }, + { OPTION_STRING, 0, "recurse-submodules-default", + &recurse_submodules_default, NULL, + "default mode for recursion", PARSE_OPT_HIDDEN }, OPT_END() }; @@ -284,6 +282,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 +300,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 +314,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, @@ -949,9 +956,10 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) { const char *options[10]; int num_options = 0; - /* Set recursion as default when we already are recursing */ - if (submodule_prefix[0]) - set_config_fetch_recurse_submodules(1); + if (recurse_submodules_default) { + int arg = parse_fetch_recurse_submodules_arg("--recurse-submodules-default", recurse_submodules_default); + set_config_fetch_recurse_submodules(arg); + } gitmodules_config(); git_config(submodule_config, NULL); add_options_to_argv(&num_options, options); -- cgit v1.2.1 From 8f0700dd33f63e594b9b34c84efe94e670ea4f45 Mon Sep 17 00:00:00 2001 From: Jens Lehmann Date: Sun, 6 Mar 2011 23:11:21 +0100 Subject: fetch/pull: Add the 'on-demand' value to the --recurse-submodules option Until now the --recurse-submodules option could only be used to either fetch all populated submodules recursively or to disable recursion completely. As fetch and pull now by default just fetch those submodules for which new commits have been fetched in the superproject, a command line option to enforce that behavior is needed to be able to override configuration settings. Signed-off-by: Jens Lehmann Signed-off-by: Junio C Hamano --- builtin/fetch.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'builtin') diff --git a/builtin/fetch.c b/builtin/fetch.c index 23c249dbf..f60393607 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -38,6 +38,20 @@ static struct transport *transport; static const char *submodule_prefix = ""; static const char *recurse_submodules_default; +static int option_parse_recurse_submodules(const struct option *opt, + const char *arg, int unset) +{ + if (unset) { + recurse_submodules = RECURSE_SUBMODULES_OFF; + } else { + if (arg) + recurse_submodules = parse_fetch_recurse_submodules_arg(opt->long_name, arg); + else + recurse_submodules = RECURSE_SUBMODULES_ON; + } + return 0; +} + static struct option builtin_fetch_options[] = { OPT__VERBOSITY(&verbosity), OPT_BOOLEAN(0, "all", &all, @@ -55,9 +69,9 @@ static struct option builtin_fetch_options[] = { "do not fetch all tags (--no-tags)", TAGS_UNSET), OPT_BOOLEAN('p', "prune", &prune, "prune remote-tracking branches no longer on remote"), - OPT_SET_INT(0, "recurse-submodules", &recurse_submodules, + { OPTION_CALLBACK, 0, "recurse-submodules", NULL, "on-demand", "control recursive fetching of submodules", - RECURSE_SUBMODULES_ON), + PARSE_OPT_OPTARG, option_parse_recurse_submodules }, OPT_BOOLEAN(0, "dry-run", &dry_run, "dry run"), OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"), @@ -817,6 +831,8 @@ static void add_options_to_argv(int *argc, const char **argv) argv[(*argc)++] = "--keep"; if (recurse_submodules == RECURSE_SUBMODULES_ON) argv[(*argc)++] = "--recurse-submodules"; + else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) + argv[(*argc)++] = "--recurse-submodules=on-demand"; if (verbosity >= 2) argv[(*argc)++] = "-v"; if (verbosity >= 1) @@ -965,7 +981,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) add_options_to_argv(&num_options, options); result = fetch_populated_submodules(num_options, options, submodule_prefix, - recurse_submodules == RECURSE_SUBMODULES_ON, + recurse_submodules, verbosity < 0); } -- cgit v1.2.1