35 from modules.Shell
import Shell
37 logger = logging.getLogger(
"format_code")
41 "src/core/NEON/kernels/assembly/gemm",
42 "src/core/NEON/kernels/assembly/arm",
52 ret_copyright_year =
str()
54 last_year = int(copyright_years[-4:])
55 if last_year == curr_year:
56 ret_copyright_year = copyright_years
57 elif last_year == (curr_year - 1):
59 if len(copyright_years) > 4
and copyright_years[-5] ==
"-":
61 ret_copyright_year = copyright_years[:-5] +
"-" +
str(curr_year)
64 ret_copyright_year = copyright_years +
"-" +
str(curr_year)
66 ret_copyright_year = copyright_years +
", " +
str(curr_year)
67 return ret_copyright_year
70 f = open(filename,
"r")
71 content = f.readlines()
73 f = open(filename,
"w")
74 year = datetime.datetime.now().year
75 ref = open(
"scripts/copyright_mit.txt",
"r").readlines()
78 if(
"SConstruct" in filename
or "SConscript" in filename):
80 if(
"SConscript" in filename):
82 m = re.match(
r"(# Copyright \(c\) )(.*\d{4})( [Arm|ARM].*)", content[start])
91 line += m.group(3).replace(
"ARM",
"Arm")
92 if(
"SConscript" in filename):
93 f.write(
'#!/usr/bin/python\n')
95 f.write(
'# -*- coding: utf-8 -*-\n\n')
98 f.write(
"".
join(content[start + 1:]))
104 m = re.match(
r"(.*Copyright \(c\) )(.*\d{4})( [Arm|ARM].*)", content[1])
106 if content[0] !=
"/*\n" or not m:
108 f.write(
"/*\n * Copyright (c) %d Arm Limited.\n" % year)
110 logger.debug(
"Found Copyright start")
111 logger.debug(
"\n\t".
join([ g
or "" for g
in m.groups()]))
120 line += m.group(3).replace(
"ARM",
"Arm")
121 f.write(
"/*\n"+line+
"\n")
124 for i
in range(1, len(ref)):
127 if line.rstrip() !=
"":
128 f.write(
" %s" % line)
133 f.write(
"".
join(content[start:]))
138 Check that the license file is up-to-date
140 f = open(filename,
"r")
141 content = f.readlines()
144 f = open(filename,
"w")
145 f.write(
"".
join(content[:2]))
147 year = datetime.datetime.now().year
149 m = re.match(
r"(.*Copyright \(c\) )(.*\d{4})( [Arm|ARM].*)", content[2])
152 f.write(
"Copyright (c) {} Arm Limited\n".
format(year))
155 f.write(
"Copyright (c) {} Arm Limited\n".
format(updated_year))
158 f.write(
"".
join(content[3:]))
163 def __init__(self, folder, error_diff=False, strategy="all"):
171 diff = self.
shell.run_single_to_str(
"git diff")
175 logger.error(
"\n"+msg)
181 self.
shell.save_cwd()
182 this_dir = os.path.dirname(__file__)
184 self.
shell.prepend_env(
"PATH",
"%s/../bin" % this_dir)
188 to_check, skip_copyright = FormatCodeRun.get_files(self.
folder, self.
strategy)
191 logger.info(
"Running ./scripts/format_doxygen.py")
192 logger.debug(self.
shell.run_single_to_str(
"./scripts/format_doxygen.py %s" %
" ".
join(to_check)))
193 retval = self.
error_on_diff(
"Doxygen comments badly formatted (check above diff output for more details) try to run ./scripts/format_doxygen.py on your patch and resubmit")
195 logger.info(
"Running ./scripts/include_functions_kernels.py")
196 logger.debug(self.
shell.run_single_to_str(
"python ./scripts/include_functions_kernels.py"))
197 retval = self.
error_on_diff(
"Some kernels or functions are not included in their corresponding master header (check above diff output to see which includes are missing)")
200 logger.info(
"Running ./scripts/check_bad_style.sh")
201 logger.debug(self.
shell.run_single_to_str(
"./scripts/check_bad_style.sh"))
203 except subprocess.CalledProcessError
as e:
204 logger.error(
"Command %s returned:\n%s" % (e.cmd, e.output))
208 raise Exception(
"format-code failed with error code %d" % retval)
215 skip_copyright =
False
216 if strategy ==
"git-head":
217 cmd =
"git diff-tree --no-commit-id --name-status -r HEAD | grep \"^[AMRT]\" | cut -f 2"
218 elif strategy ==
"git-diff":
219 cmd =
"git diff --name-status --cached -r HEAD | grep \"^[AMRT]\" | rev | cut -f 1 | rev"
221 cmd =
"git ls-tree -r HEAD --name-only"
224 skip_copyright =
True
226 grep_folder =
"grep -e \"^\\(arm_compute\\|src\\|examples\\|tests\\|utils\\|support\\)/\""
227 grep_extension =
"grep -e \"\\.\\(cpp\\|h\\|hh\\|inl\\|cl\\|cs\\|hpp\\)$\""
228 list_files = shell.run_single_to_str(cmd+
" | { "+ grep_folder+
" | "+grep_extension +
" || true; }")
229 to_check = [ f
for f
in list_files.split(
"\n")
if len(f) > 0]
232 list_files = shell.run_single_to_str(cmd+
" | { grep -e \"SC\" || true; }")
233 to_check += [ f
for f
in list_files.split(
"\n")
if len(f) > 0]
235 return (to_check, skip_copyright)
237 def __init__(self, files, folder, error_diff=False, skip_copyright=False):
246 diff = self.
shell.run_single_to_str(
"git diff")
250 logger.error(
"\n"+msg)
254 if len(self.
files) < 1:
255 logger.debug(
"No file: early exit")
258 self.
shell.save_cwd()
259 this_dir = os.path.dirname(__file__)
262 self.
shell.prepend_env(
"PATH",
"%s/../bin" % this_dir)
268 skip_this_file =
False
271 logger.warning(
"Skipping '%s' file: %s" % (e,f))
272 skip_this_file =
True
277 logger.info(
"Formatting %s" % f)
281 except subprocess.CalledProcessError
as e:
284 logger.error(
"OUTPUT= %s" % e.output)
286 retval += self.
error_on_diff(
"See above for clang-tidy errors")
289 raise Exception(
"format-code failed with error code %d" % retval)
299 self.
shell.save_cwd()
300 this_dir = os.path.dirname(__file__)
302 logger.debug(
"Running Android.bp check")
305 cmd =
"%s/generate_android_bp.py --folder %s --output_file %s" % (this_dir, self.
folder, self.
bp_output_file)
306 output = self.
shell.run_single_to_str(cmd)
309 except subprocess.CalledProcessError
as e:
312 logger.error(
"OUTPUT= %s" % e.output)
319 with open(self.
folder +
"/Android.bp",
'r')
as review_file:
320 diff = list(difflib.unified_diff(generated_file.readlines(), review_file.readlines(),
321 fromfile=
'Generated_Android.bp', tofile=
'Android.bp'))
327 num_removed_lines = 0
329 last_removed_line =
""
330 expect_add_line =
False
333 if line.startswith(
"-")
and not line.startswith(
"---"):
334 num_removed_lines += 1
335 if num_removed_lines > 1:
337 last_removed_line = line
338 expect_add_line =
True
339 elif line.startswith(
"+")
and not line.startswith(
"+++"):
341 if num_added_lines > 1:
344 last_added_line = line
346 expect_add_line =
False
348 if num_added_lines == 1
and num_removed_lines == 1:
349 re_copyright = re.compile(
"^(?:\+|\-)// Copyright © ([0-9]+)\-([0-9]+) Arm Ltd. All rights reserved.\n$")
350 generated_matches = re_copyright.search(last_removed_line)
351 review_matches = re_copyright.search(last_added_line)
353 if generated_matches
is not None and review_matches
is not None:
354 if generated_matches.group(1) == review_matches.group(1)
and \
355 int(generated_matches.group(2)) > int(review_matches.group(2)):
356 is_mismatched =
False
359 logger.error(
"Lines with '-' need to be added to Android.bp")
360 logger.error(
"Lines with '+' need to be removed from Android.bp")
363 logger.error(line.rstrip())
365 raise Exception(
"Android bp file is not updated")
368 raise Exception(
"generate Android bp file failed with error code %d" % retval)
378 to_check, skip_copyright = FormatCodeRun.get_files(folder, files)
382 logger.debug(to_check)
383 num_files = len(to_check)
384 per_thread = max( num_files / num_threads,1)
386 logger.info(
"Files to format:\n\t%s" %
"\n\t".
join(to_check))
388 for i
in range(num_threads):
389 if i == num_threads -1:
392 end= min(start+per_thread, num_files)
393 sub = to_check[start:end]
394 logger.debug(
"[%d] [%d,%d] %s" % (i, start, end, sub))
396 format_code_run =
FormatCodeRun(sub, folder, skip_copyright=skip_copyright)
397 format_code_run.run()
400 except Exception
as e:
401 logger.error(
"Exception caught in run_fix_code_formatting: %s" % e)
404 if __name__ ==
"__main__":
405 parser = argparse.ArgumentParser(
406 formatter_class=argparse.RawDescriptionHelpFormatter,
407 description=
"Build & run pre-commit tests",
410 file_sources=[
"git-diff",
"git-head",
"all"]
411 parser.add_argument(
"-D",
"--debug", action=
'store_true', help=
"Enable script debugging output")
412 parser.add_argument(
"--error_on_diff", action=
'store_true', help=
"Show diff on error and stop")
413 parser.add_argument(
"--files", nargs=
'?', metavar=
"source", choices=file_sources, help=
"Which files to run fix_code_formatting on, choices=%s" % file_sources, default=
"git-head")
414 parser.add_argument(
"--folder", metavar=
"path", help=
"Folder in which to run fix_code_formatting", default=
".")
416 args = parser.parse_args()
418 logging_level = logging.INFO
420 logging_level = logging.DEBUG
422 logging.basicConfig(level=logging_level)
424 logger.debug(
"Arguments passed: %s" %
str(args.__dict__))