Skip to content

Instantly share code, notes, and snippets.

@jbylund
Last active June 5, 2022 14:46
Show Gist options
  • Save jbylund/2bfde62b0bc7a5261747 to your computer and use it in GitHub Desktop.
Save jbylund/2bfde62b0bc7a5261747 to your computer and use it in GitHub Desktop.
pre-commit
#!/usr/bin/python
import subprocess
import os
import json
import sys
def get_staged_files():
return subprocess.check_output("git diff --cached --name-only".split()).strip().split('\n')
class Check(object):
def __init__(self, filetype=None, check_command=None):
self.filetype = filetype
self.check_command = check_command
def check_file(self, ifilename):
exit_code = 0
exit_code |= self.check_trailing_whitespace(ifilename)
exit_code |= self.check_filesize(ifilename)
if self.check_command is not None:
dev_null = open(os.devnull, 'w')
check_command = self.check_command.format(ifilename).split()
check_process = subprocess.Popen(check_command, stderr=subprocess.PIPE, stdout=dev_null)
if check_process.wait() != 0:
print >> sys.stderr, """ERROR: "{}" is not valid {}""".format(ifilename, self.filetype)
print >> sys.stderr, check_process.stderr.read().strip()
print >> sys.stderr
exit_code |= 1
if 'python' == self.filetype: # cleanup for python files
compiled_name = "{}c".format(ifilename)
os.path.exists(compiled_name) and os.remove(compiled_name)
return exit_code
def check_trailing_whitespace(self, ifilename):
exit_code = 0
with open(ifilename) as infile:
for lineno, line in enumerate(infile):
line = line.rstrip('\n\r')
if line != line.rstrip():
print """ERROR: Trailing whitespace in "{}", at line {}.""".format(infile.name, lineno + 1)
exit_code = 1
return exit_code
def check_filesize(self, ifilename):
if os.stat(ifilename).st_size > 545048:
print >> sys.stderr, """ERROR: "{}" is larger than 5mb, it's probably not code (at the very least it should be modularized).""".format(ifilename)
return 1
return 0
class FileChecker(object):
checks = {
'py': Check(filetype='python', check_command="python -m py_compile {}"),
'php': Check(filetype='php', check_command="php -l {}"),
'json': Check(filetype='json', check_command="python -m json.tool {}"),
'bash': Check(filetype='bash', check_command="bash -n {}"),
'sh': Check(filetype='bash', check_command="bash -n {}")
}
def check_file(self, ifilename):
_, _, extension = ifilename.rpartition('.')
checker = self.checks.get(extension, Check())
return checker.check_file(ifilename)
def main():
staged_files = get_staged_files()
exit_code = 0
filechecker = FileChecker()
for ifile in staged_files:
if not os.path.isfile(ifile):
continue
try:
exit_code |= filechecker.check_file(ifile)
except Exception as oops:
print >> sys.stderr, """WARNING: Check logic failed on "{}".""".format(ifile), oops
if exit_code:
print >> sys.stderr, "ERROR: Rejecting this commit, please fix issues and try again."
sys.exit(exit_code)
if "__main__" == __name__:
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment