test: Add check-non-portable-shell.pl

Add the perl script "check-non-portable-shell.pl" to detect non-portable shell syntax. "echo -n" is an example of a shell command working on Linux, but not on Mac OS X. These shell commands are checked and reported as error: - "echo -n" (printf should be used) - "sed -i" (GNUism; use a temp file instead) - "declare" (bashism, often used with arrays) - "which" (unreliable exit status and output; use type instead) - "test a == b" (bashism for "test a = b") "make test-lint-shell-syntax" can be used to run only the check. Helped-By: Jeff King <peff@peff.net> Signed-off-by: Torsten Bögershausen <tboegi@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Torsten Bögershausen committed Jan 3, 2013 at 00:20 UTC c7ce70ace9794a8f0b4774d803536a7ecdf318de
2 files changed +33 -2
t/Makefile
+6 -2
@@ -16,6 +16,7 @@ DEFAULT_TEST_TARGET ?= test
16
17 # Shell quote;
18 SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
19 +PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
20
21 T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
22 TSVN = $(sort $(wildcard t91[0-9][0-9]-*.sh))
@@ -43,7 +44,7 @@ clean-except-prove-cache:
44 clean: clean-except-prove-cache
45 $(RM) .prove
46
46 -test-lint: test-lint-duplicates test-lint-executable
47 +test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax
48
49 test-lint-duplicates:
50 @dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
@@ -55,6 +56,9 @@ test-lint-executable:
56 test -z "$$bad" || { \
57 echo >&2 "non-executable tests:" $$bad; exit 1; }
58
59 +test-lint-shell-syntax:
60 + @'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T)
61 +
62 aggregate-results-and-cleanup: $(T)
63 $(MAKE) aggregate-results
64 $(MAKE) clean
@@ -87,7 +91,7 @@ test-results:
91 mkdir -p test-results
92
93 test-results/git-smoke.tar.gz: test-results
90 - $(PERL_PATH) ./harness \
94 + '$(PERL_PATH_SQ)' ./harness \
95 --archive="test-results/git-smoke.tar.gz" \
96 $(T)
97
t/check-non-portable-shell.pl new
+27
@@ -0,0 +1,27 @@
1 +#!/usr/bin/perl
2 +
3 +# Test t0000..t9999.sh for non portable shell scripts
4 +# This script can be called with one or more filenames as parameters
5 +
6 +use strict;
7 +use warnings;
8 +
9 +my $exit_code=0;
10 +
11 +sub err {
12 + my $msg = shift;
13 + print "$ARGV:$.: error: $msg: $_\n";
14 + $exit_code = 1;
15 +}
16 +
17 +while (<>) {
18 + chomp;
19 + /^\s*sed\s+-i/ and err 'sed -i is not portable';
20 + /^\s*echo\s+-n/ and err 'echo -n is not portable (please use printf)';
21 + /^\s*declare\s+/ and err 'arrays/declare not portable';
22 + /^\s*[^#]\s*which\s/ and err 'which is not portable (please use type)';
23 + /test\s+[^=]*==/ and err '"test a == b" is not portable (please use =)';
24 + # this resets our $. for each file
25 + close ARGV if eof;
26 +}
27 +exit $exit_code;