Merge lp:~widelands-dev/widelands/automate_clang-format into lp:widelands
- automate_clang-format
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 8200 |
Proposed branch: | lp:~widelands-dev/widelands/automate_clang-format |
Merge into: | lp:widelands |
Diff against target: |
401 lines (+171/-123) 3 files modified
utils/fix_formatting.py (+48/-16) utils/merge_and_push_translations.sh (+10/-0) utils/update_authors.py (+113/-107) |
To merge this branch: | bzr merge lp:~widelands-dev/widelands/automate_clang-format |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
SirVer | Approve | ||
GunChleoc | Needs Resubmitting | ||
Review via email: mp+312287@code.launchpad.net |
Commit message
Moved utils/fix_
Description of the change
I think it would be a good idea to automate clang-format - it is starting to cost me real time when I work on a branch and trunk hasn't been formatted properly.
Can this be added to the bunnybot merge command once we have this in trunk? I'm thinking bzr merge, clang-format, bzr commit here.
bunnybot (widelandsofficial) wrote : | # |
SirVer (sirver) wrote : | # |
> Can this be added to the bunnybot merge command once we have this in trunk? I'm thinking bzr merge, clang-format, bzr commit here.
Yes, it probably can. If I can figure out how to install clang-format on the buildbot. I'll have a look.
A couple of nits inlined.
GunChleoc (gunchleoc) wrote : | # |
Thanks - all fixed.
I was just thinking - we also have fix_lua_tabs.py, which is run when we update the translations.
How about having 1 central script "fix_formating.py" that does the following:
- fix_lua_tabs.py
- run_clang_format.py
- run pyformat over utils.
This script could then be called both by merge_and_
SirVer (sirver) wrote : | # |
Sgtm.
> Am 03.12.2016 um 14:39 schrieb GunChleoc <email address hidden>:
>
> Thanks - all fixed.
>
> I was just thinking - we also have fix_lua_tabs.py, which is run when we update the translations.
>
> How about having 1 central script "fix_formating.py" that does the following:
>
> - fix_lua_tabs.py
> - run_clang_format.py
> - run pyformat over utils.
>
> This script could then be called both by merge_and_
> --
> https:/
> You are requested to review the proposed merge of lp:~widelands-dev/widelands/automate_clang-format into lp:widelands.
GunChleoc (gunchleoc) wrote : | # |
Will do that in this branch then.
GunChleoc (gunchleoc) wrote : | # |
Done. Never mind the big diff for udate_authors.py, the relevant bit is the removed call at the bottom. Pyformat already in action here ;)
SirVer (sirver) wrote : | # |
pretty hard to review this diff with the formatting changes. I found two nits, I think otherwise this is ready to merge.
GunChleoc (gunchleoc) wrote : | # |
Thanks for the review!
So, pyformat doesn't fix long lines, need to keep that in mind.
@bunnybot merge
Preview Diff
1 | === renamed file 'utils/fix_lua_tabs.py' => 'utils/fix_formatting.py' |
2 | --- utils/fix_lua_tabs.py 2015-10-31 12:11:44 +0000 |
3 | +++ utils/fix_formatting.py 2016-12-04 06:44:59 +0000 |
4 | @@ -2,29 +2,38 @@ |
5 | # -*- coding: utf-8 -*- |
6 | |
7 | |
8 | -"""The code base had inconsistent usage of tabs/spaces for indenting in Lua |
9 | +"""The code base had inconsistent usage of tabs/spaces for indenting in Lua. |
10 | + |
11 | files. Spaces were more prominent - and I prefer them over tabs. So I wrote |
12 | this small script to fix leading tabs in Lua files to spaces. |
13 | |
14 | It also saves files in unix file endings ("\r\n") and strips empty lines at the |
15 | end of files and whitespace characters at the end of lines. |
16 | + |
17 | +After fixing the Lua tabs, this script also executes clang-format over the src |
18 | +directory and pyformat over the utils directory. |
19 | + |
20 | """ |
21 | |
22 | import argparse |
23 | import os |
24 | import re |
25 | import sys |
26 | +from subprocess import call |
27 | |
28 | LEADING_TABS = re.compile(r'^\s*\t+\s*') |
29 | PYTHON3 = sys.version_info >= (3, 0) |
30 | SPACES_PER_TAB = 3 |
31 | |
32 | + |
33 | def parse_args(): |
34 | - p = argparse.ArgumentParser(description= |
35 | - "Fix common whitespace errors in Lua files. Recurses over all Lua files." |
36 | - ) |
37 | + p = argparse.ArgumentParser( |
38 | + description='Fix common whitespace errors in Lua files, run clang-format' |
39 | + ' over the code base and pyformat over the utils directory.' |
40 | + ' Recurses over all relevant files.') |
41 | return p.parse_args() |
42 | |
43 | + |
44 | def read_text_file(filename): |
45 | """Reads the contens of a text file.""" |
46 | if PYTHON3: |
47 | @@ -32,6 +41,7 @@ |
48 | else: |
49 | return open(filename, 'r').read().decode('utf-8') |
50 | |
51 | + |
52 | def write_text_file(filename, content): |
53 | """Writes 'content' into a text file.""" |
54 | if PYTHON3: |
55 | @@ -39,30 +49,52 @@ |
56 | else: |
57 | open(filename, 'w').write(content.encode('utf-8')) |
58 | |
59 | -def find_lua_files(): |
60 | - for (dirpath, _, filenames) in os.walk("."): |
61 | + |
62 | +def find_files(startpath, extensions): |
63 | + for (dirpath, _, filenames) in os.walk(startpath): |
64 | for filename in filenames: |
65 | - if os.path.splitext(filename)[-1].lower() == ".lua": |
66 | + if os.path.splitext(filename)[-1].lower() in extensions: |
67 | yield os.path.join(dirpath, filename) |
68 | |
69 | + |
70 | def main(): |
71 | parse_args() |
72 | |
73 | - if not os.path.isdir("src") or not os.path.isdir("utils"): |
74 | - print("CWD is not the root of the repository.") |
75 | + if not os.path.isdir('src') or not os.path.isdir('utils'): |
76 | + print('CWD is not the root of the repository.') |
77 | return 1 |
78 | |
79 | - for filename in find_lua_files(): |
80 | - print "Fixing %r" % filename |
81 | - lines = read_text_file(filename).strip().split("\n") |
82 | + sys.stdout.write('Fixing Lua tabs ') |
83 | + for filename in find_files('.', ['.lua']): |
84 | + sys.stdout.write('.') |
85 | + sys.stdout.flush() |
86 | + lines = read_text_file(filename).strip().split('\n') |
87 | new_lines = [] |
88 | for line in lines: |
89 | m = LEADING_TABS.match(line) |
90 | if m is not None: |
91 | - line = line[m.start():m.end()].expandtabs(SPACES_PER_TAB) + line[m.end():] |
92 | - new_lines.append(line.rstrip() + "\n") |
93 | - write_text_file(filename, "".join(new_lines)) |
94 | + line = line[m.start():m.end()].expandtabs( |
95 | + SPACES_PER_TAB) + line[m.end():] |
96 | + new_lines.append(line.rstrip() + '\n') |
97 | + write_text_file(filename, ''.join(new_lines)) |
98 | + print(' done.') |
99 | + |
100 | + sys.stdout.write('\nFormatting C++ ') |
101 | + for filename in find_files('./src', ['.cc', '.h']): |
102 | + sys.stdout.write('.') |
103 | + sys.stdout.flush() |
104 | + call(['clang-format', '-i', filename]) |
105 | + print(' done.') |
106 | + |
107 | + sys.stdout.write('\nFormatting Python utils ') |
108 | + for filename in find_files('./utils', ['.py']): |
109 | + sys.stdout.write('.') |
110 | + sys.stdout.flush() |
111 | + call(['pyformat', '-i', filename]) |
112 | + print(' done.') |
113 | + |
114 | + print 'Formatting finished.' |
115 | return 0 |
116 | |
117 | -if __name__ == "__main__": |
118 | +if __name__ == '__main__': |
119 | sys.exit(main()) |
120 | |
121 | === modified file 'utils/merge_and_push_translations.sh' |
122 | --- utils/merge_and_push_translations.sh 2016-07-25 11:47:16 +0000 |
123 | +++ utils/merge_and_push_translations.sh 2016-12-04 06:44:59 +0000 |
124 | @@ -57,6 +57,16 @@ |
125 | exit 1; |
126 | fi |
127 | |
128 | +# Fix formatting |
129 | +utils/fix_formatting.py |
130 | +if [ $? -eq 0 ] |
131 | +then |
132 | + echo "Fixed formatting"; |
133 | +else |
134 | + echo "Failed to fix formatting"; |
135 | + exit 1; |
136 | +fi |
137 | + |
138 | # Fix line breaks. |
139 | # TODO(GunChleoc): We hope that Transifex will fix these already. |
140 | # This script can be removed if we don't get any errors in the future. |
141 | |
142 | === modified file 'utils/update_authors.py' |
143 | --- utils/update_authors.py 2016-11-12 17:59:50 +0000 |
144 | +++ utils/update_authors.py 2016-12-04 06:44:59 +0000 |
145 | @@ -13,25 +13,26 @@ |
146 | # and writes the translator and developer credits to ./txts/developers.lua |
147 | # The locale information is written to ../data/i18n/locales.lua. |
148 | |
149 | -base_path = os.path.abspath(os.path.join(os.path.dirname(__file__),os.path.pardir)) |
150 | - |
151 | -print("Reading locales from JSON:") |
152 | - |
153 | -source_path = os.path.normpath(base_path + "/data/i18n/locales") |
154 | +base_path = os.path.abspath(os.path.join( |
155 | + os.path.dirname(__file__), os.path.pardir)) |
156 | + |
157 | +print('Reading locales from JSON:') |
158 | + |
159 | +source_path = os.path.normpath(base_path + '/data/i18n/locales') |
160 | |
161 | if (not os.path.isdir(source_path)): |
162 | - print("Error: Path " + source_path + " not found.") |
163 | - sys.exit(1) |
164 | + print('Error: Path ' + source_path + ' not found.') |
165 | + sys.exit(1) |
166 | |
167 | # Each language's translators live in a separate file, so we list the dir |
168 | source_files = sorted(os.listdir(source_path), key=str.lower) |
169 | |
170 | -lua_locales = "-- This file is generated by utils/update_authors.py.\n" |
171 | -lua_locales += "-- The locale data is managed in Transifex.\n\n" |
172 | -lua_locales += "return {\n" |
173 | -lua_locales += "\t-- Locales are identified by their ISO code.\n" |
174 | +lua_locales = '-- This file is generated by utils/update_authors.py.\n' |
175 | +lua_locales += '-- The locale data is managed in Transifex.\n\n' |
176 | +lua_locales += 'return {\n' |
177 | +lua_locales += '\t-- Locales are identified by their ISO code.\n' |
178 | lua_locales += ' \ten = {\n' |
179 | -lua_locales += "\t\t-- Used to display the locale in the Options menu.\n" |
180 | +lua_locales += '\t\t-- Used to display the locale in the Options menu.\n' |
181 | lua_locales += '\t\tname = "English",\n\n' |
182 | lua_locales += "\t\t-- Defines the language's position on the list in the Options menu.\n" |
183 | lua_locales += '\t\tsort_name = "English",\n\n' |
184 | @@ -39,117 +40,122 @@ |
185 | lua_locales += '\t\tfont = "default"\n' |
186 | lua_locales += '\t},\n' |
187 | |
188 | -lua_translators = "" |
189 | -lua_translators += "function translators() return {" # developers |
190 | +lua_translators = '' |
191 | +lua_translators += 'function translators() return {' # developers |
192 | |
193 | for source_filename in source_files: |
194 | - # Only json files, and not the template file please |
195 | - if source_filename.endswith(".json") and source_filename != "locales_translators.json": |
196 | - source_file = open(source_path + "/" + source_filename, "r") |
197 | - translators = json.load(source_file) |
198 | - locale_message = "- Added" |
199 | - |
200 | - # Parsing translator credits |
201 | - # Make sure we don't pick up untranslated stuff |
202 | - if translators["translator-list"] != 'translator-credits': |
203 | - locale_message += " translators and" |
204 | - lua_translators += '{' # entry |
205 | - lua_translators += 'heading = "' + translators["your-language-name"] |
206 | - if translators["your-language-name-in-english"] != 'English' and translators["your-language-name-in-english"] != translators["your-language-name"] : |
207 | - lua_translators += ' (' + translators["your-language-name-in-english"] + ')' |
208 | - lua_translators += '",' |
209 | - lua_translators += 'entries = {' # entries |
210 | - lua_translators += '{' # entry |
211 | - lua_translators += 'members = {' # members |
212 | - for transl_name in translators["translator-list"].split("\n"): |
213 | - lua_translators += '"' + transl_name + '",' |
214 | - lua_translators += "}," # members |
215 | - lua_translators += "}," # entry |
216 | - lua_translators += "}," # entries |
217 | - lua_translators += "}," # entry |
218 | - |
219 | - # Parsing locale info |
220 | - # Make sure we don't pick up untranslated stuff |
221 | - locale_code = source_filename.split(".json")[0] |
222 | - locale_message += " locale info for " + locale_code |
223 | - lua_locales += '\n\t' + locale_code + ' = {\n' # entry with locale code |
224 | - |
225 | - if translators["your-language-name"] != 'English' or locale_code == 'en': |
226 | - lua_locales += '\t\tname = "' + translators["your-language-name"] + '",\n' |
227 | - else: |
228 | - lua_locales += '\t\tname = "' + locale_code + '",\n' |
229 | - |
230 | - if translators["language-sort-name"] != 'English' or locale_code == 'en': |
231 | - lua_locales += '\t\tsort_name = "' + translators["language-sort-name"] + '",\n' |
232 | - else: |
233 | - lua_locales += '\t\tsort_name = "' + locale_code + '",\n' |
234 | - |
235 | - lua_locales += '\t\tfont = "' + translators["font-set"] + '"\n' |
236 | - lua_locales += "\t},\n" # entry |
237 | - print(locale_message) |
238 | -lua_locales += "}\n" |
239 | - |
240 | -lua_translators += "} end" # developers |
241 | - |
242 | -print("Writing locales\n") |
243 | -dest_filename = "locales.lua" |
244 | -dest_filepath = os.path.normpath(base_path + "/data/i18n") + "/" + dest_filename |
245 | + # Only json files, and not the template file please |
246 | + if source_filename.endswith('.json') and source_filename != 'locales_translators.json': |
247 | + source_file = open(source_path + '/' + source_filename, 'r') |
248 | + translators = json.load(source_file) |
249 | + locale_message = '- Added' |
250 | + |
251 | + # Parsing translator credits |
252 | + # Make sure we don't pick up untranslated stuff |
253 | + if translators['translator-list'] != 'translator-credits': |
254 | + locale_message += ' translators and' |
255 | + lua_translators += '{' # entry |
256 | + lua_translators += 'heading = "' + \ |
257 | + translators['your-language-name'] |
258 | + if translators['your-language-name-in-english'] != 'English' and translators['your-language-name-in-english'] != translators['your-language-name']: |
259 | + lua_translators += ' (' + \ |
260 | + translators['your-language-name-in-english'] + ')' |
261 | + lua_translators += '",' |
262 | + lua_translators += 'entries = {' # entries |
263 | + lua_translators += '{' # entry |
264 | + lua_translators += 'members = {' # members |
265 | + for transl_name in translators['translator-list'].split('\n'): |
266 | + lua_translators += '"' + transl_name + '",' |
267 | + lua_translators += '},' # members |
268 | + lua_translators += '},' # entry |
269 | + lua_translators += '},' # entries |
270 | + lua_translators += '},' # entry |
271 | + |
272 | + # Parsing locale info |
273 | + # Make sure we don't pick up untranslated stuff |
274 | + locale_code = source_filename.split('.json')[0] |
275 | + locale_message += ' locale info for ' + locale_code |
276 | + lua_locales += '\n\t' + locale_code + \ |
277 | + ' = {\n' # entry with locale code |
278 | + |
279 | + if translators['your-language-name'] != 'English' or locale_code == 'en': |
280 | + lua_locales += '\t\tname = "' + \ |
281 | + translators['your-language-name'] + '",\n' |
282 | + else: |
283 | + lua_locales += '\t\tname = "' + locale_code + '",\n' |
284 | + |
285 | + if translators['language-sort-name'] != 'English' or locale_code == 'en': |
286 | + lua_locales += '\t\tsort_name = "' + \ |
287 | + translators['language-sort-name'] + '",\n' |
288 | + else: |
289 | + lua_locales += '\t\tsort_name = "' + locale_code + '",\n' |
290 | + |
291 | + lua_locales += '\t\tfont = "' + translators['font-set'] + '"\n' |
292 | + lua_locales += '\t},\n' # entry |
293 | + print(locale_message) |
294 | +lua_locales += '}\n' |
295 | + |
296 | +lua_translators += '} end' # developers |
297 | + |
298 | +print('Writing locales\n') |
299 | +dest_filename = 'locales.lua' |
300 | +dest_filepath = os.path.normpath( |
301 | + base_path + '/data/i18n') + '/' + dest_filename |
302 | dest_file = codecs.open(dest_filepath, encoding='utf-8', mode='w') |
303 | dest_file.write(lua_locales) |
304 | |
305 | -print("Writing translators\n") |
306 | -dest_filename = "translators_data.lua" |
307 | -dest_filepath = os.path.normpath(base_path + "/data/txts") + "/" + dest_filename |
308 | +print('Writing translators\n') |
309 | +dest_filename = 'translators_data.lua' |
310 | +dest_filepath = os.path.normpath( |
311 | + base_path + '/data/txts') + '/' + dest_filename |
312 | dest_file = codecs.open(dest_filepath, encoding='utf-8', mode='w') |
313 | dest_file.write(lua_translators) |
314 | |
315 | -print("Reading developers from JSON") |
316 | -source_path = os.path.normpath(base_path + "/data/txts") |
317 | +print('Reading developers from JSON') |
318 | +source_path = os.path.normpath(base_path + '/data/txts') |
319 | |
320 | if (not os.path.isdir(source_path)): |
321 | - print("Error: Path " + source_path + " not found.") |
322 | - sys.exit(1) |
323 | + print('Error: Path ' + source_path + ' not found.') |
324 | + sys.exit(1) |
325 | |
326 | -source_file = open(source_path + "/developers.json", "r") |
327 | -developers = json.load(source_file)["developers"] |
328 | +source_file = open(source_path + '/developers.json', 'r') |
329 | +developers = json.load(source_file)['developers'] |
330 | |
331 | lua_string = """-- Do not edit this file - it is automatically generated |
332 | -- by utils/update_authors.py from developers.json. |
333 | """ |
334 | -lua_string += "function developers() return {" # developers |
335 | +lua_string += 'function developers() return {' # developers |
336 | |
337 | for category in developers: |
338 | - print("- Adding " + category["heading"]) |
339 | - if category["heading"] != "Translators": # Unused hook for adding translators |
340 | - lua_string += '{' # category |
341 | - lua_string += 'heading = _"' + category["heading"] + '",' # This will be localized |
342 | - lua_string += 'image = "' + category["image"] + '",' |
343 | - |
344 | - lua_string += 'entries = {' # entries |
345 | - |
346 | - for subcategory in category["entries"]: |
347 | - lua_string += '{' # entry |
348 | - if 'subheading' in subcategory: |
349 | - lua_string += 'subheading = _"' + subcategory["subheading"] + '",' # This will be localized |
350 | - |
351 | - lua_string += 'members = {' # members |
352 | - for member in subcategory["members"]: |
353 | - lua_string += '"' + member + '",' |
354 | - lua_string += "}," # members |
355 | - |
356 | - lua_string += "}," # entry |
357 | - lua_string += "}," # entries |
358 | - |
359 | - lua_string += "}," # category |
360 | -lua_string += "} end\n" # developers |
361 | - |
362 | -print("Writing developers") |
363 | -dest_filename = "developers.lua" |
364 | -dest_filepath = source_path + "/" + dest_filename |
365 | + print('- Adding ' + category['heading']) |
366 | + if category['heading'] != 'Translators': # Unused hook for adding translators |
367 | + lua_string += '{' # category |
368 | + lua_string += 'heading = _"' + \ |
369 | + category['heading'] + '",' # This will be localized |
370 | + lua_string += 'image = "' + category['image'] + '",' |
371 | + |
372 | + lua_string += 'entries = {' # entries |
373 | + |
374 | + for subcategory in category['entries']: |
375 | + lua_string += '{' # entry |
376 | + if 'subheading' in subcategory: |
377 | + lua_string += 'subheading = _"' + \ |
378 | + subcategory['subheading'] + '",' # This will be localized |
379 | + |
380 | + lua_string += 'members = {' # members |
381 | + for member in subcategory['members']: |
382 | + lua_string += '"' + member + '",' |
383 | + lua_string += '},' # members |
384 | + |
385 | + lua_string += '},' # entry |
386 | + lua_string += '},' # entries |
387 | + |
388 | + lua_string += '},' # category |
389 | +lua_string += '} end\n' # developers |
390 | + |
391 | +print('Writing developers') |
392 | +dest_filename = 'developers.lua' |
393 | +dest_filepath = source_path + '/' + dest_filename |
394 | dest_file = codecs.open(dest_filepath, encoding='utf-8', mode='w') |
395 | dest_file.write(lua_string) |
396 | - |
397 | -print("Fixing the formatting") |
398 | -import fix_lua_tabs |
399 | -fix_lua_tabs.main() |
400 | -print("Done.") |
401 | +print('Done.') |
Continuous integration builds have changed state:
Travis build 1679. State: passed. Details: https:/ /travis- ci.org/ widelands/ widelands/ builds/ 180479785. /ci.appveyor. com/project/ widelands- dev/widelands/ build/_ widelands_ dev_widelands_ automate_ clang_format- 1519.
Appveyor build 1519. State: success. Details: https:/