-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclang-format.py
executable file
·168 lines (135 loc) · 4.43 KB
/
clang-format.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#!/usr/bin/env python3
# encoding=utf-8
import os
import subprocess
import posixpath
import threading
from typing import List
class Encoding:
UTF8 = 'utf-8'
UTF8_WITH_BOM = 'utf-8-sig'
UTF16 = 'utf-16'
GB2312 = 'gb2312'
SHIFT_JIS = 'shift-jis'
@classmethod
def decode(cls, bs: bytes):
try:
encoding = cls.UTF8_WITH_BOM
decoded_content = bs.decode(encoding)
return encoding, decoded_content
except Exception as ex:
# traceback.print_exc()
pass
try:
encoding = cls.UTF8
decoded_content = bs.decode(encoding)
return encoding, decoded_content
except Exception as ex:
# traceback.print_exc()
pass
try:
encoding = cls.UTF16
decoded_content = bs.decode(encoding)
return encoding, decoded_content
except Exception as ex:
# traceback.print_exc()
pass
try:
encoding = cls.GB2312
decoded_content = bs.decode(encoding)
return encoding, decoded_content
except Exception as ex:
# traceback.print_exc()
pass
try:
encoding = cls.SHIFT_JIS
decoded_content = bs.decode(encoding)
return encoding, decoded_content
except Exception as ex:
# traceback.print_exc()
pass
return None, bs
SUPPORTED_EXTENSIONS = [
'.h',
'.c',
'.cc',
'.cpp',
'.c++',
'.java',
]
def is_supported_file(path: str):
_, ext = posixpath.splitext(path)
ext = ext.lower()
if ext in SUPPORTED_EXTENSIONS:
return True
else:
return False
def convert_string(bytes_input: bytes):
encoding, s = Encoding.decode(bytes_input)
if encoding == None:
return str(bytes_input)
else:
return s
class Command:
def __init__(self, cmd: List[str]):
self.cmd = cmd
# type is hinted implicitly (subprocess.Popen)
self.p = None
# The process is terminated by us because it took too long.
# If this flag is True then the output is broken.
self.terminated = False
self.stdout = None
self.stderr = None
def target(self):
print('>', ' '.join(self.cmd))
self.process = subprocess.Popen(
self.cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
self.stdout, self.stderr = self.process.communicate()
def run(self, timeout=5, raise_on_error=True):
thread = threading.Thread(target=self.target)
thread.start()
thread.join(timeout)
if thread.is_alive():
self.terminated = True
self.process.terminate()
# TODO Will call block our main thread for a long time?
thread.join()
if raise_on_error:
if self.terminated:
raise Exception(
f'The process is terminated because it took too long to excute!\n'
f'{convert_string(self.process.stderr)}'
)
if self.process.returncode != 0:
raise Exception(f'')
# if self.stdout is not None:
# output = convert_string(self.stdout)
# print(output)
if __name__ == '__main__':
completed_process = subprocess.run(
['git', 'ls-files'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
lines = completed_process.stdout.decode('utf-8').split('\n')
filepaths = filter(lambda x: len(x) > 0, lines)
filepaths = filter(lambda x: os.path.exists(x), filepaths)
filepaths = filter(lambda x: os.path.isfile(x), filepaths)
filepaths = filter(is_supported_file, filepaths)
filepaths = list(filepaths)
print(filepaths)
for filepath in filepaths:
file_content = Encoding.decode(open(filepath, mode='rb').read())
# TODO check for .clang-format file existence
cmd = ['clang-format', '-style=file', filepath]
sp = Command(cmd)
sp.run()
if sp.stdout is not None:
clang_formatted_content = convert_string(sp.stdout)
# TODO add 'check' or 'format' flags
if file_content != clang_formatted_content:
utf8_encoded_content = clang_formatted_content.encode('utf-8')
open(filepath, mode='wb').write(utf8_encoded_content)