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>
This commit is contained in:
parent
6d14eac3ec
commit
1fc458d958
@ -256,6 +256,13 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode.
|
|||||||
out anyway. In other words, the ref can be held by more than one
|
out anyway. In other words, the ref can be held by more than one
|
||||||
worktree.
|
worktree.
|
||||||
|
|
||||||
|
--[no-]recurse-submodules::
|
||||||
|
Using --recurse-submodules will update the content of all initialized
|
||||||
|
submodules according to the commit recorded in the superproject. If
|
||||||
|
local modifications in a submodule would be overwritten the checkout
|
||||||
|
will fail unless `-f` is used. If nothing (or --no-recurse-submodules)
|
||||||
|
is used, the work trees of submodules will not be updated.
|
||||||
|
|
||||||
<branch>::
|
<branch>::
|
||||||
Branch to checkout; if it refers to a branch (i.e., a name that,
|
Branch to checkout; if it refers to a branch (i.e., a name that,
|
||||||
when prepended with "refs/heads/", is a valid ref), then that
|
when prepended with "refs/heads/", is a valid ref), then that
|
||||||
|
@ -21,12 +21,31 @@
|
|||||||
#include "submodule-config.h"
|
#include "submodule-config.h"
|
||||||
#include "submodule.h"
|
#include "submodule.h"
|
||||||
|
|
||||||
|
static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
|
||||||
|
|
||||||
static const char * const checkout_usage[] = {
|
static const char * const checkout_usage[] = {
|
||||||
N_("git checkout [<options>] <branch>"),
|
N_("git checkout [<options>] <branch>"),
|
||||||
N_("git checkout [<options>] [<branch>] -- <file>..."),
|
N_("git checkout [<options>] [<branch>] -- <file>..."),
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int option_parse_recurse_submodules(const struct option *opt,
|
||||||
|
const char *arg, int unset)
|
||||||
|
{
|
||||||
|
if (unset) {
|
||||||
|
recurse_submodules = RECURSE_SUBMODULES_OFF;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (arg)
|
||||||
|
recurse_submodules =
|
||||||
|
parse_update_recurse_submodules_arg(opt->long_name,
|
||||||
|
arg);
|
||||||
|
else
|
||||||
|
recurse_submodules = RECURSE_SUBMODULES_ON;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct checkout_opts {
|
struct checkout_opts {
|
||||||
int patch_mode;
|
int patch_mode;
|
||||||
int quiet;
|
int quiet;
|
||||||
@ -1163,6 +1182,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
|||||||
N_("second guess 'git checkout <no-such-branch>'")),
|
N_("second guess 'git checkout <no-such-branch>'")),
|
||||||
OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees,
|
OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees,
|
||||||
N_("do not check if another worktree is holding the given ref")),
|
N_("do not check if another worktree is holding the given ref")),
|
||||||
|
{ OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules,
|
||||||
|
"checkout", "control recursive updating of submodules",
|
||||||
|
PARSE_OPT_OPTARG, option_parse_recurse_submodules },
|
||||||
OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")),
|
OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")),
|
||||||
OPT_END(),
|
OPT_END(),
|
||||||
};
|
};
|
||||||
@ -1193,6 +1215,12 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
|||||||
git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
|
git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
|
||||||
|
git_config(submodule_config, NULL);
|
||||||
|
if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT)
|
||||||
|
set_config_update_recurse_submodules(recurse_submodules);
|
||||||
|
}
|
||||||
|
|
||||||
if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1)
|
if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1)
|
||||||
die(_("-b, -B and --orphan are mutually exclusive"));
|
die(_("-b, -B and --orphan are mutually exclusive"));
|
||||||
|
|
||||||
|
@ -782,6 +782,16 @@ test_submodule_forced_switch () {
|
|||||||
|
|
||||||
test_submodule_switch_recursing () {
|
test_submodule_switch_recursing () {
|
||||||
command="$1"
|
command="$1"
|
||||||
|
RESULTDS=success
|
||||||
|
if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1
|
||||||
|
then
|
||||||
|
RESULTDS=failure
|
||||||
|
fi
|
||||||
|
RESULTR=success
|
||||||
|
if test "$KNOWN_FAILURE_SUBMODULE_RECURSIVE_NESTED" = 1
|
||||||
|
then
|
||||||
|
RESULTR=failure
|
||||||
|
fi
|
||||||
######################### Appearing submodule #########################
|
######################### Appearing submodule #########################
|
||||||
# Switching to a commit letting a submodule appear checks it out ...
|
# Switching to a commit letting a submodule appear checks it out ...
|
||||||
test_expect_success "$command: added submodule is checked out" '
|
test_expect_success "$command: added submodule is checked out" '
|
||||||
@ -891,7 +901,7 @@ test_submodule_switch_recursing () {
|
|||||||
'
|
'
|
||||||
# Replacing a submodule with files in a directory must succeeds
|
# Replacing a submodule with files in a directory must succeeds
|
||||||
# when the submodule is clean
|
# when the submodule is clean
|
||||||
test_expect_success "$command: replace submodule with a directory" '
|
test_expect_$RESULTDS "$command: replace submodule with a directory" '
|
||||||
prolog &&
|
prolog &&
|
||||||
reset_work_tree_to_interested add_sub1 &&
|
reset_work_tree_to_interested add_sub1 &&
|
||||||
(
|
(
|
||||||
@ -903,7 +913,7 @@ test_submodule_switch_recursing () {
|
|||||||
)
|
)
|
||||||
'
|
'
|
||||||
# ... absorbing a .git directory.
|
# ... absorbing a .git directory.
|
||||||
test_expect_success "$command: replace submodule containing a .git directory with a directory must absorb the git dir" '
|
test_expect_$RESULTDS "$command: replace submodule containing a .git directory with a directory must absorb the git dir" '
|
||||||
prolog &&
|
prolog &&
|
||||||
reset_work_tree_to_interested add_sub1 &&
|
reset_work_tree_to_interested add_sub1 &&
|
||||||
(
|
(
|
||||||
@ -931,7 +941,7 @@ test_submodule_switch_recursing () {
|
|||||||
'
|
'
|
||||||
|
|
||||||
# ... must check its local work tree for untracked files
|
# ... must check its local work tree for untracked files
|
||||||
test_expect_success "$command: replace submodule with a file must fail with untracked files" '
|
test_expect_$RESULTDS "$command: replace submodule with a file must fail with untracked files" '
|
||||||
prolog &&
|
prolog &&
|
||||||
reset_work_tree_to_interested add_sub1 &&
|
reset_work_tree_to_interested add_sub1 &&
|
||||||
(
|
(
|
||||||
@ -987,7 +997,8 @@ test_submodule_switch_recursing () {
|
|||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success "$command: modified submodule updates submodule recursively" '
|
# recursing deeper than one level doesn't work yet.
|
||||||
|
test_expect_$RESULTR "$command: modified submodule updates submodule recursively" '
|
||||||
prolog &&
|
prolog &&
|
||||||
reset_work_tree_to_interested add_nested_sub &&
|
reset_work_tree_to_interested add_nested_sub &&
|
||||||
(
|
(
|
||||||
@ -1006,6 +1017,11 @@ test_submodule_switch_recursing () {
|
|||||||
# the superproject as well as the submodule is allowed.
|
# the superproject as well as the submodule is allowed.
|
||||||
test_submodule_forced_switch_recursing () {
|
test_submodule_forced_switch_recursing () {
|
||||||
command="$1"
|
command="$1"
|
||||||
|
RESULT=success
|
||||||
|
if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1
|
||||||
|
then
|
||||||
|
RESULT=failure
|
||||||
|
fi
|
||||||
######################### Appearing submodule #########################
|
######################### Appearing submodule #########################
|
||||||
# Switching to a commit letting a submodule appear creates empty dir ...
|
# Switching to a commit letting a submodule appear creates empty dir ...
|
||||||
test_expect_success "$command: added submodule is checked out" '
|
test_expect_success "$command: added submodule is checked out" '
|
||||||
@ -1151,7 +1167,7 @@ test_submodule_forced_switch_recursing () {
|
|||||||
'
|
'
|
||||||
|
|
||||||
# ... but stops for untracked files that would be lost
|
# ... but stops for untracked files that would be lost
|
||||||
test_expect_success "$command: replace submodule with a file" '
|
test_expect_$RESULT "$command: replace submodule with a file stops for untracked files" '
|
||||||
prolog &&
|
prolog &&
|
||||||
reset_work_tree_to_interested add_sub1 &&
|
reset_work_tree_to_interested add_sub1 &&
|
||||||
(
|
(
|
||||||
|
@ -63,6 +63,12 @@ test_expect_success '"checkout <submodule>" honors submodule.*.ignore from .git/
|
|||||||
! test -s actual
|
! test -s actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1
|
||||||
|
KNOWN_FAILURE_SUBMODULE_RECURSIVE_NESTED=1
|
||||||
|
test_submodule_switch_recursing "git checkout --recurse-submodules"
|
||||||
|
|
||||||
|
test_submodule_forced_switch_recursing "git checkout -f --recurse-submodules"
|
||||||
|
|
||||||
test_submodule_switch "git checkout"
|
test_submodule_switch "git checkout"
|
||||||
|
|
||||||
test_submodule_forced_switch "git checkout -f"
|
test_submodule_forced_switch "git checkout -f"
|
||||||
|
Loading…
Reference in New Issue
Block a user