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>
This commit is contained in:
Torsten Bögershausen 2013-01-03 00:20:19 +01:00 committed by Junio C Hamano
parent 5d417842ef
commit c7ce70ace9
2 changed files with 33 additions and 2 deletions

View file

@ -16,6 +16,7 @@ DEFAULT_TEST_TARGET ?= test
# Shell quote;
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
TSVN = $(sort $(wildcard t91[0-9][0-9]-*.sh))
@ -43,7 +44,7 @@ clean-except-prove-cache:
clean: clean-except-prove-cache
$(RM) .prove
test-lint: test-lint-duplicates test-lint-executable
test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax
test-lint-duplicates:
@dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
@ -55,6 +56,9 @@ test-lint-executable:
test -z "$$bad" || { \
echo >&2 "non-executable tests:" $$bad; exit 1; }
test-lint-shell-syntax:
@'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T)
aggregate-results-and-cleanup: $(T)
$(MAKE) aggregate-results
$(MAKE) clean
@ -87,7 +91,7 @@ test-results:
mkdir -p test-results
test-results/git-smoke.tar.gz: test-results
$(PERL_PATH) ./harness \
'$(PERL_PATH_SQ)' ./harness \
--archive="test-results/git-smoke.tar.gz" \
$(T)

27
t/check-non-portable-shell.pl Executable file
View file

@ -0,0 +1,27 @@
#!/usr/bin/perl
# Test t0000..t9999.sh for non portable shell scripts
# This script can be called with one or more filenames as parameters
use strict;
use warnings;
my $exit_code=0;
sub err {
my $msg = shift;
print "$ARGV:$.: error: $msg: $_\n";
$exit_code = 1;
}
while (<>) {
chomp;
/^\s*sed\s+-i/ and err 'sed -i is not portable';
/^\s*echo\s+-n/ and err 'echo -n is not portable (please use printf)';
/^\s*declare\s+/ and err 'arrays/declare not portable';
/^\s*[^#]\s*which\s/ and err 'which is not portable (please use type)';
/test\s+[^=]*==/ and err '"test a == b" is not portable (please use =)';
# this resets our $. for each file
close ARGV if eof;
}
exit $exit_code;