1*103e46e4SHarish Mahendrakar# Copyright (c) 2021, Google Inc. All rights reserved. 2*103e46e4SHarish Mahendrakar# 3*103e46e4SHarish Mahendrakar# Redistribution and use in source and binary forms, with or without 4*103e46e4SHarish Mahendrakar# modification, are permitted provided that the following conditions are 5*103e46e4SHarish Mahendrakar# met: 6*103e46e4SHarish Mahendrakar# 7*103e46e4SHarish Mahendrakar# * Redistributions of source code must retain the above copyright 8*103e46e4SHarish Mahendrakar# notice, this list of conditions and the following disclaimer. 9*103e46e4SHarish Mahendrakar# 10*103e46e4SHarish Mahendrakar# * Redistributions in binary form must reproduce the above copyright 11*103e46e4SHarish Mahendrakar# notice, this list of conditions and the following disclaimer in 12*103e46e4SHarish Mahendrakar# the documentation and/or other materials provided with the 13*103e46e4SHarish Mahendrakar# distribution. 14*103e46e4SHarish Mahendrakar# 15*103e46e4SHarish Mahendrakar# * Neither the name of Google nor the names of its contributors may 16*103e46e4SHarish Mahendrakar# be used to endorse or promote products derived from this software 17*103e46e4SHarish Mahendrakar# without specific prior written permission. 18*103e46e4SHarish Mahendrakar# 19*103e46e4SHarish Mahendrakar# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20*103e46e4SHarish Mahendrakar# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21*103e46e4SHarish Mahendrakar# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22*103e46e4SHarish Mahendrakar# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23*103e46e4SHarish Mahendrakar# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24*103e46e4SHarish Mahendrakar# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25*103e46e4SHarish Mahendrakar# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26*103e46e4SHarish Mahendrakar# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27*103e46e4SHarish Mahendrakar# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28*103e46e4SHarish Mahendrakar# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29*103e46e4SHarish Mahendrakar# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30*103e46e4SHarish Mahendrakar"""Top-level presubmit script for libwebm. 31*103e46e4SHarish Mahendrakar 32*103e46e4SHarish MahendrakarSee https://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for 33*103e46e4SHarish Mahendrakardetails on the presubmit API built into depot_tools. 34*103e46e4SHarish Mahendrakar""" 35*103e46e4SHarish Mahendrakarimport re 36*103e46e4SHarish Mahendrakarimport subprocess2 37*103e46e4SHarish Mahendrakar 38*103e46e4SHarish MahendrakarUSE_PYTHON3 = True 39*103e46e4SHarish Mahendrakar_BASH_INDENTATION = "2" 40*103e46e4SHarish Mahendrakar_GIT_COMMIT_SUBJECT_LENGTH = 65 41*103e46e4SHarish Mahendrakar_INCLUDE_BASH_FILES_ONLY = [r".*\.sh$"] 42*103e46e4SHarish Mahendrakar_INCLUDE_SOURCE_FILES_ONLY = [r".*\.(c|cc|[hc]pp|h)$"] 43*103e46e4SHarish Mahendrakar_LIBWEBM_MAX_LINE_LENGTH = 80 44*103e46e4SHarish Mahendrakar 45*103e46e4SHarish Mahendrakar 46*103e46e4SHarish Mahendrakardef _CheckCommitSubjectLength(input_api, output_api): 47*103e46e4SHarish Mahendrakar """Ensures commit's subject length is no longer than 65 chars.""" 48*103e46e4SHarish Mahendrakar name = "git-commit subject" 49*103e46e4SHarish Mahendrakar cmd = ["git", "log", "-1", "--pretty=%s"] 50*103e46e4SHarish Mahendrakar start = input_api.time.time() 51*103e46e4SHarish Mahendrakar proc = subprocess2.Popen( 52*103e46e4SHarish Mahendrakar cmd, 53*103e46e4SHarish Mahendrakar stderr=subprocess2.PIPE, 54*103e46e4SHarish Mahendrakar stdout=subprocess2.PIPE, 55*103e46e4SHarish Mahendrakar universal_newlines=True) 56*103e46e4SHarish Mahendrakar 57*103e46e4SHarish Mahendrakar stdout, _ = proc.communicate() 58*103e46e4SHarish Mahendrakar duration = input_api.time.time() - start 59*103e46e4SHarish Mahendrakar 60*103e46e4SHarish Mahendrakar if not re.match(r"^Revert", 61*103e46e4SHarish Mahendrakar stdout) and (len(stdout) - 1) > _GIT_COMMIT_SUBJECT_LENGTH: 62*103e46e4SHarish Mahendrakar failure_msg = ( 63*103e46e4SHarish Mahendrakar "The commit subject: %s is too long (%d chars)\n" 64*103e46e4SHarish Mahendrakar "Try to keep this to 50 or less (up to 65 is permitted for " 65*103e46e4SHarish Mahendrakar "non-reverts).\n" 66*103e46e4SHarish Mahendrakar "https://www.git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-" 67*103e46e4SHarish Mahendrakar "Project#_commit_guidelines") % (stdout, len(stdout) - 1) 68*103e46e4SHarish Mahendrakar return output_api.PresubmitError("%s\n (%4.2fs) failed\n%s" % 69*103e46e4SHarish Mahendrakar (name, duration, failure_msg)) 70*103e46e4SHarish Mahendrakar 71*103e46e4SHarish Mahendrakar return output_api.PresubmitResult("%s\n (%4.2fs) success" % (name, duration)) 72*103e46e4SHarish Mahendrakar 73*103e46e4SHarish Mahendrakar 74*103e46e4SHarish Mahendrakardef _GetFilesToSkip(input_api): 75*103e46e4SHarish Mahendrakar """Skips libwebm-specific files.""" 76*103e46e4SHarish Mahendrakar return list(input_api.DEFAULT_FILES_TO_SKIP) + [ 77*103e46e4SHarish Mahendrakar r"\.pylintrc$", 78*103e46e4SHarish Mahendrakar ] 79*103e46e4SHarish Mahendrakar 80*103e46e4SHarish Mahendrakar 81*103e46e4SHarish Mahendrakardef _CheckChangeLintsClean(input_api, output_api): 82*103e46e4SHarish Mahendrakar """Makes sure that libwebm/ code is cpplint clean.""" 83*103e46e4SHarish Mahendrakar sources = lambda x: input_api.FilterSourceFile( 84*103e46e4SHarish Mahendrakar x, files_to_check=_INCLUDE_SOURCE_FILES_ONLY, files_to_skip=None) 85*103e46e4SHarish Mahendrakar return input_api.canned_checks.CheckChangeLintsClean(input_api, output_api, 86*103e46e4SHarish Mahendrakar sources) 87*103e46e4SHarish Mahendrakar 88*103e46e4SHarish Mahendrakar 89*103e46e4SHarish Mahendrakardef _RunShellCheckCmd(input_api, output_api, bash_file): 90*103e46e4SHarish Mahendrakar """shellcheck command wrapper.""" 91*103e46e4SHarish Mahendrakar cmd = ["shellcheck", "-x", "-oall", "-sbash", bash_file] 92*103e46e4SHarish Mahendrakar name = "Check %s file." % bash_file 93*103e46e4SHarish Mahendrakar start = input_api.time.time() 94*103e46e4SHarish Mahendrakar output, rc = subprocess2.communicate( 95*103e46e4SHarish Mahendrakar cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True) 96*103e46e4SHarish Mahendrakar duration = input_api.time.time() - start 97*103e46e4SHarish Mahendrakar if rc == 0: 98*103e46e4SHarish Mahendrakar return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" % 99*103e46e4SHarish Mahendrakar (name, " ".join(cmd), duration)) 100*103e46e4SHarish Mahendrakar return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" % 101*103e46e4SHarish Mahendrakar (name, " ".join(cmd), duration, output[1])) 102*103e46e4SHarish Mahendrakar 103*103e46e4SHarish Mahendrakar 104*103e46e4SHarish Mahendrakardef _RunShfmtCheckCmd(input_api, output_api, bash_file): 105*103e46e4SHarish Mahendrakar """shfmt command wrapper.""" 106*103e46e4SHarish Mahendrakar cmd = [ 107*103e46e4SHarish Mahendrakar "shfmt", "-i", _BASH_INDENTATION, "-bn", "-ci", "-sr", "-kp", "-d", 108*103e46e4SHarish Mahendrakar bash_file 109*103e46e4SHarish Mahendrakar ] 110*103e46e4SHarish Mahendrakar name = "Check %s file." % bash_file 111*103e46e4SHarish Mahendrakar start = input_api.time.time() 112*103e46e4SHarish Mahendrakar output, rc = subprocess2.communicate( 113*103e46e4SHarish Mahendrakar cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True) 114*103e46e4SHarish Mahendrakar duration = input_api.time.time() - start 115*103e46e4SHarish Mahendrakar if rc == 0: 116*103e46e4SHarish Mahendrakar return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" % 117*103e46e4SHarish Mahendrakar (name, " ".join(cmd), duration)) 118*103e46e4SHarish Mahendrakar return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" % 119*103e46e4SHarish Mahendrakar (name, " ".join(cmd), duration, output[1])) 120*103e46e4SHarish Mahendrakar 121*103e46e4SHarish Mahendrakar 122*103e46e4SHarish Mahendrakardef _RunCmdOnCheckedFiles(input_api, output_api, run_cmd, files_to_check): 123*103e46e4SHarish Mahendrakar """Ensure that libwebm/ files are clean.""" 124*103e46e4SHarish Mahendrakar file_filter = lambda x: input_api.FilterSourceFile( 125*103e46e4SHarish Mahendrakar x, files_to_check=files_to_check, files_to_skip=None) 126*103e46e4SHarish Mahendrakar 127*103e46e4SHarish Mahendrakar affected_files = input_api.change.AffectedFiles(file_filter=file_filter) 128*103e46e4SHarish Mahendrakar results = [ 129*103e46e4SHarish Mahendrakar run_cmd(input_api, output_api, f.AbsoluteLocalPath()) 130*103e46e4SHarish Mahendrakar for f in affected_files 131*103e46e4SHarish Mahendrakar ] 132*103e46e4SHarish Mahendrakar return results 133*103e46e4SHarish Mahendrakar 134*103e46e4SHarish Mahendrakar 135*103e46e4SHarish Mahendrakardef _CommonChecks(input_api, output_api): 136*103e46e4SHarish Mahendrakar results = [] 137*103e46e4SHarish Mahendrakar results.extend( 138*103e46e4SHarish Mahendrakar input_api.canned_checks.CheckChangeHasNoCrAndHasOnlyOneEol( 139*103e46e4SHarish Mahendrakar input_api, output_api)) 140*103e46e4SHarish Mahendrakar results.extend( 141*103e46e4SHarish Mahendrakar input_api.canned_checks.CheckChangeHasNoTabs(input_api, output_api)) 142*103e46e4SHarish Mahendrakar results.extend( 143*103e46e4SHarish Mahendrakar input_api.canned_checks.CheckChangeHasNoStrayWhitespace( 144*103e46e4SHarish Mahendrakar input_api, output_api)) 145*103e46e4SHarish Mahendrakar results.append(_CheckCommitSubjectLength(input_api, output_api)) 146*103e46e4SHarish Mahendrakar 147*103e46e4SHarish Mahendrakar source_file_filter = lambda x: input_api.FilterSourceFile( 148*103e46e4SHarish Mahendrakar x, files_to_skip=_GetFilesToSkip(input_api)) 149*103e46e4SHarish Mahendrakar results.extend( 150*103e46e4SHarish Mahendrakar input_api.canned_checks.CheckLongLines( 151*103e46e4SHarish Mahendrakar input_api, 152*103e46e4SHarish Mahendrakar output_api, 153*103e46e4SHarish Mahendrakar maxlen=_LIBWEBM_MAX_LINE_LENGTH, 154*103e46e4SHarish Mahendrakar source_file_filter=source_file_filter)) 155*103e46e4SHarish Mahendrakar 156*103e46e4SHarish Mahendrakar results.extend( 157*103e46e4SHarish Mahendrakar input_api.canned_checks.CheckPatchFormatted( 158*103e46e4SHarish Mahendrakar input_api, 159*103e46e4SHarish Mahendrakar output_api, 160*103e46e4SHarish Mahendrakar check_clang_format=True, 161*103e46e4SHarish Mahendrakar check_python=True, 162*103e46e4SHarish Mahendrakar result_factory=output_api.PresubmitError)) 163*103e46e4SHarish Mahendrakar results.extend(_CheckChangeLintsClean(input_api, output_api)) 164*103e46e4SHarish Mahendrakar 165*103e46e4SHarish Mahendrakar # Run pylint. 166*103e46e4SHarish Mahendrakar results.extend( 167*103e46e4SHarish Mahendrakar input_api.canned_checks.RunPylint( 168*103e46e4SHarish Mahendrakar input_api, 169*103e46e4SHarish Mahendrakar output_api, 170*103e46e4SHarish Mahendrakar files_to_skip=_GetFilesToSkip(input_api), 171*103e46e4SHarish Mahendrakar pylintrc=".pylintrc", 172*103e46e4SHarish Mahendrakar version="2.7")) 173*103e46e4SHarish Mahendrakar 174*103e46e4SHarish Mahendrakar # Binaries shellcheck and shfmt are not installed in depot_tools. 175*103e46e4SHarish Mahendrakar # Installation is needed 176*103e46e4SHarish Mahendrakar try: 177*103e46e4SHarish Mahendrakar subprocess2.communicate(["shellcheck", "--version"]) 178*103e46e4SHarish Mahendrakar results.extend( 179*103e46e4SHarish Mahendrakar _RunCmdOnCheckedFiles(input_api, output_api, _RunShellCheckCmd, 180*103e46e4SHarish Mahendrakar _INCLUDE_BASH_FILES_ONLY)) 181*103e46e4SHarish Mahendrakar print("shfmt") 182*103e46e4SHarish Mahendrakar subprocess2.communicate(["shfmt", "-version"]) 183*103e46e4SHarish Mahendrakar results.extend( 184*103e46e4SHarish Mahendrakar _RunCmdOnCheckedFiles(input_api, output_api, _RunShfmtCheckCmd, 185*103e46e4SHarish Mahendrakar _INCLUDE_BASH_FILES_ONLY)) 186*103e46e4SHarish Mahendrakar except OSError as os_error: 187*103e46e4SHarish Mahendrakar results.append( 188*103e46e4SHarish Mahendrakar output_api.PresubmitPromptWarning( 189*103e46e4SHarish Mahendrakar "%s\nPlease install missing binaries locally." % os_error.args[0])) 190*103e46e4SHarish Mahendrakar return results 191*103e46e4SHarish Mahendrakar 192*103e46e4SHarish Mahendrakar 193*103e46e4SHarish Mahendrakardef CheckChangeOnUpload(input_api, output_api): 194*103e46e4SHarish Mahendrakar results = [] 195*103e46e4SHarish Mahendrakar results.extend(_CommonChecks(input_api, output_api)) 196*103e46e4SHarish Mahendrakar return results 197*103e46e4SHarish Mahendrakar 198*103e46e4SHarish Mahendrakar 199*103e46e4SHarish Mahendrakardef CheckChangeOnCommit(input_api, output_api): 200*103e46e4SHarish Mahendrakar results = [] 201*103e46e4SHarish Mahendrakar results.extend(_CommonChecks(input_api, output_api)) 202*103e46e4SHarish Mahendrakar return results 203