builtin/checkout: add --recurse-submodules switch
This exposes a flag to recurse into submodules in builtin/checkout making use of the code implemented in prior patches. A new failure mode is introduced in the submodule update library, as the directory/submodule conflict is not solved in prior patches. Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Stefan Beller committed
Mar 14, 2017 at 14:46 UTC
1fc458d958be0e8347d7704933ae647afeabcd91
4 files changed
+62
-5
Documentation/git-checkout.txt
+7
@@ -256,6 +256,13 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode.
256
out anyway. In other words, the ref can be held by more than one
257
worktree.
258
259
+--[no-]recurse-submodules::
260
+ Using --recurse-submodules will update the content of all initialized
261
+ submodules according to the commit recorded in the superproject. If
262
+ local modifications in a submodule would be overwritten the checkout
263
+ will fail unless `-f` is used. If nothing (or --no-recurse-submodules)
264
+ is used, the work trees of submodules will not be updated.
265
+
266
<branch>::
267
Branch to checkout; if it refers to a branch (i.e., a name that,
268
when prepended with "refs/heads/", is a valid ref), then that
builtin/checkout.c
+28
@@ -21,12 +21,31 @@
21
#include "submodule-config.h"
22
#include "submodule.h"
23
24
+static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
25
+
26
static const char * const checkout_usage[] = {
27
N_("git checkout [<options>] <branch>"),
28
N_("git checkout [<options>] [<branch>] -- <file>..."),
29
NULL,
30
};
31
32
+static int option_parse_recurse_submodules(const struct option *opt,
33
+ const char *arg, int unset)
34
+{
35
+ if (unset) {
36
+ recurse_submodules = RECURSE_SUBMODULES_OFF;
37
+ return 0;
38
+ }
39
+ if (arg)
40
+ recurse_submodules =
41
+ parse_update_recurse_submodules_arg(opt->long_name,
42
+ arg);
43
+ else
44
+ recurse_submodules = RECURSE_SUBMODULES_ON;
45
+
46
+ return 0;
47
+}
48
+
49
struct checkout_opts {
50
int patch_mode;
51
int quiet;
@@ -1163,6 +1182,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
1182
N_("second guess 'git checkout <no-such-branch>'")),
1183
OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees,
1184
N_("do not check if another worktree is holding the given ref")),
1185
+ { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules,
1186
+ "checkout", "control recursive updating of submodules",
1187
+ PARSE_OPT_OPTARG, option_parse_recurse_submodules },
1188
OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")),
1189
OPT_END(),
1190
};
@@ -1193,6 +1215,12 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
1215
git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
1216
}
1217
1218
+ if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
1219
+ git_config(submodule_config, NULL);
1220
+ if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT)
1221
+ set_config_update_recurse_submodules(recurse_submodules);
1222
+ }
1223
+
1224
if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1)
1225
die(_("-b, -B and --orphan are mutually exclusive"));
1226
t/lib-submodule-update.sh
+21
-5
@@ -782,6 +782,16 @@ test_submodule_forced_switch () {
782
783
test_submodule_switch_recursing () {
784
command="$1"
785
+ RESULTDS=success
786
+ if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1
787
+ then
788
+ RESULTDS=failure
789
+ fi
790
+ RESULTR=success
791
+ if test "$KNOWN_FAILURE_SUBMODULE_RECURSIVE_NESTED" = 1
792
+ then
793
+ RESULTR=failure
794
+ fi
795
######################### Appearing submodule #########################
796
# Switching to a commit letting a submodule appear checks it out ...
797
test_expect_success "$command: added submodule is checked out" '
@@ -891,7 +901,7 @@ test_submodule_switch_recursing () {
901
'
902
# Replacing a submodule with files in a directory must succeeds
903
# when the submodule is clean
894
- test_expect_success "$command: replace submodule with a directory" '
904
+ test_expect_$RESULTDS "$command: replace submodule with a directory" '
905
prolog &&
906
reset_work_tree_to_interested add_sub1 &&
907
(
@@ -903,7 +913,7 @@ test_submodule_switch_recursing () {
913
)
914
'
915
# ... absorbing a .git directory.
906
- test_expect_success "$command: replace submodule containing a .git directory with a directory must absorb the git dir" '
916
+ test_expect_$RESULTDS "$command: replace submodule containing a .git directory with a directory must absorb the git dir" '
917
prolog &&
918
reset_work_tree_to_interested add_sub1 &&
919
(
@@ -931,7 +941,7 @@ test_submodule_switch_recursing () {
941
'
942
943
# ... must check its local work tree for untracked files
934
- test_expect_success "$command: replace submodule with a file must fail with untracked files" '
944
+ test_expect_$RESULTDS "$command: replace submodule with a file must fail with untracked files" '
945
prolog &&
946
reset_work_tree_to_interested add_sub1 &&
947
(
@@ -987,7 +997,8 @@ test_submodule_switch_recursing () {
997
)
998
'
999
990
- test_expect_success "$command: modified submodule updates submodule recursively" '
1000
+ # recursing deeper than one level doesn't work yet.
1001
+ test_expect_$RESULTR "$command: modified submodule updates submodule recursively" '
1002
prolog &&
1003
reset_work_tree_to_interested add_nested_sub &&
1004
(
@@ -1006,6 +1017,11 @@ test_submodule_switch_recursing () {
1017
# the superproject as well as the submodule is allowed.
1018
test_submodule_forced_switch_recursing () {
1019
command="$1"
1020
+ RESULT=success
1021
+ if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1
1022
+ then
1023
+ RESULT=failure
1024
+ fi
1025
######################### Appearing submodule #########################
1026
# Switching to a commit letting a submodule appear creates empty dir ...
1027
test_expect_success "$command: added submodule is checked out" '
@@ -1151,7 +1167,7 @@ test_submodule_forced_switch_recursing () {
1167
'
1168
1169
# ... but stops for untracked files that would be lost
1154
- test_expect_success "$command: replace submodule with a file" '
1170
+ test_expect_$RESULT "$command: replace submodule with a file stops for untracked files" '
1171
prolog &&
1172
reset_work_tree_to_interested add_sub1 &&
1173
(
t/t2013-checkout-submodule.sh
+6
@@ -63,6 +63,12 @@ test_expect_success '"checkout <submodule>" honors submodule.*.ignore from .git/
63
! test -s actual
64
'
65
66
+KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1
67
+KNOWN_FAILURE_SUBMODULE_RECURSIVE_NESTED=1
68
+test_submodule_switch_recursing "git checkout --recurse-submodules"
69
+
70
+test_submodule_forced_switch_recursing "git checkout -f --recurse-submodules"
71
+
72
test_submodule_switch "git checkout"
73
74
test_submodule_forced_switch "git checkout -f"