Merge branch 'dl/submodule-set-branch'

"git submodule" learns "set-branch" subcommand that allows the
submodule.*.branch settings to be modified.

* dl/submodule-set-branch:
  submodule: teach set-branch subcommand
  submodule--helper: teach config subcommand --unset
  git-submodule.txt: "--branch <branch>" option defaults to 'master'
This commit is contained in:
Junio C Hamano 2019-04-25 16:41:18 +09:00
commit 01f8d78887
6 changed files with 200 additions and 13 deletions

View File

@ -15,6 +15,7 @@ SYNOPSIS
'git submodule' [--quiet] init [--] [<path>...] 'git submodule' [--quiet] init [--] [<path>...]
'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...) 'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)
'git submodule' [--quiet] update [<options>] [--] [<path>...] 'git submodule' [--quiet] update [<options>] [--] [<path>...]
'git submodule' [--quiet] set-branch [<options>] [--] <path>
'git submodule' [--quiet] summary [<options>] [--] [<path>...] 'git submodule' [--quiet] summary [<options>] [--] [<path>...]
'git submodule' [--quiet] foreach [--recursive] <command> 'git submodule' [--quiet] foreach [--recursive] <command>
'git submodule' [--quiet] sync [--recursive] [--] [<path>...] 'git submodule' [--quiet] sync [--recursive] [--] [<path>...]
@ -172,6 +173,12 @@ submodule with the `--init` option.
If `--recursive` is specified, this command will recurse into the If `--recursive` is specified, this command will recurse into the
registered submodules, and update any nested submodules within. registered submodules, and update any nested submodules within.
-- --
set-branch ((-d|--default)|(-b|--branch <branch>)) [--] <path>::
Sets the default remote tracking branch for the submodule. The
`--branch` option allows the remote branch to be specified. The
`--default` option removes the submodule.<name>.branch configuration
key, which causes the tracking branch to default to 'master'.
summary [--cached|--files] [(-n|--summary-limit) <n>] [commit] [--] [<path>...]:: summary [--cached|--files] [(-n|--summary-limit) <n>] [commit] [--] [<path>...]::
Show commit summary between the given commit (defaults to HEAD) and Show commit summary between the given commit (defaults to HEAD) and
working tree/index. For a submodule in question, a series of commits working tree/index. For a submodule in question, a series of commits
@ -259,13 +266,14 @@ OPTIONS
This option is only valid for the deinit command. Unregister all This option is only valid for the deinit command. Unregister all
submodules in the working tree. submodules in the working tree.
-b:: -b <branch>::
--branch:: --branch <branch>::
Branch of repository to add as submodule. Branch of repository to add as submodule.
The name of the branch is recorded as `submodule.<name>.branch` in The name of the branch is recorded as `submodule.<name>.branch` in
`.gitmodules` for `update --remote`. A special value of `.` is used to `.gitmodules` for `update --remote`. A special value of `.` is used to
indicate that the name of the branch in the submodule should be the indicate that the name of the branch in the submodule should be the
same name as the current branch in the current repository. same name as the current branch in the current repository. If the
option is not specified, it defaults to 'master'.
-f:: -f::
--force:: --force::

View File

@ -2147,17 +2147,22 @@ static int check_name(int argc, const char **argv, const char *prefix)
static int module_config(int argc, const char **argv, const char *prefix) static int module_config(int argc, const char **argv, const char *prefix)
{ {
enum { enum {
CHECK_WRITEABLE = 1 CHECK_WRITEABLE = 1,
DO_UNSET = 2
} command = 0; } command = 0;
struct option module_config_options[] = { struct option module_config_options[] = {
OPT_CMDMODE(0, "check-writeable", &command, OPT_CMDMODE(0, "check-writeable", &command,
N_("check if it is safe to write to the .gitmodules file"), N_("check if it is safe to write to the .gitmodules file"),
CHECK_WRITEABLE), CHECK_WRITEABLE),
OPT_CMDMODE(0, "unset", &command,
N_("unset the config in the .gitmodules file"),
DO_UNSET),
OPT_END() OPT_END()
}; };
const char *const git_submodule_helper_usage[] = { const char *const git_submodule_helper_usage[] = {
N_("git submodule--helper config name [value]"), N_("git submodule--helper config <name> [<value>]"),
N_("git submodule--helper config --unset <name>"),
N_("git submodule--helper config --check-writeable"), N_("git submodule--helper config --check-writeable"),
NULL NULL
}; };
@ -2169,15 +2174,17 @@ static int module_config(int argc, const char **argv, const char *prefix)
return is_writing_gitmodules_ok() ? 0 : -1; return is_writing_gitmodules_ok() ? 0 : -1;
/* Equivalent to ACTION_GET in builtin/config.c */ /* Equivalent to ACTION_GET in builtin/config.c */
if (argc == 2) if (argc == 2 && command != DO_UNSET)
return print_config_from_gitmodules(the_repository, argv[1]); return print_config_from_gitmodules(the_repository, argv[1]);
/* Equivalent to ACTION_SET in builtin/config.c */ /* Equivalent to ACTION_SET in builtin/config.c */
if (argc == 3) { if (argc == 3 || (argc == 2 && command == DO_UNSET)) {
const char *value = (argc == 3) ? argv[2] : NULL;
if (!is_writing_gitmodules_ok()) if (!is_writing_gitmodules_ok())
die(_("please make sure that the .gitmodules file is in the working tree")); die(_("please make sure that the .gitmodules file is in the working tree"));
return config_set_in_gitmodules_file_gently(argv[1], argv[2]); return config_set_in_gitmodules_file_gently(argv[1], value);
} }
usage_with_options(git_submodule_helper_usage, module_config_options); usage_with_options(git_submodule_helper_usage, module_config_options);

View File

@ -2611,7 +2611,7 @@ _git_submodule ()
{ {
__git_has_doubledash && return __git_has_doubledash && return
local subcommands="add status init deinit update summary foreach sync absorbgitdirs" local subcommands="add status init deinit update set-branch summary foreach sync absorbgitdirs"
local subcommand="$(__git_find_on_cmdline "$subcommands")" local subcommand="$(__git_find_on_cmdline "$subcommands")"
if [ -z "$subcommand" ]; then if [ -z "$subcommand" ]; then
case "$cur" in case "$cur" in
@ -2642,6 +2642,9 @@ _git_submodule ()
--force --rebase --merge --reference --depth --recursive --jobs --force --rebase --merge --reference --depth --recursive --jobs
" "
;; ;;
set-branch,--*)
__gitcomp "--default --branch"
;;
summary,--*) summary,--*)
__gitcomp "--cached --files --summary-limit" __gitcomp "--cached --files --summary-limit"
;; ;;

View File

@ -11,6 +11,7 @@ USAGE="[--quiet] [--cached]
or: $dashless [--quiet] init [--] [<path>...] or: $dashless [--quiet] init [--] [<path>...]
or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...) or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)
or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...] or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]
or: $dashless [--quiet] set-branch (--default|--branch <branch>) [--] <path>
or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...] or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
or: $dashless [--quiet] foreach [--recursive] <command> or: $dashless [--quiet] foreach [--recursive] <command>
or: $dashless [--quiet] sync [--recursive] [--] [<path>...] or: $dashless [--quiet] sync [--recursive] [--] [<path>...]
@ -685,6 +686,72 @@ cmd_update()
} }
} }
#
# Configures a submodule's default branch
#
# $@ = requested path
#
cmd_set_branch() {
unset_branch=false
branch=
while test $# -ne 0
do
case "$1" in
-q|--quiet)
# we don't do anything with this but we need to accept it
;;
-d|--default)
unset_branch=true
;;
-b|--branch)
case "$2" in '') usage ;; esac
branch=$2
shift
;;
--)
shift
break
;;
-*)
usage
;;
*)
break
;;
esac
shift
done
if test $# -ne 1
then
usage
fi
# we can't use `git submodule--helper name` here because internally, it
# hashes the path so a trailing slash could lead to an unintentional no match
name="$(git submodule--helper list "$1" | cut -f2)"
if test -z "$name"
then
exit 1
fi
test -n "$branch"; has_branch=$?
test "$unset_branch" = true; has_unset_branch=$?
if test $((!$has_branch != !$has_unset_branch)) -eq 0
then
usage
fi
if test $has_branch -eq 0
then
git submodule--helper config submodule."$name".branch "$branch"
else
git submodule--helper config --unset submodule."$name".branch
fi
}
# #
# Show commit summary for submodules in index or working tree # Show commit summary for submodules in index or working tree
# #
@ -984,7 +1051,7 @@ cmd_absorbgitdirs()
while test $# != 0 && test -z "$command" while test $# != 0 && test -z "$command"
do do
case "$1" in case "$1" in
add | foreach | init | deinit | update | status | summary | sync | absorbgitdirs) add | foreach | init | deinit | update | set-branch | status | summary | sync | absorbgitdirs)
command=$1 command=$1
;; ;;
-q|--quiet) -q|--quiet)
@ -1025,8 +1092,8 @@ then
fi fi
fi fi
# "-b branch" is accepted only by "add" # "-b branch" is accepted only by "add" and "set-branch"
if test -n "$branch" && test "$command" != add if test -n "$branch" && (test "$command" != add || test "$command" != set-branch)
then then
usage usage
fi fi
@ -1037,4 +1104,4 @@ then
usage usage
fi fi
"cmd_$command" "$@" "cmd_$(echo $command | sed -e s/-/_/g)" "$@"

View File

@ -142,6 +142,15 @@ test_expect_success 'reading submodules config from the working tree with "submo
) )
' '
test_expect_success 'unsetting submodules config from the working tree with "submodule--helper config --unset"' '
(cd super &&
git submodule--helper config --unset submodule.submodule.url &&
git submodule--helper config submodule.submodule.url >actual &&
test_must_be_empty actual
)
'
test_expect_success 'writing submodules config with "submodule--helper config"' ' test_expect_success 'writing submodules config with "submodule--helper config"' '
(cd super && (cd super &&
echo "new_url" >expect && echo "new_url" >expect &&

93
t/t7419-submodule-set-branch.sh Executable file
View File

@ -0,0 +1,93 @@
#!/bin/sh
#
# Copyright (c) 2019 Denton Liu
#
test_description='Test submodules set-branch subcommand
This test verifies that the set-branch subcommand of git-submodule is working
as expected.
'
TEST_NO_CREATE_REPO=1
. ./test-lib.sh
test_expect_success 'submodule config cache setup' '
mkdir submodule &&
(cd submodule &&
git init &&
echo a >a &&
git add . &&
git commit -ma &&
git checkout -b topic &&
echo b >a &&
git add . &&
git commit -mb
) &&
mkdir super &&
(cd super &&
git init &&
git submodule add ../submodule &&
git commit -m "add submodule"
)
'
test_expect_success 'ensure submodule branch is unset' '
(cd super &&
test_must_fail grep branch .gitmodules
)
'
test_expect_success 'test submodule set-branch --branch' '
(cd super &&
git submodule set-branch --branch topic submodule &&
grep "branch = topic" .gitmodules &&
git submodule update --remote &&
cat <<-\EOF >expect &&
b
EOF
git -C submodule show -s --pretty=%s >actual &&
test_cmp expect actual
)
'
test_expect_success 'test submodule set-branch --default' '
(cd super &&
git submodule set-branch --default submodule &&
test_must_fail grep branch .gitmodules &&
git submodule update --remote &&
cat <<-\EOF >expect &&
a
EOF
git -C submodule show -s --pretty=%s >actual &&
test_cmp expect actual
)
'
test_expect_success 'test submodule set-branch -b' '
(cd super &&
git submodule set-branch -b topic submodule &&
grep "branch = topic" .gitmodules &&
git submodule update --remote &&
cat <<-\EOF >expect &&
b
EOF
git -C submodule show -s --pretty=%s >actual &&
test_cmp expect actual
)
'
test_expect_success 'test submodule set-branch -d' '
(cd super &&
git submodule set-branch -d submodule &&
test_must_fail grep branch .gitmodules &&
git submodule update --remote &&
cat <<-\EOF >expect &&
a
EOF
git -C submodule show -s --pretty=%s >actual &&
test_cmp expect actual
)
'
test_done