Skip to content

Commit

Permalink
fetch/pull: Add the 'on-demand' value to the --recurse-submodules option
Browse files Browse the repository at this point in the history
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 <Jens.Lehmann@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jens Lehmann authored and Junio C Hamano committed Mar 9, 2011
1 parent 88a2197 commit 8f0700d
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 10 deletions.
16 changes: 13 additions & 3 deletions Documentation/fetch-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,19 @@ ifndef::git-pull[]
specified with the remote.<name>.tagopt setting. See
linkgit:git-config[1].

--[no-]recurse-submodules::
This option controls if new commits of all populated submodules should
be fetched too (see linkgit:git-config[1] and linkgit:gitmodules[5]).
--recurse-submodules[=yes|on-demand|no]::
This option controls if and under what conditions new commits of
populated submodules should be fetched too. It can be used as a
boolean option to completely disable recursion when set to 'no' or to
unconditionally recurse into all populated submodules when set to
'yes', which is the default when this option is used without any
value. Use 'on-demand' to only recurse into a populated submodule
when the superproject retrieves a commit that updates the submodule's
reference.

--no-recurse-submodules::
Disable recursive fetching of submodules (this has the same effect as
using the '--recurse-submodules=no' option).

--submodule-prefix=<path>::
Prepend <path> to paths printed in informative messages
Expand Down
2 changes: 1 addition & 1 deletion Documentation/git-pull.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ must be given before the options meant for 'git fetch'.
--verbose::
Pass --verbose to git-fetch and git-merge.

--[no-]recurse-submodules::
--[no-]recurse-submodules[=yes|on-demand|no]::
This option controls if new commits of all populated submodules should
be fetched too (see linkgit:git-config[1] and linkgit:gitmodules[5]).
That might be necessary to get the data needed for merging submodule
Expand Down
22 changes: 19 additions & 3 deletions builtin/fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand 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"),
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}

Expand Down
3 changes: 3 additions & 0 deletions git-pull.sh
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ do
--recurse-submodules)
recurse_submodules=--recurse-submodules
;;
--recurse-submodules=*)
recurse_submodules="$1"
;;
--no-recurse-submodules)
recurse_submodules=--no-recurse-submodules
;;
Expand Down
8 changes: 6 additions & 2 deletions submodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ 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,
const char *prefix, int command_line_option,
int quiet)
{
int i, result = 0, argc = 0, default_argc;
Expand Down Expand Up @@ -376,7 +376,7 @@ int fetch_populated_submodules(int num_options, const char **options,
name = name_for_path->util;

default_argv = "yes";
if (!ignore_config) {
if (command_line_option == RECURSE_SUBMODULES_DEFAULT) {
struct string_list_item *fetch_recurse_submodules_option;
fetch_recurse_submodules_option = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, name);
if (fetch_recurse_submodules_option) {
Expand All @@ -391,6 +391,10 @@ int fetch_populated_submodules(int num_options, const char **options,
default_argv = "on-demand";
}
}
} else if (command_line_option == RECURSE_SUBMODULES_ON_DEMAND) {
if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name))
continue;
default_argv = "on-demand";
}

strbuf_addf(&submodule_path, "%s/%s", work_tree, ce->name);
Expand Down
2 changes: 1 addition & 1 deletion submodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void show_submodule_summary(FILE *f, const char *path,
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,
const char *prefix, int command_line_option,
int quiet);
unsigned is_submodule_modified(const char *path, int ignore_untracked);
int merge_submodule(unsigned char result[20], const char *path, const unsigned char base[20],
Expand Down
71 changes: 71 additions & 0 deletions t/t5526-fetch-submodules.sh
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,75 @@ test_expect_success "Recursion picks up all submodules when necessary" '
test_cmp expect.out actual.out
'

test_expect_success "'--recurse-submodules=on-demand' doesn't recurse when no new commits are fetched in the superproject (and ignores config)" '
add_upstream_commit &&
(
cd submodule &&
(
cd deepsubmodule &&
git fetch &&
git checkout -q FETCH_HEAD
) &&
head1=$(git rev-parse --short HEAD^) &&
git add deepsubmodule &&
git commit -m "new deepsubmodule"
head2=$(git rev-parse --short HEAD) &&
echo "From $pwd/submodule" > ../expect.err.sub &&
echo " $head1..$head2 master -> origin/master" >> ../expect.err.sub
) &&
(
cd downstream &&
git config fetch.recurseSubmodules true &&
git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err &&
git config --unset fetch.recurseSubmodules
) &&
! test -s actual.out &&
! test -s actual.err
'

test_expect_success "'--recurse-submodules=on-demand' recurses as deep as necessary (and ignores config)" '
head1=$(git rev-parse --short HEAD) &&
git add submodule &&
git commit -m "new submodule" &&
head2=$(git rev-parse --short HEAD) &&
tail -2 expect.err > expect.err.deepsub &&
echo "From $pwd/." > expect.err &&
echo " $head1..$head2 master -> origin/master" >> expect.err
cat expect.err.sub >> expect.err &&
cat expect.err.deepsub >> expect.err &&
(
cd downstream &&
git config fetch.recurseSubmodules false &&
(
cd submodule &&
git config -f .gitmodules submodule.deepsubmodule.fetchRecursive false
) &&
git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err &&
git config --unset fetch.recurseSubmodules
(
cd submodule &&
git config --unset -f .gitmodules submodule.deepsubmodule.fetchRecursive
)
) &&
test_cmp expect.out actual.out &&
test_cmp expect.err actual.err
'

test_expect_success "'--recurse-submodules=on-demand' stops when no new submodule commits are found in the superproject (and ignores config)" '
add_upstream_commit &&
head1=$(git rev-parse --short HEAD) &&
echo a >> file &&
git add file &&
git commit -m "new file" &&
head2=$(git rev-parse --short HEAD) &&
echo "From $pwd/." > expect.err.file &&
echo " $head1..$head2 master -> origin/master" >> expect.err.file &&
(
cd downstream &&
git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err
) &&
! test -s actual.out &&
test_cmp expect.err.file actual.err
'

test_done

0 comments on commit 8f0700d

Please sign in to comment.