{"thread":{"id":"14425","subject":"[PATCH 1/2] t/test-lib.sh: Let test_must_fail fail on signals only","startedAt":"2008-07-12T15:47:51Z","lastAt":"2008-07-17T07:25:44Z","messageCount":15,"participants":["Stephan Beyer","Jakub Narebski","Jeff King","Junio C Hamano","Johannes Sixt"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"83087","messageId":"1215877672-17049-1-git-send-email-s-beyer@gmx.net","threadId":"14425","inReplyTo":null,"subject":"[PATCH 1/2] t/test-lib.sh: Let test_must_fail fail on signals only","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-12T15:47:51Z","receivedAt":"2008-07-12T15:47:51Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"The test_must_fail function in test-lib.sh has been designed\nto distinguish segmentation faults from controlled errors.\nBut in the current implementation this only works if a git\ncommand does not return a small negative value, like -1, -2\nor -3. But some git commands do.\n\nBecause any signal (like SIGSEGV) will result in an exit status\nless than 193, this patch just adds a further check for the exit\nstatus.\n\nSigned-off-by: Stephan Beyer <s-beyer@gmx.net>\n---\n t/test-lib.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 8e2849b..11c0275 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -379,7 +379,7 @@ test_external_without_stderr () {\n \n test_must_fail () {\n \t\"$@\"\n-\ttest $? -gt 0 -a $? -le 129\n+\ttest $? -gt 0 -a $? -le 129 -o $? -gt 192\n }\n \n # test_cmp is a helper function to compare actual and expected output.\n-- \n1.5.6.2.303.g79662\n"},{"id":"83089","messageId":"1215877672-17049-2-git-send-email-s-beyer@gmx.net","threadId":"14425","inReplyTo":"1215877672-17049-1-git-send-email-s-beyer@gmx.net","subject":"[PATCH 2/2] t/: Use \"test_must_fail git\" instead of \"! git\"","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-12T15:47:52Z","receivedAt":"2008-07-12T15:47:52Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"This patch changes every occurrence of \"! git\" -- with the meaning\nthat a git call has to fail -- into \"test_must_fail git\".\n\nThis is useful to\n - make sure the test does not fail because of a signal,\n   e.g. SIGSEGV, and\n - advertise the use of \"test_must_fail\" for new tests.\n\nSigned-off-by: Stephan Beyer <s-beyer@gmx.net>\n---\n\nBecause test_must_fail has been introduced by Junio, this patch\nis only \"To:\"'ed to him and not to all the authors of the test\ncases. I hope this is ok. ;)\n\n t/t0000-basic.sh                          |    6 +-\n t/t0020-crlf.sh                           |    8 ++--\n t/t0050-filesystem.sh                     |    2 +-\n t/t1200-tutorial.sh                       |    2 +-\n t/t1300-repo-config.sh                    |   19 ++++----\n t/t1302-repo-version.sh                   |    2 +-\n t/t1400-update-ref.sh                     |    4 +-\n t/t2000-checkout-cache-clash.sh           |    2 +-\n t/t2100-update-cache-badpath.sh           |    2 +-\n t/t3020-ls-files-error-unmatch.sh         |    2 +-\n t/t3200-branch.sh                         |    8 ++--\n t/t3210-pack-refs.sh                      |    4 +-\n t/t3403-rebase-skip.sh                    |    8 ++-\n t/t3502-cherry-pick-merge.sh              |   12 +++---\n t/t3600-rm.sh                             |   26 ++++++------\n t/t3700-add.sh                            |    4 +-\n t/t4015-diff-whitespace.sh                |   28 ++++++------\n t/t4018-diff-funcname.sh                  |    2 +-\n t/t4103-apply-binary.sh                   |   16 +++---\n t/t4113-apply-ending.sh                   |    4 +-\n t/t4150-am.sh                             |    8 ++--\n t/t4200-rerere.sh                         |   10 ++--\n t/t5300-pack-object.sh                    |    2 +-\n t/t5302-pack-index.sh                     |   11 +++--\n t/t5401-update-hooks.sh                   |    3 +-\n t/t5404-tracking-branches.sh              |    4 +-\n t/t5406-remote-rejects.sh                 |    2 +-\n t/t5500-fetch-pack.sh                     |    2 +-\n t/t5505-remote.sh                         |   14 +++---\n t/t5510-fetch.sh                          |   12 +++---\n t/t5516-fetch-push.sh                     |    8 ++--\n t/t5530-upload-pack-error.sh              |    6 +-\n t/t5540-http-push.sh                      |    2 +-\n t/t5600-clone-fail-cleanup.sh             |    4 +-\n t/t6023-merge-file.sh                     |   14 +++---\n t/t6024-recursive-merge.sh                |    6 ++-\n t/t6025-merge-symlinks.sh                 |    6 +-\n t/t6101-rev-parse-parents.sh              |    2 +-\n t/t7001-mv.sh                             |    4 +-\n t/t7004-tag.sh                            |   67 +++++++++++++++--------------\n t/t7102-reset.sh                          |   48 ++++++++++----------\n t/t7103-reset-bare.sh                     |    2 +-\n t/t7300-clean.sh                          |    4 +-\n t/t7400-submodule-basic.sh                |    2 +-\n t/t7402-submodule-rebase.sh               |    2 +-\n t/t7500-commit.sh                         |    8 ++--\n t/t7501-commit.sh                         |   18 ++++----\n t/t7503-pre-commit-hook.sh                |    2 +-\n t/t7504-commit-msg-hook.sh                |    2 +-\n t/t7600-merge.sh                          |    2 +-\n t/t7610-mergetool.sh                      |    2 +-\n t/t9100-git-svn-basic.sh                  |   12 +++---\n t/t9106-git-svn-commit-diff-clobber.sh    |    6 +-\n t/t9106-git-svn-dcommit-clobber-series.sh |    2 +-\n t/t9200-git-cvsexportcommit.sh            |    6 +-\n t/t9300-fast-import.sh                    |    8 ++--\n t/t9301-fast-export.sh                    |    4 +-\n 57 files changed, 246 insertions(+), 232 deletions(-)\n\ndiff --git a/t/t0000-basic.sh b/t/t0000-basic.sh\nindex d7cbc5c..70df15c 100755\n--- a/t/t0000-basic.sh\n+++ b/t/t0000-basic.sh\n@@ -63,7 +63,7 @@ test_expect_failure 'pretend we have fixed a known breakage' '\n \n # updating a new file without --add should fail.\n test_expect_success 'git update-index without --add should fail adding.' '\n-    ! git update-index should-be-empty\n+    test_must_fail git update-index should-be-empty\n '\n \n # and with --add it should succeed, even if it is empty (it used to fail).\n@@ -83,7 +83,7 @@ test_expect_success \\\n # Removing paths.\n rm -f should-be-empty full-of-directories\n test_expect_success 'git update-index without --remove should fail removing.' '\n-    ! git update-index should-be-empty\n+    test_must_fail git update-index should-be-empty\n '\n \n test_expect_success \\\n@@ -217,7 +217,7 @@ test_expect_success \\\n     'git update-index --index-info < badobjects'\n \n test_expect_success 'writing this tree without --missing-ok.' '\n-    ! git write-tree\n+    test_must_fail git write-tree\n '\n \n test_expect_success \\\ndiff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh\nindex 2bfeac9..1be7446 100755\n--- a/t/t0020-crlf.sh\n+++ b/t/t0020-crlf.sh\n@@ -52,7 +52,7 @@ test_expect_success 'safecrlf: autocrlf=input, all CRLF' '\n \tgit config core.safecrlf true &&\n \n \tfor w in I am all CRLF; do echo $w; done | append_cr >allcrlf &&\n-\t! git add allcrlf\n+\ttest_must_fail git add allcrlf\n '\n \n test_expect_success 'safecrlf: autocrlf=input, mixed LF/CRLF' '\n@@ -61,7 +61,7 @@ test_expect_success 'safecrlf: autocrlf=input, mixed LF/CRLF' '\n \tgit config core.safecrlf true &&\n \n \tfor w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed &&\n-\t! git add mixed\n+\ttest_must_fail git add mixed\n '\n \n test_expect_success 'safecrlf: autocrlf=true, all LF' '\n@@ -70,7 +70,7 @@ test_expect_success 'safecrlf: autocrlf=true, all LF' '\n \tgit config core.safecrlf true &&\n \n \tfor w in I am all LF; do echo $w; done >alllf &&\n-\t! git add alllf\n+\ttest_must_fail git add alllf\n '\n \n test_expect_success 'safecrlf: autocrlf=true mixed LF/CRLF' '\n@@ -79,7 +79,7 @@ test_expect_success 'safecrlf: autocrlf=true mixed LF/CRLF' '\n \tgit config core.safecrlf true &&\n \n \tfor w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed &&\n-\t! git add mixed\n+\ttest_must_fail git add mixed\n '\n \n test_expect_success 'safecrlf: print warning only once' '\ndiff --git a/t/t0050-filesystem.sh b/t/t0050-filesystem.sh\nindex c5360e2..b177174 100755\n--- a/t/t0050-filesystem.sh\n+++ b/t/t0050-filesystem.sh\n@@ -43,7 +43,7 @@ test_expect_success \"detection of case insensitive filesystem during repo init\"\n else\n test_expect_success \"detection of case insensitive filesystem during repo init\" '\n \n-\t! git config --bool core.ignorecase >/dev/null ||\n+\ttest_must_fail git config --bool core.ignorecase >/dev/null ||\n \ttest $(git config --bool core.ignorecase) = false\n '\n fi\ndiff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh\nindex dcb3108..09a8199 100755\n--- a/t/t1200-tutorial.sh\n+++ b/t/t1200-tutorial.sh\n@@ -102,7 +102,7 @@ echo \"Lots of fun\" >>example\n git commit -m 'Some fun.' -i hello example\n \n test_expect_success 'git resolve now fails' '\n-\t! git merge -m \"Merge work in mybranch\" mybranch\n+\ttest_must_fail git merge -m \"Merge work in mybranch\" mybranch\n '\n \n cat > hello << EOF\ndiff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh\nindex afe7e66..64567fb 100755\n--- a/t/t1300-repo-config.sh\n+++ b/t/t1300-repo-config.sh\n@@ -201,7 +201,7 @@ test_expect_success 'non-match value' \\\n \t'test wow = $(git config --get nextsection.nonewline !for)'\n \n test_expect_success 'ambiguous get' '\n-\t! git config --get nextsection.nonewline\n+\ttest_must_fail git config --get nextsection.nonewline\n '\n \n test_expect_success 'get multivar' \\\n@@ -223,15 +223,15 @@ EOF\n test_expect_success 'multivar replace' 'cmp .git/config expect'\n \n test_expect_success 'ambiguous value' '\n-\t! git config nextsection.nonewline\n+\ttest_must_fail git config nextsection.nonewline\n '\n \n test_expect_success 'ambiguous unset' '\n-\t! git config --unset nextsection.nonewline\n+\ttest_must_fail git config --unset nextsection.nonewline\n '\n \n test_expect_success 'invalid unset' '\n-\t! git config --unset somesection.nonewline\n+\ttest_must_fail git config --unset somesection.nonewline\n '\n \n git config --unset nextsection.nonewline \"wow3$\"\n@@ -248,7 +248,7 @@ EOF\n \n test_expect_success 'multivar unset' 'cmp .git/config expect'\n \n-test_expect_success 'invalid key' '! git config inval.2key blabla'\n+test_expect_success 'invalid key' 'test_must_fail git config inval.2key blabla'\n \n test_expect_success 'correct key' 'git config 123456.a123 987'\n \n@@ -430,7 +430,8 @@ EOF\n test_expect_success \"rename succeeded\" \"test_cmp expect .git/config\"\n \n test_expect_success \"rename non-existing section\" '\n-\t! git config --rename-section branch.\"world domination\" branch.drei\n+\ttest_must_fail git config --rename-section \\\n+\t\tbranch.\"world domination\" branch.drei\n '\n \n test_expect_success \"rename succeeded\" \"test_cmp expect .git/config\"\n@@ -545,11 +546,11 @@ test_expect_success bool '\n test_expect_success 'invalid bool (--get)' '\n \n \tgit config bool.nobool foobar &&\n-\t! git config --bool --get bool.nobool'\n+\ttest_must_fail git config --bool --get bool.nobool'\n \n test_expect_success 'invalid bool (set)' '\n \n-\t! git config --bool bool.nobool foobar'\n+\ttest_must_fail git config --bool bool.nobool foobar'\n \n rm .git/config\n \n@@ -669,7 +670,7 @@ EOF\n test_expect_success 'quoting' 'cmp .git/config expect'\n \n test_expect_success 'key with newline' '\n-\t! git config \"key.with\n+\ttest_must_fail git config \"key.with\n newline\" 123'\n \n test_expect_success 'value with newline' 'git config key.sub value.with\\\\\\\ndiff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh\nindex 9be0770..8d305b4 100755\n--- a/t/t1302-repo-version.sh\n+++ b/t/t1302-repo-version.sh\n@@ -41,7 +41,7 @@ test_expect_success 'gitdir required mode on normal repos' '\n \tcd test && git apply --check --index ../test.patch)'\n \n test_expect_success 'gitdir required mode on unsupported repo' '\n-\t(cd test2 && ! git apply --check --index ../test.patch)\n+\t(cd test2 && test_must_fail git apply --check --index ../test.patch)\n '\n \n test_done\ndiff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh\nindex ca99d37..b31e4b1 100755\n--- a/t/t1400-update-ref.sh\n+++ b/t/t1400-update-ref.sh\n@@ -76,7 +76,7 @@ test_expect_success \"delete $m (by HEAD)\" '\n rm -f .git/$m\n \n test_expect_success '(not) create HEAD with old sha1' \"\n-\t! git update-ref HEAD $A $B\n+\ttest_must_fail git update-ref HEAD $A $B\n \"\n test_expect_success \"(not) prior created .git/$m\" \"\n \t! test -f .git/$m\n@@ -87,7 +87,7 @@ test_expect_success \\\n \t\"create HEAD\" \\\n \t\"git update-ref HEAD $A\"\n test_expect_success '(not) change HEAD with wrong SHA1' \"\n-\t! git update-ref HEAD $B $Z\n+\ttest_must_fail git update-ref HEAD $B $Z\n \"\n test_expect_success \"(not) changed .git/$m\" \"\n \t! test $B\"' = $(cat .git/'\"$m\"')\ndiff --git a/t/t2000-checkout-cache-clash.sh b/t/t2000-checkout-cache-clash.sh\nindex 5141fab..f7e1a73 100755\n--- a/t/t2000-checkout-cache-clash.sh\n+++ b/t/t2000-checkout-cache-clash.sh\n@@ -38,7 +38,7 @@ date >path1\n \n test_expect_success \\\n     'git checkout-index without -f should fail on conflicting work tree.' \\\n-    '! git checkout-index -a'\n+    'test_must_fail git checkout-index -a'\n \n test_expect_success \\\n     'git checkout-index with -f should succeed.' \\\ndiff --git a/t/t2100-update-cache-badpath.sh b/t/t2100-update-cache-badpath.sh\nindex 9beaecd..6ef2dcf 100755\n--- a/t/t2100-update-cache-badpath.sh\n+++ b/t/t2100-update-cache-badpath.sh\n@@ -46,6 +46,6 @@ for p in path0/file0 path1/file1 path2 path3\n do\n \ttest_expect_success \\\n \t    \"git update-index to add conflicting path $p should fail.\" \\\n-\t    \"! git update-index --add -- $p\"\n+\t    \"test_must_fail git update-index --add -- $p\"\n done\n test_done\ndiff --git a/t/t3020-ls-files-error-unmatch.sh b/t/t3020-ls-files-error-unmatch.sh\nindex f4da869..af8c412 100755\n--- a/t/t3020-ls-files-error-unmatch.sh\n+++ b/t/t3020-ls-files-error-unmatch.sh\n@@ -17,7 +17,7 @@ git-commit -m \"add foo bar\"\n \n test_expect_success \\\n     'git ls-files --error-unmatch should fail with unmatched path.' \\\n-    '! git ls-files --error-unmatch foo bar-does-not-match'\n+    'test_must_fail git ls-files --error-unmatch foo bar-does-not-match'\n \n test_expect_success \\\n     'git ls-files --error-unmatch should succeed eith matched paths.' \\\ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex 8d87686..7c583c8 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -78,13 +78,13 @@ test_expect_success \\\n test_expect_success 'git branch -m o/o o should fail when o/p exists' '\n \tgit branch o/o &&\n         git branch o/p &&\n-\t! git branch -m o/o o\n+\ttest_must_fail git branch -m o/o o\n '\n \n test_expect_success 'git branch -m q r/q should fail when r exists' '\n \tgit branch q &&\n \tgit branch r &&\n-\t! git branch -m q r/q\n+\ttest_must_fail git branch -m q r/q\n '\n \n mv .git/config .git/config-saved\n@@ -110,14 +110,14 @@ test_expect_success \\\n \n test_expect_success 'config information was renamed, too' \\\n \t\"test $(git config branch.s.dummy) = Hello &&\n-\t ! git config branch.s/s/dummy\"\n+\t test_must_fail git config branch.s/s/dummy\"\n \n test_expect_success \\\n     'git branch -m u v should fail when the reflog for u is a symlink' '\n      git branch -l u &&\n      mv .git/logs/refs/heads/u real-u &&\n      ln -s real-u .git/logs/refs/heads/u &&\n-     ! git branch -m u v\n+     test_must_fail git branch -m u v\n '\n \n test_expect_success 'test tracking setup via --track' \\\ndiff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh\nindex b64ccfb..c2dec1c 100755\n--- a/t/t3210-pack-refs.sh\n+++ b/t/t3210-pack-refs.sh\n@@ -43,7 +43,7 @@ test_expect_success 'git branch c/d should barf if branch c exists' '\n      git branch c &&\n      git pack-refs --all &&\n      rm -f .git/refs/heads/c &&\n-     ! git branch c/d\n+     test_must_fail git branch c/d\n '\n \n test_expect_success \\\n@@ -72,7 +72,7 @@ test_expect_success \\\n test_expect_success 'git branch i/j/k should barf if branch i exists' '\n      git branch i &&\n      git pack-refs --all --prune &&\n-     ! git branch i/j/k\n+     test_must_fail git branch i/j/k\n '\n \n test_expect_success \\\ndiff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh\nindex 0a26099..0d33c71 100755\n--- a/t/t3403-rebase-skip.sh\n+++ b/t/t3403-rebase-skip.sh\n@@ -32,7 +32,7 @@ test_expect_success setup '\n \t'\n \n test_expect_success 'rebase with git am -3 (default)' '\n-\t! git rebase master\n+\ttest_must_fail git rebase master\n '\n \n test_expect_success 'rebase --skip with am -3' '\n@@ -43,7 +43,7 @@ test_expect_success 'rebase moves back to skip-reference' '\n \ttest refs/heads/skip-reference = $(git symbolic-ref HEAD) &&\n \tgit branch post-rebase &&\n \tgit reset --hard pre-rebase &&\n-\t! git rebase master &&\n+\ttest_must_fail git rebase master &&\n \techo \"hello\" > hello &&\n \tgit add hello &&\n \tgit rebase --continue &&\n@@ -53,7 +53,9 @@ test_expect_success 'rebase moves back to skip-reference' '\n \n test_expect_success 'checkout skip-merge' 'git checkout -f skip-merge'\n \n-test_expect_success 'rebase with --merge' '! git rebase --merge master'\n+test_expect_success 'rebase with --merge' '\n+\ttest_must_fail git rebase --merge master\n+'\n \n test_expect_success 'rebase --skip with --merge' '\n \tgit rebase --skip\ndiff --git a/t/t3502-cherry-pick-merge.sh b/t/t3502-cherry-pick-merge.sh\nindex 7c92e26..0ab52da 100755\n--- a/t/t3502-cherry-pick-merge.sh\n+++ b/t/t3502-cherry-pick-merge.sh\n@@ -35,7 +35,7 @@ test_expect_success 'cherry-pick a non-merge with -m should fail' '\n \n \tgit reset --hard &&\n \tgit checkout a^0 &&\n-\t! git cherry-pick -m 1 b &&\n+\ttest_must_fail git cherry-pick -m 1 b &&\n \tgit diff --exit-code a --\n \n '\n@@ -44,7 +44,7 @@ test_expect_success 'cherry pick a merge without -m should fail' '\n \n \tgit reset --hard &&\n \tgit checkout a^0 &&\n-\t! git cherry-pick c &&\n+\ttest_must_fail git cherry-pick c &&\n \tgit diff --exit-code a --\n \n '\n@@ -71,7 +71,7 @@ test_expect_success 'cherry pick a merge relative to nonexistent parent should f\n \n \tgit reset --hard &&\n \tgit checkout b^0 &&\n-\t! git cherry-pick -m 3 c\n+\ttest_must_fail git cherry-pick -m 3 c\n \n '\n \n@@ -79,7 +79,7 @@ test_expect_success 'revert a non-merge with -m should fail' '\n \n \tgit reset --hard &&\n \tgit checkout c^0 &&\n-\t! git revert -m 1 b &&\n+\ttest_must_fail git revert -m 1 b &&\n \tgit diff --exit-code c\n \n '\n@@ -88,7 +88,7 @@ test_expect_success 'revert a merge without -m should fail' '\n \n \tgit reset --hard &&\n \tgit checkout c^0 &&\n-\t! git revert c &&\n+\ttest_must_fail git revert c &&\n \tgit diff --exit-code c\n \n '\n@@ -115,7 +115,7 @@ test_expect_success 'revert a merge relative to nonexistent parent should fail'\n \n \tgit reset --hard &&\n \tgit checkout c^0 &&\n-\t! git revert -m 3 c &&\n+\ttest_must_fail git revert -m 3 c &&\n \tgit diff --exit-code c\n \n '\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex f542f0a..316775e 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -67,7 +67,7 @@ test_expect_success \\\n      echo \"other content\" > foo\n      git add foo\n      echo \"yet another content\" > foo\n-     ! git rm --cached foo\n+     test_must_fail git rm --cached foo\n '\n \n test_expect_success \\\n@@ -82,7 +82,7 @@ test_expect_success \\\n \n test_expect_success \\\n     'Post-check that foo exists but is not in index after git rm foo' \\\n-    '[ -f foo ] && ! git ls-files --error-unmatch foo'\n+    '[ -f foo ] && test_must_fail git ls-files --error-unmatch foo'\n \n test_expect_success \\\n     'Pre-check that bar exists and is in index before \"git rm bar\"' \\\n@@ -94,7 +94,7 @@ test_expect_success \\\n \n test_expect_success \\\n     'Post-check that bar does not exist and is not in index after \"git rm -f bar\"' \\\n-    '! [ -f bar ] && ! git ls-files --error-unmatch bar'\n+    '! [ -f bar ] && test_must_fail git ls-files --error-unmatch bar'\n \n test_expect_success \\\n     'Test that \"git rm -- -q\" succeeds (remove a file that looks like an option)' \\\n@@ -109,7 +109,7 @@ if test \"$test_failed_remove\" = y; then\n chmod a-w .\n test_expect_success \\\n     'Test that \"git rm -f\" fails if its rm fails' \\\n-    '! git rm -f baz'\n+    'test_must_fail git rm -f baz'\n chmod 775 .\n else\n     test_expect_success 'skipping removal failure (perhaps running as root?)' :\n@@ -151,7 +151,7 @@ test_expect_success 'Re-add foo and baz' '\n \n test_expect_success 'Modify foo -- rm should refuse' '\n \techo >>foo &&\n-\t! git rm foo baz &&\n+\ttest_must_fail git rm foo baz &&\n \ttest -f foo &&\n \ttest -f baz &&\n \tgit ls-files --error-unmatch foo baz\n@@ -161,8 +161,8 @@ test_expect_success 'Modified foo -- rm -f should work' '\n \tgit rm -f foo baz &&\n \ttest ! -f foo &&\n \ttest ! -f baz &&\n-\t! git ls-files --error-unmatch foo &&\n-\t! git ls-files --error-unmatch bar\n+\ttest_must_fail git ls-files --error-unmatch foo &&\n+\ttest_must_fail git ls-files --error-unmatch bar\n '\n \n test_expect_success 'Re-add foo and baz for HEAD tests' '\n@@ -173,7 +173,7 @@ test_expect_success 'Re-add foo and baz for HEAD tests' '\n '\n \n test_expect_success 'foo is different in index from HEAD -- rm should refuse' '\n-\t! git rm foo baz &&\n+\ttest_must_fail git rm foo baz &&\n \ttest -f foo &&\n \ttest -f baz &&\n \tgit ls-files --error-unmatch foo baz\n@@ -183,8 +183,8 @@ test_expect_success 'but with -f it should work.' '\n \tgit rm -f foo baz &&\n \ttest ! -f foo &&\n \ttest ! -f baz &&\n-\t! git ls-files --error-unmatch foo\n-\t! git ls-files --error-unmatch baz\n+\ttest_must_fail git ls-files --error-unmatch foo\n+\ttest_must_fail git ls-files --error-unmatch baz\n '\n \n test_expect_success 'Recursive test setup' '\n@@ -195,14 +195,14 @@ test_expect_success 'Recursive test setup' '\n '\n \n test_expect_success 'Recursive without -r fails' '\n-\t! git rm frotz &&\n+\ttest_must_fail git rm frotz &&\n \ttest -d frotz &&\n \ttest -f frotz/nitfol\n '\n \n test_expect_success 'Recursive with -r but dirty' '\n \techo qfwfq >>frotz/nitfol\n-\t! git rm -r frotz &&\n+\ttest_must_fail git rm -r frotz &&\n \ttest -d frotz &&\n \ttest -f frotz/nitfol\n '\n@@ -214,7 +214,7 @@ test_expect_success 'Recursive with -r -f' '\n '\n \n test_expect_success 'Remove nonexistent file returns nonzero exit status' '\n-\t! git rm nonexistent\n+\ttest_must_fail git rm nonexistent\n '\n \n test_done\ndiff --git a/t/t3700-add.sh b/t/t3700-add.sh\nindex e83fa1f..7d123d1 100755\n--- a/t/t3700-add.sh\n+++ b/t/t3700-add.sh\n@@ -85,12 +85,12 @@ test_expect_success '.gitignore is honored' '\n '\n \n test_expect_success 'error out when attempting to add ignored ones without -f' '\n-\t! git add a.?? &&\n+\ttest_must_fail git add a.?? &&\n \t! (git ls-files | grep \"\\\\.ig\")\n '\n \n test_expect_success 'error out when attempting to add ignored ones without -f' '\n-\t! git add d.?? &&\n+\ttest_must_fail git add d.?? &&\n \t! (git ls-files | grep \"\\\\.ig\")\n '\n \ndiff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh\nindex 0922c70..a27fccc 100755\n--- a/t/t4015-diff-whitespace.sh\n+++ b/t/t4015-diff-whitespace.sh\n@@ -144,7 +144,7 @@ test_expect_success 'check with no whitespace errors' '\n test_expect_success 'check with trailing whitespace' '\n \n \techo \"foo(); \" > x &&\n-\t! git diff --check\n+\ttest_must_fail git diff --check\n \n '\n \n@@ -152,7 +152,7 @@ test_expect_success 'check with space before tab in indent' '\n \n \t# indent has space followed by hard tab\n \techo \" \tfoo();\" > x &&\n-\t! git diff --check\n+\ttest_must_fail git diff --check\n \n '\n \n@@ -181,7 +181,7 @@ test_expect_success 'check staged with trailing whitespace' '\n \n \techo \"foo(); \" > x &&\n \tgit add x &&\n-\t! git diff --cached --check\n+\ttest_must_fail git diff --cached --check\n \n '\n \n@@ -190,7 +190,7 @@ test_expect_success 'check staged with space before tab in indent' '\n \t# indent has space followed by hard tab\n \techo \" \tfoo();\" > x &&\n \tgit add x &&\n-\t! git diff --cached --check\n+\ttest_must_fail git diff --cached --check\n \n '\n \n@@ -206,7 +206,7 @@ test_expect_success 'check with trailing whitespace (diff-index)' '\n \n \techo \"foo(); \" > x &&\n \tgit add x &&\n-\t! git diff-index --check HEAD\n+\ttest_must_fail git diff-index --check HEAD\n \n '\n \n@@ -215,7 +215,7 @@ test_expect_success 'check with space before tab in indent (diff-index)' '\n \t# indent has space followed by hard tab\n \techo \" \tfoo();\" > x &&\n \tgit add x &&\n-\t! git diff-index --check HEAD\n+\ttest_must_fail git diff-index --check HEAD\n \n '\n \n@@ -231,7 +231,7 @@ test_expect_success 'check staged with trailing whitespace (diff-index)' '\n \n \techo \"foo(); \" > x &&\n \tgit add x &&\n-\t! git diff-index --cached --check HEAD\n+\ttest_must_fail git diff-index --cached --check HEAD\n \n '\n \n@@ -240,7 +240,7 @@ test_expect_success 'check staged with space before tab in indent (diff-index)'\n \t# indent has space followed by hard tab\n \techo \" \tfoo();\" > x &&\n \tgit add x &&\n-\t! git diff-index --cached --check HEAD\n+\ttest_must_fail git diff-index --cached --check HEAD\n \n '\n \n@@ -256,7 +256,7 @@ test_expect_success 'check with trailing whitespace (diff-tree)' '\n \n \techo \"foo(); \" > x &&\n \tgit commit -m \"another commit\" x &&\n-\t! git diff-tree --check HEAD^ HEAD\n+\ttest_must_fail git diff-tree --check HEAD^ HEAD\n \n '\n \n@@ -265,7 +265,7 @@ test_expect_success 'check with space before tab in indent (diff-tree)' '\n \t# indent has space followed by hard tab\n \techo \" \tfoo();\" > x &&\n \tgit commit -m \"yet another\" x &&\n-\t! git diff-tree --check HEAD^ HEAD\n+\ttest_must_fail git diff-tree --check HEAD^ HEAD\n \n '\n \n@@ -281,7 +281,7 @@ test_expect_success 'check trailing whitespace (trailing-space: on)' '\n \n \tgit config core.whitespace \"trailing-space\" &&\n \techo \"foo ();   \" > x &&\n-\t! git diff --check\n+\ttest_must_fail git diff --check\n \n '\n \n@@ -299,7 +299,7 @@ test_expect_success 'check space before tab in indent (space-before-tab: on)' '\n \t# indent contains space followed by HT\n \tgit config core.whitespace \"space-before-tab\" &&\n \techo \" \tfoo ();   \" > x &&\n-\t! git diff --check\n+\ttest_must_fail git diff --check\n \n '\n \n@@ -315,7 +315,7 @@ test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '\n \n \tgit config core.whitespace \"indent-with-non-tab\" &&\n \techo \"        foo ();\" > x &&\n-\t! git diff --check\n+\ttest_must_fail git diff --check\n \n '\n \n@@ -323,7 +323,7 @@ test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab:\n \n \tgit config core.whitespace \"indent-with-non-tab\" &&\n \techo \"\t                foo ();\" > x &&\n-\t! git diff --check\n+\ttest_must_fail git diff --check\n \n '\n \ndiff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh\nindex 6d3ef6c..833d6cb 100755\n--- a/t/t4018-diff-funcname.sh\n+++ b/t/t4018-diff-funcname.sh\n@@ -54,7 +54,7 @@ test_expect_success 'custom pattern' '\n \n test_expect_success 'last regexp must not be negated' '\n \tgit config diff.java.funcname \"!static\" &&\n-\t! git diff --no-index Beer.java Beer-correct.java\n+\ttest_must_fail git diff --no-index Beer.java Beer-correct.java\n '\n \n test_done\ndiff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh\nindex 1b58233..7da0b4b 100755\n--- a/t/t4103-apply-binary.sh\n+++ b/t/t4103-apply-binary.sh\n@@ -48,22 +48,22 @@ test_expect_success 'stat binary diff (copy) -- should not fail.' \\\n \n test_expect_success 'check binary diff -- should fail.' \\\n \t'git-checkout master &&\n-\t ! git apply --check B.diff'\n+\t test_must_fail git apply --check B.diff'\n \n test_expect_success 'check binary diff (copy) -- should fail.' \\\n \t'git-checkout master &&\n-\t ! git apply --check C.diff'\n+\t test_must_fail git apply --check C.diff'\n \n test_expect_success \\\n \t'check incomplete binary diff with replacement -- should fail.' '\n \tgit-checkout master &&\n-\t! git apply --check --allow-binary-replacement B.diff\n+\ttest_must_fail git apply --check --allow-binary-replacement B.diff\n '\n \n test_expect_success \\\n     'check incomplete binary diff with replacement (copy) -- should fail.' '\n \t git-checkout master &&\n-\t ! git apply --check --allow-binary-replacement C.diff\n+\t test_must_fail git apply --check --allow-binary-replacement C.diff\n '\n \n test_expect_success 'check binary diff with replacement.' \\\n@@ -84,19 +84,19 @@ do_reset () {\n \n test_expect_success 'apply binary diff -- should fail.' \\\n \t'do_reset &&\n-\t ! git apply B.diff'\n+\t test_must_fail git apply B.diff'\n \n test_expect_success 'apply binary diff -- should fail.' \\\n \t'do_reset &&\n-\t ! git apply --index B.diff'\n+\t test_must_fail git apply --index B.diff'\n \n test_expect_success 'apply binary diff (copy) -- should fail.' \\\n \t'do_reset &&\n-\t ! git apply C.diff'\n+\t test_must_fail git apply C.diff'\n \n test_expect_success 'apply binary diff (copy) -- should fail.' \\\n \t'do_reset &&\n-\t ! git apply --index C.diff'\n+\t test_must_fail git apply --index C.diff'\n \n test_expect_success 'apply binary diff without replacement.' \\\n \t'do_reset &&\ndiff --git a/t/t4113-apply-ending.sh b/t/t4113-apply-ending.sh\nindex d741039..66fa515 100755\n--- a/t/t4113-apply-ending.sh\n+++ b/t/t4113-apply-ending.sh\n@@ -30,7 +30,7 @@ test_expect_success setup \\\n # test\n \n test_expect_success 'apply at the end' \\\n-    '! git apply --index test-patch'\n+    'test_must_fail git apply --index test-patch'\n \n cat >test-patch <<\\EOF\n diff a/file b/file\n@@ -48,6 +48,6 @@ c'\n git update-index file\n \n test_expect_success 'apply at the beginning' \\\n-\t'! git apply --index test-patch'\n+\t'test_must_fail git apply --index test-patch'\n \n test_done\ndiff --git a/t/t4150-am.sh b/t/t4150-am.sh\nindex bc98260..476f20b 100755\n--- a/t/t4150-am.sh\n+++ b/t/t4150-am.sh\n@@ -182,7 +182,7 @@ test_expect_success 'am -3 falls back to 3-way merge' '\n \n test_expect_success 'am pauses on conflict' '\n \tgit checkout lorem2^^ &&\n-\t! git am lorem-move.patch &&\n+\ttest_must_fail git am lorem-move.patch &&\n \ttest -d .dotest\n '\n \n@@ -195,7 +195,7 @@ test_expect_success 'am --skip works' '\n \n test_expect_success 'am --resolved works' '\n \tgit checkout lorem2^^ &&\n-\t! git am lorem-move.patch &&\n+\ttest_must_fail git am lorem-move.patch &&\n \ttest -d .dotest &&\n \techo resolved >>file &&\n \tgit add file &&\n@@ -212,13 +212,13 @@ test_expect_success 'am takes patches from a Pine mailbox' '\n '\n \n test_expect_success 'am fails on mail without patch' '\n-\t! git am <failmail &&\n+\ttest_must_fail git am <failmail &&\n \trm -r .dotest/\n '\n \n test_expect_success 'am fails on empty patch' '\n \techo \"---\" >>failmail &&\n-\t! git am <failmail &&\n+\ttest_must_fail git am <failmail &&\n \tgit am --skip &&\n \t! test -d .dotest\n '\ndiff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh\nindex a64727d..746d61f 100755\n--- a/t/t4200-rerere.sh\n+++ b/t/t4200-rerere.sh\n@@ -41,7 +41,7 @@ git commit -q -a -m second\n \n test_expect_success 'nothing recorded without rerere' '\n \t(rm -rf .git/rr-cache; git config rerere.enabled false) &&\n-\t! git merge first &&\n+\ttest_must_fail git merge first &&\n \t! test -d .git/rr-cache\n '\n \n@@ -50,7 +50,7 @@ test_expect_success 'conflicting merge' '\n \tgit reset --hard &&\n \tmkdir .git/rr-cache &&\n \tgit config --unset rerere.enabled &&\n-\t! git merge first\n+\ttest_must_fail git merge first\n '\n \n sha1=$(sed -e 's/\t.*//' .git/rr-cache/MERGE_RR)\n@@ -61,7 +61,7 @@ test_expect_success 'rerere.enabled works, too' '\n \trm -rf .git/rr-cache &&\n \tgit config rerere.enabled true &&\n \tgit reset --hard &&\n-\t! git merge first &&\n+\ttest_must_fail git merge first &&\n \tgrep ======= $rr/preimage\n '\n \n@@ -120,7 +120,7 @@ test_expect_success 'another conflicting merge' '\n \tgit checkout -b third master &&\n \tgit show second^:a1 | sed \"s/To die: t/To die! T/\" > a1 &&\n \tgit commit -q -a -m third &&\n-\t! git pull . first\n+\ttest_must_fail git pull . first\n '\n \n git show first:a1 | sed 's/To die: t/To die! T/' > expect\n@@ -175,7 +175,7 @@ test_expect_success 'file2 added differently in two branches' '\n \techo Bello > file2 &&\n \tgit add file2 &&\n \tgit commit -m version2 &&\n-\t! git merge fourth &&\n+\ttest_must_fail git merge fourth &&\n \tsha1=$(sed -e \"s/\t.*//\" .git/rr-cache/MERGE_RR) &&\n \trr=.git/rr-cache/$sha1 &&\n \techo Cello > file2 &&\ndiff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh\nindex 983a393..645583f 100755\n--- a/t/t5300-pack-object.sh\n+++ b/t/t5300-pack-object.sh\n@@ -266,7 +266,7 @@ test_expect_success \\\n \n test_expect_success \\\n     'make sure index-pack detects the SHA1 collision' \\\n-    '! git-index-pack -o bad.idx test-3.pack'\n+    'test_must_fail git-index-pack -o bad.idx test-3.pack'\n \n test_expect_success \\\n     'honor pack.packSizeLimit' \\\ndiff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh\nindex ecec591..0639772 100755\n--- a/t/t5302-pack-index.sh\n+++ b/t/t5302-pack-index.sh\n@@ -118,7 +118,7 @@ test_expect_success \\\n \n test_expect_success \\\n     '[index v1] 4) confirm that the pack is actually corrupted' \\\n-    '! git fsck --full $commit'\n+    'test_must_fail git fsck --full $commit'\n \n test_expect_success \\\n     '[index v1] 5) pack-objects happily reuses corrupted data' \\\n@@ -127,7 +127,7 @@ test_expect_success \\\n \n test_expect_success \\\n     '[index v1] 6) newly created pack is BAD !' \\\n-    '! git verify-pack -v \"test-4-${pack1}.pack\"'\n+    'test_must_fail git verify-pack -v \"test-4-${pack1}.pack\"'\n \n test_expect_success \\\n     '[index v2] 1) stream pack to repository' \\\n@@ -156,11 +156,11 @@ test_expect_success \\\n \n test_expect_success \\\n     '[index v2] 4) confirm that the pack is actually corrupted' \\\n-    '! git fsck --full $commit'\n+    'test_must_fail git fsck --full $commit'\n \n test_expect_success \\\n     '[index v2] 5) pack-objects refuses to reuse corrupted data' \\\n-    '! git pack-objects test-5 <obj-list'\n+    'test_must_fail git pack-objects test-5 <obj-list'\n \n test_expect_success \\\n     '[index v2] 6) verify-pack detects CRC mismatch' \\\n@@ -173,7 +173,8 @@ test_expect_success \\\n      ( while read obj\n        do git cat-file -p $obj >/dev/null || exit 1\n        done <obj-list ) &&\n-     err=$(! git verify-pack \".git/objects/pack/pack-${pack1}.pack\" 2>&1) &&\n+     err=$(test_must_fail git verify-pack \\\n+       \".git/objects/pack/pack-${pack1}.pack\" 2>&1) &&\n      echo \"$err\" | grep \"CRC mismatch\"'\n \n test_done\ndiff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh\nindex 2fff300..ee769d6 100755\n--- a/t/t5401-update-hooks.sh\n+++ b/t/t5401-update-hooks.sh\n@@ -61,7 +61,8 @@ EOF\n chmod u+x victim/.git/hooks/post-update\n \n test_expect_success push '\n-    ! git-send-pack --force ./victim/.git master tofail >send.out 2>send.err\n+\ttest_must_fail git-send-pack --force ./victim/.git \\\n+\t\tmaster tofail >send.out 2>send.err\n '\n \n test_expect_success 'updated as expected' '\ndiff --git a/t/t5404-tracking-branches.sh b/t/t5404-tracking-branches.sh\nindex 64fe261..c240035 100755\n--- a/t/t5404-tracking-branches.sh\n+++ b/t/t5404-tracking-branches.sh\n@@ -35,7 +35,9 @@ test_expect_success 'prepare pushable branches' '\n \tgit commit -a -m aa-master\n '\n \n-test_expect_success 'mixed-success push returns error' '! git push'\n+test_expect_success 'mixed-success push returns error' '\n+\ttest_must_fail git push\n+'\n \n test_expect_success 'check tracking branches updated correctly after push' '\n \ttest \"$(git rev-parse origin/master)\" = \"$(git rev-parse master)\"\ndiff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh\nindex 46b2cb4..59e80a5 100755\n--- a/t/t5406-remote-rejects.sh\n+++ b/t/t5406-remote-rejects.sh\n@@ -17,7 +17,7 @@ test_expect_success 'setup' '\n \tgit commit -a -m 2\n '\n \n-test_expect_success 'push reports error' '! git push 2>stderr'\n+test_expect_success 'push reports error' 'test_must_fail git push 2>stderr'\n \n test_expect_success 'individual ref reports error' 'grep rejected stderr'\n \ndiff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh\nindex 140e874..362cf7e 100755\n--- a/t/t5500-fetch-pack.sh\n+++ b/t/t5500-fetch-pack.sh\n@@ -177,6 +177,6 @@ test_expect_success \"clone shallow object count\" \\\n \t\"test \\\"count: 18\\\" = \\\"$(grep count count.shallow)\\\"\"\n \n test_expect_success \"pull in shallow repo with missing merge base\" \\\n-\t\"(cd shallow && ! git pull --depth 4 .. A)\"\n+\t\"(cd shallow && test_must_fail git pull --depth 4 .. A)\"\n \n test_done\ndiff --git a/t/t5505-remote.sh b/t/t5505-remote.sh\nindex 1e192a2..be9ee93 100755\n--- a/t/t5505-remote.sh\n+++ b/t/t5505-remote.sh\n@@ -164,7 +164,7 @@ test_expect_success 'prune' '\n \t git fetch origin &&\n \t git remote prune origin &&\n \t git rev-parse refs/remotes/origin/side2 &&\n-\t ! git rev-parse refs/remotes/origin/side)\n+\t test_must_fail git rev-parse refs/remotes/origin/side)\n '\n \n cat > test/expect << EOF\n@@ -179,7 +179,7 @@ test_expect_success 'prune --dry-run' '\n \t(cd test &&\n \t git remote prune --dry-run origin > output &&\n \t git rev-parse refs/remotes/origin/side2 &&\n-\t ! git rev-parse refs/remotes/origin/side &&\n+\t test_must_fail git rev-parse refs/remotes/origin/side &&\n \t(cd ../one &&\n \t git branch -m side side2) &&\n \t test_cmp expect output)\n@@ -194,10 +194,10 @@ test_expect_success 'add --mirror && prune' '\n \t git branch -m side2 side) &&\n \t(cd mirror &&\n \t git rev-parse --verify refs/heads/side2 &&\n-\t ! git rev-parse --verify refs/heads/side &&\n+\t test_must_fail git rev-parse --verify refs/heads/side &&\n \t git fetch origin &&\n \t git remote prune origin &&\n-\t ! git rev-parse --verify refs/heads/side2 &&\n+\t test_must_fail git rev-parse --verify refs/heads/side2 &&\n \t git rev-parse --verify refs/heads/side)\n '\n \n@@ -212,10 +212,10 @@ test_expect_success 'add alt && prune' '\n \t git branch -m side side2) &&\n \t(cd alttst &&\n \t git rev-parse --verify refs/remotes/origin/side &&\n-\t ! git rev-parse --verify refs/remotes/origin/side2 &&\n+\t test_must_fail git rev-parse --verify refs/remotes/origin/side2 &&\n \t git fetch alt &&\n \t git remote prune alt &&\n-\t ! git rev-parse --verify refs/remotes/origin/side &&\n+\t test_must_fail git rev-parse --verify refs/remotes/origin/side &&\n \t git rev-parse --verify refs/remotes/origin/side2)\n '\n \n@@ -320,7 +320,7 @@ test_expect_success '\"remote show\" does not show symbolic refs' '\n \n test_expect_success 'reject adding remote with an invalid name' '\n \n-\t! git remote add some:url desired-name\n+\ttest_must_fail git remote add some:url desired-name\n \n '\n \ndiff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh\nindex df7750f..13d1d82 100755\n--- a/t/t5510-fetch.sh\n+++ b/t/t5510-fetch.sh\n@@ -104,7 +104,7 @@ test_expect_success 'fetch must not resolve short tag name' '\n \tcd five &&\n \tgit init &&\n \n-\t! git fetch .. anno:five\n+\ttest_must_fail git fetch .. anno:five\n \n '\n \n@@ -117,7 +117,7 @@ test_expect_success 'fetch must not resolve short remote name' '\n \tcd six &&\n \tgit init &&\n \n-\t! git fetch .. six:six\n+\ttest_must_fail git fetch .. six:six\n \n '\n \n@@ -143,7 +143,7 @@ test_expect_success 'create bundle 2' '\n test_expect_success 'unbundle 1' '\n \tcd \"$D/bundle\" &&\n \tgit checkout -b some-branch &&\n-\t! git fetch \"$D/bundle1\" master:master\n+\ttest_must_fail git fetch \"$D/bundle1\" master:master\n '\n \n test_expect_success 'bundle 1 has only 3 files ' '\n@@ -236,7 +236,7 @@ test_expect_success 'fetch with a non-applying branch.<name>.merge' '\n \n # the strange name is: a\\!'b\n test_expect_success 'quoting of a strangely named repo' '\n-\t! git fetch \"a\\\\!'\\''b\" > result 2>&1 &&\n+\ttest_must_fail git fetch \"a\\\\!'\\''b\" > result 2>&1 &&\n \tcat result &&\n \tgrep \"fatal: '\\''a\\\\\\\\!'\\''b'\\''\" result\n '\n@@ -264,7 +264,7 @@ test_expect_success 'explicit fetch should not update tracking' '\n \t\tgit fetch origin master &&\n \t\tn=$(git rev-parse --verify refs/remotes/origin/master) &&\n \t\ttest \"$o\" = \"$n\" &&\n-\t\t! git rev-parse --verify refs/remotes/origin/side\n+\t\ttest_must_fail git rev-parse --verify refs/remotes/origin/side\n \t)\n '\n \n@@ -278,7 +278,7 @@ test_expect_success 'explicit pull should not update tracking' '\n \t\tgit pull origin master &&\n \t\tn=$(git rev-parse --verify refs/remotes/origin/master) &&\n \t\ttest \"$o\" = \"$n\" &&\n-\t\t! git rev-parse --verify refs/remotes/origin/side\n+\t\ttest_must_fail git rev-parse --verify refs/remotes/origin/side\n \t)\n '\n \ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 6805032..f0030ad 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -178,7 +178,7 @@ test_expect_success 'failed (non-fast-forward) push with matching heads' '\n \tmk_test heads/master &&\n \tgit push testrepo : &&\n \tgit commit --amend -massaged &&\n-\t! git push testrepo &&\n+\ttest_must_fail git push testrepo &&\n \tcheck_push_result $the_commit heads/master &&\n \tgit reset --hard $the_commit\n \n@@ -374,7 +374,7 @@ test_expect_success 'push with +HEAD' '\n \n \t# Without force rewinding should fail\n \tgit reset --hard HEAD^ &&\n-\t! git push testrepo HEAD &&\n+\ttest_must_fail git push testrepo HEAD &&\n \tcheck_push_result $the_commit heads/local &&\n \n \t# With force rewinding should succeed\n@@ -448,7 +448,7 @@ test_expect_success 'push does not update local refs on failure' '\n \tgit clone parent child &&\n \t(cd child &&\n \t\techo two >foo && git commit -a -m two &&\n-\t\t! git push &&\n+\t\ttest_must_fail git push &&\n \t\ttest $(git rev-parse master) != \\\n \t\t\t$(git rev-parse remotes/origin/master))\n \n@@ -459,7 +459,7 @@ test_expect_success 'allow deleting an invalid remote ref' '\n \tpwd &&\n \trm -f testrepo/.git/objects/??/* &&\n \tgit push testrepo :refs/heads/master &&\n-\t(cd testrepo && ! git rev-parse --verify refs/heads/master)\n+\t(cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)\n \n '\n \ndiff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh\nindex 8b05091..1a15817 100755\n--- a/t/t5530-upload-pack-error.sh\n+++ b/t/t5530-upload-pack-error.sh\n@@ -27,7 +27,7 @@ test_expect_success 'setup and corrupt repository' '\n '\n \n test_expect_success 'fsck fails' '\n-\t! git fsck\n+\ttest_must_fail git fsck\n '\n \n test_expect_success 'upload-pack fails due to error in pack-objects' '\n@@ -46,7 +46,7 @@ test_expect_success 'corrupt repo differently' '\n '\n \n test_expect_success 'fsck fails' '\n-\t! git fsck\n+\ttest_must_fail git fsck\n '\n test_expect_success 'upload-pack fails due to error in rev-list' '\n \n@@ -66,7 +66,7 @@ test_expect_success 'create empty repository' '\n \n test_expect_success 'fetch fails' '\n \n-\t! git fetch .. master\n+\ttest_must_fail git fetch .. master\n \n '\n \ndiff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh\nindex 21dbb55..f8c17cd 100755\n--- a/t/t5540-http-push.sh\n+++ b/t/t5540-http-push.sh\n@@ -73,7 +73,7 @@ test_expect_failure 'create and delete remote branch' '\n \tgit push origin :dev &&\n \tgit branch -d -r origin/dev &&\n \tgit fetch &&\n-\t! git show-ref --verify refs/remotes/origin/dev\n+\ttest_must_fail git show-ref --verify refs/remotes/origin/dev\n '\n \n stop_httpd\ndiff --git a/t/t5600-clone-fail-cleanup.sh b/t/t5600-clone-fail-cleanup.sh\nindex acf34ce..3c013e2 100755\n--- a/t/t5600-clone-fail-cleanup.sh\n+++ b/t/t5600-clone-fail-cleanup.sh\n@@ -13,7 +13,7 @@ remove the directory before attempting a clone again.'\n \n test_expect_success \\\n     'clone of non-existent source should fail' \\\n-    '! git-clone foo bar'\n+    'test_must_fail git-clone foo bar'\n \n test_expect_success \\\n     'failed clone should not leave a directory' \\\n@@ -29,7 +29,7 @@ test_create_repo foo\n # current path not to the target dir\n test_expect_success \\\n     'clone of non-existent (relative to $PWD) source should fail' \\\n-    '! git-clone ../foo baz'\n+    'test_must_fail git-clone ../foo baz'\n \n test_expect_success \\\n     'clone should work now that source exists' \\\ndiff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh\nindex 74e9e66..f674c48 100755\n--- a/t/t6023-merge-file.sh\n+++ b/t/t6023-merge-file.sh\n@@ -67,7 +67,7 @@ test_expect_success \"merge result added missing LF\" \\\n \n cp test.txt backup.txt\n test_expect_success \"merge with conflicts\" \\\n-\t\"! git merge-file test.txt orig.txt new3.txt\"\n+\t\"test_must_fail git merge-file test.txt orig.txt new3.txt\"\n \n cat > expect.txt << EOF\n <<<<<<< test.txt\n@@ -90,7 +90,7 @@ test_expect_success \"expected conflict markers\" \"test_cmp test.txt expect.txt\"\n \n cp backup.txt test.txt\n test_expect_success \"merge with conflicts, using -L\" \\\n-\t\"! git merge-file -L 1 -L 2 test.txt orig.txt new3.txt\"\n+\t\"test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt\"\n \n cat > expect.txt << EOF\n <<<<<<< 1\n@@ -114,7 +114,7 @@ test_expect_success \"expected conflict markers, with -L\" \\\n \n sed \"s/ tu / TU /\" < new1.txt > new5.txt\n test_expect_success \"conflict in removed tail\" \\\n-\t\"! git merge-file -p orig.txt new1.txt new5.txt > out\"\n+\t\"test_must_fail git merge-file -p orig.txt new1.txt new5.txt > out\"\n \n cat > expect << EOF\n Dominus regit me,\n@@ -135,7 +135,8 @@ EOF\n test_expect_success \"expected conflict markers\" \"test_cmp expect out\"\n \n test_expect_success 'binary files cannot be merged' '\n-\t! git merge-file -p orig.txt ../test4012.png new1.txt 2> merge.err &&\n+\ttest_must_fail git merge-file -p \\\n+\t\torig.txt ../test4012.png new1.txt 2> merge.err &&\n \tgrep \"Cannot merge binary files\" merge.err\n '\n \n@@ -144,7 +145,7 @@ sed -e \"s/deerit.$/deerit,/\" -e \"s/me;$/me,/\" < new5.txt > new7.txt\n \n test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' '\n \n-\t! git merge-file -p new6.txt new5.txt new7.txt > output &&\n+\ttest_must_fail git merge-file -p new6.txt new5.txt new7.txt > output &&\n \ttest 1 = $(grep ======= < output | wc -l)\n \n '\n@@ -154,7 +155,8 @@ sed -e 's/deerit./&\\n\\n\\n\\n/' -e \"s/locavit,/locavit --/\" < new7.txt > new9.txt\n \n test_expect_success 'ZEALOUS_ALNUM' '\n \n-\t! git merge-file -p new8.txt new5.txt new9.txt > merge.out &&\n+\ttest_must_fail git merge-file -p \\\n+\t\tnew8.txt new5.txt new9.txt > merge.out &&\n \ttest 1 = $(grep ======= < merge.out | wc -l)\n \n '\ndiff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh\nindex 6a6a130..802d0d0 100755\n--- a/t/t6024-recursive-merge.sh\n+++ b/t/t6024-recursive-merge.sh\n@@ -60,7 +60,9 @@ git update-index a1 &&\n GIT_AUTHOR_DATE=\"2006-12-12 23:00:08\" git commit -m F\n '\n \n-test_expect_success \"combined merge conflicts\" \"! git merge -m final G\"\n+test_expect_success \"combined merge conflicts\" \"\n+\ttest_must_fail git merge -m final G\n+\"\n \n cat > expect << EOF\n <<<<<<< HEAD:a1\n@@ -90,7 +92,7 @@ test_expect_success 'refuse to merge binary files' '\n \tprintf \"\\0\\0\" > binary-file &&\n \tgit add binary-file &&\n \tgit commit -m binary2 &&\n-\t! git merge F > merge.out 2> merge.err &&\n+\ttest_must_fail git merge F > merge.out 2> merge.err &&\n \tgrep \"Cannot merge binary files: HEAD:binary-file vs. F:binary-file\" \\\n \t\tmerge.err\n '\ndiff --git a/t/t6025-merge-symlinks.sh b/t/t6025-merge-symlinks.sh\nindex 6004deb..fc58456 100755\n--- a/t/t6025-merge-symlinks.sh\n+++ b/t/t6025-merge-symlinks.sh\n@@ -33,7 +33,7 @@ git-commit -m b-file'\n test_expect_success \\\n 'merge master into b-symlink, which has a different symbolic link' '\n git-checkout b-symlink &&\n-! git-merge master'\n+test_must_fail git-merge master'\n \n test_expect_success \\\n 'the merge result must be a file' '\n@@ -42,7 +42,7 @@ test -f symlink'\n test_expect_success \\\n 'merge master into b-file, which has a file instead of a symbolic link' '\n git-reset --hard && git-checkout b-file &&\n-! git-merge master'\n+test_must_fail git-merge master'\n \n test_expect_success \\\n 'the merge result must be a file' '\n@@ -52,7 +52,7 @@ test_expect_success \\\n 'merge b-file, which has a file instead of a symbolic link, into master' '\n git-reset --hard &&\n git-checkout master &&\n-! git-merge b-file'\n+test_must_fail git-merge b-file'\n \n test_expect_success \\\n 'the merge result must be a file' '\ndiff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh\nindex 2328b69..efc8313 100755\n--- a/t/t6101-rev-parse-parents.sh\n+++ b/t/t6101-rev-parse-parents.sh\n@@ -26,7 +26,7 @@ test_expect_success 'final^1^1^1 = final^^^' \"test $(git rev-parse final^1^1^1)\n test_expect_success 'final^1^2' \"test $(git rev-parse start2) = $(git rev-parse final^1^2)\"\n test_expect_success 'final^1^2 != final^1^1' \"test $(git rev-parse final^1^2) != $(git rev-parse final^1^1)\"\n test_expect_success 'final^1^3 not valid' \"if git rev-parse --verify final^1^3; then false; else :; fi\"\n-test_expect_success '--verify start2^1' '! git rev-parse --verify start2^1'\n+test_expect_success '--verify start2^1' 'test_must_fail git rev-parse --verify start2^1'\n test_expect_success '--verify start2^0' 'git rev-parse --verify start2^0'\n \n test_expect_success 'repack for next test' 'git repack -a -d'\ndiff --git a/t/t7001-mv.sh b/t/t7001-mv.sh\nindex fa382c5..336cfaa 100755\n--- a/t/t7001-mv.sh\n+++ b/t/t7001-mv.sh\n@@ -80,7 +80,7 @@ test_expect_success \\\n \n test_expect_success \\\n     'do not move directory over existing directory' \\\n-    'mkdir path0 && mkdir path0/path2 && ! git mv path2 path0'\n+    'mkdir path0 && mkdir path0/path2 && test_must_fail git mv path2 path0'\n \n test_expect_success \\\n     'move into \".\"' \\\n@@ -149,7 +149,7 @@ test_expect_success 'absolute pathname outside should fail' '(\n \t>sub/file &&\n \tgit add sub/file &&\n \n-\t! git mv sub \"$out/out\" &&\n+\ttest_must_fail git mv sub \"$out/out\" &&\n \ttest -d sub &&\n \t! test -d ../in &&\n \tgit ls-files --error-unmatch sub/file\ndiff --git a/t/t7004-tag.sh b/t/t7004-tag.sh\nindex 241c70d..bc7ce2c 100755\n--- a/t/t7004-tag.sh\n+++ b/t/t7004-tag.sh\n@@ -30,17 +30,17 @@ test_expect_success 'looking for a tag in an empty tree should fail' \\\n \t'! (tag_exists mytag)'\n \n test_expect_success 'creating a tag in an empty tree should fail' '\n-\t! git-tag mynotag &&\n+\ttest_must_fail git-tag mynotag &&\n \t! tag_exists mynotag\n '\n \n test_expect_success 'creating a tag for HEAD in an empty tree should fail' '\n-\t! git-tag mytaghead HEAD &&\n+\ttest_must_fail git-tag mytaghead HEAD &&\n \t! tag_exists mytaghead\n '\n \n test_expect_success 'creating a tag for an unknown revision should fail' '\n-\t! git-tag mytagnorev aaaaaaaaaaa &&\n+\ttest_must_fail git-tag mytagnorev aaaaaaaaaaa &&\n \t! tag_exists mytagnorev\n '\n \n@@ -85,16 +85,16 @@ test_expect_success \\\n \n test_expect_success \\\n \t'trying to create a tag with the name of one existing should fail' \\\n-\t'! git tag mytag'\n+\t'test_must_fail git tag mytag'\n \n test_expect_success \\\n \t'trying to create a tag with a non-valid name should fail' '\n \ttest `git-tag -l | wc -l` -eq 1 &&\n-\t! git tag \"\" &&\n-\t! git tag .othertag &&\n-\t! git tag \"other tag\" &&\n-\t! git tag \"othertag^\" &&\n-\t! git tag \"other~tag\" &&\n+\ttest_must_fail git tag \"\" &&\n+\ttest_must_fail git tag .othertag &&\n+\ttest_must_fail git tag \"other tag\" &&\n+\ttest_must_fail git tag \"othertag^\" &&\n+\ttest_must_fail git tag \"other~tag\" &&\n \ttest `git-tag -l | wc -l` -eq 1\n '\n \n@@ -107,7 +107,7 @@ test_expect_success 'creating a tag using HEAD directly should succeed' '\n \n test_expect_success 'trying to delete an unknown tag should fail' '\n \t! tag_exists unknown-tag &&\n-\t! git-tag -d unknown-tag\n+\ttest_must_fail git-tag -d unknown-tag\n '\n \n cat >expect <<EOF\n@@ -141,13 +141,13 @@ test_expect_success \\\n \t'trying to delete two tags, existing and not, should fail in the 2nd' '\n \ttag_exists mytag &&\n \t! tag_exists myhead &&\n-\t! git-tag -d mytag anothertag &&\n+\ttest_must_fail git-tag -d mytag anothertag &&\n \t! tag_exists mytag &&\n \t! tag_exists myhead\n '\n \n test_expect_success 'trying to delete an already deleted tag should fail' \\\n-\t'! git-tag -d mytag'\n+\t'test_must_fail git-tag -d mytag'\n \n # listing various tags with pattern matching:\n \n@@ -266,15 +266,15 @@ test_expect_success \\\n '\n \n test_expect_success 'trying to verify an unknown tag should fail' \\\n-\t'! git-tag -v unknown-tag'\n+\t'test_must_fail git-tag -v unknown-tag'\n \n test_expect_success \\\n \t'trying to verify a non-annotated and non-signed tag should fail' \\\n-\t'! git-tag -v non-annotated-tag'\n+\t'test_must_fail git-tag -v non-annotated-tag'\n \n test_expect_success \\\n \t'trying to verify many non-annotated or unknown tags, should fail' \\\n-\t'! git-tag -v unknown-tag1 non-annotated-tag unknown-tag2'\n+\t'test_must_fail git-tag -v unknown-tag1 non-annotated-tag unknown-tag2'\n \n # creating annotated tags:\n \n@@ -334,7 +334,7 @@ test_expect_success \\\n \t'trying to create a tag with a non-existing -F file should fail' '\n \t! test -f nonexistingfile &&\n \t! tag_exists notag &&\n-\t! git-tag -F nonexistingfile notag &&\n+\ttest_must_fail git-tag -F nonexistingfile notag &&\n \t! tag_exists notag\n '\n \n@@ -343,11 +343,12 @@ test_expect_success \\\n \techo \"message file 1\" >msgfile1 &&\n \techo \"message file 2\" >msgfile2 &&\n \t! tag_exists msgtag &&\n-\t! git-tag -m \"message 1\" -F msgfile1 msgtag &&\n+\ttest_must_fail git-tag -m \"message 1\" -F msgfile1 msgtag &&\n \t! tag_exists msgtag &&\n-\t! git-tag -F msgfile1 -m \"message 1\" msgtag &&\n+\ttest_must_fail git-tag -F msgfile1 -m \"message 1\" msgtag &&\n \t! tag_exists msgtag &&\n-\t! git-tag -m \"message 1\" -F msgfile1 -m \"message 2\" msgtag &&\n+\ttest_must_fail git-tag -m \"message 1\" -F msgfile1 \\\n+\t\t-m \"message 2\" msgtag &&\n \t! tag_exists msgtag\n '\n \n@@ -591,19 +592,19 @@ fi\n test_expect_success \\\n \t'trying to verify an annotated non-signed tag should fail' '\n \ttag_exists annotated-tag &&\n-\t! git-tag -v annotated-tag\n+\ttest_must_fail git-tag -v annotated-tag\n '\n \n test_expect_success \\\n \t'trying to verify a file-annotated non-signed tag should fail' '\n \ttag_exists file-annotated-tag &&\n-\t! git-tag -v file-annotated-tag\n+\ttest_must_fail git-tag -v file-annotated-tag\n '\n \n test_expect_success \\\n \t'trying to verify two annotated non-signed tags should fail' '\n \ttag_exists annotated-tag file-annotated-tag &&\n-\t! git-tag -v annotated-tag file-annotated-tag\n+\ttest_must_fail git-tag -v annotated-tag file-annotated-tag\n '\n \n # creating and verifying signed tags:\n@@ -651,13 +652,14 @@ test_expect_success 'sign with a given key id' '\n \n test_expect_success 'sign with an unknown id (1)' '\n \n-\t! git tag -u author@example.com -m \"Another message\" o-signed-tag\n+\ttest_must_fail git tag -u author@example.com \\\n+\t\t-m \"Another message\" o-signed-tag\n \n '\n \n test_expect_success 'sign with an unknown id (2)' '\n \n-\t! git tag -u DEADBEEF -m \"Another message\" o-signed-tag\n+\ttest_must_fail git tag -u DEADBEEF -m \"Another message\" o-signed-tag\n \n '\n \n@@ -718,7 +720,7 @@ test_expect_success \\\n \t'trying to create a signed tag with non-existing -F file should fail' '\n \t! test -f nonexistingfile &&\n \t! tag_exists nosigtag &&\n-\t! git-tag -s -F nonexistingfile nosigtag &&\n+\ttest_must_fail git-tag -s -F nonexistingfile nosigtag &&\n \t! tag_exists nosigtag\n '\n \n@@ -730,10 +732,11 @@ test_expect_success 'verifying two signed tags in one command should succeed' \\\n \n test_expect_success \\\n \t'verifying many signed and non-signed tags should fail' '\n-\t! git-tag -v signed-tag annotated-tag &&\n-\t! git-tag -v file-annotated-tag file-signed-tag &&\n-\t! git-tag -v annotated-tag file-signed-tag file-annotated-tag &&\n-\t! git-tag -v signed-tag annotated-tag file-signed-tag\n+\ttest_must_fail git-tag -v signed-tag annotated-tag &&\n+\ttest_must_fail git-tag -v file-annotated-tag file-signed-tag &&\n+\ttest_must_fail git-tag -v annotated-tag \\\n+\t\tfile-signed-tag file-annotated-tag &&\n+\ttest_must_fail git-tag -v signed-tag annotated-tag file-signed-tag\n '\n \n test_expect_success 'verifying a forged tag should fail' '\n@@ -741,7 +744,7 @@ test_expect_success 'verifying a forged tag should fail' '\n \t\tsed -e \"s/signed-tag/forged-tag/\" |\n \t\tgit mktag) &&\n \tgit tag forged-tag $forged &&\n-\t! git-tag -v forged-tag\n+\ttest_must_fail git-tag -v forged-tag\n '\n \n # blank and empty messages for signed tags:\n@@ -1031,7 +1034,7 @@ test_expect_success \\\n git config user.signingkey BobTheMouse\n test_expect_success \\\n \t'git-tag -s fails if gpg is misconfigured' \\\n-\t'! git tag -s -m tail tag-gpg-failure'\n+\t'test_must_fail git tag -s -m tail tag-gpg-failure'\n git config --unset user.signingkey\n \n # try to verify without gpg:\n@@ -1039,7 +1042,7 @@ git config --unset user.signingkey\n rm -rf gpghome\n test_expect_success \\\n \t'verify signed tag fails when public key is not present' \\\n-\t'! git-tag -v signed-tag'\n+\t'test_must_fail git-tag -v signed-tag'\n \n test_expect_success \\\n \t'git-tag -a fails if tag annotation is empty' '\ndiff --git a/t/t7102-reset.sh b/t/t7102-reset.sh\nindex 96d1508..0bfc1e9 100755\n--- a/t/t7102-reset.sh\n+++ b/t/t7102-reset.sh\n@@ -52,10 +52,10 @@ secondfile:\n EOF\n \n test_expect_success 'giving a non existing revision should fail' '\n-\t! git reset aaaaaa &&\n-\t! git reset --mixed aaaaaa &&\n-\t! git reset --soft aaaaaa &&\n-\t! git reset --hard aaaaaa &&\n+\ttest_must_fail git reset aaaaaa &&\n+\ttest_must_fail git reset --mixed aaaaaa &&\n+\ttest_must_fail git reset --soft aaaaaa &&\n+\ttest_must_fail git reset --hard aaaaaa &&\n \tcheck_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc\n '\n \n@@ -63,29 +63,29 @@ test_expect_success 'reset --soft with unmerged index should fail' '\n \ttouch .git/MERGE_HEAD &&\n \techo \"100644 44c5b5884550c17758737edcced463447b91d42b 1\tun\" |\n \t\tgit update-index --index-info &&\n-\t! git reset --soft HEAD &&\n+\ttest_must_fail git reset --soft HEAD &&\n \trm .git/MERGE_HEAD &&\n \tgit rm --cached -- un\n '\n \n test_expect_success \\\n \t'giving paths with options different than --mixed should fail' '\n-\t! git reset --soft -- first &&\n-\t! git reset --hard -- first &&\n-\t! git reset --soft HEAD^ -- first &&\n-\t! git reset --hard HEAD^ -- first &&\n+\ttest_must_fail git reset --soft -- first &&\n+\ttest_must_fail git reset --hard -- first &&\n+\ttest_must_fail git reset --soft HEAD^ -- first &&\n+\ttest_must_fail git reset --hard HEAD^ -- first &&\n \tcheck_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc\n '\n \n test_expect_success 'giving unrecognized options should fail' '\n-\t! git reset --other &&\n-\t! git reset -o &&\n-\t! git reset --mixed --other &&\n-\t! git reset --mixed -o &&\n-\t! git reset --soft --other &&\n-\t! git reset --soft -o &&\n-\t! git reset --hard --other &&\n-\t! git reset --hard -o &&\n+\ttest_must_fail git reset --other &&\n+\ttest_must_fail git reset -o &&\n+\ttest_must_fail git reset --mixed --other &&\n+\ttest_must_fail git reset --mixed -o &&\n+\ttest_must_fail git reset --soft --other &&\n+\ttest_must_fail git reset --soft -o &&\n+\ttest_must_fail git reset --hard --other &&\n+\ttest_must_fail git reset --hard -o &&\n \tcheck_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc\n '\n \n@@ -102,8 +102,8 @@ test_expect_success \\\n \techo \"3rd line in branch2\" >>secondfile &&\n \tgit commit -a -m \"change in branch2\" &&\n \n-\t! git merge branch1 &&\n-\t! git reset --soft &&\n+\ttest_must_fail git merge branch1 &&\n+\ttest_must_fail git reset --soft &&\n \n \tprintf \"1st line 2nd file\\n2nd line 2nd file\\n3rd line\" >secondfile &&\n \tgit commit -a -m \"the change in branch2\" &&\n@@ -126,7 +126,7 @@ test_expect_success \\\n \techo \"3rd line in branch4\" >>secondfile &&\n \n \tgit checkout -m branch3 &&\n-\t! git reset --soft &&\n+\ttest_must_fail git reset --soft &&\n \n \tprintf \"1st line 2nd file\\n2nd line 2nd file\\n3rd line\" >secondfile &&\n \tgit commit -a -m \"the line in branch3\" &&\n@@ -326,7 +326,7 @@ test_expect_success '--hard reset to HEAD should clear a failed merge' '\n \techo \"3rd line in branch2\" >>secondfile &&\n \tgit commit -a -m \"change in branch2\" &&\n \n-\t! git pull . branch1 &&\n+\ttest_must_fail git pull . branch1 &&\n \tgit reset --hard &&\n \tcheck_changes 77abb337073fb4369a7ad69ff6f5ec0e4d6b54bb\n '\n@@ -388,7 +388,7 @@ test_expect_success 'test --mixed <paths>' '\n \techo 4 > file4 &&\n \techo 5 > file1 &&\n \tgit add file1 file3 file4 &&\n-\t! git reset HEAD -- file1 file2 file3 &&\n+\ttest_must_fail git reset HEAD -- file1 file2 file3 &&\n \tgit diff > output &&\n \ttest_cmp output expect &&\n \tgit diff --cached > output &&\n@@ -402,11 +402,11 @@ test_expect_success 'test resetting the index at give paths' '\n \t>sub/file2 &&\n \tgit update-index --add sub/file1 sub/file2 &&\n \tT=$(git write-tree) &&\n-\t! git reset HEAD sub/file2 &&\n+\ttest_must_fail git reset HEAD sub/file2 &&\n \tU=$(git write-tree) &&\n \techo \"$T\" &&\n \techo \"$U\" &&\n-\t! git diff-index --cached --exit-code \"$T\" &&\n+\ttest_must_fail git diff-index --cached --exit-code \"$T\" &&\n \ttest \"$T\" != \"$U\"\n \n '\ndiff --git a/t/t7103-reset-bare.sh b/t/t7103-reset-bare.sh\nindex b25a77f..cdecebe 100755\n--- a/t/t7103-reset-bare.sh\n+++ b/t/t7103-reset-bare.sh\n@@ -17,7 +17,7 @@ test_expect_success 'setup bare' '\n '\n \n test_expect_success 'hard reset is not allowed' '\n-\t! git reset --hard HEAD^\n+\ttest_must_fail  git reset --hard HEAD^\n '\n \n test_expect_success 'soft reset is allowed' '\ndiff --git a/t/t7300-clean.sh b/t/t7300-clean.sh\nindex bd77239..2b51c0d 100755\n--- a/t/t7300-clean.sh\n+++ b/t/t7300-clean.sh\n@@ -316,14 +316,14 @@ test_expect_success 'git-clean -d -X' '\n test_expect_success 'clean.requireForce defaults to true' '\n \n \tgit config --unset clean.requireForce &&\n-\t! git-clean\n+\ttest_must_fail git clean\n \n '\n \n test_expect_success 'clean.requireForce' '\n \n \tgit config clean.requireForce true &&\n-\t! git-clean\n+\ttest_must_fail git clean\n \n '\n \ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex 6c7b902..cbc0c34 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -75,7 +75,7 @@ test_expect_success 'init should register submodule url in .git/config' '\n \tthen\n \t\techo \"[OOPS] init succeeded but submodule url is wrong\"\n \t\tfalse\n-\telif ! git config submodule.example.url ./.subrepo\n+\telif test_must_fail git config submodule.example.url ./.subrepo\n \tthen\n \t\techo \"[OOPS] init succeeded but update of url failed\"\n \t\tfalse\ndiff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh\nindex 5becb3e..f919c8d 100755\n--- a/t/t7402-submodule-rebase.sh\n+++ b/t/t7402-submodule-rebase.sh\n@@ -71,7 +71,7 @@ test_expect_success 'rebase with dirty file and submodule fails' '\n \ttest_tick &&\n \tgit commit -m rewrite file &&\n \techo dirty > file &&\n-\t! git rebase --onto HEAD~2 HEAD^\n+\ttest_must_fail git rebase --onto HEAD~2 HEAD^\n \n '\n \ndiff --git a/t/t7500-commit.sh b/t/t7500-commit.sh\nindex baed6ce..d89f91a 100755\n--- a/t/t7500-commit.sh\n+++ b/t/t7500-commit.sh\n@@ -23,12 +23,12 @@ test_expect_success 'a basic commit in an empty tree should succeed' '\n test_expect_success 'nonexistent template file should return error' '\n \techo changes >> foo &&\n \tgit add foo &&\n-\t! git commit --template \"$PWD\"/notexist\n+\ttest_must_fail git commit --template \"$PWD\"/notexist\n '\n \n test_expect_success 'nonexistent template file in config should return error' '\n \tgit config commit.template \"$PWD\"/notexist &&\n-\t! git commit &&\n+\ttest_must_fail git commit &&\n \tgit config --unset commit.template\n '\n \n@@ -37,12 +37,12 @@ TEMPLATE=\"$PWD\"/template\n \n test_expect_success 'unedited template should not commit' '\n \techo \"template line\" > \"$TEMPLATE\" &&\n-\t! git commit --template \"$TEMPLATE\"\n+\ttest_must_fail git commit --template \"$TEMPLATE\"\n '\n \n test_expect_success 'unedited template with comments should not commit' '\n \techo \"# comment in template\" >> \"$TEMPLATE\" &&\n-\t! git commit --template \"$TEMPLATE\"\n+\ttest_must_fail git commit --template \"$TEMPLATE\"\n '\n \n test_expect_success 'a Signed-off-by line by itself should not commit' '\ndiff --git a/t/t7501-commit.sh b/t/t7501-commit.sh\nindex d3370ff..0edd9dd 100755\n--- a/t/t7501-commit.sh\n+++ b/t/t7501-commit.sh\n@@ -19,7 +19,7 @@ test_expect_success \\\n \n test_expect_success \\\n \t\"fail initial amend\" \\\n-\t\"! git-commit --amend\"\n+\t\"test_must_fail git-commit --amend\"\n \n test_expect_success \\\n \t\"initial commit\" \\\n@@ -27,16 +27,16 @@ test_expect_success \\\n \n test_expect_success \\\n \t\"invalid options 1\" \\\n-\t\"! git-commit -m foo -m bar -F file\"\n+\t\"test_must_fail git-commit -m foo -m bar -F file\"\n \n test_expect_success \\\n \t\"invalid options 2\" \\\n-\t\"! git-commit -C HEAD -m illegal\"\n+\t\"test_must_fail git-commit -C HEAD -m illegal\"\n \n test_expect_success \\\n \t\"using paths with -a\" \\\n \t\"echo King of the bongo >file &&\n-\t! git-commit -m foo -a file\"\n+\ttest_must_fail git-commit -m foo -a file\"\n \n test_expect_success \\\n \t\"using paths with --interactive\" \\\n@@ -45,11 +45,11 @@ test_expect_success \\\n \n test_expect_success \\\n \t\"using invalid commit with -C\" \\\n-\t\"! git-commit -C bogus\"\n+\t\"test_must_fail git-commit -C bogus\"\n \n test_expect_success \\\n \t\"testing nothing to commit\" \\\n-\t\"! git-commit -m initial\"\n+\t\"test_must_fail git-commit -m initial\"\n \n test_expect_success \\\n \t\"next commit\" \\\n@@ -59,7 +59,7 @@ test_expect_success \\\n test_expect_success \\\n \t\"commit message from non-existing file\" \\\n \t\"echo 'more bongo: bongo bongo bongo bongo' >file && \\\n-\t ! git-commit -F gah -a\"\n+\t test_must_fail git-commit -F gah -a\"\n \n # Empty except stray tabs and spaces on a few lines.\n sed -e 's/@$//' >msg <<EOF\n@@ -70,7 +70,7 @@ Signed-off-by: hula\n EOF\n test_expect_success \\\n \t\"empty commit message\" \\\n-\t\"! git-commit -F msg -a\"\n+\t\"test_must_fail git-commit -F msg -a\"\n \n test_expect_success \\\n \t\"commit message from file\" \\\n@@ -91,7 +91,7 @@ test_expect_success \\\n test_expect_success \\\n \t\"passing -m and -F\" \\\n \t\"echo 'enough with the bongos' >file && \\\n-\t ! git-commit -F msg -m amending .\"\n+\t test_must_fail git-commit -F msg -m amending .\"\n \n test_expect_success \\\n \t\"using message from other commit\" \\\ndiff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh\nindex 2dd5a5e..b069095 100755\n--- a/t/t7503-pre-commit-hook.sh\n+++ b/t/t7503-pre-commit-hook.sh\n@@ -56,7 +56,7 @@ test_expect_success 'with failing hook' '\n \n \techo \"another\" >> file &&\n \tgit add file &&\n-\t! git commit -m \"another\"\n+\ttest_must_fail git commit -m \"another\"\n \n '\n \ndiff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh\nindex 88577af..47680e6 100755\n--- a/t/t7504-commit-msg-hook.sh\n+++ b/t/t7504-commit-msg-hook.sh\n@@ -105,7 +105,7 @@ test_expect_success 'with failing hook' '\n \n \techo \"another\" >> file &&\n \tgit add file &&\n-\t! git commit -m \"another\"\n+\ttest_must_fail git commit -m \"another\"\n \n '\n \ndiff --git a/t/t7600-merge.sh b/t/t7600-merge.sh\nindex d21cd29..7d182b5 100755\n--- a/t/t7600-merge.sh\n+++ b/t/t7600-merge.sh\n@@ -126,7 +126,7 @@ verify_merge() {\n \t\techo \"[OOPS] unmerged files\"\n \t\tfalse\n \tfi &&\n-\tif ! git diff --exit-code\n+\tif test_must_fail git diff --exit-code\n \tthen\n \t\techo \"[OOPS] working tree != index\"\n \t\tfalse\ndiff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh\nindex 6b0483f..9285071 100755\n--- a/t/t7610-mergetool.sh\n+++ b/t/t7610-mergetool.sh\n@@ -35,7 +35,7 @@ test_expect_success 'custom mergetool' '\n     git config mergetool.mytool.cmd \"cat \\\"\\$REMOTE\\\" >\\\"\\$MERGED\\\"\" &&\n     git config mergetool.mytool.trustExitCode true &&\n \tgit checkout branch1 &&\n-    ! git merge master >/dev/null 2>&1 &&\n+    test_must_fail git merge master >/dev/null 2>&1 &&\n     ( yes \"\" | git mergetool file1>/dev/null 2>&1 ) &&\n     ( yes \"\" | git mergetool file2>/dev/null 2>&1 ) &&\n     test \"$(cat file1)\" = \"master updated\" &&\ndiff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh\nindex 3bc6164..843a501 100755\n--- a/t/t9100-git-svn-basic.sh\n+++ b/t/t9100-git-svn-basic.sh\n@@ -63,7 +63,7 @@ test_expect_success \"$name\" \"\n \tgit update-index --remove dir/file &&\n \tgit update-index --add dir/file/file &&\n \tgit commit -m '$name' &&\n-\t! git-svn set-tree --find-copies-harder --rmdir \\\n+\ttest_must_fail git-svn set-tree --find-copies-harder --rmdir \\\n \t\tremotes/git-svn..mybranch\" || true\n \n \n@@ -77,7 +77,7 @@ test_expect_success \"$name\" '\n \tgit update-index --remove -- bar/zzz &&\n \tgit update-index --add -- bar &&\n \tgit commit -m \"$name\" &&\n-\t! git-svn set-tree --find-copies-harder --rmdir \\\n+\ttest_must_fail git-svn set-tree --find-copies-harder --rmdir \\\n \t\tremotes/git-svn..mybranch2' || true\n \n \n@@ -91,7 +91,7 @@ test_expect_success \"$name\" '\n \techo yyy > bar/zzz/yyy &&\n \tgit update-index --add bar/zzz/yyy &&\n \tgit commit -m \"$name\" &&\n-\t! git-svn set-tree --find-copies-harder --rmdir \\\n+\ttest_must_fail git-svn set-tree --find-copies-harder --rmdir \\\n \t\tremotes/git-svn..mybranch3' || true\n \n \n@@ -105,7 +105,7 @@ test_expect_success \"$name\" '\n \techo asdf > dir &&\n \tgit update-index --add -- dir &&\n \tgit commit -m \"$name\" &&\n-\t! git-svn set-tree --find-copies-harder --rmdir \\\n+\ttest_must_fail git-svn set-tree --find-copies-harder --rmdir \\\n \t\tremotes/git-svn..mybranch4' || true\n \n \n@@ -216,7 +216,7 @@ test_expect_success \"$name\" \"test_cmp a expected\"\n test_expect_success 'exit if remote refs are ambigious' \"\n         git config --add svn-remote.svn.fetch \\\n                               bar:refs/remotes/git-svn &&\n-\t! git-svn migrate\n+\ttest_must_fail git-svn migrate\n \"\n \n test_expect_success 'exit if init-ing a would clobber a URL' '\n@@ -224,7 +224,7 @@ test_expect_success 'exit if init-ing a would clobber a URL' '\n         svn mkdir -m \"mkdir bar\" \"${svnrepo}2/bar\" &&\n         git config --unset svn-remote.svn.fetch \\\n                                 \"^bar:refs/remotes/git-svn$\" &&\n-\t! git-svn init \"${svnrepo}2/bar\"\n+\ttest_must_fail git-svn init \"${svnrepo}2/bar\"\n         '\n \n test_expect_success \\\ndiff --git a/t/t9106-git-svn-commit-diff-clobber.sh b/t/t9106-git-svn-commit-diff-clobber.sh\nindex 58a3a7b..a57ff68 100755\n--- a/t/t9106-git-svn-commit-diff-clobber.sh\n+++ b/t/t9106-git-svn-commit-diff-clobber.sh\n@@ -27,7 +27,7 @@ test_expect_success 'commit change from svn side' '\n test_expect_success 'commit conflicting change from git' '\n \techo second line from git >> file &&\n \tgit commit -a -m \"second line from git\" &&\n-\t! git-svn commit-diff -r1 HEAD~1 HEAD \"$svnrepo\"\n+\ttest_must_fail git-svn commit-diff -r1 HEAD~1 HEAD \"$svnrepo\"\n '\n \n test_expect_success 'commit complementing change from git' '\n@@ -52,7 +52,7 @@ test_expect_success 'dcommit fails to commit because of conflict' '\n \trm -rf t.svn &&\n \techo \"fourth line from git\" >> file &&\n \tgit commit -a -m \"fourth line from git\" &&\n-\t! git-svn dcommit\n+\ttest_must_fail git-svn dcommit\n \t'\n \n test_expect_success 'dcommit does the svn equivalent of an index merge' \"\n@@ -83,7 +83,7 @@ test_expect_success 'multiple dcommit from git-svn will not clobber svn' \"\n \tgit commit -a -m 'new file' &&\n \techo clobber > file &&\n \tgit commit -a -m 'clobber' &&\n-\t! git svn dcommit\n+\ttest_must_fail git svn dcommit\n \t\"\n \n \ndiff --git a/t/t9106-git-svn-dcommit-clobber-series.sh b/t/t9106-git-svn-dcommit-clobber-series.sh\nindex f8f4718..bc37db9 100755\n--- a/t/t9106-git-svn-dcommit-clobber-series.sh\n+++ b/t/t9106-git-svn-dcommit-clobber-series.sh\n@@ -57,7 +57,7 @@ test_expect_success 'change file but in unrelated area' \"\n test_expect_success 'attempt to dcommit with a dirty index' '\n \techo foo >>file &&\n \tgit add file &&\n-\t! git svn dcommit\n+\ttest_must_fail git svn dcommit\n '\n \n test_done\ndiff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh\nindex b1dc32d..3e32e84 100755\n--- a/t/t9200-git-cvsexportcommit.sh\n+++ b/t/t9200-git-cvsexportcommit.sh\n@@ -100,7 +100,7 @@ test_expect_success \\\n      git commit -a -m \"generation 2\" &&\n      id=$(git rev-list --max-count=1 HEAD) &&\n      (cd \"$CVSWORK\" &&\n-     ! git cvsexportcommit -c $id\n+     test_must_fail git cvsexportcommit -c $id\n      )'\n \n #test_expect_success \\\n@@ -112,7 +112,7 @@ test_expect_success \\\n #     git commit -a -m \"generation 3\" &&\n #     id=$(git rev-list --max-count=1 HEAD) &&\n #     (cd \"$CVSWORK\" &&\n-#     ! git cvsexportcommit -c $id\n+#     test_must_fail git cvsexportcommit -c $id\n #     )'\n \n # We reuse the state from two tests back here\n@@ -222,7 +222,7 @@ test_expect_success \\\n       git commit -a -m \"Update two\" &&\n       id=$(git rev-list --max-count=1 HEAD) &&\n       (cd \"$CVSWORK\" &&\n-      ! git-cvsexportcommit -c $id\n+      test_must_fail git-cvsexportcommit -c $id\n       )'\n \n case \"$(git config --bool core.filemode)\" in\ndiff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\nindex 5edf56f..e17afa8 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -166,7 +166,7 @@ M 755 0000000000000000000000000000000000000001 zero1\n \n INPUT_END\n test_expect_success 'B: fail on invalid blob sha1' '\n-    ! git-fast-import <input\n+    test_must_fail git-fast-import <input\n '\n rm -f .git/objects/pack_* .git/objects/index_*\n \n@@ -181,7 +181,7 @@ from refs/heads/master\n \n INPUT_END\n test_expect_success 'B: fail on invalid branch name \".badbranchname\"' '\n-    ! git-fast-import <input\n+    test_must_fail git-fast-import <input\n '\n rm -f .git/objects/pack_* .git/objects/index_*\n \n@@ -196,7 +196,7 @@ from refs/heads/master\n \n INPUT_END\n test_expect_success 'B: fail on invalid branch name \"bad[branch]name\"' '\n-    ! git-fast-import <input\n+    test_must_fail git-fast-import <input\n '\n rm -f .git/objects/pack_* .git/objects/index_*\n \n@@ -340,7 +340,7 @@ from refs/heads/branch^0\n \n INPUT_END\n test_expect_success 'E: rfc2822 date, --date-format=raw' '\n-    ! git-fast-import --date-format=raw <input\n+    test_must_fail git-fast-import --date-format=raw <input\n '\n test_expect_success \\\n     'E: rfc2822 date, --date-format=rfc2822' \\\ndiff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh\nindex f1bc5ce..0959f2f 100755\n--- a/t/t9301-fast-export.sh\n+++ b/t/t9301-fast-export.sh\n@@ -59,7 +59,7 @@ test_expect_success 'fast-export master~2..master' '\n \t\t test $MASTER != $(git rev-parse --verify refs/heads/partial) &&\n \t\t git diff master..partial &&\n \t\t git diff master^..partial^ &&\n-\t\t ! git rev-parse partial~2)\n+\t\t test_must_fail git rev-parse partial~2)\n \n '\n \n@@ -125,7 +125,7 @@ test_expect_success 'set up faked signed tag' '\n \n test_expect_success 'signed-tags=abort' '\n \n-\t! git fast-export --signed-tags=abort sign-your-name\n+\ttest_must_fail git fast-export --signed-tags=abort sign-your-name\n \n '\n \n-- \n1.5.6.2.303.g79662\n"},{"id":"83092","messageId":"m3vdzbccoq.fsf@localhost.localdomain","threadId":"14425","inReplyTo":"1215877672-17049-2-git-send-email-s-beyer@gmx.net","subject":"Re: [PATCH 2/2] t/: Use \"test_must_fail git\" instead of \"! git\"","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-07-12T16:04:21Z","receivedAt":"2008-07-12T16:04:21Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Stephan Beyer <s-beyer@gmx.net> writes:\n\n> This patch changes every occurrence of \"! git\" -- with the meaning\n> that a git call has to fail -- into \"test_must_fail git\".\n> \n> This is useful to\n\n>  - advertise the use of \"test_must_fail\" for new tests.\n\nHmmm... I think advertising the use of 'test_must_fail' would be\nthe best served by adding information about this function to\nt/README\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"83103","messageId":"1215898229-21363-1-git-send-email-s-beyer@gmx.net","threadId":"14425","inReplyTo":"1215877672-17049-2-git-send-email-s-beyer@gmx.net","subject":"[SQUASH PATCH] t9001: Use \"test_must_fail git\" instead of \"! git\"","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-12T21:30:29Z","receivedAt":"2008-07-12T21:30:29Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Signed-off-by: Stephan Beyer <s-beyer@gmx.net>\n---\n\nThis one was mysteriously *g* excluded from the last patch :(\nJunio, if you apply, can you squash this?\n\nSorry,\n  Stephan\n\n t/t9001-send-email.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh\nindex 3e4eb63..de5b980 100755\n--- a/t/t9001-send-email.sh\n+++ b/t/t9001-send-email.sh\n@@ -91,7 +91,7 @@ test_expect_success 'reject long lines' '\n \tclean_fake_sendmail &&\n \tcp $patches longline.patch &&\n \techo $z512$z512 >>longline.patch &&\n-\t! git send-email \\\n+\ttest_must_fail git send-email \\\n \t\t--from=\"Example <nobody@example.com>\" \\\n \t\t--to=nobody@example.com \\\n \t\t--smtp-server=\"$(pwd)/fake.sendmail\" \\\n-- \n1.5.6.2.303.g79662\n"},{"id":"83105","messageId":"20080712214359.GA22323@leksak.fem-net","threadId":"14425","inReplyTo":"m3vdzbccoq.fsf@localhost.localdomain","subject":"Re: [PATCH 2/2] t/: Use \"test_must_fail git\" instead of \"! git\"","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-12T21:43:59Z","receivedAt":"2008-07-12T21:43:59Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nJakub Narebski wrote:\n> Stephan Beyer <s-beyer@gmx.net> writes:\n> \n> > This patch changes every occurrence of \"! git\" -- with the meaning\n> > that a git call has to fail -- into \"test_must_fail git\".\n> > \n> > This is useful to\n> \n> >  - advertise the use of \"test_must_fail\" for new tests.\n> \n> Hmmm... I think advertising the use of 'test_must_fail' would be\n> the best served by adding information about this function to\n> t/README\n\nThis is true.\nThis is not only true for test_must_fail, it is also true for\nstuff like test_tick, test_set_editor, test_cmp and the like.\n\nBut, well, t/README says also, that \"existing programs are the best\nsource of the information.\"\nAnd I think it is right ;-)\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"83473","messageId":"20080716051829.GB4030@segfault.peff.net","threadId":"14425","inReplyTo":"1215877672-17049-1-git-send-email-s-beyer@gmx.net","subject":"Re: [PATCH 1/2] t/test-lib.sh: Let test_must_fail fail on signals only","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-07-16T05:18:29Z","receivedAt":"2008-07-16T05:18:29Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Jul 12, 2008 at 05:47:51PM +0200, Stephan Beyer wrote:\n\n> The test_must_fail function in test-lib.sh has been designed\n> to distinguish segmentation faults from controlled errors.\n> But in the current implementation this only works if a git\n> command does not return a small negative value, like -1, -2\n> or -3. But some git commands do.\n\nThis is probably a fine protective measure, and it looks like Junio has\nalready applied it. But shouldn't any git commands returning such values\nbe fixed? Which commands return such bogus error codes?\n\n-Peff\n"},{"id":"83474","messageId":"7v4p6qwezy.fsf@gitster.siamese.dyndns.org","threadId":"14425","inReplyTo":"20080716051829.GB4030@segfault.peff.net","subject":"Re: [PATCH 1/2] t/test-lib.sh: Let test_must_fail fail on signals only","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-07-16T05:54:25Z","receivedAt":"2008-07-16T05:54:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> This is probably a fine protective measure, and it looks like Junio has\n> already applied it. But shouldn't any git commands returning such values\n> be fixed? Which commands return such bogus error codes?\n\nAnything that returns error() from its cmd_xxx() routine, for example,\nwould end up exiting with (-1).  Is it \"such bogus\" error codes, though?\n\nI am somewhat tired tonight, so I'll leave it up to the list to do the\ngrepping and go to bed ;-)\n"},{"id":"83508","messageId":"20080716115732.GB25087@leksak.fem-net","threadId":"14425","inReplyTo":"20080716051829.GB4030@segfault.peff.net","subject":"Re: [PATCH 1/2] t/test-lib.sh: Let test_must_fail fail on signals only","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-16T11:57:32Z","receivedAt":"2008-07-16T11:57:32Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nJeff King wrote:\n> On Sat, Jul 12, 2008 at 05:47:51PM +0200, Stephan Beyer wrote:\n> \n> > The test_must_fail function in test-lib.sh has been designed\n> > to distinguish segmentation faults from controlled errors.\n> > But in the current implementation this only works if a git\n> > command does not return a small negative value, like -1, -2\n> > or -3. But some git commands do.\n> \n> This is probably a fine protective measure, and it looks like Junio has\n> already applied it. But shouldn't any git commands returning such values\n> be fixed?\n\nI didn't want to change any error codes and I wouldn't say that the term\n\"fix\" is the right one here.\n\n> Which commands return such bogus error codes?\n\nWhy bogus?\n\nTo answer your question, some are:\n\tgit diff-files\n\tgit diff-index\n\tgit diff\n\tgit merge-file\n\nI think at least one test case failed \"test_must_fail git merge-file ...\"\nwithout that change.\n\nRegards.\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"83639","messageId":"20080717051833.GA3100@sigio.intra.peff.net","threadId":"14425","inReplyTo":"7v4p6qwezy.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 1/2] t/test-lib.sh: Let test_must_fail fail on signals only","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-07-17T05:18:34Z","receivedAt":"2008-07-17T05:18:34Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Jul 15, 2008 at 10:54:25PM -0700, Junio C Hamano wrote:\n\n> Anything that returns error() from its cmd_xxx() routine, for example,\n> would end up exiting with (-1).  Is it \"such bogus\" error codes, though?\n\nI think it is bogus, because it is being implicitly truncated to an\nunsigned 8-bit value (at least on Linux -- I have no idea what other\nplatforms do). So your -1 is actually 255. Portably speaking, C defines\nonly the macros EXIT_SUCCESS and EXIT_FAILURE; in practice, I don't know\nwhat is most common.\n\nBad side effects of not treating your exit codes as unsigned 8-bit\nintegers:\n\n  - the exit values are easily confused with other things, like signal\n    death. As in this case. We have modified our checking code in the\n    test scripts, but there may be other, less robust code out there.\n\n  - other exit values can be mistaken as success. Obviously 256, -256,\n    512, -512, etc all produce an erroneous \"success\". Now we aren't\n    doing this, as we are using \"-1\", but it just seems a bit cleaner to\n    be up front about what is happening (and the 255 we end up with is\n    unnecessarily confusing; some documents, like this one:\n\n      http://tldp.org/LDP/abs/html/exitcodes.html\n\n    claim 255 as \"out of range\").\n\nSo what we are doing now isn't terrible, but since it was noted (and did\nin fact cause a problem!), I just expected a \"let's stop doing that\"\npatch in the original series.\n\n-Peff\n"},{"id":"83640","messageId":"7v3am9m5ne.fsf@gitster.siamese.dyndns.org","threadId":"14425","inReplyTo":"20080717051833.GA3100@sigio.intra.peff.net","subject":"Re: [PATCH 1/2] t/test-lib.sh: Let test_must_fail fail on signals only","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-07-17T05:38:45Z","receivedAt":"2008-07-17T05:38:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Tue, Jul 15, 2008 at 10:54:25PM -0700, Junio C Hamano wrote:\n>\n>> Anything that returns error() from its cmd_xxx() routine, for example,\n>> would end up exiting with (-1).  Is it \"such bogus\" error codes, though?\n>\n> I think it is bogus, because it is being implicitly truncated to an\n> unsigned 8-bit value (at least on Linux -- I have no idea what other\n> platforms do). \n\n\"Only the least significant 8 bits (that is, status & 0377) shall be\navailable to a waiting parent process\".  So it is not just \"at least on\nLinux\" but is a well defined behaviour.\n\nhttp://www.opengroup.org/onlinepubs/000095399/functions/exit.html\n\nI would however agree that when we do mean 255 we should probably write\n255, not (-1).  It is easier to document things that way.\n"},{"id":"83641","messageId":"20080717060143.GA3338@sigill.intra.peff.net","threadId":"14425","inReplyTo":"7v3am9m5ne.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 1/2] t/test-lib.sh: Let test_must_fail fail on signals only","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-07-17T06:01:43Z","receivedAt":"2008-07-17T06:01:43Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jul 16, 2008 at 10:38:45PM -0700, Junio C Hamano wrote:\n\n> \"Only the least significant 8 bits (that is, status & 0377) shall be\n> available to a waiting parent process\".  So it is not just \"at least on\n> Linux\" but is a well defined behaviour.\n> \n> http://www.opengroup.org/onlinepubs/000095399/functions/exit.html\n\nAh, thanks. I read that same text in the Linux manpage but didn't think\nto check that it was POSIX. However, some of our systems aren't quite\nPOSIX...check out 2488df84 (builtin run_command: do not exit with -1) by\nJohannes Sixt [who is now cc'd]. I assume that was a Windows fallout.\n\n> I would however agree that when we do mean 255 we should probably write\n> 255, not (-1).  It is easier to document things that way.\n\nI started to fix the callsites that Stephan mentioned, but it really is\nconvenient to be able to 'return error(\"foo\")' (or even return\nfunc_that_calls_error(), and tracking down deep calls is time consuming\nand error prone). So maybe we should just enhance the change from\n2488df84 and special case \"-1\" into \"1\"?\n\ndiff --git a/git.c b/git.c\nindex 6b600b5..4f28e8c 100644\n--- a/git.c\n+++ b/git.c\n@@ -240,7 +240,7 @@ static int run_command(struct cmd_struct *p, int argc, const char **argv)\n \n \tstatus = p->fn(argc, argv, prefix);\n \tif (status)\n-\t\treturn status & 0xff;\n+\t\treturn status == -1 ? 1 : status & 0xff;\n \n \t/* Somebody closed stdout? */\n \tif (fstat(fileno(stdout), &st))\n\n-Peff\n"},{"id":"83642","messageId":"7vlk01komq.fsf@gitster.siamese.dyndns.org","threadId":"14425","inReplyTo":"20080717060143.GA3338@sigill.intra.peff.net","subject":"Re: [PATCH 1/2] t/test-lib.sh: Let test_must_fail fail on signals only","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-07-17T06:31:41Z","receivedAt":"2008-07-17T06:31:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n>> I would however agree that when we do mean 255 we should probably write\n>> 255, not (-1).  It is easier to document things that way.\n>\n> I started to fix the callsites that Stephan mentioned, but it really is\n> convenient to be able to 'return error(\"foo\")' (or even return\n> func_that_calls_error(), and tracking down deep calls is time consuming\n> and error prone). So maybe we should just enhance the change from\n> 2488df84 and special case \"-1\" into \"1\"?\n\nDidn't the patch to testsuite that triggered this thread talk about \"small\nnegative integer\" not \"-1\"?  I suspect there might be other negative\nreturn values from cmd_foo(), although I haven't checked.\n\nIs it that somebody do not want 255 exit value, or anything that has 7th\nbit set?  2488df8 (builtin run_command: do not exit with -1., 2007-11-13)\nsuggests otherwise at least for Windows runtime, so what we currently have\nthat does extra truncation ourselves might be sufficient.\n"},{"id":"83643","messageId":"20080717063856.GA10450@sigill.intra.peff.net","threadId":"14425","inReplyTo":"7vlk01komq.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 1/2] t/test-lib.sh: Let test_must_fail fail on signals only","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-07-17T06:38:56Z","receivedAt":"2008-07-17T06:38:56Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jul 16, 2008 at 11:31:41PM -0700, Junio C Hamano wrote:\n\n> > I started to fix the callsites that Stephan mentioned, but it really is\n> > convenient to be able to 'return error(\"foo\")' (or even return\n> > func_that_calls_error(), and tracking down deep calls is time consuming\n> > and error prone). So maybe we should just enhance the change from\n> > 2488df84 and special case \"-1\" into \"1\"?\n> \n> Didn't the patch to testsuite that triggered this thread talk about \"small\n> negative integer\" not \"-1\"?  I suspect there might be other negative\n> return values from cmd_foo(), although I haven't checked.\n\nIt did say that, but I never saw anything in the code except explicit\n\"return -1\" and \"return error()\". However, some of the diff code may end\nup with different values, as I didn't trace it all the way down.\nStephan?\n\n> Is it that somebody do not want 255 exit value, or anything that has 7th\n> bit set?  2488df8 (builtin run_command: do not exit with -1., 2007-11-13)\n> suggests otherwise at least for Windows runtime, so what we currently have\n> that does extra truncation ourselves might be sufficient.\n\nJohannes will have to answer that; however, the truncation there does\nleave the extra 7th bit. Maybe & 0x7f would be more appropriate?\n\n-Peff\n"},{"id":"83645","messageId":"487EF31D.8090007@viscovery.net","threadId":"14425","inReplyTo":"20080717063856.GA10450@sigill.intra.peff.net","subject":"Re: [PATCH 1/2] t/test-lib.sh: Let test_must_fail fail on signals only","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-07-17T07:22:05Z","receivedAt":"2008-07-17T07:22:05Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Jeff King schrieb:\n> On Wed, Jul 16, 2008 at 11:31:41PM -0700, Junio C Hamano wrote:\n>> Is it that somebody do not want 255 exit value, or anything that has 7th\n>> bit set?  2488df8 (builtin run_command: do not exit with -1., 2007-11-13)\n>> suggests otherwise at least for Windows runtime, so what we currently have\n>> that does extra truncation ourselves might be sufficient.\n> \n> Johannes will have to answer that; however, the truncation there does\n> leave the extra 7th bit. Maybe & 0x7f would be more appropriate?\n\nI never found out the real reason why -1 would not be recognized as\n\"failure\"; the conclusion of my debugging session was that MSYS bash has\nan issue, and I chose to append '& 0xff' because the documentation of\nWEXITSTATUS() says that it can receive only 8 bits of the exit() code. The\nintention of 2488df8 was to keep as much information as possible. But if\nthat extra information hurts, we should better truncate to 7 bits.\n\nThe source code of Windows's C runtime suggests that any value that fits\nin 4 bytes can be supplied to exit() and can be received by cwait()\n(Windows's version of waitpid()); but I haven't looked at how MSYS\nimplements waitpit() and whether it can receive that much information.\n\n-- Hannes\n"},{"id":"83646","messageId":"7vabghkm4n.fsf@gitster.siamese.dyndns.org","threadId":"14425","inReplyTo":"487EF31D.8090007@viscovery.net","subject":"Re: [PATCH 1/2] t/test-lib.sh: Let test_must_fail fail on signals only","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-07-17T07:25:44Z","receivedAt":"2008-07-17T07:25:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j.sixt@viscovery.net> writes:\n\n> Jeff King schrieb:\n>> On Wed, Jul 16, 2008 at 11:31:41PM -0700, Junio C Hamano wrote:\n>>> Is it that somebody do not want 255 exit value, or anything that has 7th\n>>> bit set?  2488df8 (builtin run_command: do not exit with -1., 2007-11-13)\n>>> suggests otherwise at least for Windows runtime, so what we currently have\n>>> that does extra truncation ourselves might be sufficient.\n>> \n>> Johannes will have to answer that; however, the truncation there does\n>> leave the extra 7th bit. Maybe & 0x7f would be more appropriate?\n>\n> I never found out the real reason why -1 would not be recognized as\n> \"failure\"; the conclusion of my debugging session was that MSYS bash has\n> an issue, and I chose to append '& 0xff' because the documentation of\n> WEXITSTATUS() says that it can receive only 8 bits of the exit() code. The\n> intention of 2488df8 was to keep as much information as possible. But if\n> that extra information hurts, we should better truncate to 7 bits.\n>\n> The source code of Windows's C runtime suggests that any value that fits\n> in 4 bytes can be supplied to exit() and can be received by cwait()\n> (Windows's version of waitpid()); but I haven't looked at how MSYS\n> implements waitpit() and whether it can receive that much information.\n\nWell, POSIX cannot do that much anyway, but does allow 8-bit, so I'd say\nthe current code is fine.\n"}]}