Skip to content

Instantly share code, notes, and snippets.

@acdha
Last active April 18, 2024 02:22
Show Gist options
  • Save acdha/8717683 to your computer and use it in GitHub Desktop.
Save acdha/8717683 to your computer and use it in GitHub Desktop.
Git pre-commit hook which runs various code linters. Install this to .git/hooks/pre-commit inside your favorite repos
#!/usr/bin/env PYTHONIOENCODING=utf-8 python
# encoding: utf-8
"""Git pre-commit hook which lints Python, JavaScript, SASS and CSS"""
from __future__ import absolute_import, print_function, unicode_literals
import os
import subprocess
import sys
FS_ENCODING = sys.getfilesystemencoding()
def check_linter(cmd, files, **kwargs):
if not files:
return
print('Running %s' % cmd[0])
return subprocess.check_output(cmd + files, stderr=subprocess.STDOUT, **kwargs).decode(FS_ENCODING)
def filter_ext(extension, files, exclude=None):
files = [f for f in files if f.endswith(extension)]
if exclude is not None:
files = [i for i in files if exclude not in i]
return files
def lint_files(changed_files):
changed_files = [i.strip() for i in changed_files.splitlines() if '/external/' not in i]
changed_extensions = {ext for root, ext in map(os.path.splitext, changed_files)}
if '.py' in changed_extensions:
py_files = filter_ext('.py', changed_files)
check_linter(['frosted'], py_files)
check_linter(['isort', '-c'], py_files)
if '.js' in changed_extensions:
check_linter(['eslint'], filter_ext('.js', changed_files, exclude='.min.'))
if '.scss' in changed_extensions:
try:
check_linter(['scss-lint'], filter_ext('.scss', changed_files))
except subprocess.CalledProcessError as exc:
if exc.returncode == 1:
# scss-lint rc=1 means no message more severe than a warning
pass
else:
raise
if '.css' in changed_extensions:
check_linter(['csslint'], filter_ext('.css', changed_files, exclude='.min.'))
if __name__ == "__main__":
os.chdir(os.path.join(os.path.dirname(__file__), '..', '..'))
changed_files = subprocess.check_output('git diff --cached --name-only --diff-filter=ACM'.split())
changed_files = changed_files.decode(FS_ENCODING)
try:
lint_files(changed_files)
except subprocess.CalledProcessError as exc:
print('Quality check failed:', file=sys.stderr)
print(' '.join(exc.cmd), file=sys.stderr)
if exc.output:
output = exc.output.decode(FS_ENCODING)
print('\t', '\n\t'.join(output.splitlines()), sep='', file=sys.stderr)
sys.exit(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment