1# Copyright (C) 2018 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15from __future__ import print_function 16import time 17import subprocess 18from os.path import relpath, dirname, join 19 20USE_PYTHON3 = True 21 22 23def RunAndReportIfLong(func, *args, **kargs): 24 start = time.time() 25 results = func(*args, **kargs) 26 end = time.time() 27 limit = 0.5 # seconds 28 name = func.__name__ 29 runtime = end - start 30 if runtime > limit: 31 print("{} took >{:.2}s ({:.2}s)".format(name, limit, runtime)) 32 return results 33 34 35def CheckChange(input, output): 36 results = [] 37 results += RunAndReportIfLong(CheckEslint, input, output) 38 results += RunAndReportIfLong(CheckPrettier, input, output) 39 results += RunAndReportIfLong(CheckImports, input, output) 40 results += RunAndReportIfLong(CheckAnyRachet, input, output) 41 return results 42 43 44def CheckChangeOnUpload(input_api, output_api): 45 return CheckChange(input_api, output_api) 46 47 48def CheckChangeOnCommit(input_api, output_api): 49 return CheckChange(input_api, output_api) 50 51 52def CheckEslint(input_api, output_api): 53 path = input_api.os_path 54 ui_path = input_api.PresubmitLocalPath() 55 module_path = path.join(ui_path, 'node_modules', '.bin', 'eslint') 56 lint_path = path.join(ui_path, 'eslint') 57 58 if not path.exists(module_path): 59 repo_root = input_api.change.RepositoryRoot() 60 install_path = path.join(repo_root, 'tools', 'install-build-deps') 61 return [ 62 output_api.PresubmitError( 63 f"eslint not found. Please first run\n $ {install_path} --ui") 64 ] 65 66 def file_filter(x): 67 return input_api.FilterSourceFile( 68 x, 69 files_to_check=[r'.*\.ts$', r'.*\.js$'], 70 files_to_skip=[r'.*\.eslintrc\.js']) 71 72 files = input_api.AffectedSourceFiles(file_filter) 73 74 if not files: 75 return [] 76 paths = [f.AbsoluteLocalPath() for f in files] 77 78 cmd = [lint_path] + paths 79 if subprocess.call(cmd): 80 s = ' '.join(cmd) 81 return [output_api.PresubmitError(f"eslint errors. Run: $ {s}")] 82 return [] 83 84 85def CheckPrettier(input_api, output_api): 86 path = input_api.os_path 87 ui_path = input_api.PresubmitLocalPath() 88 module_path = path.join(ui_path, 'node_modules', '.bin', 'prettier') 89 prettier_path = path.join(ui_path, 'prettier') 90 91 if not path.exists(module_path): 92 repo_root = input_api.change.RepositoryRoot() 93 install_path = path.join(repo_root, 'tools', 'install-build-deps') 94 return [ 95 output_api.PresubmitError( 96 f"prettier not found. Please first run\n $ {install_path} --ui") 97 ] 98 99 def file_filter(x): 100 return input_api.FilterSourceFile( 101 x, files_to_check=[r'.*\.ts$', r'.*\.js$', r'.*\.scss$']) 102 103 files = input_api.AffectedSourceFiles(file_filter) 104 105 if not files: 106 return [] 107 paths = [f.AbsoluteLocalPath() for f in files] 108 109 cmd = [prettier_path, '--check'] + paths 110 if subprocess.call(cmd): 111 s = ' '.join(cmd) 112 return [ 113 output_api.PresubmitError(f"""Prettier errors. To fix, run: 114{prettier_path} -w {'_'.join(paths)}""") 115 ] 116 return [] 117 118 119def CheckImports(input_api, output_api): 120 path = input_api.os_path 121 ui_path = input_api.PresubmitLocalPath() 122 check_imports_path = join(dirname(ui_path), 'tools', 'check_imports') 123 124 def file_filter(x): 125 return input_api.FilterSourceFile( 126 x, files_to_check=[r'.*\.ts$', r'.*\.js$']) 127 128 files = input_api.AffectedSourceFiles(file_filter) 129 130 if not files: 131 return [] 132 133 if subprocess.call([check_imports_path]): 134 return [output_api.PresubmitError(f"")] 135 return [] 136 137 138def CheckAnyRachet(input_api, output_api): 139 path = input_api.os_path 140 ui_path = input_api.PresubmitLocalPath() 141 check_ratchet_path = join(dirname(ui_path), 'tools', 'check_ratchet') 142 143 def file_filter(x): 144 return input_api.FilterSourceFile(x, files_to_check=[r'.*\.ts$']) 145 146 files = input_api.AffectedSourceFiles(file_filter) 147 148 if not files: 149 return [] 150 151 if subprocess.call([check_ratchet_path]): 152 return [output_api.PresubmitError(f"")] 153 return [] 154