Created
December 24, 2011 18:19
-
-
Save mjallday/1518000 to your computer and use it in GitHub Desktop.
git pre-commit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
for f in crystal knox pound poundpay-python poundweb precog sterling | |
do | |
ln -s ~/code/poundpay/pre-commit $f/.git/hooks/pre-commit | |
done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
""" | |
A pre-commit hook for git that uses Pylint for automated code review. | |
If any python file's rating falls below the ``PYLINT_PASS_THRESHOLD``, this | |
script will return nonzero and the commit will be rejected. | |
This script must be located at ``$REPO/.git/hooks/pre-commit`` and be | |
executable. | |
Copyright 2009 Nick Fitzgerald - MIT Licensed. | |
""" | |
import os | |
import re | |
import sys | |
from subprocess import Popen, PIPE | |
# Threshold for code to pass the Pylint test. 10 is the highest score Pylint | |
# will give to any peice of code. | |
PYLINT_PASS_THRESHOLD = 7 | |
# Lives at poundwebroot/.pylintrc by default | |
PYLINT_RC = '.pylintrc' | |
def pylint(): | |
"""Checks your git commit with Pylint!""" | |
# Run the git command that gets the filenames of every file that has been | |
# locally modified since the last commit. | |
sub = Popen("git diff --staged --name-only HEAD".split(), | |
stdout=PIPE) | |
sub.wait() | |
# Filter out non-python or deleted files. | |
py_files_changed = [file | |
for file in [f.strip() for f in sub.stdout.readlines()] | |
if (file.endswith(".py") and os.path.exists(file)) | |
or is_py_script(file)] | |
# Run Pylint on each file, collect the results, and display them for the | |
# user. | |
results = {} | |
for file in py_files_changed: | |
pylint = Popen(("pylint --rcfile={} -f text {}".format(PYLINT_RC, | |
file)).split(), | |
stdout=PIPE) | |
pylint.wait() | |
output = pylint.stdout.read() | |
print output | |
results_re = re.compile(r"Your code has been rated at ([\d\.]+)/10") | |
results[file] = float(results_re.findall(output)[0]) | |
# Display a summary of the results (if any files were checked). | |
if len(results.values()) > 0: | |
print "===============================================" | |
print "Final Results:" | |
for file in results: | |
result = results[file] | |
grade = "FAIL" if result < PYLINT_PASS_THRESHOLD else "pass" | |
print "[ %s ] %s: %.2f/10" % (grade, file, result) | |
# If any of the files failed the Pylint test, exit nonzero and stop the | |
# commit from continuing. | |
if any([(result < PYLINT_PASS_THRESHOLD) | |
for result in results.values()]): | |
print "git: fatal: commit failed, Pylint tests failing." | |
sys.exit(1) | |
def run_tests(): | |
nose = Popen("nosetests".split(), stdout=PIPE) | |
nose.wait() | |
output = nose.stdout.read() | |
if nose.returncode: | |
print "Unit tests failed, quitting..." | |
sys.exit(1) | |
def pep8(): | |
pep8 = Popen("pep8 .".split(), stdout=PIPE) | |
pep8.wait() | |
output = pep8.stdout.read() | |
if pep8.returncode: | |
print("Pep8 errors, quitting...") | |
print output | |
sys.exit(1) | |
def is_py_script(filename): | |
"""Returns True if a file is a python executable.""" | |
if not os.access(filename, os.X_OK): | |
return False | |
else: | |
try: | |
first_line = open(filename, "r").next().strip() | |
return "#!" in first_line and "python" in first_line | |
except StopIteration: | |
return False | |
if __name__ == "__main__": | |
pep8() | |
pylint() | |
run_tests() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
+1