CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/Tools/gittools/pre-commit.py
Views: 1798
1
#!/usr/bin/env python
2
3
'''
4
A script suitable for use as a git pre-commit hook to ensure your
5
files are flake8-compliant before committing them.
6
7
Use this by copying it to a file called $ARDUPILOT_ROOT/.git/hooks/pre-commit
8
9
AP_FLAKE8_CLEAN
10
'''
11
12
import os
13
import re
14
import sys
15
import subprocess
16
17
18
class AP_PreCommit(object):
19
20
@staticmethod
21
def progress(message):
22
print(f"***** {message}")
23
24
@staticmethod
25
def has_flake8_tag(filepath):
26
with open(filepath) as fp:
27
return "AP_FLAKE8_CLEAN" in fp.read()
28
29
def files_are_flake8_clean(self, files_to_check):
30
if files_to_check:
31
for path in files_to_check:
32
self.progress("Checking (%s)" % path)
33
try:
34
subprocess.check_output(["flake8"] + files_to_check, stderr=subprocess.STDOUT)
35
except subprocess.CalledProcessError as e:
36
self.progress(f"Flake8 check failed: ({e.output})")
37
return False
38
return True
39
40
@staticmethod
41
def split_git_diff_output(output):
42
'''split output from git-diff into a list of (status, filepath) tuples'''
43
ret = []
44
if isinstance(output, bytes):
45
output = output.decode('utf-8')
46
for line in output.split("\n"):
47
if len(line) == 0:
48
continue
49
ret.append(re.split(r"\s+", line))
50
return ret
51
52
def run(self):
53
# generate a list of files which have changes not marked for commit
54
output = subprocess.check_output([
55
"git", "diff", "--name-status"])
56
dirty_list = self.split_git_diff_output(output)
57
dirty = set()
58
for (status, dirty_filepath) in dirty_list:
59
dirty.add(dirty_filepath)
60
61
# check files marked for commit:
62
output = subprocess.check_output([
63
"git", "diff", "--cached", "--name-status"])
64
output_tuples = self.split_git_diff_output(output)
65
files_to_check_flake8 = []
66
for output_tuple in output_tuples:
67
if len(output_tuple) > 2:
68
if output_tuple[0].startswith('R'):
69
# rename, check destination
70
(status, filepath) = (output_tuple[0], output_tuple[2])
71
else:
72
raise ValueError(f"Unknown status {output_tuple[0]}")
73
else:
74
(status, filepath) = output_tuple
75
if filepath in dirty:
76
self.progress("WARNING: (%s) has unstaged changes" % filepath)
77
if status == 'D':
78
# don't check deleted files
79
continue
80
(base, extension) = os.path.splitext(filepath)
81
if extension == ".py" and self.has_flake8_tag(filepath):
82
files_to_check_flake8.append(filepath)
83
if not self.files_are_flake8_clean(files_to_check_flake8):
84
return 1
85
return 0
86
87
88
if __name__ == '__main__':
89
precommit = AP_PreCommit()
90
sys.exit(precommit.run())
91
92