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>

Stefan Beller committed May 5, 2016 at 12:52 UTC f6a527997743b79d6986a16313a7488cfc53d123
3 files changed +48 -10
Documentation/git-submodule.txt
+13 -6
@@ -13,7 +13,7 @@ SYNOPSIS
13 [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]
14 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
15 'git submodule' [--quiet] init [--] [<path>...]
16 -'git submodule' [--quiet] deinit [-f|--force] [--] <path>...
16 +'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)
17 'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch]
18 [-f|--force] [--rebase|--merge] [--reference <repository>]
19 [--depth <depth>] [--recursive] [--] [<path>...]
@@ -140,12 +140,15 @@ deinit::
140 tree. Further calls to `git submodule update`, `git submodule foreach`
141 and `git submodule sync` will skip any unregistered submodules until
142 they are initialized again, so use this command if you don't want to
143 - have a local checkout of the submodule in your work tree anymore. If
143 + have a local checkout of the submodule in your working tree anymore. If
144 you really want to remove a submodule from the repository and commit
145 that use linkgit:git-rm[1] instead.
146 +
147 -If `--force` is specified, the submodule's work tree will be removed even if
148 -it contains local modifications.
147 +When the command is run without pathspec, it errors out,
148 +instead of deinit-ing everything, to prevent mistakes.
149 ++
150 +If `--force` is specified, the submodule's working tree will
151 +be removed even if it contains local modifications.
152
153 update::
154 +
@@ -247,6 +250,10 @@ OPTIONS
250 --quiet::
251 Only print error messages.
252
253 +--all::
254 + This option is only valid for the deinit command. Unregister all
255 + submodules in the working tree.
256 +
257 -b::
258 --branch::
259 Branch of repository to add as submodule.
@@ -257,8 +264,8 @@ OPTIONS
264 --force::
265 This option is only valid for add, deinit and update commands.
266 When running add, allow adding an otherwise ignored submodule path.
260 - When running deinit the submodule work trees will be removed even if
261 - they contain local changes.
267 + When running deinit the submodule working trees will be removed even
268 + if they contain local changes.
269 When running update (only effective with the checkout procedure),
270 throw away local changes in submodules when switching to a
271 different commit; and always run a checkout operation in the
git-submodule.sh
+12 -3
@@ -8,7 +8,7 @@ dashless=$(basename "$0" | sed -e 's/-/ /')
8 USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
9 or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
10 or: $dashless [--quiet] init [--] [<path>...]
11 - or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
11 + or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)
12 or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--reference <repository>] [--recursive] [--] [<path>...]
13 or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
14 or: $dashless [--quiet] foreach [--recursive] <command>
@@ -521,6 +521,7 @@ cmd_init()
521 cmd_deinit()
522 {
523 # parse $args after "submodule ... deinit".
524 + deinit_all=
525 while test $# -ne 0
526 do
527 case "$1" in
@@ -530,6 +531,9 @@ cmd_deinit()
531 -q|--quiet)
532 GIT_QUIET=1
533 ;;
534 + --all)
535 + deinit_all=t
536 + ;;
537 --)
538 shift
539 break
@@ -544,9 +548,14 @@ cmd_deinit()
548 shift
549 done
550
547 - if test $# = 0
551 + if test -n "$deinit_all" && test "$#" -ne 0
552 + then
553 + echo >&2 "$(eval_gettext "pathspec and --all are incompatible")"
554 + usage
555 + fi
556 + if test $# = 0 && test -z "$deinit_all"
557 then
549 - die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
558 + die "$(eval_gettext "Use '--all' if you really want to deinitialize all submodules")"
559 fi
560
561 git submodule--helper list --prefix "$wt_prefix" "$@" |
t/t7400-submodule-basic.sh
+23 -1
@@ -11,6 +11,10 @@ subcommands of git submodule.
11
12 . ./test-lib.sh
13
14 +test_expect_success 'submodule deinit works on empty repository' '
15 + git submodule deinit --all
16 +'
17 +
18 test_expect_success 'setup - initial commit' '
19 >t &&
20 git add t &&
@@ -858,7 +862,8 @@ test_expect_success 'submodule deinit works on repository without submodules' '
862 >file &&
863 git add file &&
864 git commit -m "repo should not be empty"
861 - git submodule deinit .
865 + git submodule deinit . &&
866 + git submodule deinit --all
867 )
868 '
869
@@ -900,6 +905,19 @@ test_expect_success 'submodule deinit . deinits all initialized submodules' '
905 rmdir init example2
906 '
907
908 +test_expect_success 'submodule deinit --all deinits all initialized submodules' '
909 + git submodule update --init &&
910 + git config submodule.example.foo bar &&
911 + git config submodule.example2.frotz nitfol &&
912 + test_must_fail git submodule deinit &&
913 + git submodule deinit --all >actual &&
914 + test -z "$(git config --get-regexp "submodule\.example\.")" &&
915 + test -z "$(git config --get-regexp "submodule\.example2\.")" &&
916 + test_i18ngrep "Cleared directory .init" actual &&
917 + test_i18ngrep "Cleared directory .example2" actual &&
918 + rmdir init example2
919 +'
920 +
921 test_expect_success 'submodule deinit deinits a submodule when its work tree is missing or empty' '
922 git submodule update --init &&
923 rm -rf init example2/* example2/.git &&
@@ -966,6 +984,10 @@ test_expect_success 'submodule deinit is silent when used on an uninitialized su
984 test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual &&
985 test_i18ngrep ! "Submodule .example2. (.*) unregistered for path .example2" actual &&
986 test_i18ngrep "Cleared directory .init" actual &&
987 + git submodule deinit --all >actual &&
988 + test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual &&
989 + test_i18ngrep ! "Submodule .example2. (.*) unregistered for path .example2" actual &&
990 + test_i18ngrep "Cleared directory .init" actual &&
991 rmdir init example2
992 '
993