forked from delsauce/pre-commit-hooks
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
219 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# fw-precommit-hooks | ||
Contains custom hooks for the [pre-commit](https://pre-commit.com/) python package for checking source code. | ||
|
||
## Support | ||
This works with two different tools to format source code with the help of pre-commit: | ||
* [astyle](https://astyle.sourceforge.net/) - an old package that does a pretty decent job, but no longer maintained | ||
* [clang-format](https://clang.llvm.org/docs/ClangFormat.html) - a newer tools that is well supported with lots of formatting options | ||
|
||
## Usage | ||
In order to use this, you need to add a section to your .pre-commit-config.yaml file to get this hook that specifies which of the formatters you want to use and give it a path to the options file(s). You can use either or both `astyle` or `clang-format` | ||
|
||
Here is an example of clang format usage: | ||
``` | ||
- repo: https://github.com/delsauce/pre-commit-hooks | ||
rev: v1.0.0 | ||
hooks: | ||
- id: format-c-source | ||
types: [file, c] | ||
args: [--clangformat, 'path-to-clang-format-options-file'] | ||
``` | ||
|
||
If you'd rather use `astyle` change the args: | ||
``` | ||
args: [--astlye, 'path-to-astyle-options-file'] | ||
``` |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
""" | ||
Version info for this package | ||
""" | ||
__version__ = "1.0.0" |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
""" | ||
This module runs various style tools to format source code files. It is meant to be used | ||
in conjunction with the python module precommit (https://pre-commit.com/) to help enforce | ||
guidelines before code is committed to a git repository. | ||
""" | ||
import os | ||
import subprocess | ||
import argparse | ||
import shutil | ||
import sys | ||
from typing import ( | ||
Optional, | ||
Sequence | ||
) | ||
|
||
def main(argv: Optional[Sequence[str]] = None) -> int: | ||
""" | ||
Format specified text source files | ||
:param argv: list of filenames to process | ||
:return program exit code, 0 = success, > 0 fail (1 for generic error) | ||
""" | ||
|
||
parser = argparse.ArgumentParser() | ||
parser.add_argument( | ||
'filenames', nargs='*', | ||
help='Filenames pre-commit believes are changed.', | ||
) | ||
|
||
# Eventually we can add other tool options here... | ||
parser.add_argument( | ||
'-a', '--astyle', type=str, | ||
help='path to astyle config file', | ||
) | ||
parser.add_argument( | ||
'-c', '--clangformat', type=str, | ||
help='path to clang-format options file', | ||
) | ||
|
||
args = parser.parse_args(argv) | ||
|
||
if not (args.astyle or args.clangformat): | ||
parser.error('No action requested, add --astyle or --clangformat') | ||
|
||
# Bail early if there are no files to process | ||
if len(args.filenames) == 0: | ||
print('No files') | ||
return 0 | ||
|
||
# Note: sourcetree doesn't use the same system path when running commit hooks (there | ||
# is a bug in their tool). We can try to fix that here (not really sure what | ||
# happens on windows -- so not handling that now) | ||
if sys.platform != 'win32': | ||
if '/usr/local/bin' not in os.environ['PATH']: | ||
os.environ['PATH'] += os.pathsep + '/usr/local/bin' | ||
|
||
if args.astyle: | ||
# check to make sure astyle is installed | ||
locate = shutil.which('astyle') | ||
|
||
if locate is None: | ||
print('astyle executable not found on in PATH, is it installed?') | ||
print('Consult your favorite package manager for installation') | ||
print('(e.g. \'brew install astyle\' on mac or \'apt-get install astyle\' on Ubuntu)') | ||
return 1 | ||
|
||
# Check to make sure that options file is present | ||
if not os.path.exists(args.astyle): | ||
print(f'{args.astyle} not found. Please check that the file exists') | ||
return 1 | ||
|
||
# Run astyle | ||
for fname in args.filenames: | ||
# Since check=True below, this will throw an exception if the call | ||
# to astyle fails for some reason. Note, as long as the options and | ||
# filename passed to astyle are OK, it should never fail (always returns | ||
# a '0' whether it formatted a file or not. Need to check the output | ||
# to know if it actually changed anything in the file or not. | ||
astyle_result = subprocess.run(["astyle", | ||
"--options=" + args.astyle, fname], | ||
capture_output=True, text=True, | ||
check=True) | ||
|
||
if 'Formatted' in astyle_result.stdout: | ||
print('Formatted: ' + fname) | ||
|
||
|
||
if args.clangformat: | ||
# check to make sure astyle is installed | ||
locate = shutil.which('clang-format') | ||
|
||
if locate is None: | ||
print('clang-format executable not found on in PATH, is it installed?') | ||
print('Consult your favorite package manager for installation') | ||
print('(e.g. \'brew install clang-format\' on mac or \'apt-get install clang-format\' on Debian/Ubuntu)') | ||
return 1 | ||
|
||
# Check to make sure that options file is present | ||
if not os.path.exists(args.clangformat): | ||
print(f'{args.clangformat} not found. Please check that the file exists') | ||
return 1 | ||
|
||
# Run clang-format | ||
for fname in args.filenames: | ||
# Since check=True below, this will throw an exception if the call | ||
# to clang-format fails for some reason. Note, as long as the options and | ||
# filename passed to clang-format are OK, it should never fail. | ||
|
||
# First do a dry run to see if the file needs formatting or not | ||
# (this is just to support better info being printed during execution) | ||
clang_result = subprocess.run(["clang-format", | ||
"--dry-run", | ||
"--Werror", | ||
"--style=file:" + args.clangformat, | ||
"-i", fname], | ||
capture_output=True, text=True) | ||
|
||
if clang_result.returncode != 0: | ||
# Error code set means the file needs formatting | ||
clang_result = subprocess.run(["clang-format", | ||
"--style=file:" + args.clangformat, | ||
"-i", fname]) | ||
|
||
if clang_result.returncode == 0: | ||
print('Formatted: ' + fname) | ||
else: | ||
print('clang-format can not format file: ' + clang_result.stdout) | ||
return 1 | ||
|
||
return 0 | ||
|
||
|
||
if __name__ == '__main__': | ||
sys.exit(main()) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# No requirements necessary for the module, add to this file if changes needed | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
''' | ||
pip package configuration for embedded c coding standard compliance | ||
''' | ||
import codecs | ||
import os | ||
from setuptools import setup | ||
|
||
# pylint: disable-next=consider-using-with | ||
reqs: list = open("requirements.txt", "r",encoding='utf-8').read().splitlines() | ||
|
||
def read(rel_path): | ||
''' | ||
Supporting function to read the __init__.py file from the package | ||
to get attributes. See get_version() below for more details. | ||
''' | ||
here = os.path.abspath(os.path.dirname(__file__)) | ||
# intentionally *not* adding an encoding option to open, See: | ||
# https://github.com/pypa/virtualenv/issues/201#issuecomment-3145690 | ||
with codecs.open(os.path.join(here, rel_path), 'r') as file_pointer: | ||
return file_pointer.read() | ||
|
||
def get_version(rel_path): | ||
''' | ||
Allows the version of the package to be fetched via the one | ||
stored in the __init__.py file. This enables a single location | ||
to store this information (rather than having to pass it in | ||
with the metadata in the call to setup()) | ||
See here: | ||
https://packaging.python.org/guides/single-sourcing-package-version/ | ||
''' | ||
for line in read(rel_path).splitlines(): | ||
if line.startswith('__version__'): | ||
delim = '"' if '"' in line else "'" | ||
return line.split(delim)[1] | ||
|
||
raise RuntimeError("Unable to find version string.") | ||
|
||
setup(name='pre_commit_hooks', | ||
description='C/C++ File formatting and cleanup per coding standards', | ||
url='https://github.com/delsauce/pre-commit-hooks', | ||
license='MIT', | ||
packages=['pre_commit_hooks'], | ||
zip_safe=False, | ||
version=get_version("hooks/__init__.py"), | ||
entry_points={ | ||
'console_scripts': [ | ||
'format-c-source=hooks.format_c_source:main', | ||
], | ||
}, | ||
|
||
python_requires='>=3.7', | ||
install_requires=reqs | ||
) |