[libcamera-devel] [PATCH 2/2] checkstyle: Add support for pre-commit hook
nicolas at ndufresne.ca
nicolas at ndufresne.ca
Thu Jan 16 19:26:03 CET 2020
From: Nicolas Dufresne <nicolas.dufresne at collabora.com>
This adds support for pre-commit hook workflow. In pre-commit hook we
check the style on the changes currently staged. Note that this patch
also includes a bit of sugar to support --amend.
Signed-off-by: Nicolas Dufresne <nicolas.dufresne at collabora.com>
---
utils/checkstyle.py | 55 +++++++++++++++++++++++++++++-------------
utils/hooks/pre-commit | 16 ++++++++++++
2 files changed, 54 insertions(+), 17 deletions(-)
mode change 100644 => 100755 utils/checkstyle.py
create mode 100755 utils/hooks/pre-commit
diff --git a/utils/checkstyle.py b/utils/checkstyle.py
old mode 100644
new mode 100755
index 7edea25..23eb3f6
--- a/utils/checkstyle.py
+++ b/utils/checkstyle.py
@@ -458,11 +458,16 @@ class StripTrailingSpaceFormatter(Formatter):
# Style checking
#
-def check_file(top_level, commit, filename):
+def check_file(top_level, commit, filename, staged):
# Extract the line numbers touched by the commit.
- diff = subprocess.run(['git', 'diff', '%s~..%s' % (commit, commit), '--',
- '%s/%s' % (top_level, filename)],
- stdout=subprocess.PIPE).stdout
+ if staged:
+ diff = subprocess.run(['git', 'diff', '--staged', commit, '--',
+ '%s/%s' % (top_level, filename)],
+ stdout=subprocess.PIPE).stdout
+ else:
+ diff = subprocess.run(['git', 'diff', '%s~..%s' % (commit, commit), '--',
+ '%s/%s' % (top_level, filename)],
+ stdout=subprocess.PIPE).stdout
diff = diff.decode('utf-8').splitlines(True)
commit_diff = parse_diff(diff)
@@ -476,8 +481,12 @@ def check_file(top_level, commit, filename):
# Format the file after the commit with all formatters and compute the diff
# between the unformatted and formatted contents.
- after = subprocess.run(['git', 'show', '%s:%s' % (commit, filename)],
- stdout=subprocess.PIPE).stdout
+ if staged:
+ after = subprocess.run(['git', 'show', ':%s' % (filename)],
+ stdout=subprocess.PIPE).stdout
+ else:
+ after = subprocess.run(['git', 'show', '%s:%s' % (commit, filename)],
+ stdout=subprocess.PIPE).stdout
after = after.decode('utf-8')
formatted = after
@@ -521,13 +530,20 @@ def check_file(top_level, commit, filename):
return len(formatted_diff) + len(issues)
-def check_style(top_level, commit):
- # Get the commit title and list of files.
- ret = subprocess.run(['git', 'show', '--pretty=oneline','--name-only', commit],
- stdout=subprocess.PIPE)
- files = ret.stdout.decode('utf-8').splitlines()
- title = files[0]
- files = files[1:]
+def check_style(top_level, commit, staged):
+ if staged:
+ # Get list of staged changed files
+ ret = subprocess.run(['git', 'diff', '--staged', '--name-only', commit],
+ stdout=subprocess.PIPE)
+ files = ret.stdout.decode('utf-8').splitlines()
+ title = "Pre-commit"
+ else:
+ # Get the commit title and list of files.
+ ret = subprocess.run(['git', 'show', '--pretty=oneline', '--name-only', commit],
+ stdout=subprocess.PIPE)
+ files = ret.stdout.decode('utf-8').splitlines()
+ title = files[0]
+ files = files[1:]
separator = '-' * len(title)
print(separator)
@@ -541,11 +557,11 @@ def check_style(top_level, commit):
files = [f for f in files if len([p for p in patterns if fnmatch.fnmatch(os.path.basename(f), p)])]
if len(files) == 0:
print("Commit doesn't touch source files, skipping")
- return
+ return 0
issues = 0
for f in files:
- issues += check_file(top_level, commit, f)
+ issues += check_file(top_level, commit, f, staged)
if issues == 0:
print("No style issue detected")
@@ -554,6 +570,8 @@ def check_style(top_level, commit):
print("%u potential style %s detected, please review" % \
(issues, 'issue' if issues == 1 else 'issues'))
+ return issues
+
def extract_revlist(revs):
"""Extract a list of commits on which to operate from a revision or revision
@@ -595,6 +613,8 @@ def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument('--formatter', '-f', type=str, choices=['astyle', 'clang-format'],
help='Code formatter. Default to clang-format if not specified.')
+ parser.add_argument('--staged', '-s', action='store_true',
+ help='Looks at the staged changes, used for pre-commit, defaults to False')
parser.add_argument('revision_range', type=str, default='HEAD', nargs='?',
help='Revision range (as defined by git rev-parse). Defaults to HEAD if not specified.')
args = parser.parse_args(argv[1:])
@@ -632,11 +652,12 @@ def main(argv):
revlist = extract_revlist(args.revision_range)
+ issues = 0
for commit in revlist:
- check_style(top_level, commit)
+ issues += check_style(top_level, commit, args.staged)
print('')
- return 0
+ return issues
if __name__ == '__main__':
diff --git a/utils/hooks/pre-commit b/utils/hooks/pre-commit
new file mode 100755
index 0000000..57d23ef
--- /dev/null
+++ b/utils/hooks/pre-commit
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Execute the checkstyle script before committing any code, failing the commit
+# if needed. With this workflow, false positive can be ignored using:
+# git commit -n
+#
+# To utilise this hook, install this file with:
+# cp utils/hooks/pre-commit .git/hooks/pre-commit
+
+commit=
+if ps -ocommand= -p $PPID | grep -- "--amend"
+then
+ commit="HEAD~"
+fi
+
+./utils/checkstyle.py --staged $commit
--
2.24.1
More information about the libcamera-devel
mailing list