1*8975f5c5SAndroid Build Coastguard Worker# Copyright 2019 The ANGLE Project Authors. All rights reserved. 2*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 3*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 4*8975f5c5SAndroid Build Coastguard Worker"""Top-level presubmit script for code generation. 5*8975f5c5SAndroid Build Coastguard Worker 6*8975f5c5SAndroid Build Coastguard WorkerSee http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts 7*8975f5c5SAndroid Build Coastguard Workerfor more details on the presubmit API built into depot_tools. 8*8975f5c5SAndroid Build Coastguard Worker""" 9*8975f5c5SAndroid Build Coastguard Worker 10*8975f5c5SAndroid Build Coastguard Workerimport itertools 11*8975f5c5SAndroid Build Coastguard Workerimport os 12*8975f5c5SAndroid Build Coastguard Workerimport re 13*8975f5c5SAndroid Build Coastguard Workerimport shutil 14*8975f5c5SAndroid Build Coastguard Workerimport subprocess 15*8975f5c5SAndroid Build Coastguard Workerimport sys 16*8975f5c5SAndroid Build Coastguard Workerimport tempfile 17*8975f5c5SAndroid Build Coastguard Workerimport textwrap 18*8975f5c5SAndroid Build Coastguard Workerimport pathlib 19*8975f5c5SAndroid Build Coastguard Worker 20*8975f5c5SAndroid Build Coastguard Worker# This line is 'magic' in that git-cl looks for it to decide whether to 21*8975f5c5SAndroid Build Coastguard Worker# use Python3 instead of Python2 when running the code in this file. 22*8975f5c5SAndroid Build Coastguard WorkerUSE_PYTHON3 = True 23*8975f5c5SAndroid Build Coastguard Worker 24*8975f5c5SAndroid Build Coastguard Worker# Fragment of a regular expression that matches C/C++ and Objective-C++ implementation files and headers. 25*8975f5c5SAndroid Build Coastguard Worker_IMPLEMENTATION_AND_HEADER_EXTENSIONS = r'\.(c|cc|cpp|cxx|mm|h|hpp|hxx)$' 26*8975f5c5SAndroid Build Coastguard Worker 27*8975f5c5SAndroid Build Coastguard Worker# Fragment of a regular expression that matches C++ and Objective-C++ header files. 28*8975f5c5SAndroid Build Coastguard Worker_HEADER_EXTENSIONS = r'\.(h|hpp|hxx)$' 29*8975f5c5SAndroid Build Coastguard Worker 30*8975f5c5SAndroid Build Coastguard Worker_PRIMARY_EXPORT_TARGETS = [ 31*8975f5c5SAndroid Build Coastguard Worker '//:libEGL', 32*8975f5c5SAndroid Build Coastguard Worker '//:libGLESv1_CM', 33*8975f5c5SAndroid Build Coastguard Worker '//:libGLESv2', 34*8975f5c5SAndroid Build Coastguard Worker '//:translator', 35*8975f5c5SAndroid Build Coastguard Worker] 36*8975f5c5SAndroid Build Coastguard Worker 37*8975f5c5SAndroid Build Coastguard Worker 38*8975f5c5SAndroid Build Coastguard Workerdef _SplitIntoMultipleCommits(description_text): 39*8975f5c5SAndroid Build Coastguard Worker paragraph_split_pattern = r"(?m)(^\s*$\n)" 40*8975f5c5SAndroid Build Coastguard Worker multiple_paragraphs = re.split(paragraph_split_pattern, description_text) 41*8975f5c5SAndroid Build Coastguard Worker multiple_commits = [""] 42*8975f5c5SAndroid Build Coastguard Worker change_id_pattern = re.compile(r"(?m)^Change-Id: [a-zA-Z0-9]*$") 43*8975f5c5SAndroid Build Coastguard Worker for paragraph in multiple_paragraphs: 44*8975f5c5SAndroid Build Coastguard Worker multiple_commits[-1] += paragraph 45*8975f5c5SAndroid Build Coastguard Worker if change_id_pattern.search(paragraph): 46*8975f5c5SAndroid Build Coastguard Worker multiple_commits.append("") 47*8975f5c5SAndroid Build Coastguard Worker if multiple_commits[-1] == "": 48*8975f5c5SAndroid Build Coastguard Worker multiple_commits.pop() 49*8975f5c5SAndroid Build Coastguard Worker return multiple_commits 50*8975f5c5SAndroid Build Coastguard Worker 51*8975f5c5SAndroid Build Coastguard Worker 52*8975f5c5SAndroid Build Coastguard Workerdef _CheckCommitMessageFormatting(input_api, output_api): 53*8975f5c5SAndroid Build Coastguard Worker 54*8975f5c5SAndroid Build Coastguard Worker def _IsLineBlank(line): 55*8975f5c5SAndroid Build Coastguard Worker return line.isspace() or line == "" 56*8975f5c5SAndroid Build Coastguard Worker 57*8975f5c5SAndroid Build Coastguard Worker def _PopBlankLines(lines, reverse=False): 58*8975f5c5SAndroid Build Coastguard Worker if reverse: 59*8975f5c5SAndroid Build Coastguard Worker while len(lines) > 0 and _IsLineBlank(lines[-1]): 60*8975f5c5SAndroid Build Coastguard Worker lines.pop() 61*8975f5c5SAndroid Build Coastguard Worker else: 62*8975f5c5SAndroid Build Coastguard Worker while len(lines) > 0 and _IsLineBlank(lines[0]): 63*8975f5c5SAndroid Build Coastguard Worker lines.pop(0) 64*8975f5c5SAndroid Build Coastguard Worker 65*8975f5c5SAndroid Build Coastguard Worker def _IsTagLine(line): 66*8975f5c5SAndroid Build Coastguard Worker return ":" in line 67*8975f5c5SAndroid Build Coastguard Worker 68*8975f5c5SAndroid Build Coastguard Worker def _CheckTabInCommit(lines): 69*8975f5c5SAndroid Build Coastguard Worker return all([line.find("\t") == -1 for line in lines]) 70*8975f5c5SAndroid Build Coastguard Worker 71*8975f5c5SAndroid Build Coastguard Worker allowlist_strings = ['Revert', 'Roll', 'Manual roll', 'Reland', 'Re-land'] 72*8975f5c5SAndroid Build Coastguard Worker summary_linelength_warning_lower_limit = 65 73*8975f5c5SAndroid Build Coastguard Worker summary_linelength_warning_upper_limit = 70 74*8975f5c5SAndroid Build Coastguard Worker description_linelength_limit = 72 75*8975f5c5SAndroid Build Coastguard Worker 76*8975f5c5SAndroid Build Coastguard Worker git_output = input_api.change.DescriptionText() 77*8975f5c5SAndroid Build Coastguard Worker 78*8975f5c5SAndroid Build Coastguard Worker multiple_commits = _SplitIntoMultipleCommits(git_output) 79*8975f5c5SAndroid Build Coastguard Worker errors = [] 80*8975f5c5SAndroid Build Coastguard Worker 81*8975f5c5SAndroid Build Coastguard Worker for k in range(len(multiple_commits)): 82*8975f5c5SAndroid Build Coastguard Worker commit_msg_lines = multiple_commits[k].splitlines() 83*8975f5c5SAndroid Build Coastguard Worker commit_number = len(multiple_commits) - k 84*8975f5c5SAndroid Build Coastguard Worker commit_tag = "Commit " + str(commit_number) + ":" 85*8975f5c5SAndroid Build Coastguard Worker commit_msg_line_numbers = {} 86*8975f5c5SAndroid Build Coastguard Worker for i in range(len(commit_msg_lines)): 87*8975f5c5SAndroid Build Coastguard Worker commit_msg_line_numbers[commit_msg_lines[i]] = i + 1 88*8975f5c5SAndroid Build Coastguard Worker _PopBlankLines(commit_msg_lines, True) 89*8975f5c5SAndroid Build Coastguard Worker _PopBlankLines(commit_msg_lines, False) 90*8975f5c5SAndroid Build Coastguard Worker allowlisted = False 91*8975f5c5SAndroid Build Coastguard Worker if len(commit_msg_lines) > 0: 92*8975f5c5SAndroid Build Coastguard Worker for allowlist_string in allowlist_strings: 93*8975f5c5SAndroid Build Coastguard Worker if commit_msg_lines[0].startswith(allowlist_string): 94*8975f5c5SAndroid Build Coastguard Worker allowlisted = True 95*8975f5c5SAndroid Build Coastguard Worker break 96*8975f5c5SAndroid Build Coastguard Worker if allowlisted: 97*8975f5c5SAndroid Build Coastguard Worker continue 98*8975f5c5SAndroid Build Coastguard Worker 99*8975f5c5SAndroid Build Coastguard Worker if not _CheckTabInCommit(commit_msg_lines): 100*8975f5c5SAndroid Build Coastguard Worker errors.append( 101*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError(commit_tag + "Tabs are not allowed in commit message.")) 102*8975f5c5SAndroid Build Coastguard Worker 103*8975f5c5SAndroid Build Coastguard Worker # the tags paragraph is at the end of the message 104*8975f5c5SAndroid Build Coastguard Worker # the break between the tags paragraph is the first line without ":" 105*8975f5c5SAndroid Build Coastguard Worker # this is sufficient because if a line is blank, it will not have ":" 106*8975f5c5SAndroid Build Coastguard Worker last_paragraph_line_count = 0 107*8975f5c5SAndroid Build Coastguard Worker while len(commit_msg_lines) > 0 and _IsTagLine(commit_msg_lines[-1]): 108*8975f5c5SAndroid Build Coastguard Worker last_paragraph_line_count += 1 109*8975f5c5SAndroid Build Coastguard Worker commit_msg_lines.pop() 110*8975f5c5SAndroid Build Coastguard Worker if last_paragraph_line_count == 0: 111*8975f5c5SAndroid Build Coastguard Worker errors.append( 112*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError( 113*8975f5c5SAndroid Build Coastguard Worker commit_tag + 114*8975f5c5SAndroid Build Coastguard Worker "Please ensure that there are tags (e.g., Bug:, Test:) in your description.")) 115*8975f5c5SAndroid Build Coastguard Worker if len(commit_msg_lines) > 0: 116*8975f5c5SAndroid Build Coastguard Worker if not _IsLineBlank(commit_msg_lines[-1]): 117*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError(commit_tag + 118*8975f5c5SAndroid Build Coastguard Worker "Please ensure that there exists 1 blank line " + 119*8975f5c5SAndroid Build Coastguard Worker "between tags and description body.") 120*8975f5c5SAndroid Build Coastguard Worker else: 121*8975f5c5SAndroid Build Coastguard Worker # pop the blank line between tag paragraph and description body 122*8975f5c5SAndroid Build Coastguard Worker commit_msg_lines.pop() 123*8975f5c5SAndroid Build Coastguard Worker if len(commit_msg_lines) > 0 and _IsLineBlank(commit_msg_lines[-1]): 124*8975f5c5SAndroid Build Coastguard Worker errors.append( 125*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError( 126*8975f5c5SAndroid Build Coastguard Worker commit_tag + 'Please ensure that there exists only 1 blank line ' 127*8975f5c5SAndroid Build Coastguard Worker 'between tags and description body.')) 128*8975f5c5SAndroid Build Coastguard Worker # pop all the remaining blank lines between tag and description body 129*8975f5c5SAndroid Build Coastguard Worker _PopBlankLines(commit_msg_lines, True) 130*8975f5c5SAndroid Build Coastguard Worker if len(commit_msg_lines) == 0: 131*8975f5c5SAndroid Build Coastguard Worker errors.append( 132*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError(commit_tag + 133*8975f5c5SAndroid Build Coastguard Worker 'Please ensure that your description summary' 134*8975f5c5SAndroid Build Coastguard Worker ' and description body are not blank.')) 135*8975f5c5SAndroid Build Coastguard Worker continue 136*8975f5c5SAndroid Build Coastguard Worker 137*8975f5c5SAndroid Build Coastguard Worker if summary_linelength_warning_lower_limit <= len(commit_msg_lines[0]) \ 138*8975f5c5SAndroid Build Coastguard Worker <= summary_linelength_warning_upper_limit: 139*8975f5c5SAndroid Build Coastguard Worker errors.append( 140*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitPromptWarning( 141*8975f5c5SAndroid Build Coastguard Worker commit_tag + "Your description summary should be on one line of " + 142*8975f5c5SAndroid Build Coastguard Worker str(summary_linelength_warning_lower_limit - 1) + " or less characters.")) 143*8975f5c5SAndroid Build Coastguard Worker elif len(commit_msg_lines[0]) > summary_linelength_warning_upper_limit: 144*8975f5c5SAndroid Build Coastguard Worker errors.append( 145*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError( 146*8975f5c5SAndroid Build Coastguard Worker commit_tag + "Please ensure that your description summary is on one line of " + 147*8975f5c5SAndroid Build Coastguard Worker str(summary_linelength_warning_lower_limit - 1) + " or less characters.")) 148*8975f5c5SAndroid Build Coastguard Worker commit_msg_lines.pop(0) # get rid of description summary 149*8975f5c5SAndroid Build Coastguard Worker if len(commit_msg_lines) == 0: 150*8975f5c5SAndroid Build Coastguard Worker continue 151*8975f5c5SAndroid Build Coastguard Worker if not _IsLineBlank(commit_msg_lines[0]): 152*8975f5c5SAndroid Build Coastguard Worker errors.append( 153*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError(commit_tag + 154*8975f5c5SAndroid Build Coastguard Worker 'Please ensure the summary is only 1 line and ' 155*8975f5c5SAndroid Build Coastguard Worker 'there is 1 blank line between the summary ' 156*8975f5c5SAndroid Build Coastguard Worker 'and description body.')) 157*8975f5c5SAndroid Build Coastguard Worker else: 158*8975f5c5SAndroid Build Coastguard Worker commit_msg_lines.pop(0) # pop first blank line 159*8975f5c5SAndroid Build Coastguard Worker if len(commit_msg_lines) == 0: 160*8975f5c5SAndroid Build Coastguard Worker continue 161*8975f5c5SAndroid Build Coastguard Worker if _IsLineBlank(commit_msg_lines[0]): 162*8975f5c5SAndroid Build Coastguard Worker errors.append( 163*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError(commit_tag + 164*8975f5c5SAndroid Build Coastguard Worker 'Please ensure that there exists only 1 blank line ' 165*8975f5c5SAndroid Build Coastguard Worker 'between description summary and description body.')) 166*8975f5c5SAndroid Build Coastguard Worker # pop all the remaining blank lines between 167*8975f5c5SAndroid Build Coastguard Worker # description summary and description body 168*8975f5c5SAndroid Build Coastguard Worker _PopBlankLines(commit_msg_lines) 169*8975f5c5SAndroid Build Coastguard Worker 170*8975f5c5SAndroid Build Coastguard Worker # loop through description body 171*8975f5c5SAndroid Build Coastguard Worker while len(commit_msg_lines) > 0: 172*8975f5c5SAndroid Build Coastguard Worker line = commit_msg_lines.pop(0) 173*8975f5c5SAndroid Build Coastguard Worker # lines starting with 4 spaces, quotes or lines without space(urls) 174*8975f5c5SAndroid Build Coastguard Worker # are exempt from length check 175*8975f5c5SAndroid Build Coastguard Worker if line.startswith(" ") or line.startswith("> ") or " " not in line: 176*8975f5c5SAndroid Build Coastguard Worker continue 177*8975f5c5SAndroid Build Coastguard Worker if len(line) > description_linelength_limit: 178*8975f5c5SAndroid Build Coastguard Worker errors.append( 179*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError( 180*8975f5c5SAndroid Build Coastguard Worker commit_tag + 'Line ' + str(commit_msg_line_numbers[line]) + 181*8975f5c5SAndroid Build Coastguard Worker ' is too long.\n' + '"' + line + '"\n' + 'Please wrap it to ' + 182*8975f5c5SAndroid Build Coastguard Worker str(description_linelength_limit) + ' characters. ' + 183*8975f5c5SAndroid Build Coastguard Worker "Lines without spaces or lines starting with 4 spaces are exempt.")) 184*8975f5c5SAndroid Build Coastguard Worker break 185*8975f5c5SAndroid Build Coastguard Worker return errors 186*8975f5c5SAndroid Build Coastguard Worker 187*8975f5c5SAndroid Build Coastguard Worker 188*8975f5c5SAndroid Build Coastguard Workerdef _CheckChangeHasBugField(input_api, output_api): 189*8975f5c5SAndroid Build Coastguard Worker """Requires that the changelist have a Bug: field from a known project.""" 190*8975f5c5SAndroid Build Coastguard Worker bugs = input_api.change.BugsFromDescription() 191*8975f5c5SAndroid Build Coastguard Worker 192*8975f5c5SAndroid Build Coastguard Worker # The bug must be in the form of "project:number". None is also accepted, which is used by 193*8975f5c5SAndroid Build Coastguard Worker # rollers as well as in very minor changes. 194*8975f5c5SAndroid Build Coastguard Worker if len(bugs) == 1 and bugs[0] == 'None': 195*8975f5c5SAndroid Build Coastguard Worker return [] 196*8975f5c5SAndroid Build Coastguard Worker 197*8975f5c5SAndroid Build Coastguard Worker projects = [ 198*8975f5c5SAndroid Build Coastguard Worker 'angleproject:', 'chromium:', 'dawn:', 'fuchsia:', 'skia:', 'swiftshader:', 'tint:', 'b/' 199*8975f5c5SAndroid Build Coastguard Worker ] 200*8975f5c5SAndroid Build Coastguard Worker bug_regex = re.compile(r"([a-z]+[:/])(\d+)") 201*8975f5c5SAndroid Build Coastguard Worker errors = [] 202*8975f5c5SAndroid Build Coastguard Worker extra_help = False 203*8975f5c5SAndroid Build Coastguard Worker 204*8975f5c5SAndroid Build Coastguard Worker if not bugs: 205*8975f5c5SAndroid Build Coastguard Worker errors.append('Please ensure that your description contains\n' 206*8975f5c5SAndroid Build Coastguard Worker 'Bug: bugtag\n' 207*8975f5c5SAndroid Build Coastguard Worker 'directly above the Change-Id tag (no empty line in-between)') 208*8975f5c5SAndroid Build Coastguard Worker extra_help = True 209*8975f5c5SAndroid Build Coastguard Worker 210*8975f5c5SAndroid Build Coastguard Worker for bug in bugs: 211*8975f5c5SAndroid Build Coastguard Worker if bug == 'None': 212*8975f5c5SAndroid Build Coastguard Worker errors.append('Invalid bug tag "None" in presence of other bug tags.') 213*8975f5c5SAndroid Build Coastguard Worker continue 214*8975f5c5SAndroid Build Coastguard Worker 215*8975f5c5SAndroid Build Coastguard Worker match = re.match(bug_regex, bug) 216*8975f5c5SAndroid Build Coastguard Worker if match == None or bug != match.group(0) or match.group(1) not in projects: 217*8975f5c5SAndroid Build Coastguard Worker errors.append('Incorrect bug tag "' + bug + '".') 218*8975f5c5SAndroid Build Coastguard Worker extra_help = True 219*8975f5c5SAndroid Build Coastguard Worker 220*8975f5c5SAndroid Build Coastguard Worker if extra_help: 221*8975f5c5SAndroid Build Coastguard Worker change_ids = re.findall('^Change-Id:', input_api.change.FullDescriptionText(), re.M) 222*8975f5c5SAndroid Build Coastguard Worker if len(change_ids) > 1: 223*8975f5c5SAndroid Build Coastguard Worker errors.append('Note: multiple Change-Id tags found in description') 224*8975f5c5SAndroid Build Coastguard Worker 225*8975f5c5SAndroid Build Coastguard Worker errors.append('''Acceptable bugtags: 226*8975f5c5SAndroid Build Coastguard Worker project:bugnumber - where project is one of ({projects}) 227*8975f5c5SAndroid Build Coastguard Worker b/bugnumber - for Buganizer/IssueTracker bugs 228*8975f5c5SAndroid Build Coastguard Worker'''.format(projects=', '.join(p[:-1] for p in projects if p != 'b/'))) 229*8975f5c5SAndroid Build Coastguard Worker 230*8975f5c5SAndroid Build Coastguard Worker return [output_api.PresubmitError('\n\n'.join(errors))] if errors else [] 231*8975f5c5SAndroid Build Coastguard Worker 232*8975f5c5SAndroid Build Coastguard Worker 233*8975f5c5SAndroid Build Coastguard Workerdef _CheckCodeGeneration(input_api, output_api): 234*8975f5c5SAndroid Build Coastguard Worker 235*8975f5c5SAndroid Build Coastguard Worker class Msg(output_api.PresubmitError): 236*8975f5c5SAndroid Build Coastguard Worker """Specialized error message""" 237*8975f5c5SAndroid Build Coastguard Worker 238*8975f5c5SAndroid Build Coastguard Worker def __init__(self, message, **kwargs): 239*8975f5c5SAndroid Build Coastguard Worker super(output_api.PresubmitError, self).__init__( 240*8975f5c5SAndroid Build Coastguard Worker message, 241*8975f5c5SAndroid Build Coastguard Worker long_text='Please ensure your ANGLE repositiory is synced to tip-of-tree\n' 242*8975f5c5SAndroid Build Coastguard Worker 'and all ANGLE DEPS are fully up-to-date by running gclient sync.\n' 243*8975f5c5SAndroid Build Coastguard Worker '\n' 244*8975f5c5SAndroid Build Coastguard Worker 'If that fails, run scripts/run_code_generation.py to refresh generated hashes.\n' 245*8975f5c5SAndroid Build Coastguard Worker '\n' 246*8975f5c5SAndroid Build Coastguard Worker 'If you are building ANGLE inside Chromium you must bootstrap ANGLE\n' 247*8975f5c5SAndroid Build Coastguard Worker 'before gclient sync. See the DevSetup documentation for more details.\n', 248*8975f5c5SAndroid Build Coastguard Worker **kwargs) 249*8975f5c5SAndroid Build Coastguard Worker 250*8975f5c5SAndroid Build Coastguard Worker code_gen_path = input_api.os_path.join(input_api.PresubmitLocalPath(), 251*8975f5c5SAndroid Build Coastguard Worker 'scripts/run_code_generation.py') 252*8975f5c5SAndroid Build Coastguard Worker cmd_name = 'run_code_generation' 253*8975f5c5SAndroid Build Coastguard Worker cmd = [input_api.python3_executable, code_gen_path, '--verify-no-dirty'] 254*8975f5c5SAndroid Build Coastguard Worker test_cmd = input_api.Command(name=cmd_name, cmd=cmd, kwargs={}, message=Msg) 255*8975f5c5SAndroid Build Coastguard Worker if input_api.verbose: 256*8975f5c5SAndroid Build Coastguard Worker print('Running ' + cmd_name) 257*8975f5c5SAndroid Build Coastguard Worker return input_api.RunTests([test_cmd]) 258*8975f5c5SAndroid Build Coastguard Worker 259*8975f5c5SAndroid Build Coastguard Worker 260*8975f5c5SAndroid Build Coastguard Worker# Taken directly from Chromium's PRESUBMIT.py 261*8975f5c5SAndroid Build Coastguard Workerdef _CheckNewHeaderWithoutGnChange(input_api, output_api): 262*8975f5c5SAndroid Build Coastguard Worker """Checks that newly added header files have corresponding GN changes. 263*8975f5c5SAndroid Build Coastguard Worker Note that this is only a heuristic. To be precise, run script: 264*8975f5c5SAndroid Build Coastguard Worker build/check_gn_headers.py. 265*8975f5c5SAndroid Build Coastguard Worker """ 266*8975f5c5SAndroid Build Coastguard Worker 267*8975f5c5SAndroid Build Coastguard Worker def headers(f): 268*8975f5c5SAndroid Build Coastguard Worker return input_api.FilterSourceFile(f, files_to_check=(r'.+%s' % _HEADER_EXTENSIONS,)) 269*8975f5c5SAndroid Build Coastguard Worker 270*8975f5c5SAndroid Build Coastguard Worker new_headers = [] 271*8975f5c5SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(headers): 272*8975f5c5SAndroid Build Coastguard Worker if f.Action() != 'A': 273*8975f5c5SAndroid Build Coastguard Worker continue 274*8975f5c5SAndroid Build Coastguard Worker new_headers.append(f.LocalPath()) 275*8975f5c5SAndroid Build Coastguard Worker 276*8975f5c5SAndroid Build Coastguard Worker def gn_files(f): 277*8975f5c5SAndroid Build Coastguard Worker return input_api.FilterSourceFile(f, files_to_check=(r'.+\.gn',)) 278*8975f5c5SAndroid Build Coastguard Worker 279*8975f5c5SAndroid Build Coastguard Worker all_gn_changed_contents = '' 280*8975f5c5SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(gn_files): 281*8975f5c5SAndroid Build Coastguard Worker for _, line in f.ChangedContents(): 282*8975f5c5SAndroid Build Coastguard Worker all_gn_changed_contents += line 283*8975f5c5SAndroid Build Coastguard Worker 284*8975f5c5SAndroid Build Coastguard Worker problems = [] 285*8975f5c5SAndroid Build Coastguard Worker for header in new_headers: 286*8975f5c5SAndroid Build Coastguard Worker basename = input_api.os_path.basename(header) 287*8975f5c5SAndroid Build Coastguard Worker if basename not in all_gn_changed_contents: 288*8975f5c5SAndroid Build Coastguard Worker problems.append(header) 289*8975f5c5SAndroid Build Coastguard Worker 290*8975f5c5SAndroid Build Coastguard Worker if problems: 291*8975f5c5SAndroid Build Coastguard Worker return [ 292*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitPromptWarning( 293*8975f5c5SAndroid Build Coastguard Worker 'Missing GN changes for new header files', 294*8975f5c5SAndroid Build Coastguard Worker items=sorted(problems), 295*8975f5c5SAndroid Build Coastguard Worker long_text='Please double check whether newly added header files need ' 296*8975f5c5SAndroid Build Coastguard Worker 'corresponding changes in gn or gni files.\nThis checking is only a ' 297*8975f5c5SAndroid Build Coastguard Worker 'heuristic. Run build/check_gn_headers.py to be precise.\n' 298*8975f5c5SAndroid Build Coastguard Worker 'Read https://crbug.com/661774 for more info.') 299*8975f5c5SAndroid Build Coastguard Worker ] 300*8975f5c5SAndroid Build Coastguard Worker return [] 301*8975f5c5SAndroid Build Coastguard Worker 302*8975f5c5SAndroid Build Coastguard Worker 303*8975f5c5SAndroid Build Coastguard Workerdef _CheckExportValidity(input_api, output_api): 304*8975f5c5SAndroid Build Coastguard Worker outdir = tempfile.mkdtemp() 305*8975f5c5SAndroid Build Coastguard Worker # shell=True is necessary on Windows, as otherwise subprocess fails to find 306*8975f5c5SAndroid Build Coastguard Worker # either 'gn' or 'vpython3' even if they are findable via PATH. 307*8975f5c5SAndroid Build Coastguard Worker use_shell = input_api.is_windows 308*8975f5c5SAndroid Build Coastguard Worker try: 309*8975f5c5SAndroid Build Coastguard Worker try: 310*8975f5c5SAndroid Build Coastguard Worker subprocess.check_output(['gn', 'gen', outdir], shell=use_shell) 311*8975f5c5SAndroid Build Coastguard Worker except subprocess.CalledProcessError as e: 312*8975f5c5SAndroid Build Coastguard Worker return [ 313*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError('Unable to run gn gen for export_targets.py: %s' % 314*8975f5c5SAndroid Build Coastguard Worker e.output.decode()) 315*8975f5c5SAndroid Build Coastguard Worker ] 316*8975f5c5SAndroid Build Coastguard Worker export_target_script = os.path.join(input_api.PresubmitLocalPath(), 'scripts', 317*8975f5c5SAndroid Build Coastguard Worker 'export_targets.py') 318*8975f5c5SAndroid Build Coastguard Worker try: 319*8975f5c5SAndroid Build Coastguard Worker subprocess.check_output( 320*8975f5c5SAndroid Build Coastguard Worker ['vpython3', export_target_script, outdir] + _PRIMARY_EXPORT_TARGETS, 321*8975f5c5SAndroid Build Coastguard Worker stderr=subprocess.STDOUT, 322*8975f5c5SAndroid Build Coastguard Worker shell=use_shell) 323*8975f5c5SAndroid Build Coastguard Worker except subprocess.CalledProcessError as e: 324*8975f5c5SAndroid Build Coastguard Worker if input_api.is_committing: 325*8975f5c5SAndroid Build Coastguard Worker return [ 326*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError('export_targets.py failed: %s' % e.output.decode()) 327*8975f5c5SAndroid Build Coastguard Worker ] 328*8975f5c5SAndroid Build Coastguard Worker return [ 329*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitPromptWarning( 330*8975f5c5SAndroid Build Coastguard Worker 'export_targets.py failed, this may just be due to your local checkout: %s' % 331*8975f5c5SAndroid Build Coastguard Worker e.output.decode()) 332*8975f5c5SAndroid Build Coastguard Worker ] 333*8975f5c5SAndroid Build Coastguard Worker return [] 334*8975f5c5SAndroid Build Coastguard Worker finally: 335*8975f5c5SAndroid Build Coastguard Worker shutil.rmtree(outdir) 336*8975f5c5SAndroid Build Coastguard Worker 337*8975f5c5SAndroid Build Coastguard Worker 338*8975f5c5SAndroid Build Coastguard Workerdef _CheckTabsInSourceFiles(input_api, output_api): 339*8975f5c5SAndroid Build Coastguard Worker """Forbids tab characters in source files due to a WebKit repo requirement.""" 340*8975f5c5SAndroid Build Coastguard Worker 341*8975f5c5SAndroid Build Coastguard Worker def implementation_and_headers_including_third_party(f): 342*8975f5c5SAndroid Build Coastguard Worker # Check third_party files too, because WebKit's checks don't make exceptions. 343*8975f5c5SAndroid Build Coastguard Worker return input_api.FilterSourceFile( 344*8975f5c5SAndroid Build Coastguard Worker f, 345*8975f5c5SAndroid Build Coastguard Worker files_to_check=(r'.+%s' % _IMPLEMENTATION_AND_HEADER_EXTENSIONS,), 346*8975f5c5SAndroid Build Coastguard Worker files_to_skip=[f for f in input_api.DEFAULT_FILES_TO_SKIP if not "third_party" in f]) 347*8975f5c5SAndroid Build Coastguard Worker 348*8975f5c5SAndroid Build Coastguard Worker files_with_tabs = [] 349*8975f5c5SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(implementation_and_headers_including_third_party): 350*8975f5c5SAndroid Build Coastguard Worker for (num, line) in f.ChangedContents(): 351*8975f5c5SAndroid Build Coastguard Worker if '\t' in line: 352*8975f5c5SAndroid Build Coastguard Worker files_with_tabs.append(f) 353*8975f5c5SAndroid Build Coastguard Worker break 354*8975f5c5SAndroid Build Coastguard Worker 355*8975f5c5SAndroid Build Coastguard Worker if files_with_tabs: 356*8975f5c5SAndroid Build Coastguard Worker return [ 357*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError( 358*8975f5c5SAndroid Build Coastguard Worker 'Tab characters in source files.', 359*8975f5c5SAndroid Build Coastguard Worker items=sorted(files_with_tabs), 360*8975f5c5SAndroid Build Coastguard Worker long_text= 361*8975f5c5SAndroid Build Coastguard Worker 'Tab characters are forbidden in ANGLE source files because WebKit\'s Subversion\n' 362*8975f5c5SAndroid Build Coastguard Worker 'repository does not allow tab characters in source files.\n' 363*8975f5c5SAndroid Build Coastguard Worker 'Please remove tab characters from these files.') 364*8975f5c5SAndroid Build Coastguard Worker ] 365*8975f5c5SAndroid Build Coastguard Worker return [] 366*8975f5c5SAndroid Build Coastguard Worker 367*8975f5c5SAndroid Build Coastguard Worker 368*8975f5c5SAndroid Build Coastguard Worker# https://stackoverflow.com/a/196392 369*8975f5c5SAndroid Build Coastguard Workerdef is_ascii(s): 370*8975f5c5SAndroid Build Coastguard Worker return all(ord(c) < 128 for c in s) 371*8975f5c5SAndroid Build Coastguard Worker 372*8975f5c5SAndroid Build Coastguard Worker 373*8975f5c5SAndroid Build Coastguard Workerdef _CheckNonAsciiInSourceFiles(input_api, output_api): 374*8975f5c5SAndroid Build Coastguard Worker """Forbids non-ascii characters in source files.""" 375*8975f5c5SAndroid Build Coastguard Worker 376*8975f5c5SAndroid Build Coastguard Worker def implementation_and_headers(f): 377*8975f5c5SAndroid Build Coastguard Worker return input_api.FilterSourceFile( 378*8975f5c5SAndroid Build Coastguard Worker f, files_to_check=(r'.+%s' % _IMPLEMENTATION_AND_HEADER_EXTENSIONS,)) 379*8975f5c5SAndroid Build Coastguard Worker 380*8975f5c5SAndroid Build Coastguard Worker files_with_non_ascii = [] 381*8975f5c5SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(implementation_and_headers): 382*8975f5c5SAndroid Build Coastguard Worker for (num, line) in f.ChangedContents(): 383*8975f5c5SAndroid Build Coastguard Worker if not is_ascii(line): 384*8975f5c5SAndroid Build Coastguard Worker files_with_non_ascii.append("%s: %s" % (f, line)) 385*8975f5c5SAndroid Build Coastguard Worker break 386*8975f5c5SAndroid Build Coastguard Worker 387*8975f5c5SAndroid Build Coastguard Worker if files_with_non_ascii: 388*8975f5c5SAndroid Build Coastguard Worker return [ 389*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError( 390*8975f5c5SAndroid Build Coastguard Worker 'Non-ASCII characters in source files.', 391*8975f5c5SAndroid Build Coastguard Worker items=sorted(files_with_non_ascii), 392*8975f5c5SAndroid Build Coastguard Worker long_text='Non-ASCII characters are forbidden in ANGLE source files.\n' 393*8975f5c5SAndroid Build Coastguard Worker 'Please remove non-ASCII characters from these files.') 394*8975f5c5SAndroid Build Coastguard Worker ] 395*8975f5c5SAndroid Build Coastguard Worker return [] 396*8975f5c5SAndroid Build Coastguard Worker 397*8975f5c5SAndroid Build Coastguard Worker 398*8975f5c5SAndroid Build Coastguard Workerdef _CheckCommentBeforeTestInTestFiles(input_api, output_api): 399*8975f5c5SAndroid Build Coastguard Worker """Require a comment before TEST_P() and other tests.""" 400*8975f5c5SAndroid Build Coastguard Worker 401*8975f5c5SAndroid Build Coastguard Worker def test_files(f): 402*8975f5c5SAndroid Build Coastguard Worker return input_api.FilterSourceFile( 403*8975f5c5SAndroid Build Coastguard Worker f, files_to_check=(r'^src/tests/.+\.cpp$', r'^src/.+_unittest\.cpp$')) 404*8975f5c5SAndroid Build Coastguard Worker 405*8975f5c5SAndroid Build Coastguard Worker tests_with_no_comment = [] 406*8975f5c5SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(test_files): 407*8975f5c5SAndroid Build Coastguard Worker diff = f.GenerateScmDiff() 408*8975f5c5SAndroid Build Coastguard Worker last_line_was_comment = False 409*8975f5c5SAndroid Build Coastguard Worker for line in diff.splitlines(): 410*8975f5c5SAndroid Build Coastguard Worker # Skip removed lines 411*8975f5c5SAndroid Build Coastguard Worker if line.startswith('-'): 412*8975f5c5SAndroid Build Coastguard Worker continue 413*8975f5c5SAndroid Build Coastguard Worker 414*8975f5c5SAndroid Build Coastguard Worker new_line_is_comment = line.startswith(' //') or line.startswith('+//') 415*8975f5c5SAndroid Build Coastguard Worker new_line_is_test_declaration = ( 416*8975f5c5SAndroid Build Coastguard Worker line.startswith('+TEST_P(') or line.startswith('+TEST(') or 417*8975f5c5SAndroid Build Coastguard Worker line.startswith('+TYPED_TEST(')) 418*8975f5c5SAndroid Build Coastguard Worker 419*8975f5c5SAndroid Build Coastguard Worker if new_line_is_test_declaration and not last_line_was_comment: 420*8975f5c5SAndroid Build Coastguard Worker tests_with_no_comment.append(line[1:]) 421*8975f5c5SAndroid Build Coastguard Worker 422*8975f5c5SAndroid Build Coastguard Worker last_line_was_comment = new_line_is_comment 423*8975f5c5SAndroid Build Coastguard Worker 424*8975f5c5SAndroid Build Coastguard Worker if tests_with_no_comment: 425*8975f5c5SAndroid Build Coastguard Worker return [ 426*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError( 427*8975f5c5SAndroid Build Coastguard Worker 'Tests without comment.', 428*8975f5c5SAndroid Build Coastguard Worker items=sorted(tests_with_no_comment), 429*8975f5c5SAndroid Build Coastguard Worker long_text='ANGLE requires a comment describing what a test does.') 430*8975f5c5SAndroid Build Coastguard Worker ] 431*8975f5c5SAndroid Build Coastguard Worker return [] 432*8975f5c5SAndroid Build Coastguard Worker 433*8975f5c5SAndroid Build Coastguard Worker 434*8975f5c5SAndroid Build Coastguard Workerdef _CheckWildcardInTestExpectationFiles(input_api, output_api): 435*8975f5c5SAndroid Build Coastguard Worker """Require wildcard as API tag (i.e. in foo.bar/*) in expectations when no additional feature is 436*8975f5c5SAndroid Build Coastguard Worker enabled.""" 437*8975f5c5SAndroid Build Coastguard Worker 438*8975f5c5SAndroid Build Coastguard Worker def expectation_files(f): 439*8975f5c5SAndroid Build Coastguard Worker return input_api.FilterSourceFile( 440*8975f5c5SAndroid Build Coastguard Worker f, files_to_check=[r'^src/tests/angle_end2end_tests_expectations.txt$']) 441*8975f5c5SAndroid Build Coastguard Worker 442*8975f5c5SAndroid Build Coastguard Worker expectation_pattern = re.compile(r'^.*:\s*[a-zA-Z0-9._*]+\/([^ ]*)\s*=.*$') 443*8975f5c5SAndroid Build Coastguard Worker 444*8975f5c5SAndroid Build Coastguard Worker expectations_without_wildcard = [] 445*8975f5c5SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(expectation_files): 446*8975f5c5SAndroid Build Coastguard Worker diff = f.GenerateScmDiff() 447*8975f5c5SAndroid Build Coastguard Worker for line in diff.splitlines(): 448*8975f5c5SAndroid Build Coastguard Worker # Only look at new lines 449*8975f5c5SAndroid Build Coastguard Worker if not line.startswith('+'): 450*8975f5c5SAndroid Build Coastguard Worker continue 451*8975f5c5SAndroid Build Coastguard Worker 452*8975f5c5SAndroid Build Coastguard Worker match = re.match(expectation_pattern, line[1:].strip()) 453*8975f5c5SAndroid Build Coastguard Worker if match is None: 454*8975f5c5SAndroid Build Coastguard Worker continue 455*8975f5c5SAndroid Build Coastguard Worker 456*8975f5c5SAndroid Build Coastguard Worker tag = match.group(1) 457*8975f5c5SAndroid Build Coastguard Worker 458*8975f5c5SAndroid Build Coastguard Worker # The tag is in the following general form: 459*8975f5c5SAndroid Build Coastguard Worker # 460*8975f5c5SAndroid Build Coastguard Worker # FRONTENDAPI_BACKENDAPI[_FEATURE]* 461*8975f5c5SAndroid Build Coastguard Worker # 462*8975f5c5SAndroid Build Coastguard Worker # Any part of the above may be a wildcard. Warn about usage of FRONTEND_BACKENDAPI as 463*8975f5c5SAndroid Build Coastguard Worker # the tag. Instead, the backend should be specified before the : and `*` used as the 464*8975f5c5SAndroid Build Coastguard Worker # tag. If any additional tags are present, it's a specific expectation that should 465*8975f5c5SAndroid Build Coastguard Worker # remain specific (and not wildcarded). NoFixture is an exception as X_Y_NoFixture is 466*8975f5c5SAndroid Build Coastguard Worker # the generic form of the tags of tests that don't use the fixture. 467*8975f5c5SAndroid Build Coastguard Worker 468*8975f5c5SAndroid Build Coastguard Worker sections = [section for section in tag.split('_') if section != 'NoFixture'] 469*8975f5c5SAndroid Build Coastguard Worker 470*8975f5c5SAndroid Build Coastguard Worker # Allow '*_...', or 'FRONTENDAPI_*_...'. 471*8975f5c5SAndroid Build Coastguard Worker if '*' in sections[0] or (len(sections) > 1 and '*' in sections[1]): 472*8975f5c5SAndroid Build Coastguard Worker continue 473*8975f5c5SAndroid Build Coastguard Worker 474*8975f5c5SAndroid Build Coastguard Worker # Warn if no additional tags are present 475*8975f5c5SAndroid Build Coastguard Worker if len(sections) == 2: 476*8975f5c5SAndroid Build Coastguard Worker expectations_without_wildcard.append(line[1:]) 477*8975f5c5SAndroid Build Coastguard Worker 478*8975f5c5SAndroid Build Coastguard Worker if expectations_without_wildcard: 479*8975f5c5SAndroid Build Coastguard Worker return [ 480*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError( 481*8975f5c5SAndroid Build Coastguard Worker 'Use wildcard in API tags (after /) in angle_end2end_tests_expectations.txt.', 482*8975f5c5SAndroid Build Coastguard Worker items=expectations_without_wildcard, 483*8975f5c5SAndroid Build Coastguard Worker long_text="""ANGLE prefers end2end expections to use the following form: 484*8975f5c5SAndroid Build Coastguard Worker 485*8975f5c5SAndroid Build Coastguard Worker1234 MAC OPENGL : Foo.Bar/* = SKIP 486*8975f5c5SAndroid Build Coastguard Worker 487*8975f5c5SAndroid Build Coastguard Workerinstead of: 488*8975f5c5SAndroid Build Coastguard Worker 489*8975f5c5SAndroid Build Coastguard Worker1234 MAC OPENGL : Foo.Bar/ES2_OpenGL = SKIP 490*8975f5c5SAndroid Build Coastguard Worker1234 MAC OPENGL : Foo.Bar/ES3_OpenGL = SKIP 491*8975f5c5SAndroid Build Coastguard Worker 492*8975f5c5SAndroid Build Coastguard WorkerExpectatations that are specific (such as Foo.Bar/ES2_OpenGL_SomeFeature) are allowed.""") 493*8975f5c5SAndroid Build Coastguard Worker ] 494*8975f5c5SAndroid Build Coastguard Worker return [] 495*8975f5c5SAndroid Build Coastguard Worker 496*8975f5c5SAndroid Build Coastguard Worker 497*8975f5c5SAndroid Build Coastguard Workerdef _CheckShaderVersionInShaderLangHeader(input_api, output_api): 498*8975f5c5SAndroid Build Coastguard Worker """Requires an update to ANGLE_SH_VERSION when ShaderLang.h or ShaderVars.h change.""" 499*8975f5c5SAndroid Build Coastguard Worker 500*8975f5c5SAndroid Build Coastguard Worker def headers(f): 501*8975f5c5SAndroid Build Coastguard Worker return input_api.FilterSourceFile( 502*8975f5c5SAndroid Build Coastguard Worker f, 503*8975f5c5SAndroid Build Coastguard Worker files_to_check=(r'^include/GLSLANG/ShaderLang.h$', r'^include/GLSLANG/ShaderVars.h$')) 504*8975f5c5SAndroid Build Coastguard Worker 505*8975f5c5SAndroid Build Coastguard Worker headers_changed = input_api.AffectedSourceFiles(headers) 506*8975f5c5SAndroid Build Coastguard Worker if len(headers_changed) == 0: 507*8975f5c5SAndroid Build Coastguard Worker return [] 508*8975f5c5SAndroid Build Coastguard Worker 509*8975f5c5SAndroid Build Coastguard Worker # Skip this check for reverts and rolls. Unlike 510*8975f5c5SAndroid Build Coastguard Worker # _CheckCommitMessageFormatting, relands are still checked because the 511*8975f5c5SAndroid Build Coastguard Worker # original change might have incremented the version correctly, but the 512*8975f5c5SAndroid Build Coastguard Worker # rebase over a new version could accidentally remove that (because another 513*8975f5c5SAndroid Build Coastguard Worker # change in the meantime identically incremented it). 514*8975f5c5SAndroid Build Coastguard Worker git_output = input_api.change.DescriptionText() 515*8975f5c5SAndroid Build Coastguard Worker multiple_commits = _SplitIntoMultipleCommits(git_output) 516*8975f5c5SAndroid Build Coastguard Worker for commit in multiple_commits: 517*8975f5c5SAndroid Build Coastguard Worker if commit.startswith('Revert') or commit.startswith('Roll'): 518*8975f5c5SAndroid Build Coastguard Worker return [] 519*8975f5c5SAndroid Build Coastguard Worker 520*8975f5c5SAndroid Build Coastguard Worker diffs = '\n'.join(f.GenerateScmDiff() for f in headers_changed) 521*8975f5c5SAndroid Build Coastguard Worker versions = dict(re.findall(r'^([-+])#define ANGLE_SH_VERSION\s+(\d+)', diffs, re.M)) 522*8975f5c5SAndroid Build Coastguard Worker 523*8975f5c5SAndroid Build Coastguard Worker if len(versions) != 2 or int(versions['+']) <= int(versions['-']): 524*8975f5c5SAndroid Build Coastguard Worker return [ 525*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError( 526*8975f5c5SAndroid Build Coastguard Worker 'ANGLE_SH_VERSION should be incremented when ShaderLang.h or ShaderVars.h change.', 527*8975f5c5SAndroid Build Coastguard Worker ) 528*8975f5c5SAndroid Build Coastguard Worker ] 529*8975f5c5SAndroid Build Coastguard Worker return [] 530*8975f5c5SAndroid Build Coastguard Worker 531*8975f5c5SAndroid Build Coastguard Worker 532*8975f5c5SAndroid Build Coastguard Workerdef _CheckGClientExists(input_api, output_api, search_limit=None): 533*8975f5c5SAndroid Build Coastguard Worker presubmit_path = pathlib.Path(input_api.PresubmitLocalPath()) 534*8975f5c5SAndroid Build Coastguard Worker 535*8975f5c5SAndroid Build Coastguard Worker for current_path in itertools.chain([presubmit_path], presubmit_path.parents): 536*8975f5c5SAndroid Build Coastguard Worker gclient_path = current_path.joinpath('.gclient') 537*8975f5c5SAndroid Build Coastguard Worker if gclient_path.exists() and gclient_path.is_file(): 538*8975f5c5SAndroid Build Coastguard Worker return [] 539*8975f5c5SAndroid Build Coastguard Worker # search_limit parameter is used in unit tests to prevent searching all the way to root 540*8975f5c5SAndroid Build Coastguard Worker # directory for reproducibility. 541*8975f5c5SAndroid Build Coastguard Worker elif search_limit != None and current_path == search_limit: 542*8975f5c5SAndroid Build Coastguard Worker break 543*8975f5c5SAndroid Build Coastguard Worker 544*8975f5c5SAndroid Build Coastguard Worker return [ 545*8975f5c5SAndroid Build Coastguard Worker output_api.PresubmitError( 546*8975f5c5SAndroid Build Coastguard Worker 'Missing .gclient file.', 547*8975f5c5SAndroid Build Coastguard Worker long_text=textwrap.fill( 548*8975f5c5SAndroid Build Coastguard Worker width=100, 549*8975f5c5SAndroid Build Coastguard Worker text='The top level directory of the repository must contain a .gclient file.' 550*8975f5c5SAndroid Build Coastguard Worker ' You can follow the steps outlined in the link below to get set up for ANGLE' 551*8975f5c5SAndroid Build Coastguard Worker ' development:') + 552*8975f5c5SAndroid Build Coastguard Worker '\n\nhttps://chromium.googlesource.com/angle/angle/+/refs/heads/main/doc/DevSetup.md') 553*8975f5c5SAndroid Build Coastguard Worker ] 554*8975f5c5SAndroid Build Coastguard Worker 555*8975f5c5SAndroid Build Coastguard Workerdef CheckChangeOnUpload(input_api, output_api): 556*8975f5c5SAndroid Build Coastguard Worker results = [] 557*8975f5c5SAndroid Build Coastguard Worker results.extend(input_api.canned_checks.CheckForCommitObjects(input_api, output_api)) 558*8975f5c5SAndroid Build Coastguard Worker results.extend(_CheckTabsInSourceFiles(input_api, output_api)) 559*8975f5c5SAndroid Build Coastguard Worker results.extend(_CheckNonAsciiInSourceFiles(input_api, output_api)) 560*8975f5c5SAndroid Build Coastguard Worker results.extend(_CheckCommentBeforeTestInTestFiles(input_api, output_api)) 561*8975f5c5SAndroid Build Coastguard Worker results.extend(_CheckWildcardInTestExpectationFiles(input_api, output_api)) 562*8975f5c5SAndroid Build Coastguard Worker results.extend(_CheckShaderVersionInShaderLangHeader(input_api, output_api)) 563*8975f5c5SAndroid Build Coastguard Worker results.extend(_CheckCodeGeneration(input_api, output_api)) 564*8975f5c5SAndroid Build Coastguard Worker results.extend(_CheckChangeHasBugField(input_api, output_api)) 565*8975f5c5SAndroid Build Coastguard Worker results.extend(input_api.canned_checks.CheckChangeHasDescription(input_api, output_api)) 566*8975f5c5SAndroid Build Coastguard Worker results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api)) 567*8975f5c5SAndroid Build Coastguard Worker results.extend(_CheckExportValidity(input_api, output_api)) 568*8975f5c5SAndroid Build Coastguard Worker results.extend( 569*8975f5c5SAndroid Build Coastguard Worker input_api.canned_checks.CheckPatchFormatted( 570*8975f5c5SAndroid Build Coastguard Worker input_api, output_api, result_factory=output_api.PresubmitError)) 571*8975f5c5SAndroid Build Coastguard Worker results.extend(_CheckCommitMessageFormatting(input_api, output_api)) 572*8975f5c5SAndroid Build Coastguard Worker results.extend(_CheckGClientExists(input_api, output_api)) 573*8975f5c5SAndroid Build Coastguard Worker 574*8975f5c5SAndroid Build Coastguard Worker return results 575*8975f5c5SAndroid Build Coastguard Worker 576*8975f5c5SAndroid Build Coastguard Worker 577*8975f5c5SAndroid Build Coastguard Workerdef CheckChangeOnCommit(input_api, output_api): 578*8975f5c5SAndroid Build Coastguard Worker return CheckChangeOnUpload(input_api, output_api) 579