forked from scipy/scipy
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathpre-commit-hook.py
executable file
·101 lines (77 loc) · 3.17 KB
/
pre-commit-hook.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/env python
#
# Pre-commit linting hook.
#
# Install from root of repository with:
#
# cp tools/pre-commit-hook.py .git/hooks/pre-commit
import subprocess
import sys
import os
# Run lint.py from the scipy source tree
linters = [
'../../tools/lint.py',
'tools/lint.py',
'lint.py' # in case pre-commit hook is run from tools dir
]
linter = [f for f in linters if os.path.exists(f)][0]
unicode_checks = [
'../../tools/unicode-check.py',
'tools/unicode-check.py',
'unicode-check.py' # in case pre-commit hook is run from tools dir
]
unicode_check = [f for f in unicode_checks if os.path.exists(f)][0]
# names of files that were staged
# add '*.pxd', '*.pxi' once cython-lint supports it
p = subprocess.run(['git', 'diff',
'--cached', '--name-only', '-z',
'--diff-filter=ACMR',
'--', '*.py', '*.pyx'],
capture_output=True, check=True)
files = p.stdout.decode(sys.getfilesystemencoding()).split('\0')
files = [f for f in files if f]
# create a temporary copy of what would get committed, without unstaged
# modifications (e.g., only certain changes in a file may have been committed)
git_dir = os.environ.get('GIT_DIR', '.git')
work_dir = os.path.join(git_dir, '.pre-commit-work_dir')
p = subprocess.run(['git', 'write-tree'], capture_output=True, check=True)
tree_hash = p.stdout.decode('ascii').split('\n')[0]
p = subprocess.run(['git', 'commit-tree', '-p', 'HEAD',
tree_hash, '-m', '...'], capture_output=True, check=True)
fake_commit = p.stdout.decode('ascii').split('\n')[0]
if not os.path.isdir(work_dir):
subprocess.run(['git', 'clone', '-qns', git_dir, work_dir])
subprocess.run(['git', 'reset', '--quiet', '--hard', 'HEAD'],
env={}, cwd=work_dir, check=True)
subprocess.run(['git', 'checkout', '-q', fake_commit],
env={}, cwd=work_dir, check=True)
subprocess.run(['git', 'reset', '--quiet', '--hard', fake_commit],
env={}, cwd=work_dir, check=True)
if '--fix' in sys.argv:
print('Running linter to fix errors...')
p = subprocess.run([linter, '--fix', '--files'] + files)
# Discover which files were modified
p = subprocess.run([linter, '--fix', '--files'] + files, cwd=work_dir)
p = subprocess.run(['git', 'diff', '--name-only', '--', '*.py', '*.pyx'],
capture_output=True, check=True, cwd=work_dir)
files = p.stdout.decode(sys.getfilesystemencoding()).split('\0')
files = [f for f in files if f]
if files:
print('The following files were modified:')
print()
print('\n'.join(files))
else:
print('No files were modified.\n')
print('Please remember to `git add` modified files.')
sys.exit(p.returncode)
p = subprocess.run([linter, '--files'] + files, cwd=work_dir)
if p.returncode != 0:
print('!! Linting failed; please fix errors, `git add` files, and re-commit.')
print()
print('Some errors may be fixable automatically by running:')
print()
print(' ./tools/pre-commit-hook.py --fix')
sys.exit(p.returncode)
p = subprocess.run(unicode_check, cwd=work_dir)
if p.returncode != 0:
sys.exit(p.returncode)