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 <Jens.Lehmann@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jens Lehmann committed
Mar 6, 2011 at 23:11 UTC
8f0700dd33f63e594b9b34c84efe94e670ea4f45
7 files changed
+114
-10
Documentation/fetch-options.txt
+13
-3
@@ -65,9 +65,19 @@ ifndef::git-pull[]
65
specified with the remote.<name>.tagopt setting. See
66
linkgit:git-config[1].
67
68
---[no-]recurse-submodules::
69
- This option controls if new commits of all populated submodules should
70
- be fetched too (see linkgit:git-config[1] and linkgit:gitmodules[5]).
68
+--recurse-submodules[=yes|on-demand|no]::
69
+ This option controls if and under what conditions new commits of
70
+ populated submodules should be fetched too. It can be used as a
71
+ boolean option to completely disable recursion when set to 'no' or to
72
+ unconditionally recurse into all populated submodules when set to
73
+ 'yes', which is the default when this option is used without any
74
+ value. Use 'on-demand' to only recurse into a populated submodule
75
+ when the superproject retrieves a commit that updates the submodule's
76
+ reference.
77
+
78
+--no-recurse-submodules::
79
+ Disable recursive fetching of submodules (this has the same effect as
80
+ using the '--recurse-submodules=no' option).
81
82
--submodule-prefix=<path>::
83
Prepend <path> to paths printed in informative messages
Documentation/git-pull.txt
+1
-1
@@ -84,7 +84,7 @@ must be given before the options meant for 'git fetch'.
84
--verbose::
85
Pass --verbose to git-fetch and git-merge.
86
87
---[no-]recurse-submodules::
87
+--[no-]recurse-submodules[=yes|on-demand|no]::
88
This option controls if new commits of all populated submodules should
89
be fetched too (see linkgit:git-config[1] and linkgit:gitmodules[5]).
90
That might be necessary to get the data needed for merging submodule
builtin/fetch.c
+19
-3
@@ -38,6 +38,20 @@ static struct transport *transport;
38
static const char *submodule_prefix = "";
39
static const char *recurse_submodules_default;
40
41
+static int option_parse_recurse_submodules(const struct option *opt,
42
+ const char *arg, int unset)
43
+{
44
+ if (unset) {
45
+ recurse_submodules = RECURSE_SUBMODULES_OFF;
46
+ } else {
47
+ if (arg)
48
+ recurse_submodules = parse_fetch_recurse_submodules_arg(opt->long_name, arg);
49
+ else
50
+ recurse_submodules = RECURSE_SUBMODULES_ON;
51
+ }
52
+ return 0;
53
+}
54
+
55
static struct option builtin_fetch_options[] = {
56
OPT__VERBOSITY(&verbosity),
57
OPT_BOOLEAN(0, "all", &all,
@@ -55,9 +69,9 @@ static struct option builtin_fetch_options[] = {
69
"do not fetch all tags (--no-tags)", TAGS_UNSET),
70
OPT_BOOLEAN('p', "prune", &prune,
71
"prune remote-tracking branches no longer on remote"),
58
- OPT_SET_INT(0, "recurse-submodules", &recurse_submodules,
72
+ { OPTION_CALLBACK, 0, "recurse-submodules", NULL, "on-demand",
73
"control recursive fetching of submodules",
60
- RECURSE_SUBMODULES_ON),
74
+ PARSE_OPT_OPTARG, option_parse_recurse_submodules },
75
OPT_BOOLEAN(0, "dry-run", &dry_run,
76
"dry run"),
77
OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
@@ -817,6 +831,8 @@ static void add_options_to_argv(int *argc, const char **argv)
831
argv[(*argc)++] = "--keep";
832
if (recurse_submodules == RECURSE_SUBMODULES_ON)
833
argv[(*argc)++] = "--recurse-submodules";
834
+ else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
835
+ argv[(*argc)++] = "--recurse-submodules=on-demand";
836
if (verbosity >= 2)
837
argv[(*argc)++] = "-v";
838
if (verbosity >= 1)
@@ -965,7 +981,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
981
add_options_to_argv(&num_options, options);
982
result = fetch_populated_submodules(num_options, options,
983
submodule_prefix,
968
- recurse_submodules == RECURSE_SUBMODULES_ON,
984
+ recurse_submodules,
985
verbosity < 0);
986
}
987
git-pull.sh
+3
@@ -108,6 +108,9 @@ do
108
--recurse-submodules)
109
recurse_submodules=--recurse-submodules
110
;;
111
+ --recurse-submodules=*)
112
+ recurse_submodules="$1"
113
+ ;;
114
--no-recurse-submodules)
115
recurse_submodules=--no-recurse-submodules
116
;;
submodule.c
+6
-2
@@ -330,7 +330,7 @@ void check_for_new_submodule_commits(unsigned char new_sha1[20])
330
}
331
332
int fetch_populated_submodules(int num_options, const char **options,
333
- const char *prefix, int ignore_config,
333
+ const char *prefix, int command_line_option,
334
int quiet)
335
{
336
int i, result = 0, argc = 0, default_argc;
@@ -376,7 +376,7 @@ int fetch_populated_submodules(int num_options, const char **options,
376
name = name_for_path->util;
377
378
default_argv = "yes";
379
- if (!ignore_config) {
379
+ if (command_line_option == RECURSE_SUBMODULES_DEFAULT) {
380
struct string_list_item *fetch_recurse_submodules_option;
381
fetch_recurse_submodules_option = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, name);
382
if (fetch_recurse_submodules_option) {
@@ -391,6 +391,10 @@ int fetch_populated_submodules(int num_options, const char **options,
391
default_argv = "on-demand";
392
}
393
}
394
+ } else if (command_line_option == RECURSE_SUBMODULES_ON_DEMAND) {
395
+ if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name))
396
+ continue;
397
+ default_argv = "on-demand";
398
}
399
400
strbuf_addf(&submodule_path, "%s/%s", work_tree, ce->name);
submodule.h
+1
-1
@@ -24,7 +24,7 @@ void show_submodule_summary(FILE *f, const char *path,
24
void set_config_fetch_recurse_submodules(int value);
25
void check_for_new_submodule_commits(unsigned char new_sha1[20]);
26
int fetch_populated_submodules(int num_options, const char **options,
27
- const char *prefix, int ignore_config,
27
+ const char *prefix, int command_line_option,
28
int quiet);
29
unsigned is_submodule_modified(const char *path, int ignore_untracked);
30
int merge_submodule(unsigned char result[20], const char *path, const unsigned char base[20],
t/t5526-fetch-submodules.sh
+71
@@ -301,4 +301,75 @@ test_expect_success "Recursion picks up all submodules when necessary" '
301
test_cmp expect.out actual.out
302
'
303
304
+test_expect_success "'--recurse-submodules=on-demand' doesn't recurse when no new commits are fetched in the superproject (and ignores config)" '
305
+ add_upstream_commit &&
306
+ (
307
+ cd submodule &&
308
+ (
309
+ cd deepsubmodule &&
310
+ git fetch &&
311
+ git checkout -q FETCH_HEAD
312
+ ) &&
313
+ head1=$(git rev-parse --short HEAD^) &&
314
+ git add deepsubmodule &&
315
+ git commit -m "new deepsubmodule"
316
+ head2=$(git rev-parse --short HEAD) &&
317
+ echo "From $pwd/submodule" > ../expect.err.sub &&
318
+ echo " $head1..$head2 master -> origin/master" >> ../expect.err.sub
319
+ ) &&
320
+ (
321
+ cd downstream &&
322
+ git config fetch.recurseSubmodules true &&
323
+ git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err &&
324
+ git config --unset fetch.recurseSubmodules
325
+ ) &&
326
+ ! test -s actual.out &&
327
+ ! test -s actual.err
328
+'
329
+
330
+test_expect_success "'--recurse-submodules=on-demand' recurses as deep as necessary (and ignores config)" '
331
+ head1=$(git rev-parse --short HEAD) &&
332
+ git add submodule &&
333
+ git commit -m "new submodule" &&
334
+ head2=$(git rev-parse --short HEAD) &&
335
+ tail -2 expect.err > expect.err.deepsub &&
336
+ echo "From $pwd/." > expect.err &&
337
+ echo " $head1..$head2 master -> origin/master" >> expect.err
338
+ cat expect.err.sub >> expect.err &&
339
+ cat expect.err.deepsub >> expect.err &&
340
+ (
341
+ cd downstream &&
342
+ git config fetch.recurseSubmodules false &&
343
+ (
344
+ cd submodule &&
345
+ git config -f .gitmodules submodule.deepsubmodule.fetchRecursive false
346
+ ) &&
347
+ git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err &&
348
+ git config --unset fetch.recurseSubmodules
349
+ (
350
+ cd submodule &&
351
+ git config --unset -f .gitmodules submodule.deepsubmodule.fetchRecursive
352
+ )
353
+ ) &&
354
+ test_cmp expect.out actual.out &&
355
+ test_cmp expect.err actual.err
356
+'
357
+
358
+test_expect_success "'--recurse-submodules=on-demand' stops when no new submodule commits are found in the superproject (and ignores config)" '
359
+ add_upstream_commit &&
360
+ head1=$(git rev-parse --short HEAD) &&
361
+ echo a >> file &&
362
+ git add file &&
363
+ git commit -m "new file" &&
364
+ head2=$(git rev-parse --short HEAD) &&
365
+ echo "From $pwd/." > expect.err.file &&
366
+ echo " $head1..$head2 master -> origin/master" >> expect.err.file &&
367
+ (
368
+ cd downstream &&
369
+ git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err
370
+ ) &&
371
+ ! test -s actual.out &&
372
+ test_cmp expect.err.file actual.err
373
+'
374
+
375
test_done