Skip to content
Snippets Groups Projects
Unverified Commit 260d16dd authored by René Fritze's avatar René Fritze
Browse files

adds our clang-format script and config

parent b0888a93
No related branches found
No related tags found
No related merge requests found
config 0 → 100644
# all key value pairs get set in the module local
# git config by dunecontrol
hooks.clangformat clang-format-3.8
#!/usr/bin/env python3
"""
This pre-commit hook checks each staged file if it complies to the
formatting rules, as defined by clang-format (or the programm specified
in `git config hooks.clangformat`).
"""
import os
import subprocess
import sys
import tempfile
CPP_EXTENSIONS = ('.c', '.cc', '.cxx', '.h', '.hh', '.hxx', '.pbh')
class FormatRunException(RuntimeError):
pass
class NonEmptyDiffException(Exception):
pass
def check_dir(basedir, mode='staged'):
"""
:param basedir: absolute path to git root
:param mode: anyof 'staged', 'modified' or 'all' to select which files to check. Note
staged files do not count as modified
:return: list of filename with non-empty diff to current state after applying clang-format
"""
commands = {'staged': ['git', 'diff', '--name-only', '--cached'],
'modified': ['git', 'ls-files', '-m'],
'all': ['git', 'ls-files']}
os.chdir(basedir)
# alternative clang-format binary given?
try:
clangformat = subprocess.check_output(['git', 'config', 'hooks.clangformat'],
universal_newlines=True).strip()
except subprocess.CalledProcessError as _:
clangformat = 'clang-format'
out = subprocess.check_output(commands[mode],
universal_newlines=True)
fails = []
for changed_file in sorted(out.splitlines()):
try:
check_file(changed_file, basedir, clangformat)
except NonEmptyDiffException:
fails.append(changed_file)
return fails
def check_file(touched_file, basedir, format_binary, extension_whitelist=CPP_EXTENSIONS):
if os.path.splitext(touched_file)[1] not in extension_whitelist:
return
filename = os.path.join(basedir, touched_file)
try:
out = subprocess.check_output([format_binary, '-style=file', filename],
universal_newlines=True)
except subprocess.CalledProcessError as e:
raise FormatRunException('Error executing {} on file\n{}'.format(format_binary, filename, e.output))
tmp_filename = tempfile.NamedTemporaryFile(mode='wb', delete=False).name
with open(tmp_filename, 'w') as tmp_file:
tmp_file.write(out)
try:
subprocess.check_output(['diff', filename, tmp_filename],
universal_newlines=True)
except subprocess.CalledProcessError as res:
if res.returncode == 1:
raise NonEmptyDiffException('clang-format has to be applied to \'{}\'!'.format(filename))
raise RuntimeError('error diffing {} vs {}'.format(touched_file, tmp_filename))
finally:
os.remove(tmp_filename)
if __name__ == '__main__':
dirname = os.path.abspath(sys.argv[1] if len(sys.argv) > 1 else os.getcwd())
fails = check_dir(dirname, mode='staged')
if len(fails) > 0:
print('files need to be formatted:\n\t{}'.format('\n\t'.join(fails)) )
sys.exit(len(fails))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment