PRESUBMIT.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. # Copyright 2019 The ANGLE Project Authors. All rights reserved.
  2. # Use of this source code is governed by a BSD-style license that can be
  3. # found in the LICENSE file.
  4. """Top-level presubmit script for code generation.
  5. See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
  6. for more details on the presubmit API built into depot_tools.
  7. """
  8. from subprocess import call
  9. # Fragment of a regular expression that matches C++ and Objective-C++ implementation files.
  10. _IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
  11. # Fragment of a regular expression that matches C++ and Objective-C++ header files.
  12. _HEADER_EXTENSIONS = r'\.(h|hpp|hxx)$'
  13. def _CheckChangeHasBugField(input_api, output_api):
  14. """Requires that the changelist have a Bug: field."""
  15. bugs = input_api.change.BugsFromDescription()
  16. if not bugs:
  17. return [
  18. output_api.PresubmitError(
  19. 'If this change has an associated bug, add Bug: angleproject:[bug number].')
  20. ]
  21. elif not all([' ' not in bug for bug in bugs]):
  22. return [
  23. output_api.PresubmitError(
  24. 'Check bug tag formatting. Ensure there are no spaces after the colon.')
  25. ]
  26. else:
  27. return []
  28. def _CheckCodeGeneration(input_api, output_api):
  29. class Msg(output_api.PresubmitError):
  30. """Specialized error message"""
  31. def __init__(self, message):
  32. super(output_api.PresubmitError, self).__init__(
  33. message,
  34. long_text='Please run scripts/run_code_generation.py to refresh generated hashes.\n'
  35. '\n'
  36. 'If that fails, ensure your ANGLE repositiory is synced to tip-of-tree\n'
  37. 'and all ANGLE DEPS are fully up-to-date by running gclient sync.\n'
  38. '\n'
  39. 'If you are building ANGLE inside Chromium you must bootstrap ANGLE\n'
  40. 'before gclient sync. See the DevSetup documentation for more details.\n')
  41. code_gen_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
  42. 'scripts/run_code_generation.py')
  43. cmd_name = 'run_code_generation'
  44. cmd = [input_api.python_executable, code_gen_path, '--verify-no-dirty']
  45. test_cmd = input_api.Command(name=cmd_name, cmd=cmd, kwargs={}, message=Msg)
  46. if input_api.verbose:
  47. print('Running ' + cmd_name)
  48. return input_api.RunTests([test_cmd])
  49. # Taken directly from Chromium's PRESUBMIT.py
  50. def _CheckNewHeaderWithoutGnChange(input_api, output_api):
  51. """Checks that newly added header files have corresponding GN changes.
  52. Note that this is only a heuristic. To be precise, run script:
  53. build/check_gn_headers.py.
  54. """
  55. def headers(f):
  56. return input_api.FilterSourceFile(f, white_list=(r'.+%s' % _HEADER_EXTENSIONS,))
  57. new_headers = []
  58. for f in input_api.AffectedSourceFiles(headers):
  59. if f.Action() != 'A':
  60. continue
  61. new_headers.append(f.LocalPath())
  62. def gn_files(f):
  63. return input_api.FilterSourceFile(f, white_list=(r'.+\.gn',))
  64. all_gn_changed_contents = ''
  65. for f in input_api.AffectedSourceFiles(gn_files):
  66. for _, line in f.ChangedContents():
  67. all_gn_changed_contents += line
  68. problems = []
  69. for header in new_headers:
  70. basename = input_api.os_path.basename(header)
  71. if basename not in all_gn_changed_contents:
  72. problems.append(header)
  73. if problems:
  74. return [
  75. output_api.PresubmitPromptWarning(
  76. 'Missing GN changes for new header files',
  77. items=sorted(problems),
  78. long_text='Please double check whether newly added header files need '
  79. 'corresponding changes in gn or gni files.\nThis checking is only a '
  80. 'heuristic. Run build/check_gn_headers.py to be precise.\n'
  81. 'Read https://crbug.com/661774 for more info.')
  82. ]
  83. return []
  84. def CheckChangeOnUpload(input_api, output_api):
  85. results = []
  86. results.extend(_CheckCodeGeneration(input_api, output_api))
  87. results.extend(_CheckChangeHasBugField(input_api, output_api))
  88. results.extend(input_api.canned_checks.CheckChangeHasDescription(input_api, output_api))
  89. results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
  90. results.extend(
  91. input_api.canned_checks.CheckPatchFormatted(
  92. input_api, output_api, result_factory=output_api.PresubmitError))
  93. return results
  94. def CheckChangeOnCommit(input_api, output_api):
  95. results = []
  96. results.extend(_CheckCodeGeneration(input_api, output_api))
  97. results.extend(
  98. input_api.canned_checks.CheckPatchFormatted(
  99. input_api, output_api, result_factory=output_api.PresubmitError))
  100. results.extend(_CheckChangeHasBugField(input_api, output_api))
  101. results.extend(input_api.canned_checks.CheckChangeHasDescription(input_api, output_api))
  102. return results