pre-commit: Avoid launching python subprocesses.

This makes Python required only for (portable) fnmatch().

Change the ignore script to work as a filter.

Multi-platform improvements.

Change-Id: I6ac757d48ba2ff965da5da3dc9c25047a0e37f92
Reviewed-on: https://code.wireshark.org/review/13693
Reviewed-by: Michael Mann <mmann78@netscape.net>
Reviewed-by: João Valverde <j@v6e.pt>
This commit is contained in:
João Valverde 2016-01-30 03:49:41 +00:00 committed by João Valverde
parent fd9e71d15d
commit fe1de0146e
4 changed files with 63 additions and 53 deletions

View File

@ -169,6 +169,8 @@ EXTRA_DIST = \
parse_xml2skinny_dissector.py \
pkt-from-core.py \
pre-commit \
pre-commit-ignore.conf \
pre-commit-ignore.py \
process-x11-fields.pl \
process-x11-xcb.pl \
randpkt-test.sh \

View File

@ -19,12 +19,22 @@
# If the commit identifier is not given, use HEAD instead.
COMMIT_ID="${1:-HEAD}"
UNAME=`uname -o`
case "$UNAME" in
Msys)
pyvar="pythonw.exe"
;;
*)
pyvar="python"
;;
esac
PYBIN=${WS_GITHOOK_PYTHON:-$pyvar}
# Path to hook script in the .git directory
hook_script=${GIT_DIR:-.git}/hooks/pre-commit
# Path to check script in the tools directory
check_script=./tools/pre-commit-check.py
# Always start in the root directory of the source tree, this allows for
# invocations via relative paths (such as ../tools/pre-commit):
cd "$(git rev-parse --show-toplevel)"
@ -37,14 +47,41 @@ fi
exit_status=0
if [ -e "$check_script" ]
then
python "$check_script" ${COMMIT_ID} || exit_status=1
else
echo "File '$check_script' not found. Aborting."
COMMIT_FILES=`git diff-index --cached --name-status ${COMMIT_ID} | grep -v "^D" | cut -f2 | grep "\.[ch]$"`
# Path to filter script in the tools directory
filter_script=${PWD}/tools/pre-commit-ignore.py
filter_conf=${PWD}/tools/pre-commit-ignore.conf
if [ ! -e "$filter_script" ]; then
echo "File '$filter_script' does not exist. Aborting."
exit 1
fi
CHECK_FILES=`echo "$COMMIT_FILES" | "$PYBIN" "$filter_script" "$filter_conf"`
if [ $? -ne 0 ]; then
exit 1
fi
# On windows python will output \r\n line endings - we don't want that
CHECK_FILES=`echo "$CHECK_FILES" | sed 's/\r//g'`
for FILE in $CHECK_FILES; do
#Check if checkhf is good
./tools/checkhf.pl $FILE || exit_status=1
#Check if checkAPIs is good
./tools/checkAPIs.pl -p $FILE || exit_status=1
#Check if fix-encoding-args is good
./tools/fix-encoding-args.pl $FILE || exit_status=1
#Check if checkfiltername is good
./tools/checkfiltername.pl $FILE || exit_status=1
done
# If there are whitespace errors, print the offending file names and fail. (from git pre-commit.sample)
git diff-index --check --cached ${COMMIT_ID} || exit_status=1

View File

@ -4,7 +4,7 @@
# Each line is compared against the output of 'git diff-index --name-only'.
# For example to skip checking this file add:
#
# tools/pre-commit-check.conf
# tools/pre-commit-ignore.conf
#
# The pathname wildcards allowed are: '*', '?', character set '[abc]' or
# negated with '[!abc]'.

View File

@ -20,24 +20,18 @@
import sys
import os
import re
import fnmatch
import filecmp
TOOLS_DIR = "tools"
CHECK_CONF = "pre-commit-check.conf"
CHECK_LIST = ["checkhf.pl", "checkAPIs.pl -p", "fix-encoding-args.pl", "checkfiltername.pl"]
IGNORE_CONF = "pre-commit-ignore.conf"
if len(sys.argv) > 2:
print("Usage: {0} [COMMIT]".format(sys.argv[0]))
print("Usage: {0} [path/to/ignore.conf]".format(sys.argv[0]))
sys.exit(1)
# If the commit identifier is not given, use HEAD instead.
if len(sys.argv) == 2:
COMMIT_ID = sys.argv[1]
ignore_path = sys.argv[1]
else:
COMMIT_ID = "HEAD"
ignore_path = IGNORE_CONF
# Function to load our patterns from 'path' for modified files
# to be ignored (skipping any comments)
@ -46,47 +40,24 @@ def load_checkignore(path):
with open(path) as f:
patterns = f.read()
except OSError as err:
print("'" + path + "':", str(err))
print(str(err))
return []
ign = [l.strip() for l in patterns.splitlines()]
ign = [l for l in ign if l and not l.startswith("#")]
return ign
IGNORE_LIST = load_checkignore(os.path.join(TOOLS_DIR, CHECK_CONF))
ignore_list = load_checkignore(ignore_path)
# Run git-diff index and process/filter output
def run_diff_index():
ret = []
with os.popen("git diff-index --cached --name-status " + COMMIT_ID) as p:
diff = p.read()
for l in diff.splitlines():
l = l.lstrip()
if l.startswith("D"):
continue
l = l.split()
f = l[1].strip()
if not re.search("\.[ch]$", f):
continue
for pattern in IGNORE_LIST:
if fnmatch.fnmatchcase(f, pattern):
f = None
break
if f:
ret.append(f)
return ret
def ignore_match(f):
for p in ignore_list:
if fnmatch.fnmatchcase(f, p):
return True
return False
exit_status = 0
# For each valid modified file run our checks
for f in run_diff_index():
for c in CHECK_LIST:
script = os.path.join(TOOLS_DIR, c)
cmd = "perl {0} {1}".format(script, f)
ret = os.system(cmd)
if ret != 0:
exit_status = 1
sys.exit(exit_status)
for line in sys.stdin:
line = line.strip()
if not ignore_match(line):
print(line)
#
# Editor modelines