submodule deinit: require '--all' instead of '.' for all submodules

The discussion in [1] pointed out that '.' is a faulty suggestion as
there is a corner case where it fails:

> "submodule deinit ." may have "worked" in the sense that you would
> have at least one path in your tree and avoided this "nothing
> matches" most of the time.  It would have still failed with the
> exactly same error if run in an empty repository, i.e.
>
>        $ E=/var/tmp/x/empty && rm -fr "$E" && mkdir -p "$E" && cd "$E"
>        $ git init
>        $ rungit v2.6.6 submodule deinit .
>        error: pathspec '.' did not match any file(s) known to git.
>        Did you forget to 'git add'?
>        $ >file && git add file
>        $ rungit v2.6.6 submodule deinit .
>        $ echo $?
>        0

So instead of a pathspec add the '--all' option to deinit all submodules
and add a test to check for the corner case of an empty repository.

The code only needs to learn about the '--all' option and doesn't
require further changes as `git submodule--helper list "$@"` will list
all submodules when "$@" is empty.

[1] http://news.gmane.org/gmane.comp.version-control.git/289535

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Stefan Beller <sbeller@google.com>
Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Stefan Beller 2016-05-05 12:52:32 -07:00 committed by Junio C Hamano
parent 90f7b16b3a
commit f6a5279977
3 changed files with 48 additions and 10 deletions

View file

@ -13,7 +13,7 @@ SYNOPSIS
[--reference <repository>] [--depth <depth>] [--] <repository> [<path>]
'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
'git submodule' [--quiet] init [--] [<path>...]
'git submodule' [--quiet] deinit [-f|--force] [--] <path>...
'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)
'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch]
[-f|--force] [--rebase|--merge] [--reference <repository>]
[--depth <depth>] [--recursive] [--] [<path>...]
@ -140,12 +140,15 @@ deinit::
tree. Further calls to `git submodule update`, `git submodule foreach`
and `git submodule sync` will skip any unregistered submodules until
they are initialized again, so use this command if you don't want to
have a local checkout of the submodule in your work tree anymore. If
have a local checkout of the submodule in your working tree anymore. If
you really want to remove a submodule from the repository and commit
that use linkgit:git-rm[1] instead.
+
If `--force` is specified, the submodule's work tree will be removed even if
it contains local modifications.
When the command is run without pathspec, it errors out,
instead of deinit-ing everything, to prevent mistakes.
+
If `--force` is specified, the submodule's working tree will
be removed even if it contains local modifications.
update::
+
@ -247,6 +250,10 @@ OPTIONS
--quiet::
Only print error messages.
--all::
This option is only valid for the deinit command. Unregister all
submodules in the working tree.
-b::
--branch::
Branch of repository to add as submodule.
@ -257,8 +264,8 @@ OPTIONS
--force::
This option is only valid for add, deinit and update commands.
When running add, allow adding an otherwise ignored submodule path.
When running deinit the submodule work trees will be removed even if
they contain local changes.
When running deinit the submodule working trees will be removed even
if they contain local changes.
When running update (only effective with the checkout procedure),
throw away local changes in submodules when switching to a
different commit; and always run a checkout operation in the

View file

@ -8,7 +8,7 @@ dashless=$(basename "$0" | sed -e 's/-/ /')
USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
or: $dashless [--quiet] init [--] [<path>...]
or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)
or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--reference <repository>] [--recursive] [--] [<path>...]
or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
or: $dashless [--quiet] foreach [--recursive] <command>
@ -521,6 +521,7 @@ cmd_init()
cmd_deinit()
{
# parse $args after "submodule ... deinit".
deinit_all=
while test $# -ne 0
do
case "$1" in
@ -530,6 +531,9 @@ cmd_deinit()
-q|--quiet)
GIT_QUIET=1
;;
--all)
deinit_all=t
;;
--)
shift
break
@ -544,9 +548,14 @@ cmd_deinit()
shift
done
if test $# = 0
if test -n "$deinit_all" && test "$#" -ne 0
then
die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
echo >&2 "$(eval_gettext "pathspec and --all are incompatible")"
usage
fi
if test $# = 0 && test -z "$deinit_all"
then
die "$(eval_gettext "Use '--all' if you really want to deinitialize all submodules")"
fi
git submodule--helper list --prefix "$wt_prefix" "$@" |

View file

@ -11,6 +11,10 @@ subcommands of git submodule.
. ./test-lib.sh
test_expect_success 'submodule deinit works on empty repository' '
git submodule deinit --all
'
test_expect_success 'setup - initial commit' '
>t &&
git add t &&
@ -858,7 +862,8 @@ test_expect_success 'submodule deinit works on repository without submodules' '
>file &&
git add file &&
git commit -m "repo should not be empty"
git submodule deinit .
git submodule deinit . &&
git submodule deinit --all
)
'
@ -900,6 +905,19 @@ test_expect_success 'submodule deinit . deinits all initialized submodules' '
rmdir init example2
'
test_expect_success 'submodule deinit --all deinits all initialized submodules' '
git submodule update --init &&
git config submodule.example.foo bar &&
git config submodule.example2.frotz nitfol &&
test_must_fail git submodule deinit &&
git submodule deinit --all >actual &&
test -z "$(git config --get-regexp "submodule\.example\.")" &&
test -z "$(git config --get-regexp "submodule\.example2\.")" &&
test_i18ngrep "Cleared directory .init" actual &&
test_i18ngrep "Cleared directory .example2" actual &&
rmdir init example2
'
test_expect_success 'submodule deinit deinits a submodule when its work tree is missing or empty' '
git submodule update --init &&
rm -rf init example2/* example2/.git &&
@ -966,6 +984,10 @@ test_expect_success 'submodule deinit is silent when used on an uninitialized su
test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual &&
test_i18ngrep ! "Submodule .example2. (.*) unregistered for path .example2" actual &&
test_i18ngrep "Cleared directory .init" actual &&
git submodule deinit --all >actual &&
test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual &&
test_i18ngrep ! "Submodule .example2. (.*) unregistered for path .example2" actual &&
test_i18ngrep "Cleared directory .init" actual &&
rmdir init example2
'