Git 挂钩仅在提交时失败
Git hook fails ONLY on commit
执行摘要
我有一个带有自定义预提交挂钩的项目,树看起来像这样:
parent
|
- .git - hooks - pre-commit
|
- smoketests - argument_tests.sh
|
- bitshuffle.py
当我 运行 .git/hooks/pre-commit 时,它 运行 非常完美,并且每个测试都通过了。但是,当我 运行 git commit
时,一些测试失败了。我的索引与我的工作树完全一样。我不知道出了什么问题。
感谢您的帮助。
详情
状态
$ git status
On branch staging
Your branch is up-to-date with 'origin/staging'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: smoketest/argument_tests.sh
renamed: smoketest/do_test.sh -> smoketest/library_tests.sh
回溯
$ git commit
Running tests...
When run with no args, prints help... PASSED
When run with '-h', prints help... PASSED
When given bad compresstype, prints help... PASSED
When given bad editor, prints editor not found... FAILED
'Editor /nonexistent not found' does not match logfile
Nothing to decode or nothing matched spec. Aborting.
When given bad input, prints file not found... PASSED
1 tests failed.
自行运行预提交
$ .git/hooks/pre-commit
Running tests...
When run with no args, prints help... PASSED
When run with '-h', prints help... PASSED
When given bad compresstype, prints help... PASSED
When given bad editor, prints editor not found... PASSED
When given bad input, prints file not found... PASSED
0 tests failed.
预提交内容
#!/bin/sh
## custom
# smoketesting
if ! smoketest/library_tests.sh; then exit 1; fi;
# arguments
if ! smoketest/argument_tests.sh; then exit 1; fi;
# codestyle
if ! pycodestyle *.py; then exit 1; fi;
差异
$ git diff --cached
diff --git smoketest/argument_tests.sh smoketest/argument_tests.sh
new file mode 100755
index 0000000..0133819
--- /dev/null
+++ smoketest/argument_tests.sh
@@ -0,0 +1,90 @@
+#!/bin/bash
+
+# .SHELLDOC
+
+# Smoketests for argument handling. Exit code is # of failed tests.
+# Heavily influenced by existing smoketests.
+
+# .ENDOC
+
+TEST_DIR="`readlink -e $(dirname "[=16=]")`"
+BITSHUFFLE="$TEST_DIR/../bitshuffle.py"
+TESTS_FAILED=0
+
+if [ ! -x "$BITSHUFFLE" ] ; then
+ echo "FATAL: '$BITSHUFFLE' does not exist"
+ exit 9999
+fi
+
+# Note: of necessity, the following can only test non-interactive
+# situations. Interactive tests are not a priority at the current moment.
+
+print_log_file() {
+# takes 1 parameter, a text file
+ while read -r line; do
+ printf "\t$line\n"
+ done <
+ printf "\n\n"
+}
+
+
+expect_usage_error () {
+ LOG_FILE="/tmp/`uuidgen`"
+ $BITSHUFFLE $@ > "$LOG_FILE" 2>&1
+ if grep -q "usage: .*" $LOG_FILE; then
+ echo "PASSED"
+ else
+ printf "FAILED\n\n"
+
+ printf "\t'usage: .*' does not match logfile\n\n"
+ print_log_file $LOG_FILE
+ TESTS_FAILED=`echo "$TESTS_FAILED + 1" | bc`
+ rm -f $LOG_FILE
+ fi
+}
+
+printf "Running tests...\n\n"
+
+printf "When run with no args, prints help... "
+expect_usage_error
+
+printf "When run with '-h', prints help... "
+expect_usage_error -h
+
+printf "When given bad compresstype, prints help... "
+expect_usage_error -t gmander
+
+printf "When given bad editor, prints editor not found... "
+LOG_FILE="/tmp/`uuidgen`"
+$BITSHUFFLE --editor /nonexistent > "$LOG_FILE" 2>&1
+if [ "`cat $LOG_FILE`" = "Editor /nonexistent not found" ]; then
+ echo "PASSED"
+else
+ printf "FAILED\n\n"
+
+ printf "'Editor /nonexistent not found' does not match logfile\n\n"
+
+ print_log_file $LOG_FILE
+ TESTS_FAILED="`echo $TESTS_FAILED + 1 | bc`"
+ rm -f $LOG_FILE
+fi
+
+LOG_FILE="/tmp/`uuidgen`"
+printf "When given bad input, prints file not found... "
+$BITSHUFFLE --input /nonexistent/nope > "$LOG_FILE" 2>&1
+if [ "`cat $LOG_FILE`" = "Error: Input file not found" ]; then
+ echo "PASSED"
+else
+ printf "FAILED\n\n"
+
+ printf "\t'Error: Input file not found' \
+ does not match logfile\n\n"
+
+ print_log_file $LOG_FILE
+ TESTS_FAILED=`echo $TESTS_FAILED + 1 | bc`
+ rm -f $LOG_FILE
+fi
+
+printf "\n$TESTS_FAILED tests failed.\n"
+exit $TESTS_FAILED
+
diff --git smoketest/do_test.sh smoketest/library_tests.sh
similarity index 100%
rename from smoketest/do_test.sh
rename to smoketest/library_tests.sh
想通了。如果终端是交互式的与非交互式的,程序响应不同。 运行 来自脚本的测试使终端成为非交互式。
罪魁祸首:
if stdin.isatty() and args.input == '/dev/stdin':
# ask the user to paste the packets into $VISUAL
is_tmp = True
if not args.editor:
args.editor = find_editor()
if not check_for_file(args.editor):
print("Editor %s not found" % args.editor)
sys.exit(4)
如果 stdin.isatty()
返回 false,则此位永远不会 运行。
执行摘要
我有一个带有自定义预提交挂钩的项目,树看起来像这样:
parent
|
- .git - hooks - pre-commit
|
- smoketests - argument_tests.sh
|
- bitshuffle.py
当我 运行 .git/hooks/pre-commit 时,它 运行 非常完美,并且每个测试都通过了。但是,当我 运行 git commit
时,一些测试失败了。我的索引与我的工作树完全一样。我不知道出了什么问题。
感谢您的帮助。
详情
状态
$ git status
On branch staging
Your branch is up-to-date with 'origin/staging'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: smoketest/argument_tests.sh
renamed: smoketest/do_test.sh -> smoketest/library_tests.sh
回溯
$ git commit
Running tests...
When run with no args, prints help... PASSED
When run with '-h', prints help... PASSED
When given bad compresstype, prints help... PASSED
When given bad editor, prints editor not found... FAILED
'Editor /nonexistent not found' does not match logfile
Nothing to decode or nothing matched spec. Aborting.
When given bad input, prints file not found... PASSED
1 tests failed.
自行运行预提交
$ .git/hooks/pre-commit
Running tests...
When run with no args, prints help... PASSED
When run with '-h', prints help... PASSED
When given bad compresstype, prints help... PASSED
When given bad editor, prints editor not found... PASSED
When given bad input, prints file not found... PASSED
0 tests failed.
预提交内容
#!/bin/sh
## custom
# smoketesting
if ! smoketest/library_tests.sh; then exit 1; fi;
# arguments
if ! smoketest/argument_tests.sh; then exit 1; fi;
# codestyle
if ! pycodestyle *.py; then exit 1; fi;
差异
$ git diff --cached
diff --git smoketest/argument_tests.sh smoketest/argument_tests.sh
new file mode 100755
index 0000000..0133819
--- /dev/null
+++ smoketest/argument_tests.sh
@@ -0,0 +1,90 @@
+#!/bin/bash
+
+# .SHELLDOC
+
+# Smoketests for argument handling. Exit code is # of failed tests.
+# Heavily influenced by existing smoketests.
+
+# .ENDOC
+
+TEST_DIR="`readlink -e $(dirname "[=16=]")`"
+BITSHUFFLE="$TEST_DIR/../bitshuffle.py"
+TESTS_FAILED=0
+
+if [ ! -x "$BITSHUFFLE" ] ; then
+ echo "FATAL: '$BITSHUFFLE' does not exist"
+ exit 9999
+fi
+
+# Note: of necessity, the following can only test non-interactive
+# situations. Interactive tests are not a priority at the current moment.
+
+print_log_file() {
+# takes 1 parameter, a text file
+ while read -r line; do
+ printf "\t$line\n"
+ done <
+ printf "\n\n"
+}
+
+
+expect_usage_error () {
+ LOG_FILE="/tmp/`uuidgen`"
+ $BITSHUFFLE $@ > "$LOG_FILE" 2>&1
+ if grep -q "usage: .*" $LOG_FILE; then
+ echo "PASSED"
+ else
+ printf "FAILED\n\n"
+
+ printf "\t'usage: .*' does not match logfile\n\n"
+ print_log_file $LOG_FILE
+ TESTS_FAILED=`echo "$TESTS_FAILED + 1" | bc`
+ rm -f $LOG_FILE
+ fi
+}
+
+printf "Running tests...\n\n"
+
+printf "When run with no args, prints help... "
+expect_usage_error
+
+printf "When run with '-h', prints help... "
+expect_usage_error -h
+
+printf "When given bad compresstype, prints help... "
+expect_usage_error -t gmander
+
+printf "When given bad editor, prints editor not found... "
+LOG_FILE="/tmp/`uuidgen`"
+$BITSHUFFLE --editor /nonexistent > "$LOG_FILE" 2>&1
+if [ "`cat $LOG_FILE`" = "Editor /nonexistent not found" ]; then
+ echo "PASSED"
+else
+ printf "FAILED\n\n"
+
+ printf "'Editor /nonexistent not found' does not match logfile\n\n"
+
+ print_log_file $LOG_FILE
+ TESTS_FAILED="`echo $TESTS_FAILED + 1 | bc`"
+ rm -f $LOG_FILE
+fi
+
+LOG_FILE="/tmp/`uuidgen`"
+printf "When given bad input, prints file not found... "
+$BITSHUFFLE --input /nonexistent/nope > "$LOG_FILE" 2>&1
+if [ "`cat $LOG_FILE`" = "Error: Input file not found" ]; then
+ echo "PASSED"
+else
+ printf "FAILED\n\n"
+
+ printf "\t'Error: Input file not found' \
+ does not match logfile\n\n"
+
+ print_log_file $LOG_FILE
+ TESTS_FAILED=`echo $TESTS_FAILED + 1 | bc`
+ rm -f $LOG_FILE
+fi
+
+printf "\n$TESTS_FAILED tests failed.\n"
+exit $TESTS_FAILED
+
diff --git smoketest/do_test.sh smoketest/library_tests.sh
similarity index 100%
rename from smoketest/do_test.sh
rename to smoketest/library_tests.sh
想通了。如果终端是交互式的与非交互式的,程序响应不同。 运行 来自脚本的测试使终端成为非交互式。
罪魁祸首:
if stdin.isatty() and args.input == '/dev/stdin':
# ask the user to paste the packets into $VISUAL
is_tmp = True
if not args.editor:
args.editor = find_editor()
if not check_for_file(args.editor):
print("Editor %s not found" % args.editor)
sys.exit(4)
如果 stdin.isatty()
返回 false,则此位永远不会 运行。