PRESUBMIT.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. # Copyright 2013 The Chromium 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. """Presubmit script for changes affecting chrome/app/
  5. See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
  6. for more details about the presubmit API built into depot_tools.
  7. """
  8. USE_PYTHON3 = True
  9. import os
  10. from xml.dom import minidom
  11. def _CheckNoProductNameInGeneratedResources(input_api, output_api):
  12. """Check that no PRODUCT_NAME placeholders are found in resources files.
  13. These kinds of strings prevent proper localization in some languages. For
  14. more information, see the following chromium-dev thread:
  15. https://groups.google.com/a/chromium.org/forum/#!msg/chromium-dev/PBs5JfR0Aoc/NOcIHII9u14J
  16. """
  17. problems = []
  18. filename_filter = lambda x: x.LocalPath().endswith(('.grd', '.grdp'))
  19. for f, line_num, line in input_api.RightHandSideLines(filename_filter):
  20. if 'PRODUCT_NAME' in line:
  21. problems.append('%s:%d' % (f.LocalPath(), line_num))
  22. if problems:
  23. return [output_api.PresubmitPromptWarning(
  24. "Don't use PRODUCT_NAME placeholders in string resources. Instead, add "
  25. "separate strings to google_chrome_strings.grd and "
  26. "chromium_strings.grd. See http://goo.gl/6614MQ for more information."
  27. "Problems with this check? Contact dubroy@chromium.org.",
  28. items=problems)]
  29. return []
  30. def _CheckFlagsMessageNotTranslated(input_api, output_api):
  31. """Check: all about:flags messages are marked as not requiring translation.
  32. This assumes that such messages are only added to generated_resources.grd and
  33. that all such messages have names starting with IDS_FLAGS_. The expected mark
  34. for not requiring translation is 'translateable="false"'.
  35. """
  36. problems = []
  37. filename_filter = lambda x: x.LocalPath().endswith("generated_resources.grd")
  38. for f, line_num, line in input_api.RightHandSideLines(filename_filter):
  39. if "name=\"IDS_FLAGS_" in line and not "translateable=\"false\"" in line:
  40. problems.append("Missing translateable=\"false\" in %s:%d"
  41. % (f.LocalPath(), line_num))
  42. problems.append(line)
  43. if problems:
  44. return [output_api.PresubmitError(
  45. "If you define a flag name, description or value, mark it as not "
  46. "requiring translation by adding the 'translateable' attribute with "
  47. "value \"false\". See https://crbug.com/587272 for more context.",
  48. items=problems)]
  49. return []
  50. def _GetInfoStrings(file_contents):
  51. """Retrieves IDS_EDU_LOGIN_INFO_* messages from the file contents
  52. Args:
  53. file_contents: string
  54. Returns:
  55. A list of tuples, where each element represents a message.
  56. element[0] is the 'name' attribute of the message
  57. element[1] is the message contents
  58. """
  59. return [(message.getAttribute('name'), message.firstChild.nodeValue)
  60. for message in (file_contents.getElementsByTagName('grit-part')[0]
  61. .getElementsByTagName('message'))
  62. if message.getAttribute('name').startswith('IDS_EDU_LOGIN_INFO_')]
  63. strings_file = next((af for af in input_api.change.AffectedFiles()
  64. if af.AbsoluteLocalPath() == CHROMEOS_STRINGS_PATH), None)
  65. if strings_file is None:
  66. return []
  67. old_info_strings = _GetInfoStrings(
  68. minidom.parseString('\n'.join(strings_file.OldContents())))
  69. new_info_strings = _GetInfoStrings(
  70. minidom.parseString('\n'.join(strings_file.NewContents())))
  71. if set(old_info_strings) == set(new_info_strings):
  72. return []
  73. if input_api.change.issue == 0:
  74. # First upload, notify about string changes.
  75. return [
  76. output_api.PresubmitNotifyResult(
  77. UPDATE_TEXT_VERSION_MESSAGE % "v<GERRIT_CL_NUMBER>"),
  78. output_api.PresubmitNotifyResult(
  79. UPDATE_INVALIDATION_VERSION_MESSAGE % "iv<GERRIT_CL_NUMBER>"),
  80. ]
  81. new_text_version = "v" + str(input_api.change.issue)
  82. new_invalidation_version = "iv" + str(input_api.change.issue)
  83. text_version_file = next((af for af in input_api.change.AffectedFiles()
  84. if af.AbsoluteLocalPath() == TEXT_VERSION_PATH),
  85. None)
  86. result = []
  87. # Check if text version was updated.
  88. if text_version_file is None or new_text_version not in '\n'.join(
  89. text_version_file.NewContents()):
  90. result.append(
  91. output_api.PresubmitError(
  92. UPDATE_TEXT_VERSION_MESSAGE % new_text_version))
  93. # Check if invalidation version was updated.
  94. if text_version_file is None or new_invalidation_version not in '\n'.join(
  95. text_version_file.NewContents()):
  96. result.append(
  97. output_api.PresubmitNotifyResult(
  98. UPDATE_INVALIDATION_VERSION_MESSAGE % new_invalidation_version))
  99. return result
  100. def _CommonChecks(input_api, output_api):
  101. """Checks common to both upload and commit."""
  102. results = []
  103. results.extend(_CheckNoProductNameInGeneratedResources(input_api, output_api))
  104. results.extend(_CheckFlagsMessageNotTranslated(input_api, output_api))
  105. return results
  106. def CheckChangeOnUpload(input_api, output_api):
  107. return _CommonChecks(input_api, output_api)
  108. def CheckChangeOnCommit(input_api, output_api):
  109. return _CommonChecks(input_api, output_api)