1*cc02d7e2SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*cc02d7e2SAndroid Build Coastguard Worker# Copyright 2017 gRPC authors. 3*cc02d7e2SAndroid Build Coastguard Worker# 4*cc02d7e2SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 5*cc02d7e2SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*cc02d7e2SAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*cc02d7e2SAndroid Build Coastguard Worker# 8*cc02d7e2SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*cc02d7e2SAndroid Build Coastguard Worker# 10*cc02d7e2SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*cc02d7e2SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 12*cc02d7e2SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*cc02d7e2SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*cc02d7e2SAndroid Build Coastguard Worker# limitations under the License. 15*cc02d7e2SAndroid Build Coastguard Worker 16*cc02d7e2SAndroid Build Coastguard Workerimport argparse 17*cc02d7e2SAndroid Build Coastguard Workerimport multiprocessing 18*cc02d7e2SAndroid Build Coastguard Workerimport os 19*cc02d7e2SAndroid Build Coastguard Workerimport subprocess 20*cc02d7e2SAndroid Build Coastguard Workerimport sys 21*cc02d7e2SAndroid Build Coastguard Worker 22*cc02d7e2SAndroid Build Coastguard Workersys.path.append( 23*cc02d7e2SAndroid Build Coastguard Worker os.path.join( 24*cc02d7e2SAndroid Build Coastguard Worker os.path.dirname(sys.argv[0]), "..", "run_tests", "python_utils" 25*cc02d7e2SAndroid Build Coastguard Worker ) 26*cc02d7e2SAndroid Build Coastguard Worker) 27*cc02d7e2SAndroid Build Coastguard Workerimport jobset 28*cc02d7e2SAndroid Build Coastguard Worker 29*cc02d7e2SAndroid Build Coastguard Workerclang_tidy = os.environ.get("CLANG_TIDY", "clang-tidy") 30*cc02d7e2SAndroid Build Coastguard Worker 31*cc02d7e2SAndroid Build Coastguard Workerargp = argparse.ArgumentParser(description="Run clang-tidy against core") 32*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument("files", nargs="+", help="Files to tidy") 33*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument("--fix", dest="fix", action="store_true") 34*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument( 35*cc02d7e2SAndroid Build Coastguard Worker "-j", 36*cc02d7e2SAndroid Build Coastguard Worker "--jobs", 37*cc02d7e2SAndroid Build Coastguard Worker type=int, 38*cc02d7e2SAndroid Build Coastguard Worker default=multiprocessing.cpu_count(), 39*cc02d7e2SAndroid Build Coastguard Worker help="Number of CPUs to use", 40*cc02d7e2SAndroid Build Coastguard Worker) 41*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument("--only-changed", dest="only_changed", action="store_true") 42*cc02d7e2SAndroid Build Coastguard Workerargp.set_defaults(fix=False, only_changed=False) 43*cc02d7e2SAndroid Build Coastguard Workerargs = argp.parse_args() 44*cc02d7e2SAndroid Build Coastguard Worker 45*cc02d7e2SAndroid Build Coastguard Worker# Explicitly passing the .clang-tidy config by reading it. 46*cc02d7e2SAndroid Build Coastguard Worker# This is required because source files in the compilation database are 47*cc02d7e2SAndroid Build Coastguard Worker# in a different source tree so clang-tidy cannot find the right config file 48*cc02d7e2SAndroid Build Coastguard Worker# by seeking their parent directories. 49*cc02d7e2SAndroid Build Coastguard Workerwith open(".clang-tidy") as f: 50*cc02d7e2SAndroid Build Coastguard Worker config = f.read() 51*cc02d7e2SAndroid Build Coastguard Workercmdline = [ 52*cc02d7e2SAndroid Build Coastguard Worker clang_tidy, 53*cc02d7e2SAndroid Build Coastguard Worker "--config=" + config, 54*cc02d7e2SAndroid Build Coastguard Worker] 55*cc02d7e2SAndroid Build Coastguard Worker 56*cc02d7e2SAndroid Build Coastguard Workerif args.fix: 57*cc02d7e2SAndroid Build Coastguard Worker cmdline.append("--fix-errors") 58*cc02d7e2SAndroid Build Coastguard Worker 59*cc02d7e2SAndroid Build Coastguard Workerif args.only_changed: 60*cc02d7e2SAndroid Build Coastguard Worker orig_files = set(args.files) 61*cc02d7e2SAndroid Build Coastguard Worker actual_files = [] 62*cc02d7e2SAndroid Build Coastguard Worker output = subprocess.check_output( 63*cc02d7e2SAndroid Build Coastguard Worker ["git", "diff", "upstream/master", "HEAD", "--name-only"] 64*cc02d7e2SAndroid Build Coastguard Worker ) 65*cc02d7e2SAndroid Build Coastguard Worker for line in output.decode("ascii").splitlines(False): 66*cc02d7e2SAndroid Build Coastguard Worker if line in orig_files: 67*cc02d7e2SAndroid Build Coastguard Worker print(("check: %s" % line)) 68*cc02d7e2SAndroid Build Coastguard Worker actual_files.append(line) 69*cc02d7e2SAndroid Build Coastguard Worker else: 70*cc02d7e2SAndroid Build Coastguard Worker print(("skip: %s - not in the build" % line)) 71*cc02d7e2SAndroid Build Coastguard Worker args.files = actual_files 72*cc02d7e2SAndroid Build Coastguard Worker 73*cc02d7e2SAndroid Build Coastguard Workerjobs = [] 74*cc02d7e2SAndroid Build Coastguard Workerfor filename in args.files: 75*cc02d7e2SAndroid Build Coastguard Worker jobs.append( 76*cc02d7e2SAndroid Build Coastguard Worker jobset.JobSpec( 77*cc02d7e2SAndroid Build Coastguard Worker cmdline + [filename], 78*cc02d7e2SAndroid Build Coastguard Worker shortname=filename, 79*cc02d7e2SAndroid Build Coastguard Worker timeout_seconds=15 * 60, 80*cc02d7e2SAndroid Build Coastguard Worker ) 81*cc02d7e2SAndroid Build Coastguard Worker ) 82*cc02d7e2SAndroid Build Coastguard Worker 83*cc02d7e2SAndroid Build Coastguard Workernum_fails, res_set = jobset.run(jobs, maxjobs=args.jobs, quiet_success=True) 84*cc02d7e2SAndroid Build Coastguard Workersys.exit(num_fails) 85