diff options
Diffstat (limited to 'PRESUBMIT.py')
-rw-r--r-- | PRESUBMIT.py | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/PRESUBMIT.py b/PRESUBMIT.py new file mode 100644 index 0000000..58be26d --- /dev/null +++ b/PRESUBMIT.py @@ -0,0 +1,202 @@ +# Copyright (c) 2021, Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Google nor the names of its contributors may +# be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +"""Top-level presubmit script for libwebm. + +See https://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for +details on the presubmit API built into depot_tools. +""" +import re +import subprocess2 + +USE_PYTHON3 = True +_BASH_INDENTATION = "2" +_GIT_COMMIT_SUBJECT_LENGTH = 65 +_INCLUDE_BASH_FILES_ONLY = [r".*\.sh$"] +_INCLUDE_SOURCE_FILES_ONLY = [r".*\.(c|cc|[hc]pp|h)$"] +_LIBWEBM_MAX_LINE_LENGTH = 80 + + +def _CheckCommitSubjectLength(input_api, output_api): + """Ensures commit's subject length is no longer than 65 chars.""" + name = "git-commit subject" + cmd = ["git", "log", "-1", "--pretty=%s"] + start = input_api.time.time() + proc = subprocess2.Popen( + cmd, + stderr=subprocess2.PIPE, + stdout=subprocess2.PIPE, + universal_newlines=True) + + stdout, _ = proc.communicate() + duration = input_api.time.time() - start + + if not re.match(r"^Revert", + stdout) and (len(stdout) - 1) > _GIT_COMMIT_SUBJECT_LENGTH: + failure_msg = ( + "The commit subject: %s is too long (%d chars)\n" + "Try to keep this to 50 or less (up to 65 is permitted for " + "non-reverts).\n" + "https://www.git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-" + "Project#_commit_guidelines") % (stdout, len(stdout) - 1) + return output_api.PresubmitError("%s\n (%4.2fs) failed\n%s" % + (name, duration, failure_msg)) + + return output_api.PresubmitResult("%s\n (%4.2fs) success" % (name, duration)) + + +def _GetFilesToSkip(input_api): + """Skips libwebm-specific files.""" + return list(input_api.DEFAULT_FILES_TO_SKIP) + [ + r"\.pylintrc$", + ] + + +def _CheckChangeLintsClean(input_api, output_api): + """Makes sure that libwebm/ code is cpplint clean.""" + sources = lambda x: input_api.FilterSourceFile( + x, files_to_check=_INCLUDE_SOURCE_FILES_ONLY, files_to_skip=None) + return input_api.canned_checks.CheckChangeLintsClean(input_api, output_api, + sources) + + +def _RunShellCheckCmd(input_api, output_api, bash_file): + """shellcheck command wrapper.""" + cmd = ["shellcheck", "-x", "-oall", "-sbash", bash_file] + name = "Check %s file." % bash_file + start = input_api.time.time() + output, rc = subprocess2.communicate( + cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True) + duration = input_api.time.time() - start + if rc == 0: + return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" % + (name, " ".join(cmd), duration)) + return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" % + (name, " ".join(cmd), duration, output[1])) + + +def _RunShfmtCheckCmd(input_api, output_api, bash_file): + """shfmt command wrapper.""" + cmd = [ + "shfmt", "-i", _BASH_INDENTATION, "-bn", "-ci", "-sr", "-kp", "-d", + bash_file + ] + name = "Check %s file." % bash_file + start = input_api.time.time() + output, rc = subprocess2.communicate( + cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True) + duration = input_api.time.time() - start + if rc == 0: + return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" % + (name, " ".join(cmd), duration)) + return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" % + (name, " ".join(cmd), duration, output[1])) + + +def _RunCmdOnCheckedFiles(input_api, output_api, run_cmd, files_to_check): + """Ensure that libwebm/ files are clean.""" + file_filter = lambda x: input_api.FilterSourceFile( + x, files_to_check=files_to_check, files_to_skip=None) + + affected_files = input_api.change.AffectedFiles(file_filter=file_filter) + results = [ + run_cmd(input_api, output_api, f.AbsoluteLocalPath()) + for f in affected_files + ] + return results + + +def _CommonChecks(input_api, output_api): + results = [] + results.extend( + input_api.canned_checks.CheckChangeHasNoCrAndHasOnlyOneEol( + input_api, output_api)) + results.extend( + input_api.canned_checks.CheckChangeHasNoTabs(input_api, output_api)) + results.extend( + input_api.canned_checks.CheckChangeHasNoStrayWhitespace( + input_api, output_api)) + results.append(_CheckCommitSubjectLength(input_api, output_api)) + + source_file_filter = lambda x: input_api.FilterSourceFile( + x, files_to_skip=_GetFilesToSkip(input_api)) + results.extend( + input_api.canned_checks.CheckLongLines( + input_api, + output_api, + maxlen=_LIBWEBM_MAX_LINE_LENGTH, + source_file_filter=source_file_filter)) + + results.extend( + input_api.canned_checks.CheckPatchFormatted( + input_api, + output_api, + check_clang_format=True, + check_python=True, + result_factory=output_api.PresubmitError)) + results.extend(_CheckChangeLintsClean(input_api, output_api)) + + # Run pylint. + results.extend( + input_api.canned_checks.RunPylint( + input_api, + output_api, + files_to_skip=_GetFilesToSkip(input_api), + pylintrc=".pylintrc", + version="2.7")) + + # Binaries shellcheck and shfmt are not installed in depot_tools. + # Installation is needed + try: + subprocess2.communicate(["shellcheck", "--version"]) + results.extend( + _RunCmdOnCheckedFiles(input_api, output_api, _RunShellCheckCmd, + _INCLUDE_BASH_FILES_ONLY)) + print("shfmt") + subprocess2.communicate(["shfmt", "-version"]) + results.extend( + _RunCmdOnCheckedFiles(input_api, output_api, _RunShfmtCheckCmd, + _INCLUDE_BASH_FILES_ONLY)) + except OSError as os_error: + results.append( + output_api.PresubmitPromptWarning( + "%s\nPlease install missing binaries locally." % os_error.args[0])) + return results + + +def CheckChangeOnUpload(input_api, output_api): + results = [] + results.extend(_CommonChecks(input_api, output_api)) + return results + + +def CheckChangeOnCommit(input_api, output_api): + results = [] + results.extend(_CommonChecks(input_api, output_api)) + return results |