Let submodule command exit with error status if path does not exist

Various subcommands of the "git submodule" command exited with 0 status even though the path given by the user did not exist. The reason behind that was that they all pipe the output of module_list into the while loop which then does the action on the paths specified by the commandline. Since the exit code of the command on the upstream side of the pipe is ignored by the shell, the status code of "ls-files --error-unmatch" nor "module_list" was not propagated. In case ls-files returns with an error code, we write a special string that is not possible in non error situations, and no other output, so that the downstream can detect the error and die with an error code. The error message that there is an unmatched pathspec comes through stderr directly from ls-files. So the user still gets a hint whats going on. Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Heiko Voigt committed Aug 14, 2012 at 22:35 UTC be9d0a3a4cbd736911afc10154c7a541129503bd
2 files changed +52 -7
git-submodule.sh
+30 -3
@@ -73,26 +73,48 @@ resolve_relative_url ()
73 #
74 module_list()
75 {
76 - git ls-files --error-unmatch --stage -- "$@" |
76 + (
77 + git ls-files --error-unmatch --stage -- "$@" ||
78 + echo "unmatched pathspec exists"
79 + ) |
80 perl -e '
81 my %unmerged = ();
82 my ($null_sha1) = ("0" x 40);
83 + my @out = ();
84 + my $unmatched = 0;
85 while (<STDIN>) {
86 + if (/^unmatched pathspec/) {
87 + $unmatched = 1;
88 + next;
89 + }
90 chomp;
91 my ($mode, $sha1, $stage, $path) =
92 /^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
93 next unless $mode eq "160000";
94 if ($stage ne "0") {
95 if (!$unmerged{$path}++) {
87 - print "$mode $null_sha1 U\t$path\n";
96 + push @out, "$mode $null_sha1 U\t$path\n";
97 }
98 next;
99 }
91 - print "$_\n";
100 + push @out, "$_\n";
101 + }
102 + if ($unmatched) {
103 + print "#unmatched\n";
104 + } else {
105 + print for (@out);
106 }
107 '
108 }
109
110 +die_if_unmatched ()
111 +{
112 + if test "$1" = "#unmatched"
113 + then
114 + exit 1
115 + fi
116 +}
117 +
118 #
119 # Map submodule path to submodule name
120 #
@@ -346,6 +368,7 @@ cmd_foreach()
368 module_list |
369 while read mode sha1 stage sm_path
370 do
371 + die_if_unmatched "$mode"
372 if test -e "$sm_path"/.git
373 then
374 say "$(eval_gettext "Entering '\$prefix\$sm_path'")"
@@ -398,6 +421,7 @@ cmd_init()
421 module_list "$@" |
422 while read mode sha1 stage sm_path
423 do
424 + die_if_unmatched "$mode"
425 name=$(module_name "$sm_path") || exit
426
427 # Copy url setting when it is not set yet
@@ -498,6 +522,7 @@ cmd_update()
522 err=
523 while read mode sha1 stage sm_path
524 do
525 + die_if_unmatched "$mode"
526 if test "$stage" = U
527 then
528 echo >&2 "Skipping unmerged submodule $sm_path"
@@ -893,6 +918,7 @@ cmd_status()
918 module_list "$@" |
919 while read mode sha1 stage sm_path
920 do
921 + die_if_unmatched "$mode"
922 name=$(module_name "$sm_path") || exit
923 url=$(git config submodule."$name".url)
924 displaypath="$prefix$sm_path"
@@ -961,6 +987,7 @@ cmd_sync()
987 module_list "$@" |
988 while read mode sha1 stage sm_path
989 do
990 + die_if_unmatched "$mode"
991 name=$(module_name "$sm_path")
992 url=$(git config -f .gitmodules --get submodule."$name".url)
993
t/t7400-submodule-basic.sh
+22 -4
@@ -258,6 +258,27 @@ test_expect_success 'init should register submodule url in .git/config' '
258 test_cmp expect url
259 '
260
261 +test_failure_with_unknown_submodule () {
262 + test_must_fail git submodule $1 no-such-submodule 2>output.err &&
263 + grep "^error: .*no-such-submodule" output.err
264 +}
265 +
266 +test_expect_success 'init should fail with unknown submodule' '
267 + test_failure_with_unknown_submodule init
268 +'
269 +
270 +test_expect_success 'update should fail with unknown submodule' '
271 + test_failure_with_unknown_submodule update
272 +'
273 +
274 +test_expect_success 'status should fail with unknown submodule' '
275 + test_failure_with_unknown_submodule status
276 +'
277 +
278 +test_expect_success 'sync should fail with unknown submodule' '
279 + test_failure_with_unknown_submodule sync
280 +'
281 +
282 test_expect_success 'update should fail when path is used by a file' '
283 echo hello >expect &&
284
@@ -418,10 +439,7 @@ test_expect_success 'moving to a commit without submodule does not leave empty d
439 '
440
441 test_expect_success 'submodule <invalid-path> warns' '
421 -
422 - git submodule no-such-submodule 2> output.err &&
423 - grep "^error: .*no-such-submodule" output.err
424 -
442 + test_failure_with_unknown_submodule
443 '
444
445 test_expect_success 'add submodules without specifying an explicit path' '