git-submodule: forward exit code of git-submodule--helper more faithfully

git-submodule--helper is invoked as the upstream of a pipe in several places. Usually, the failure of a program in this position is not detected by the shell. For this reason, the code inserts a token in the output stream when git-submodule--helper fails that is detected downstream, where the shell script is quit with exit code 1. There happens to be a bug in git-submodule--helper that leads to a segmentation fault. The test suite triggers the crash in several places, all of which are protected by 'test_must_fail'. But due to the inspecific exit code 1, the crash remains undiagnosed. Extend the failure protocol such that git-submodule--helper's exit code is passed downstream (only in the case of failure). This enables the downstream to use it as its own exit code, and 'test_must_fail' to identify the segmentation fault as an unexpected failure. The bug itself is fixed in the next commit. Signed-off-by: Johannes Sixt <j6t@kdbg.org> Acked-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Sixt committed Jul 22, 2016 at 21:14 UTC c4c02bf16c47f8751958458e540269ec13f4bd98
3 files changed +15 -15
git-submodule.sh
+11 -11
@@ -50,7 +50,7 @@ die_if_unmatched ()
50 {
51 if test "$1" = "#unmatched"
52 then
53 - exit 1
53 + exit ${2:-1}
54 fi
55 }
56
@@ -312,11 +312,11 @@ cmd_foreach()
312
313 {
314 git submodule--helper list --prefix "$wt_prefix" ||
315 - echo "#unmatched"
315 + echo "#unmatched" $?
316 } |
317 while read mode sha1 stage sm_path
318 do
319 - die_if_unmatched "$mode"
319 + die_if_unmatched "$mode" "$sha1"
320 if test -e "$sm_path"/.git
321 then
322 displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix")
@@ -423,11 +423,11 @@ cmd_deinit()
423
424 {
425 git submodule--helper list --prefix "$wt_prefix" "$@" ||
426 - echo "#unmatched"
426 + echo "#unmatched" $?
427 } |
428 while read mode sha1 stage sm_path
429 do
430 - die_if_unmatched "$mode"
430 + die_if_unmatched "$mode" "$sha1"
431 name=$(git submodule--helper name "$sm_path") || exit
432
433 displaypath=$(git submodule--helper relative-path "$sm_path" "$wt_prefix")
@@ -580,12 +580,12 @@ cmd_update()
580 ${depth:+--depth "$depth"} \
581 ${recommend_shallow:+"$recommend_shallow"} \
582 ${jobs:+$jobs} \
583 - "$@" || echo "#unmatched"
583 + "$@" || echo "#unmatched" $?
584 } | {
585 err=
586 while read mode sha1 stage just_cloned sm_path
587 do
588 - die_if_unmatched "$mode"
588 + die_if_unmatched "$mode" "$sha1"
589
590 name=$(git submodule--helper name "$sm_path") || exit
591 url=$(git config submodule."$name".url)
@@ -993,11 +993,11 @@ cmd_status()
993
994 {
995 git submodule--helper list --prefix "$wt_prefix" "$@" ||
996 - echo "#unmatched"
996 + echo "#unmatched" $?
997 } |
998 while read mode sha1 stage sm_path
999 do
1000 - die_if_unmatched "$mode"
1000 + die_if_unmatched "$mode" "$sha1"
1001 name=$(git submodule--helper name "$sm_path") || exit
1002 url=$(git config submodule."$name".url)
1003 displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix")
@@ -1074,11 +1074,11 @@ cmd_sync()
1074 cd_to_toplevel
1075 {
1076 git submodule--helper list --prefix "$wt_prefix" "$@" ||
1077 - echo "#unmatched"
1077 + echo "#unmatched" $?
1078 } |
1079 while read mode sha1 stage sm_path
1080 do
1081 - die_if_unmatched "$mode"
1081 + die_if_unmatched "$mode" "$sha1"
1082 name=$(git submodule--helper name "$sm_path")
1083 url=$(git config -f .gitmodules --get submodule."$name".url)
1084
t/t5815-submodule-protos.sh
+2 -2
@@ -18,7 +18,7 @@ test_expect_success 'setup repository with submodules' '
18 git commit -m "add submodules"
19 '
20
21 -test_expect_success 'clone with recurse-submodules fails' '
21 +test_expect_failure 'clone with recurse-submodules fails' '
22 test_must_fail git clone --recurse-submodules . dst
23 '
24
@@ -32,7 +32,7 @@ test_expect_success 'update of ssh allowed' '
32 git -C dst submodule update ssh-module
33 '
34
35 -test_expect_success 'update of ext not allowed' '
35 +test_expect_failure 'update of ext not allowed' '
36 test_must_fail git -C dst submodule update ext-module
37 '
38
t/t7400-submodule-basic.sh
+2 -2
@@ -352,7 +352,7 @@ test_expect_success 'sync should fail with unknown submodule' '
352 test_failure_with_unknown_submodule sync
353 '
354
355 -test_expect_success 'update should fail when path is used by a file' '
355 +test_expect_failure 'update should fail when path is used by a file' '
356 echo hello >expect &&
357
358 echo "hello" >init &&
@@ -361,7 +361,7 @@ test_expect_success 'update should fail when path is used by a file' '
361 test_cmp expect init
362 '
363
364 -test_expect_success 'update should fail when path is used by a nonempty directory' '
364 +test_expect_failure 'update should fail when path is used by a nonempty directory' '
365 echo hello >expect &&
366
367 rm -fr init &&